| ... | @@ -110,6 +110,7 @@ pub const ElfFile = struct { | ... | @@ -110,6 +110,7 @@ pub const ElfFile = struct { |
| 110 | /// The index into the program headers of the global offset table. | 110 | /// The index into the program headers of the global offset table. |
| 111 | /// It needs PT_LOAD and Read flags. | 111 | /// It needs PT_LOAD and Read flags. |
| 112 | phdr_got_index: ?u16 = null, | 112 | phdr_got_index: ?u16 = null, |
| | 113 | phdr_got_plt_index: ?u16 = null, |
| 113 | entry_addr: ?u64 = null, | 114 | entry_addr: ?u64 = null, |
| 114 | | 115 | |
| 115 | shstrtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){}, | 116 | shstrtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){}, |
| ... | @@ -118,6 +119,7 @@ pub const ElfFile = struct { | ... | @@ -118,6 +119,7 @@ pub const ElfFile = struct { |
| 118 | text_section_index: ?u16 = null, | 119 | text_section_index: ?u16 = null, |
| 119 | symtab_section_index: ?u16 = null, | 120 | symtab_section_index: ?u16 = null, |
| 120 | got_section_index: ?u16 = null, | 121 | got_section_index: ?u16 = null, |
| | 122 | got_plt_section_index: ?u16 = null, |
| 121 | | 123 | |
| 122 | /// The same order as in the file. ELF requires global symbols to all be after the | 124 | /// The same order as in the file. ELF requires global symbols to all be after the |
| 123 | /// local symbols, they cannot be mixed. So we must buffer all the global symbols and | 125 | /// local symbols, they cannot be mixed. So we must buffer all the global symbols and |
| ... | @@ -130,11 +132,16 @@ pub const ElfFile = struct { | ... | @@ -130,11 +132,16 @@ pub const ElfFile = struct { |
| 130 | /// If the vaddr of the executable program header changes, the entire | 132 | /// If the vaddr of the executable program header changes, the entire |
| 131 | /// offset table needs to be rewritten. | 133 | /// offset table needs to be rewritten. |
| 132 | offset_table: std.ArrayListUnmanaged(u64) = std.ArrayListUnmanaged(u64){}, | 134 | offset_table: std.ArrayListUnmanaged(u64) = std.ArrayListUnmanaged(u64){}, |
| | 135 | /// Same order as in the file. The value is the absolute vaddr value. |
| | 136 | /// If the vaddr of the executable program header changes, the entire |
| | 137 | /// fn trampoline table needs to be rewritten. |
| | 138 | fn_trampoline_table: std.ArrayListUnmanaged(u64) = std.ArrayListUnmanaged(u64){}, |
| 133 | | 139 | |
| 134 | phdr_table_dirty: bool = false, | 140 | phdr_table_dirty: bool = false, |
| 135 | shdr_table_dirty: bool = false, | 141 | shdr_table_dirty: bool = false, |
| 136 | shstrtab_dirty: bool = false, | 142 | shstrtab_dirty: bool = false, |
| 137 | offset_table_count_dirty: bool = false, | 143 | offset_table_count_dirty: bool = false, |
| | 144 | fn_trampoline_table_count_dirty: bool = false, |
| 138 | | 145 | |
| 139 | error_flags: ErrorFlags = ErrorFlags{}, | 146 | error_flags: ErrorFlags = ErrorFlags{}, |
| 140 | | 147 | |
| ... | @@ -150,12 +157,18 @@ pub const ElfFile = struct { | ... | @@ -150,12 +157,18 @@ pub const ElfFile = struct { |
| 150 | /// If this field is 0, it means the codegen size = 0 and there is no symbol or | 157 | /// If this field is 0, it means the codegen size = 0 and there is no symbol or |
| 151 | /// offset table entry. | 158 | /// offset table entry. |
| 152 | local_sym_index: u32, | 159 | local_sym_index: u32, |
| 153 | /// This field is undefined for symbols with size = 0. | 160 | /// when size = 0 and there is no offset table index |
| 154 | offset_table_index: u32, | 161 | offset_table_index: union { |
| | 162 | unallocated: void, |
| | 163 | /// This is an index into offset_table |
| | 164 | got: u32, |
| | 165 | /// This is an index into fn_trampoline_table |
| | 166 | plt: u32, |
| | 167 | }, |
| 155 | | 168 | |
| 156 | pub const empty = Decl{ | 169 | pub const empty = Decl{ |
| 157 | .local_sym_index = 0, | 170 | .local_sym_index = 0, |
| 158 | .offset_table_index = undefined, | 171 | .offset_table_index = .{ .unallocated = {} }, |
| 159 | }; | 172 | }; |
| 160 | }; | 173 | }; |
| 161 | | 174 | |
| ... | @@ -170,6 +183,7 @@ pub const ElfFile = struct { | ... | @@ -170,6 +183,7 @@ pub const ElfFile = struct { |
| 170 | self.local_symbols.deinit(self.allocator); | 183 | self.local_symbols.deinit(self.allocator); |
| 171 | self.global_symbols.deinit(self.allocator); | 184 | self.global_symbols.deinit(self.allocator); |
| 172 | self.offset_table.deinit(self.allocator); | 185 | self.offset_table.deinit(self.allocator); |
| | 186 | self.fn_trampoline_table.deinit(self.allocator); |
| 173 | if (self.owns_file_handle) { | 187 | if (self.owns_file_handle) { |
| 174 | if (self.file) |f| f.close(); | 188 | if (self.file) |f| f.close(); |
| 175 | } | 189 | } |
| ... | @@ -343,6 +357,30 @@ pub const ElfFile = struct { | ... | @@ -343,6 +357,30 @@ pub const ElfFile = struct { |
| 343 | }); | 357 | }); |
| 344 | self.phdr_table_dirty = true; | 358 | self.phdr_table_dirty = true; |
| 345 | } | 359 | } |
| | 360 | if (self.phdr_got_plt_index == null) { |
| | 361 | self.phdr_got_plt_index = @intCast(u16, self.program_headers.items.len); |
| | 362 | const file_size = @as(u64, ptr_size) * self.options.symbol_count_hint; |
| | 363 | // We really only need ptr alignment but since we are using PROGBITS, linux requires |
| | 364 | // page align. |
| | 365 | const p_align = 0x1000; |
| | 366 | const off = self.findFreeSpace(file_size, p_align); |
| | 367 | //std.debug.warn("found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); |
| | 368 | // TODO instead of hard coding the vaddr, make a function to find a vaddr to put things at. |
| | 369 | // we'll need to re-use that function anyway, in case the GOT grows and overlaps something |
| | 370 | // else in virtual memory. |
| | 371 | const default_got_plt_addr = 0x6000000; |
| | 372 | try self.program_headers.append(self.allocator, .{ |
| | 373 | .p_type = elf.PT_LOAD, |
| | 374 | .p_offset = off, |
| | 375 | .p_filesz = file_size, |
| | 376 | .p_vaddr = default_got_plt_addr, |
| | 377 | .p_paddr = default_got_plt_addr, |
| | 378 | .p_memsz = file_size, |
| | 379 | .p_align = p_align, |
| | 380 | .p_flags = elf.PF_R, |
| | 381 | }); |
| | 382 | self.phdr_table_dirty = true; |
| | 383 | } |
| 346 | if (self.shstrtab_index == null) { | 384 | if (self.shstrtab_index == null) { |
| 347 | self.shstrtab_index = @intCast(u16, self.sections.items.len); | 385 | self.shstrtab_index = @intCast(u16, self.sections.items.len); |
| 348 | assert(self.shstrtab.items.len == 0); | 386 | assert(self.shstrtab.items.len == 0); |
| ... | @@ -400,6 +438,24 @@ pub const ElfFile = struct { | ... | @@ -400,6 +438,24 @@ pub const ElfFile = struct { |
| 400 | }); | 438 | }); |
| 401 | self.shdr_table_dirty = true; | 439 | self.shdr_table_dirty = true; |
| 402 | } | 440 | } |
| | 441 | if (self.got_plt_section_index == null) { |
| | 442 | self.got_plt_section_index = @intCast(u16, self.sections.items.len); |
| | 443 | const phdr = &self.program_headers.items[self.phdr_got_plt_index.?]; |
| | 444 | |
| | 445 | try self.sections.append(self.allocator, .{ |
| | 446 | .sh_name = try self.makeString(".got.plt"), |
| | 447 | .sh_type = elf.SHT_PROGBITS, |
| | 448 | .sh_flags = elf.SHF_ALLOC, |
| | 449 | .sh_addr = phdr.p_vaddr, |
| | 450 | .sh_offset = phdr.p_offset, |
| | 451 | .sh_size = phdr.p_filesz, |
| | 452 | .sh_link = 0, |
| | 453 | .sh_info = 0, |
| | 454 | .sh_addralign = phdr.p_align, |
| | 455 | .sh_entsize = 0, |
| | 456 | }); |
| | 457 | self.shdr_table_dirty = true; |
| | 458 | } |
| 403 | if (self.symtab_section_index == null) { | 459 | if (self.symtab_section_index == null) { |
| 404 | self.symtab_section_index = @intCast(u16, self.sections.items.len); | 460 | self.symtab_section_index = @intCast(u16, self.sections.items.len); |
| 405 | const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym); | 461 | const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym); |
| ... | @@ -584,6 +640,7 @@ pub const ElfFile = struct { | ... | @@ -584,6 +640,7 @@ pub const ElfFile = struct { |
| 584 | assert(!self.shdr_table_dirty); | 640 | assert(!self.shdr_table_dirty); |
| 585 | assert(!self.shstrtab_dirty); | 641 | assert(!self.shstrtab_dirty); |
| 586 | assert(!self.offset_table_count_dirty); | 642 | assert(!self.offset_table_count_dirty); |
| | 643 | assert(!self.fn_trampoline_table_count_dirty); |
| 587 | const syms_sect = &self.sections.items[self.symtab_section_index.?]; | 644 | const syms_sect = &self.sections.items[self.symtab_section_index.?]; |
| 588 | assert(syms_sect.sh_info == self.local_symbols.items.len); | 645 | assert(syms_sect.sh_info == self.local_symbols.items.len); |
| 589 | } | 646 | } |
| ... | @@ -740,6 +797,7 @@ pub const ElfFile = struct { | ... | @@ -740,6 +797,7 @@ pub const ElfFile = struct { |
| 740 | const amt = try self.file.?.copyRangeAll(shdr.sh_offset, self.file.?, new_offset, text_size); | 797 | const amt = try self.file.?.copyRangeAll(shdr.sh_offset, self.file.?, new_offset, text_size); |
| 741 | if (amt != text_size) return error.InputOutput; | 798 | if (amt != text_size) return error.InputOutput; |
| 742 | shdr.sh_offset = new_offset; | 799 | shdr.sh_offset = new_offset; |
| | 800 | phdr.p_offset = new_offset; |
| 743 | } | 801 | } |
| 744 | // Now that we know the code size, we need to update the program header for executable code | 802 | // Now that we know the code size, we need to update the program header for executable code |
| 745 | shdr.sh_size = needed_size; | 803 | shdr.sh_size = needed_size; |
| ... | @@ -778,10 +836,14 @@ pub const ElfFile = struct { | ... | @@ -778,10 +836,14 @@ pub const ElfFile = struct { |
| 778 | pub fn allocateDeclIndexes(self: *ElfFile, decl: *Module.Decl) !void { | 836 | pub fn allocateDeclIndexes(self: *ElfFile, decl: *Module.Decl) !void { |
| 779 | if (decl.link.local_sym_index != 0) return; | 837 | if (decl.link.local_sym_index != 0) return; |
| 780 | | 838 | |
| | 839 | const is_fn = (decl.typed_value.most_recent.typed_value.ty.zigTypeTag() == .Fn); |
| | 840 | |
| 781 | try self.local_symbols.ensureCapacity(self.allocator, self.local_symbols.items.len + 1); | 841 | try self.local_symbols.ensureCapacity(self.allocator, self.local_symbols.items.len + 1); |
| 782 | try self.offset_table.ensureCapacity(self.allocator, self.offset_table.items.len + 1); | 842 | try self.offset_table.ensureCapacity(self.allocator, self.offset_table.items.len + 1); |
| | 843 | try self.fn_trampoline_table.ensureCapacity(self.allocator, self.fn_trampoline_table.items.len + 1); |
| 783 | const local_sym_index = self.local_symbols.items.len; | 844 | const local_sym_index = self.local_symbols.items.len; |
| 784 | const offset_table_index = self.offset_table.items.len; | 845 | const offset_table_index = self.offset_table.items.len; |
| | 846 | const fn_trampoline_table_index = self.fn_trampoline_table.items.len; |
| 785 | const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; | 847 | const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; |
| 786 | | 848 | |
| 787 | self.local_symbols.appendAssumeCapacity(.{ | 849 | self.local_symbols.appendAssumeCapacity(.{ |
| ... | @@ -792,15 +854,20 @@ pub const ElfFile = struct { | ... | @@ -792,15 +854,20 @@ pub const ElfFile = struct { |
| 792 | .st_value = phdr.p_vaddr, | 854 | .st_value = phdr.p_vaddr, |
| 793 | .st_size = 0, | 855 | .st_size = 0, |
| 794 | }); | 856 | }); |
| 795 | errdefer self.local_symbols.shrink(self.allocator, self.local_symbols.items.len - 1); | 857 | if (is_fn) { |
| 796 | self.offset_table.appendAssumeCapacity(0); | 858 | self.fn_trampoline_table.appendAssumeCapacity(0); |
| 797 | errdefer self.offset_table.shrink(self.allocator, self.offset_table.items.len - 1); | 859 | self.fn_trampoline_table_count_dirty = true; |
| 798 | | 860 | } else { |
| 799 | self.offset_table_count_dirty = true; | 861 | self.offset_table.appendAssumeCapacity(0); |
| | 862 | self.offset_table_count_dirty = true; |
| | 863 | } |
| 800 | | 864 | |
| 801 | decl.link = .{ | 865 | decl.link = .{ |
| 802 | .local_sym_index = @intCast(u32, local_sym_index), | 866 | .local_sym_index = @intCast(u32, local_sym_index), |
| 803 | .offset_table_index = @intCast(u32, offset_table_index), | 867 | .offset_table_index = if (is_fn) |
| | 868 | .{ .plt = @intCast(u32, fn_trampoline_table_index) } |
| | 869 | else |
| | 870 | .{ .got = @intCast(u32, offset_table_index) }, |
| 804 | }; | 871 | }; |
| 805 | } | 872 | } |
| 806 | | 873 | |
| ... | @@ -818,6 +885,7 @@ pub const ElfFile = struct { | ... | @@ -818,6 +885,7 @@ pub const ElfFile = struct { |
| 818 | return; | 885 | return; |
| 819 | }, | 886 | }, |
| 820 | }; | 887 | }; |
| | 888 | const is_fn = (typed_value.ty.zigTypeTag() == .Fn); |
| 821 | | 889 | |
| 822 | const required_alignment = typed_value.ty.abiAlignment(self.options.target); | 890 | const required_alignment = typed_value.ty.abiAlignment(self.options.target); |
| 823 | | 891 | |
| ... | @@ -837,14 +905,13 @@ pub const ElfFile = struct { | ... | @@ -837,14 +905,13 @@ pub const ElfFile = struct { |
| 837 | const file_offset = if (need_realloc) fo: { | 905 | const file_offset = if (need_realloc) fo: { |
| 838 | const new_block = try self.allocateTextBlock(code.len, required_alignment); | 906 | const new_block = try self.allocateTextBlock(code.len, required_alignment); |
| 839 | local_sym.st_value = new_block.vaddr; | 907 | local_sym.st_value = new_block.vaddr; |
| 840 | self.offset_table.items[decl.link.offset_table_index] = new_block.vaddr; | 908 | if (is_fn) { |
| 841 | | 909 | self.fn_trampoline_table.items[decl.link.offset_table_index.plt] = new_block.vaddr; |
| 842 | //std.debug.warn("{}: writing got index {}=0x{x}\n", .{ | 910 | try self.writeFnTrampolineEntry(decl.link.offset_table_index.plt); |
| 843 | // decl.name, | 911 | } else { |
| 844 | // decl.link.offset_table_index, | 912 | self.offset_table.items[decl.link.offset_table_index.got] = new_block.vaddr; |
| 845 | // self.offset_table.items[decl.link.offset_table_index], | 913 | try self.writeOffsetTableEntry(decl.link.offset_table_index.got); |
| 846 | //}); | 914 | } |
| 847 | try self.writeOffsetTableEntry(decl.link.offset_table_index); | | |
| 848 | | 915 | |
| 849 | break :fo new_block.file_offset; | 916 | break :fo new_block.file_offset; |
| 850 | } else existing_block.file_offset; | 917 | } else existing_block.file_offset; |
| ... | @@ -861,11 +928,13 @@ pub const ElfFile = struct { | ... | @@ -861,11 +928,13 @@ pub const ElfFile = struct { |
| 861 | } else { | 928 | } else { |
| 862 | try self.local_symbols.ensureCapacity(self.allocator, self.local_symbols.items.len + 1); | 929 | try self.local_symbols.ensureCapacity(self.allocator, self.local_symbols.items.len + 1); |
| 863 | try self.offset_table.ensureCapacity(self.allocator, self.offset_table.items.len + 1); | 930 | try self.offset_table.ensureCapacity(self.allocator, self.offset_table.items.len + 1); |
| | 931 | try self.fn_trampoline_table.ensureCapacity(self.allocator, self.fn_trampoline_table.items.len + 1); |
| 864 | const decl_name = mem.spanZ(decl.name); | 932 | const decl_name = mem.spanZ(decl.name); |
| 865 | const name_str_index = try self.makeString(decl_name); | 933 | const name_str_index = try self.makeString(decl_name); |
| 866 | const new_block = try self.allocateTextBlock(code.len, required_alignment); | 934 | const new_block = try self.allocateTextBlock(code.len, required_alignment); |
| 867 | const local_sym_index = self.local_symbols.items.len; | 935 | const local_sym_index = self.local_symbols.items.len; |
| 868 | const offset_table_index = self.offset_table.items.len; | 936 | const offset_table_index = self.offset_table.items.len; |
| | 937 | const fn_trampoline_table_index = self.fn_trampoline_table.items.len; |
| 869 | | 938 | |
| 870 | //std.debug.warn("add symbol for {} at vaddr 0x{x}, size {}\n", .{ decl.name, new_block.vaddr, code.len }); | 939 | //std.debug.warn("add symbol for {} at vaddr 0x{x}, size {}\n", .{ decl.name, new_block.vaddr, code.len }); |
| 871 | self.local_symbols.appendAssumeCapacity(.{ | 940 | self.local_symbols.appendAssumeCapacity(.{ |
| ... | @@ -877,17 +946,32 @@ pub const ElfFile = struct { | ... | @@ -877,17 +946,32 @@ pub const ElfFile = struct { |
| 877 | .st_size = code.len, | 946 | .st_size = code.len, |
| 878 | }); | 947 | }); |
| 879 | errdefer self.local_symbols.shrink(self.allocator, self.local_symbols.items.len - 1); | 948 | errdefer self.local_symbols.shrink(self.allocator, self.local_symbols.items.len - 1); |
| 880 | self.offset_table.appendAssumeCapacity(new_block.vaddr); | 949 | if (is_fn) { |
| 881 | errdefer self.offset_table.shrink(self.allocator, self.offset_table.items.len - 1); | 950 | self.fn_trampoline_table.appendAssumeCapacity(new_block.vaddr); |
| 882 | | 951 | } else { |
| 883 | self.offset_table_count_dirty = true; | 952 | self.offset_table.appendAssumeCapacity(new_block.vaddr); |
| | 953 | } |
| | 954 | errdefer if (is_fn) { |
| | 955 | self.fn_trampoline_table.shrink(self.allocator, self.fn_trampoline_table.items.len - 1); |
| | 956 | } else { |
| | 957 | self.offset_table.shrink(self.allocator, self.offset_table.items.len - 1); |
| | 958 | }; |
| 884 | | 959 | |
| 885 | try self.writeSymbol(local_sym_index); | 960 | try self.writeSymbol(local_sym_index); |
| 886 | try self.writeOffsetTableEntry(offset_table_index); | 961 | if (is_fn) { |
| | 962 | try self.writeFnTrampolineEntry(fn_trampoline_table_index); |
| | 963 | self.fn_trampoline_table_count_dirty = true; |
| | 964 | } else { |
| | 965 | try self.writeOffsetTableEntry(offset_table_index); |
| | 966 | self.offset_table_count_dirty = true; |
| | 967 | } |
| 887 | | 968 | |
| 888 | decl.link = .{ | 969 | decl.link = .{ |
| 889 | .local_sym_index = @intCast(u32, local_sym_index), | 970 | .local_sym_index = @intCast(u32, local_sym_index), |
| 890 | .offset_table_index = @intCast(u32, offset_table_index), | 971 | .offset_table_index = if (is_fn) |
| | 972 | .{ .plt = @intCast(u32, fn_trampoline_table_index) } |
| | 973 | else |
| | 974 | .{ .got = @intCast(u32, offset_table_index) }, |
| 891 | }; | 975 | }; |
| 892 | | 976 | |
| 893 | //std.debug.warn("writing new {} at vaddr 0x{x}\n", .{ decl.name, new_block.vaddr }); | 977 | //std.debug.warn("writing new {} at vaddr 0x{x}\n", .{ decl.name, new_block.vaddr }); |
| ... | @@ -1017,6 +1101,40 @@ pub const ElfFile = struct { | ... | @@ -1017,6 +1101,40 @@ pub const ElfFile = struct { |
| 1017 | } | 1101 | } |
| 1018 | } | 1102 | } |
| 1019 | | 1103 | |
| | 1104 | fn writeFnTrampolineEntry(self: *ElfFile, index: usize) !void { |
| | 1105 | const shdr = &self.sections.items[self.got_plt_section_index.?]; |
| | 1106 | const phdr = &self.program_headers.items[self.phdr_got_plt_index.?]; |
| | 1107 | const entry_size = codegen.pltEntrySize(self.options.target); |
| | 1108 | var entry_buf: [16]u8 = undefined; |
| | 1109 | assert(entry_size <= entry_buf.len); |
| | 1110 | |
| | 1111 | if (self.fn_trampoline_table_count_dirty) { |
| | 1112 | // TODO Also detect virtual address collisions. |
| | 1113 | const allocated_size = self.allocatedSize(shdr.sh_offset); |
| | 1114 | const needed_size = self.local_symbols.items.len * entry_size; |
| | 1115 | if (needed_size > allocated_size) { |
| | 1116 | // Must move the entire .got.plt section. |
| | 1117 | const new_offset = self.findFreeSpace(needed_size, entry_size); |
| | 1118 | const amt = try self.file.?.copyRangeAll(shdr.sh_offset, self.file.?, new_offset, shdr.sh_size); |
| | 1119 | if (amt != shdr.sh_size) return error.InputOutput; |
| | 1120 | shdr.sh_offset = new_offset; |
| | 1121 | phdr.p_offset = new_offset; |
| | 1122 | } |
| | 1123 | shdr.sh_size = needed_size; |
| | 1124 | phdr.p_memsz = needed_size; |
| | 1125 | phdr.p_filesz = needed_size; |
| | 1126 | |
| | 1127 | self.shdr_table_dirty = true; // TODO look into making only the one section dirty |
| | 1128 | self.phdr_table_dirty = true; // TODO look into making only the one program header dirty |
| | 1129 | |
| | 1130 | self.fn_trampoline_table_count_dirty = false; |
| | 1131 | } |
| | 1132 | const off = shdr.sh_offset + @as(u64, entry_size) * index; |
| | 1133 | const vaddr = @intCast(u32, self.fn_trampoline_table.items[index]); |
| | 1134 | codegen.writePltEntry(self.options.target, &entry_buf, vaddr); |
| | 1135 | try self.file.?.pwriteAll(entry_buf[0..entry_size], off); |
| | 1136 | } |
| | 1137 | |
| 1020 | fn writeOffsetTableEntry(self: *ElfFile, index: usize) !void { | 1138 | fn writeOffsetTableEntry(self: *ElfFile, index: usize) !void { |
| 1021 | const shdr = &self.sections.items[self.got_section_index.?]; | 1139 | const shdr = &self.sections.items[self.got_section_index.?]; |
| 1022 | const phdr = &self.program_headers.items[self.phdr_got_index.?]; | 1140 | const phdr = &self.program_headers.items[self.phdr_got_index.?]; |
| ... | @@ -1034,6 +1152,7 @@ pub const ElfFile = struct { | ... | @@ -1034,6 +1152,7 @@ pub const ElfFile = struct { |
| 1034 | const amt = try self.file.?.copyRangeAll(shdr.sh_offset, self.file.?, new_offset, shdr.sh_size); | 1152 | const amt = try self.file.?.copyRangeAll(shdr.sh_offset, self.file.?, new_offset, shdr.sh_size); |
| 1035 | if (amt != shdr.sh_size) return error.InputOutput; | 1153 | if (amt != shdr.sh_size) return error.InputOutput; |
| 1036 | shdr.sh_offset = new_offset; | 1154 | shdr.sh_offset = new_offset; |
| | 1155 | phdr.p_offset = new_offset; |
| 1037 | } | 1156 | } |
| 1038 | shdr.sh_size = needed_size; | 1157 | shdr.sh_size = needed_size; |
| 1039 | phdr.p_memsz = needed_size; | 1158 | phdr.p_memsz = needed_size; |