authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-14 07:32:38+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-02-14 07:32:38+01:00
log3f5593205dd687e9c637d7c34bd05b3ba53c2312
tree7ccf8c6c1014412fed368f2c245f7404c5214b1b
parent5f925582909916b3843323c77b2edc05acc3f172
parent216a5594f62aca7524012e0a2bbf226c4064fae4
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #18918 from ziglang/elf-better-addr-mgmt

elf: store relative offsets in atom and symbol

8 files changed, 139 insertions(+), 156 deletions(-)

src/link/Elf.zig+60-70
...@@ -138,40 +138,40 @@ comdat_group_sections: std.ArrayListUnmanaged(ComdatGroupSection) = .{},...@@ -138,40 +138,40 @@ comdat_group_sections: std.ArrayListUnmanaged(ComdatGroupSection) = .{},
138138
139/// Tracked section headers with incremental updates to Zig object.139/// Tracked section headers with incremental updates to Zig object.
140/// .rela.* sections are only used when emitting a relocatable object file.140/// .rela.* sections are only used when emitting a relocatable object file.
141zig_text_section_index: ?u16 = null,141zig_text_section_index: ?u32 = null,
142zig_data_rel_ro_section_index: ?u16 = null,142zig_data_rel_ro_section_index: ?u32 = null,
143zig_data_section_index: ?u16 = null,143zig_data_section_index: ?u32 = null,
144zig_bss_section_index: ?u16 = null,144zig_bss_section_index: ?u32 = null,
145zig_got_section_index: ?u16 = null,145zig_got_section_index: ?u32 = null,
146146
147debug_info_section_index: ?u16 = null,147debug_info_section_index: ?u32 = null,
148debug_abbrev_section_index: ?u16 = null,148debug_abbrev_section_index: ?u32 = null,
149debug_str_section_index: ?u16 = null,149debug_str_section_index: ?u32 = null,
150debug_aranges_section_index: ?u16 = null,150debug_aranges_section_index: ?u32 = null,
151debug_line_section_index: ?u16 = null,151debug_line_section_index: ?u32 = null,
152152
153copy_rel_section_index: ?u16 = null,153copy_rel_section_index: ?u32 = null,
154dynamic_section_index: ?u16 = null,154dynamic_section_index: ?u32 = null,
155dynstrtab_section_index: ?u16 = null,155dynstrtab_section_index: ?u32 = null,
156dynsymtab_section_index: ?u16 = null,156dynsymtab_section_index: ?u32 = null,
157eh_frame_section_index: ?u16 = null,157eh_frame_section_index: ?u32 = null,
158eh_frame_rela_section_index: ?u16 = null,158eh_frame_rela_section_index: ?u32 = null,
159eh_frame_hdr_section_index: ?u16 = null,159eh_frame_hdr_section_index: ?u32 = null,
160hash_section_index: ?u16 = null,160hash_section_index: ?u32 = null,
161gnu_hash_section_index: ?u16 = null,161gnu_hash_section_index: ?u32 = null,
162got_section_index: ?u16 = null,162got_section_index: ?u32 = null,
163got_plt_section_index: ?u16 = null,163got_plt_section_index: ?u32 = null,
164interp_section_index: ?u16 = null,164interp_section_index: ?u32 = null,
165plt_section_index: ?u16 = null,165plt_section_index: ?u32 = null,
166plt_got_section_index: ?u16 = null,166plt_got_section_index: ?u32 = null,
167rela_dyn_section_index: ?u16 = null,167rela_dyn_section_index: ?u32 = null,
168rela_plt_section_index: ?u16 = null,168rela_plt_section_index: ?u32 = null,
169versym_section_index: ?u16 = null,169versym_section_index: ?u32 = null,
170verneed_section_index: ?u16 = null,170verneed_section_index: ?u32 = null,
171171
172shstrtab_section_index: ?u16 = null,172shstrtab_section_index: ?u32 = null,
173strtab_section_index: ?u16 = null,173strtab_section_index: ?u32 = null,
174symtab_section_index: ?u16 = null,174symtab_section_index: ?u32 = null,
175175
176// Linker-defined symbols176// Linker-defined symbols
177dynamic_index: ?Symbol.Index = null,177dynamic_index: ?Symbol.Index = null,
...@@ -931,7 +931,7 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {...@@ -931,7 +931,7 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
931 try self.base.file.?.pwriteAll(&[1]u8{0}, end_pos);931 try self.base.file.?.pwriteAll(&[1]u8{0}, end_pos);
932}932}
933933
934pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {934pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void {
935 const shdr = &self.shdrs.items[shdr_index];935 const shdr = &self.shdrs.items[shdr_index];
936 const maybe_phdr = if (self.phdr_to_shdr_table.get(shdr_index)) |phndx| &self.phdrs.items[phndx] else null;936 const maybe_phdr = if (self.phdr_to_shdr_table.get(shdr_index)) |phndx| &self.phdrs.items[phndx] else null;
937 const is_zerofill = shdr.sh_type == elf.SHT_NOBITS;937 const is_zerofill = shdr.sh_type == elf.SHT_NOBITS;
...@@ -981,7 +981,7 @@ pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {...@@ -981,7 +981,7 @@ pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {
981981
982pub fn growNonAllocSection(982pub fn growNonAllocSection(
983 self: *Elf,983 self: *Elf,
984 shdr_index: u16,984 shdr_index: u32,
985 needed_size: u64,985 needed_size: u64,
986 min_alignment: u32,986 min_alignment: u32,
987 requires_file_copy: bool,987 requires_file_copy: bool,
...@@ -1018,7 +1018,7 @@ pub fn growNonAllocSection(...@@ -1018,7 +1018,7 @@ pub fn growNonAllocSection(
1018 self.markDirty(shdr_index);1018 self.markDirty(shdr_index);
1019}1019}
10201020
1021pub fn markDirty(self: *Elf, shdr_index: u16) void {1021pub fn markDirty(self: *Elf, shdr_index: u32) void {
1022 const zig_object = self.zigObjectPtr().?;1022 const zig_object = self.zigObjectPtr().?;
1023 if (zig_object.dwarf) |_| {1023 if (zig_object.dwarf) |_| {
1024 if (self.debug_info_section_index.? == shdr_index) {1024 if (self.debug_info_section_index.? == shdr_index) {
...@@ -1332,7 +1332,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node)...@@ -1332,7 +1332,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node)
1332 try self.sortPhdrs();1332 try self.sortPhdrs();
1333 try self.allocateNonAllocSections();1333 try self.allocateNonAllocSections();
1334 self.allocateSpecialPhdrs();1334 self.allocateSpecialPhdrs();
1335 self.allocateAtoms();
1336 self.allocateLinkerDefinedSymbols();1335 self.allocateLinkerDefinedSymbols();
13371336
1338 // Dump the state for easy debugging.1337 // Dump the state for easy debugging.
...@@ -1352,7 +1351,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node)...@@ -1352,7 +1351,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node)
1352 if (shdr.sh_type == elf.SHT_NOBITS) continue;1351 if (shdr.sh_type == elf.SHT_NOBITS) continue;
1353 const code = try zig_object.codeAlloc(self, atom_index);1352 const code = try zig_object.codeAlloc(self, atom_index);
1354 defer gpa.free(code);1353 defer gpa.free(code);
1355 const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr;1354 const file_offset = shdr.sh_offset + atom_ptr.value;
1356 atom_ptr.resolveRelocsAlloc(self, code) catch |err| switch (err) {1355 atom_ptr.resolveRelocsAlloc(self, code) catch |err| switch (err) {
1357 // TODO1356 // TODO
1358 error.RelaxFail, error.InvalidInstruction, error.CannotEncode => {1357 error.RelaxFail, error.InvalidInstruction, error.CannotEncode => {
...@@ -2907,7 +2906,7 @@ pub fn writeElfHeader(self: *Elf) !void {...@@ -2907,7 +2906,7 @@ pub fn writeElfHeader(self: *Elf) !void {
2907 mem.writeInt(u32, hdr_buf[index..][0..4], 1, endian);2906 mem.writeInt(u32, hdr_buf[index..][0..4], 1, endian);
2908 index += 4;2907 index += 4;
29092908
2910 const e_entry = if (self.entry_index) |entry_index| self.symbol(entry_index).value else 0;2909 const e_entry = if (self.entry_index) |entry_index| self.symbol(entry_index).address(.{}, self) else 0;
2911 const phdr_table_offset = if (self.phdr_table_index) |phndx| self.phdrs.items[phndx].p_offset else 0;2910 const phdr_table_offset = if (self.phdr_table_index) |phndx| self.phdrs.items[phndx].p_offset else 0;
2912 switch (self.ptr_width) {2911 switch (self.ptr_width) {
2913 .p32 => {2912 .p32 => {
...@@ -2970,7 +2969,7 @@ pub fn writeElfHeader(self: *Elf) !void {...@@ -2970,7 +2969,7 @@ pub fn writeElfHeader(self: *Elf) !void {
2970 mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian);2969 mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian);
2971 index += 2;2970 index += 2;
29722971
2973 mem.writeInt(u16, hdr_buf[index..][0..2], self.shstrtab_section_index.?, endian);2972 mem.writeInt(u16, hdr_buf[index..][0..2], @intCast(self.shstrtab_section_index.?), endian);
2974 index += 2;2973 index += 2;
29752974
2976 assert(index == e_ehsize);2975 assert(index == e_ehsize);
...@@ -3710,7 +3709,7 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void {...@@ -3710,7 +3709,7 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void {
3710 }3709 }
3711}3710}
37123711
3713fn shdrRank(self: *Elf, shndx: u16) u8 {3712fn shdrRank(self: *Elf, shndx: u32) u8 {
3714 const shdr = self.shdrs.items[shndx];3713 const shdr = self.shdrs.items[shndx];
3715 const name = self.getShString(shdr.sh_name);3714 const name = self.getShString(shdr.sh_name);
3716 const flags = shdr.sh_flags;3715 const flags = shdr.sh_flags;
...@@ -3760,7 +3759,7 @@ fn shdrRank(self: *Elf, shndx: u16) u8 {...@@ -3760,7 +3759,7 @@ fn shdrRank(self: *Elf, shndx: u16) u8 {
37603759
3761pub fn sortShdrs(self: *Elf) !void {3760pub fn sortShdrs(self: *Elf) !void {
3762 const Entry = struct {3761 const Entry = struct {
3763 shndx: u16,3762 shndx: u32,
37643763
3765 pub fn lessThan(elf_file: *Elf, lhs: @This(), rhs: @This()) bool {3764 pub fn lessThan(elf_file: *Elf, lhs: @This(), rhs: @This()) bool {
3766 return elf_file.shdrRank(lhs.shndx) < elf_file.shdrRank(rhs.shndx);3765 return elf_file.shdrRank(lhs.shndx) < elf_file.shdrRank(rhs.shndx);
...@@ -3771,15 +3770,15 @@ pub fn sortShdrs(self: *Elf) !void {...@@ -3771,15 +3770,15 @@ pub fn sortShdrs(self: *Elf) !void {
3771 var entries = try std.ArrayList(Entry).initCapacity(gpa, self.shdrs.items.len);3770 var entries = try std.ArrayList(Entry).initCapacity(gpa, self.shdrs.items.len);
3772 defer entries.deinit();3771 defer entries.deinit();
3773 for (0..self.shdrs.items.len) |shndx| {3772 for (0..self.shdrs.items.len) |shndx| {
3774 entries.appendAssumeCapacity(.{ .shndx = @as(u16, @intCast(shndx)) });3773 entries.appendAssumeCapacity(.{ .shndx = @intCast(shndx) });
3775 }3774 }
37763775
3777 mem.sort(Entry, entries.items, self, Entry.lessThan);3776 mem.sort(Entry, entries.items, self, Entry.lessThan);
37783777
3779 const backlinks = try gpa.alloc(u16, entries.items.len);3778 const backlinks = try gpa.alloc(u32, entries.items.len);
3780 defer gpa.free(backlinks);3779 defer gpa.free(backlinks);
3781 for (entries.items, 0..) |entry, i| {3780 for (entries.items, 0..) |entry, i| {
3782 backlinks[entry.shndx] = @as(u16, @intCast(i));3781 backlinks[entry.shndx] = @intCast(i);
3783 }3782 }
37843783
3785 const slice = try self.shdrs.toOwnedSlice(gpa);3784 const slice = try self.shdrs.toOwnedSlice(gpa);
...@@ -3793,10 +3792,10 @@ pub fn sortShdrs(self: *Elf) !void {...@@ -3793,10 +3792,10 @@ pub fn sortShdrs(self: *Elf) !void {
3793 try self.resetShdrIndexes(backlinks);3792 try self.resetShdrIndexes(backlinks);
3794}3793}
37953794
3796fn resetShdrIndexes(self: *Elf, backlinks: []const u16) !void {3795fn resetShdrIndexes(self: *Elf, backlinks: []const u32) !void {
3797 const gpa = self.base.comp.gpa;3796 const gpa = self.base.comp.gpa;
37983797
3799 for (&[_]*?u16{3798 for (&[_]*?u32{
3800 &self.eh_frame_section_index,3799 &self.eh_frame_section_index,
3801 &self.eh_frame_rela_section_index,3800 &self.eh_frame_rela_section_index,
3802 &self.eh_frame_hdr_section_index,3801 &self.eh_frame_hdr_section_index,
...@@ -4192,7 +4191,7 @@ pub fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void {...@@ -4192,7 +4191,7 @@ pub fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void {
4192 // virtual and file offsets. However, the simple one will do for one4191 // virtual and file offsets. However, the simple one will do for one
4193 // as we are more interested in quick turnaround and compatibility4192 // as we are more interested in quick turnaround and compatibility
4194 // with `findFreeSpace` mechanics than anything else.4193 // with `findFreeSpace` mechanics than anything else.
4195 const Cover = std.ArrayList(u16);4194 const Cover = std.ArrayList(u32);
4196 const gpa = self.base.comp.gpa;4195 const gpa = self.base.comp.gpa;
4197 var covers: [max_number_of_object_segments]Cover = undefined;4196 var covers: [max_number_of_object_segments]Cover = undefined;
4198 for (&covers) |*cover| {4197 for (&covers) |*cover| {
...@@ -4348,7 +4347,7 @@ pub fn allocateNonAllocSections(self: *Elf) !void {...@@ -4348,7 +4347,7 @@ pub fn allocateNonAllocSections(self: *Elf) !void {
4348}4347}
43494348
4350fn allocateSpecialPhdrs(self: *Elf) void {4349fn allocateSpecialPhdrs(self: *Elf) void {
4351 for (&[_]struct { ?u16, ?u16 }{4350 for (&[_]struct { ?u16, ?u32 }{
4352 .{ self.phdr_interp_index, self.interp_section_index },4351 .{ self.phdr_interp_index, self.interp_section_index },
4353 .{ self.phdr_dynamic_index, self.dynamic_section_index },4352 .{ self.phdr_dynamic_index, self.dynamic_section_index },
4354 .{ self.phdr_gnu_eh_frame_index, self.eh_frame_hdr_section_index },4353 .{ self.phdr_gnu_eh_frame_index, self.eh_frame_hdr_section_index },
...@@ -4371,7 +4370,7 @@ fn allocateSpecialPhdrs(self: *Elf) void {...@@ -4371,7 +4370,7 @@ fn allocateSpecialPhdrs(self: *Elf) void {
4371 if (self.phdr_tls_index) |index| {4370 if (self.phdr_tls_index) |index| {
4372 const slice = self.shdrs.items;4371 const slice = self.shdrs.items;
4373 const phdr = &self.phdrs.items[index];4372 const phdr = &self.phdrs.items[index];
4374 var shndx: u16 = 0;4373 var shndx: u32 = 0;
4375 while (shndx < slice.len) {4374 while (shndx < slice.len) {
4376 const shdr = slice[shndx];4375 const shdr = slice[shndx];
4377 if (shdr.sh_flags & elf.SHF_TLS == 0) {4376 if (shdr.sh_flags & elf.SHF_TLS == 0) {
...@@ -4402,15 +4401,6 @@ fn allocateSpecialPhdrs(self: *Elf) void {...@@ -4402,15 +4401,6 @@ fn allocateSpecialPhdrs(self: *Elf) void {
4402 }4401 }
4403}4402}
44044403
4405pub fn allocateAtoms(self: *Elf) void {
4406 if (self.zigObjectPtr()) |zig_object| {
4407 zig_object.allocateTlvAtoms(self);
4408 }
4409 for (self.objects.items) |index| {
4410 self.file(index).?.object.allocateAtoms(self);
4411 }
4412}
4413
4414fn writeAtoms(self: *Elf) !void {4404fn writeAtoms(self: *Elf) !void {
4415 const gpa = self.base.comp.gpa;4405 const gpa = self.base.comp.gpa;
44164406
...@@ -4464,7 +4454,7 @@ fn writeAtoms(self: *Elf) !void {...@@ -4464,7 +4454,7 @@ fn writeAtoms(self: *Elf) !void {
4464 const atom_ptr = self.atom(atom_index).?;4454 const atom_ptr = self.atom(atom_index).?;
4465 assert(atom_ptr.flags.alive);4455 assert(atom_ptr.flags.alive);
44664456
4467 const offset = math.cast(usize, atom_ptr.value - shdr.sh_addr - base_offset) orelse4457 const offset = math.cast(usize, atom_ptr.value - base_offset) orelse
4468 return error.Overflow;4458 return error.Overflow;
4469 const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;4459 const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;
44704460
...@@ -5148,8 +5138,8 @@ const CsuObjects = struct {...@@ -5148,8 +5138,8 @@ const CsuObjects = struct {
5148 }5138 }
5149};5139};
51505140
5151pub fn isZigSection(self: Elf, shndx: u16) bool {5141pub fn isZigSection(self: Elf, shndx: u32) bool {
5152 inline for (&[_]?u16{5142 inline for (&[_]?u32{
5153 self.zig_text_section_index,5143 self.zig_text_section_index,
5154 self.zig_data_rel_ro_section_index,5144 self.zig_data_rel_ro_section_index,
5155 self.zig_data_section_index,5145 self.zig_data_section_index,
...@@ -5163,8 +5153,8 @@ pub fn isZigSection(self: Elf, shndx: u16) bool {...@@ -5163,8 +5153,8 @@ pub fn isZigSection(self: Elf, shndx: u16) bool {
5163 return false;5153 return false;
5164}5154}
51655155
5166pub fn isDebugSection(self: Elf, shndx: u16) bool {5156pub fn isDebugSection(self: Elf, shndx: u32) bool {
5167 inline for (&[_]?u16{5157 inline for (&[_]?u32{
5168 self.debug_info_section_index,5158 self.debug_info_section_index,
5169 self.debug_abbrev_section_index,5159 self.debug_abbrev_section_index,
5170 self.debug_str_section_index,5160 self.debug_str_section_index,
...@@ -5202,7 +5192,7 @@ fn addPhdr(self: *Elf, opts: struct {...@@ -5202,7 +5192,7 @@ fn addPhdr(self: *Elf, opts: struct {
5202 return index;5192 return index;
5203}5193}
52045194
5205pub fn addRelaShdr(self: *Elf, name: [:0]const u8, shndx: u16) !u16 {5195pub fn addRelaShdr(self: *Elf, name: [:0]const u8, shndx: u32) !u32 {
5206 const entsize: u64 = switch (self.ptr_width) {5196 const entsize: u64 = switch (self.ptr_width) {
5207 .p32 => @sizeOf(elf.Elf32_Rela),5197 .p32 => @sizeOf(elf.Elf32_Rela),
5208 .p64 => @sizeOf(elf.Elf64_Rela),5198 .p64 => @sizeOf(elf.Elf64_Rela),
...@@ -5233,9 +5223,9 @@ pub const AddSectionOpts = struct {...@@ -5233,9 +5223,9 @@ pub const AddSectionOpts = struct {
5233 offset: u64 = 0,5223 offset: u64 = 0,
5234};5224};
52355225
5236pub fn addSection(self: *Elf, opts: AddSectionOpts) !u16 {5226pub fn addSection(self: *Elf, opts: AddSectionOpts) !u32 {
5237 const gpa = self.base.comp.gpa;5227 const gpa = self.base.comp.gpa;
5238 const index = @as(u16, @intCast(self.shdrs.items.len));5228 const index = @as(u32, @intCast(self.shdrs.items.len));
5239 const shdr = try self.shdrs.addOne(gpa);5229 const shdr = try self.shdrs.addOne(gpa);
5240 shdr.* = .{5230 shdr.* = .{
5241 .sh_name = try self.insertShString(opts.name),5231 .sh_name = try self.insertShString(opts.name),
...@@ -5252,10 +5242,10 @@ pub fn addSection(self: *Elf, opts: AddSectionOpts) !u16 {...@@ -5252,10 +5242,10 @@ pub fn addSection(self: *Elf, opts: AddSectionOpts) !u16 {
5252 return index;5242 return index;
5253}5243}
52545244
5255pub fn sectionByName(self: *Elf, name: [:0]const u8) ?u16 {5245pub fn sectionByName(self: *Elf, name: [:0]const u8) ?u32 {
5256 for (self.shdrs.items, 0..) |*shdr, i| {5246 for (self.shdrs.items, 0..) |*shdr, i| {
5257 const this_name = self.getShString(shdr.sh_name);5247 const this_name = self.getShString(shdr.sh_name);
5258 if (mem.eql(u8, this_name, name)) return @as(u16, @intCast(i));5248 if (mem.eql(u8, this_name, name)) return @intCast(i);
5259 } else return null;5249 } else return null;
5260}5250}
52615251
src/link/Elf/Atom.zig+26-17
...@@ -17,7 +17,7 @@ alignment: Alignment = .@"1",...@@ -17,7 +17,7 @@ alignment: Alignment = .@"1",
17input_section_index: u32 = 0,17input_section_index: u32 = 0,
1818
19/// Index of the output section.19/// Index of the output section.
20output_section_index: u16 = 0,20output_section_index: u32 = 0,
2121
22/// Index of the input section containing this atom's relocs.22/// Index of the input section containing this atom's relocs.
23relocs_section_index: u32 = 0,23relocs_section_index: u32 = 0,
...@@ -54,6 +54,12 @@ pub fn name(self: Atom, elf_file: *Elf) []const u8 {...@@ -54,6 +54,12 @@ pub fn name(self: Atom, elf_file: *Elf) []const u8 {
54 };54 };
55}55}
5656
57pub fn address(self: Atom, elf_file: *Elf) u64 {
58 const shndx = self.outputShndx() orelse return self.value;
59 const shdr = elf_file.shdrs.items[shndx];
60 return shdr.sh_addr + self.value;
61}
62
57pub fn file(self: Atom, elf_file: *Elf) ?File {63pub fn file(self: Atom, elf_file: *Elf) ?File {
58 return elf_file.file(self.file_index);64 return elf_file.file(self.file_index);
59}65}
...@@ -71,7 +77,7 @@ pub fn relocsShndx(self: Atom) ?u32 {...@@ -71,7 +77,7 @@ pub fn relocsShndx(self: Atom) ?u32 {
71 return self.relocs_section_index;77 return self.relocs_section_index;
72}78}
7379
74pub fn outputShndx(self: Atom) ?u16 {80pub fn outputShndx(self: Atom) ?u32 {
75 if (self.output_section_index == 0) return null;81 if (self.output_section_index == 0) return null;
76 return self.output_section_index;82 return self.output_section_index;
77}83}
...@@ -85,14 +91,17 @@ pub fn priority(self: Atom, elf_file: *Elf) u64 {...@@ -85,14 +91,17 @@ pub fn priority(self: Atom, elf_file: *Elf) u64 {
85/// File offset relocation happens transparently, so it is not included in91/// File offset relocation happens transparently, so it is not included in
86/// this calculation.92/// this calculation.
87pub fn capacity(self: Atom, elf_file: *Elf) u64 {93pub fn capacity(self: Atom, elf_file: *Elf) u64 {
88 const next_value = if (elf_file.atom(self.next_index)) |next| next.value else std.math.maxInt(u32);94 const next_addr = if (elf_file.atom(self.next_index)) |next|
89 return next_value - self.value;95 next.address(elf_file)
96 else
97 std.math.maxInt(u32);
98 return next_addr - self.address(elf_file);
90}99}
91100
92pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {101pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {
93 // No need to keep a free list node for the last block.102 // No need to keep a free list node for the last block.
94 const next = elf_file.atom(self.next_index) orelse return false;103 const next = elf_file.atom(self.next_index) orelse return false;
95 const cap = next.value - self.value;104 const cap = next.address(elf_file) - self.address(elf_file);
96 const ideal_cap = Elf.padToIdeal(self.size);105 const ideal_cap = Elf.padToIdeal(self.size);
97 if (cap <= ideal_cap) return false;106 if (cap <= ideal_cap) return false;
98 const surplus = cap - ideal_cap;107 const surplus = cap - ideal_cap;
...@@ -160,15 +169,15 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {...@@ -160,15 +169,15 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
160 atom_placement = last.atom_index;169 atom_placement = last.atom_index;
161 break :blk new_start_vaddr;170 break :blk new_start_vaddr;
162 } else {171 } else {
163 break :blk shdr.sh_addr;172 break :blk 0;
164 }173 }
165 };174 };
166175
167 log.debug("allocated atom({d}) : '{s}' at 0x{x} to 0x{x}", .{176 log.debug("allocated atom({d}) : '{s}' at 0x{x} to 0x{x}", .{
168 self.atom_index,177 self.atom_index,
169 self.name(elf_file),178 self.name(elf_file),
170 self.value,179 self.address(elf_file),
171 self.value + self.size,180 self.address(elf_file) + self.size,
172 });181 });
173182
174 const expand_section = if (atom_placement) |placement_index|183 const expand_section = if (atom_placement) |placement_index|
...@@ -176,7 +185,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {...@@ -176,7 +185,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
176 else185 else
177 true;186 true;
178 if (expand_section) {187 if (expand_section) {
179 const needed_size = (self.value + self.size) - shdr.sh_addr;188 const needed_size = self.value + self.size;
180 try elf_file.growAllocSection(self.outputShndx().?, needed_size);189 try elf_file.growAllocSection(self.outputShndx().?, needed_size);
181 last_atom_index.* = self.atom_index;190 last_atom_index.* = self.atom_index;
182191
...@@ -301,7 +310,7 @@ pub fn relocs(self: Atom, elf_file: *Elf) []align(1) const elf.Elf64_Rela {...@@ -301,7 +310,7 @@ pub fn relocs(self: Atom, elf_file: *Elf) []align(1) const elf.Elf64_Rela {
301}310}
302311
303pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.Elf64_Rela)) !void {312pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.Elf64_Rela)) !void {
304 relocs_log.debug("0x{x}: {s}", .{ self.value, self.name(elf_file) });313 relocs_log.debug("0x{x}: {s}", .{ self.address(elf_file), self.name(elf_file) });
305314
306 const file_ptr = self.file(elf_file).?;315 const file_ptr = self.file(elf_file).?;
307 for (self.relocs(elf_file)) |rel| {316 for (self.relocs(elf_file)) |rel| {
...@@ -322,7 +331,7 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El...@@ -322,7 +331,7 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El
322 var r_sym: u32 = 0;331 var r_sym: u32 = 0;
323 switch (target.type(elf_file)) {332 switch (target.type(elf_file)) {
324 elf.STT_SECTION => {333 elf.STT_SECTION => {
325 r_addend += @intCast(target.value);334 r_addend += @intCast(target.address(.{}, elf_file));
326 r_sym = elf_file.sectionSymbolOutputSymtabIndex(target.outputShndx().?);335 r_sym = elf_file.sectionSymbolOutputSymtabIndex(target.outputShndx().?);
327 },336 },
328 else => {337 else => {
...@@ -778,7 +787,7 @@ fn reportUndefined(...@@ -778,7 +787,7 @@ fn reportUndefined(
778}787}
779788
780pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) !void {789pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) !void {
781 relocs_log.debug("0x{x}: {s}", .{ self.value, self.name(elf_file) });790 relocs_log.debug("0x{x}: {s}", .{ self.address(elf_file), self.name(elf_file) });
782791
783 const file_ptr = self.file(elf_file).?;792 const file_ptr = self.file(elf_file).?;
784 var stream = std.io.fixedBufferStream(code);793 var stream = std.io.fixedBufferStream(code);
...@@ -802,7 +811,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) !void {...@@ -802,7 +811,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) !void {
802 // https://intezer.com/blog/malware-analysis/executable-and-linkable-format-101-part-3-relocations/811 // https://intezer.com/blog/malware-analysis/executable-and-linkable-format-101-part-3-relocations/
803 //812 //
804 // Address of the source atom.813 // Address of the source atom.
805 const P = @as(i64, @intCast(self.value + rel.r_offset));814 const P = @as(i64, @intCast(self.address(elf_file) + rel.r_offset));
806 // Addend from the relocation.815 // Addend from the relocation.
807 const A = rel.r_addend;816 const A = rel.r_addend;
808 // Address of the target symbol - can be address of the symbol within an atom or address of PLT stub.817 // Address of the target symbol - can be address of the symbol within an atom or address of PLT stub.
...@@ -969,7 +978,7 @@ fn resolveDynAbsReloc(...@@ -969,7 +978,7 @@ fn resolveDynAbsReloc(
969) !void {978) !void {
970 const comp = elf_file.base.comp;979 const comp = elf_file.base.comp;
971 const gpa = comp.gpa;980 const gpa = comp.gpa;
972 const P = self.value + rel.r_offset;981 const P = self.address(elf_file) + rel.r_offset;
973 const A = rel.r_addend;982 const A = rel.r_addend;
974 const S = @as(i64, @intCast(target.address(.{}, elf_file)));983 const S = @as(i64, @intCast(target.address(.{}, elf_file)));
975 const is_writeable = self.inputShdr(elf_file).sh_flags & elf.SHF_WRITE != 0;984 const is_writeable = self.inputShdr(elf_file).sh_flags & elf.SHF_WRITE != 0;
...@@ -1058,7 +1067,7 @@ fn applyDynamicReloc(value: i64, elf_file: *Elf, writer: anytype) !void {...@@ -1058,7 +1067,7 @@ fn applyDynamicReloc(value: i64, elf_file: *Elf, writer: anytype) !void {
1058}1067}
10591068
1060pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: anytype) !void {1069pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: anytype) !void {
1061 relocs_log.debug("0x{x}: {s}", .{ self.value, self.name(elf_file) });1070 relocs_log.debug("0x{x}: {s}", .{ self.address(elf_file), self.name(elf_file) });
10621071
1063 const file_ptr = self.file(elf_file).?;1072 const file_ptr = self.file(elf_file).?;
1064 var stream = std.io.fixedBufferStream(code);1073 var stream = std.io.fixedBufferStream(code);
...@@ -1097,7 +1106,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any...@@ -1097,7 +1106,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
1097 // We will use equation format to resolve relocations:1106 // We will use equation format to resolve relocations:
1098 // https://intezer.com/blog/malware-analysis/executable-and-linkable-format-101-part-3-relocations/1107 // https://intezer.com/blog/malware-analysis/executable-and-linkable-format-101-part-3-relocations/
1099 //1108 //
1100 const P = @as(i64, @intCast(self.value + rel.r_offset));1109 const P = @as(i64, @intCast(self.address(elf_file) + rel.r_offset));
1101 // Addend from the relocation.1110 // Addend from the relocation.
1102 const A = rel.r_addend;1111 const A = rel.r_addend;
1103 // Address of the target symbol - can be address of the symbol within an atom or address of PLT stub.1112 // Address of the target symbol - can be address of the symbol within an atom or address of PLT stub.
...@@ -1248,7 +1257,7 @@ fn format2(...@@ -1248,7 +1257,7 @@ fn format2(
1248 const atom = ctx.atom;1257 const atom = ctx.atom;
1249 const elf_file = ctx.elf_file;1258 const elf_file = ctx.elf_file;
1250 try writer.print("atom({d}) : {s} : @{x} : shdr({d}) : align({x}) : size({x})", .{1259 try writer.print("atom({d}) : {s} : @{x} : shdr({d}) : align({x}) : size({x})", .{
1251 atom.atom_index, atom.name(elf_file), atom.value,1260 atom.atom_index, atom.name(elf_file), atom.address(elf_file),
1252 atom.output_section_index, atom.alignment, atom.size,1261 atom.output_section_index, atom.alignment, atom.size,
1253 });1262 });
1254 if (atom.fde_start != atom.fde_end) {1263 if (atom.fde_start != atom.fde_end) {
src/link/Elf/Object.zig+5-16
...@@ -126,7 +126,7 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil...@@ -126,7 +126,7 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil
126 try self.strtab.appendSlice(allocator, shstrtab);126 try self.strtab.appendSlice(allocator, shstrtab);
127127
128 const symtab_index = for (self.shdrs.items, 0..) |shdr, i| switch (shdr.sh_type) {128 const symtab_index = for (self.shdrs.items, 0..) |shdr, i| switch (shdr.sh_type) {
129 elf.SHT_SYMTAB => break @as(u16, @intCast(i)),129 elf.SHT_SYMTAB => break @as(u32, @intCast(i)),
130 else => {},130 else => {},
131 } else null;131 } else null;
132132
...@@ -223,7 +223,7 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:...@@ -223,7 +223,7 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:
223 => {},223 => {},
224224
225 else => {225 else => {
226 const shndx = @as(u16, @intCast(i));226 const shndx = @as(u32, @intCast(i));
227 if (self.skipShdr(shndx, elf_file)) continue;227 if (self.skipShdr(shndx, elf_file)) continue;
228 try self.addAtom(allocator, handle, shdr, shndx, elf_file);228 try self.addAtom(allocator, handle, shdr, shndx, elf_file);
229 },229 },
...@@ -268,7 +268,7 @@ fn addAtom(self: *Object, allocator: Allocator, handle: std.fs.File, shdr: elf.E...@@ -268,7 +268,7 @@ fn addAtom(self: *Object, allocator: Allocator, handle: std.fs.File, shdr: elf.E
268 }268 }
269}269}
270270
271fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{OutOfMemory}!u16 {271fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{OutOfMemory}!u32 {
272 const name = blk: {272 const name = blk: {
273 const name = self.getString(shdr.sh_name);273 const name = self.getString(shdr.sh_name);
274 if (elf_file.base.isRelocatable()) break :blk name;274 if (elf_file.base.isRelocatable()) break :blk name;
...@@ -316,7 +316,7 @@ fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{O...@@ -316,7 +316,7 @@ fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{O
316 return out_shndx;316 return out_shndx;
317}317}
318318
319fn skipShdr(self: *Object, index: u16, elf_file: *Elf) bool {319fn skipShdr(self: *Object, index: u32, elf_file: *Elf) bool {
320 const comp = elf_file.base.comp;320 const comp = elf_file.base.comp;
321 const shdr = self.shdrs.items[index];321 const shdr = self.shdrs.items[index];
322 const name = self.getString(shdr.sh_name);322 const name = self.getString(shdr.sh_name);
...@@ -673,7 +673,7 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {...@@ -673,7 +673,7 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
673673
674 var sh_flags: u32 = elf.SHF_ALLOC | elf.SHF_WRITE;674 var sh_flags: u32 = elf.SHF_ALLOC | elf.SHF_WRITE;
675 if (is_tls) sh_flags |= elf.SHF_TLS;675 if (is_tls) sh_flags |= elf.SHF_TLS;
676 const shndx = @as(u16, @intCast(self.shdrs.items.len));676 const shndx = @as(u32, @intCast(self.shdrs.items.len));
677 const shdr = try self.shdrs.addOne(gpa);677 const shdr = try self.shdrs.addOne(gpa);
678 const sh_size = math.cast(usize, this_sym.st_size) orelse return error.Overflow;678 const sh_size = math.cast(usize, this_sym.st_size) orelse return error.Overflow;
679 shdr.* = .{679 shdr.* = .{
...@@ -718,21 +718,11 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {...@@ -718,21 +718,11 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {
718 if (!gop.found_existing) gop.value_ptr.* = .{};718 if (!gop.found_existing) gop.value_ptr.* = .{};
719 try gop.value_ptr.append(gpa, atom_index);719 try gop.value_ptr.append(gpa, atom_index);
720 }720 }
721}
722
723pub fn allocateAtoms(self: Object, elf_file: *Elf) void {
724 for (self.atoms.items) |atom_index| {
725 const atom = elf_file.atom(atom_index) orelse continue;
726 if (!atom.flags.alive) continue;
727 const shdr = elf_file.shdrs.items[atom.output_section_index];
728 atom.value += shdr.sh_addr;
729 }
730721
731 for (self.locals()) |local_index| {722 for (self.locals()) |local_index| {
732 const local = elf_file.symbol(local_index);723 const local = elf_file.symbol(local_index);
733 const atom = local.atom(elf_file) orelse continue;724 const atom = local.atom(elf_file) orelse continue;
734 if (!atom.flags.alive) continue;725 if (!atom.flags.alive) continue;
735 local.value += atom.value;
736 local.output_section_index = atom.output_section_index;726 local.output_section_index = atom.output_section_index;
737 }727 }
738728
...@@ -741,7 +731,6 @@ pub fn allocateAtoms(self: Object, elf_file: *Elf) void {...@@ -741,7 +731,6 @@ pub fn allocateAtoms(self: Object, elf_file: *Elf) void {
741 const atom = global.atom(elf_file) orelse continue;731 const atom = global.atom(elf_file) orelse continue;
742 if (!atom.flags.alive) continue;732 if (!atom.flags.alive) continue;
743 if (global.file(elf_file).?.index() != self.index) continue;733 if (global.file(elf_file).?.index() != self.index) continue;
744 global.value += atom.value;
745 global.output_section_index = atom.output_section_index;734 global.output_section_index = atom.output_section_index;
746 }735 }
747}736}
src/link/Elf/Symbol.zig+16-9
...@@ -15,7 +15,7 @@ file_index: File.Index = 0,...@@ -15,7 +15,7 @@ file_index: File.Index = 0,
15atom_index: Atom.Index = 0,15atom_index: Atom.Index = 0,
1616
17/// Assigned output section index for this atom.17/// Assigned output section index for this atom.
18output_section_index: u16 = 0,18output_section_index: u32 = 0,
1919
20/// Index of the source symbol this symbol references.20/// Index of the source symbol this symbol references.
21/// Use `elfSym` to pull the source symbol from the relevant file.21/// Use `elfSym` to pull the source symbol from the relevant file.
...@@ -37,7 +37,7 @@ pub fn isAbs(symbol: Symbol, elf_file: *Elf) bool {...@@ -37,7 +37,7 @@ pub fn isAbs(symbol: Symbol, elf_file: *Elf) bool {
37 file_ptr != .linker_defined;37 file_ptr != .linker_defined;
38}38}
3939
40pub fn outputShndx(symbol: Symbol) ?u16 {40pub fn outputShndx(symbol: Symbol) ?u32 {
41 if (symbol.output_section_index == 0) return null;41 if (symbol.output_section_index == 0) return null;
42 return symbol.output_section_index;42 return symbol.output_section_index;
43}43}
...@@ -104,6 +104,9 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true }, elf_file: *Elf...@@ -104,6 +104,9 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true }, elf_file: *Elf
104 // Lazy-bound function it is!104 // Lazy-bound function it is!
105 return symbol.pltAddress(elf_file);105 return symbol.pltAddress(elf_file);
106 }106 }
107 if (symbol.atom(elf_file)) |atom_ptr| {
108 return atom_ptr.address(elf_file) + symbol.value;
109 }
107 return symbol.value;110 return symbol.value;
108}111}
109112
...@@ -234,12 +237,12 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {...@@ -234,12 +237,12 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
234 if (file_ptr == .shared_object) break :blk elf.STB_GLOBAL;237 if (file_ptr == .shared_object) break :blk elf.STB_GLOBAL;
235 break :blk esym.st_bind();238 break :blk esym.st_bind();
236 };239 };
237 const st_shndx = blk: {240 const st_shndx: u16 = blk: {
238 if (symbol.flags.has_copy_rel) break :blk elf_file.copy_rel_section_index.?;241 if (symbol.flags.has_copy_rel) break :blk @intCast(elf_file.copy_rel_section_index.?);
239 if (file_ptr == .shared_object or esym.st_shndx == elf.SHN_UNDEF) break :blk elf.SHN_UNDEF;242 if (file_ptr == .shared_object or esym.st_shndx == elf.SHN_UNDEF) break :blk elf.SHN_UNDEF;
240 if (elf_file.base.isRelocatable() and esym.st_shndx == elf.SHN_COMMON) break :blk elf.SHN_COMMON;243 if (elf_file.base.isRelocatable() and esym.st_shndx == elf.SHN_COMMON) break :blk elf.SHN_COMMON;
241 if (symbol.atom(elf_file) == null and file_ptr != .linker_defined) break :blk elf.SHN_ABS;244 if (symbol.atom(elf_file) == null and file_ptr != .linker_defined) break :blk elf.SHN_ABS;
242 break :blk symbol.outputShndx() orelse elf.SHN_UNDEF;245 break :blk @intCast(symbol.outputShndx() orelse elf.SHN_UNDEF);
243 };246 };
244 const st_value = blk: {247 const st_value = blk: {
245 if (symbol.flags.has_copy_rel) break :blk symbol.address(.{}, elf_file);248 if (symbol.flags.has_copy_rel) break :blk symbol.address(.{}, elf_file);
...@@ -247,11 +250,11 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {...@@ -247,11 +250,11 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
247 if (symbol.flags.is_canonical) break :blk symbol.address(.{}, elf_file);250 if (symbol.flags.is_canonical) break :blk symbol.address(.{}, elf_file);
248 break :blk 0;251 break :blk 0;
249 }252 }
250 if (st_shndx == elf.SHN_ABS or st_shndx == elf.SHN_COMMON) break :blk symbol.value;253 if (st_shndx == elf.SHN_ABS or st_shndx == elf.SHN_COMMON) break :blk symbol.address(.{ .plt = false }, elf_file);
251 const shdr = &elf_file.shdrs.items[st_shndx];254 const shdr = &elf_file.shdrs.items[st_shndx];
252 if (shdr.sh_flags & elf.SHF_TLS != 0 and file_ptr != .linker_defined)255 if (shdr.sh_flags & elf.SHF_TLS != 0 and file_ptr != .linker_defined)
253 break :blk symbol.value - elf_file.tlsAddress();256 break :blk symbol.address(.{ .plt = false }, elf_file) - elf_file.tlsAddress();
254 break :blk symbol.value;257 break :blk symbol.address(.{ .plt = false }, elf_file);
255 };258 };
256 out.st_info = (st_bind << 4) | st_type;259 out.st_info = (st_bind << 4) | st_type;
257 out.st_other = esym.st_other;260 out.st_other = esym.st_other;
...@@ -323,7 +326,11 @@ fn format2(...@@ -323,7 +326,11 @@ fn format2(
323 _ = options;326 _ = options;
324 _ = unused_fmt_string;327 _ = unused_fmt_string;
325 const symbol = ctx.symbol;328 const symbol = ctx.symbol;
326 try writer.print("%{d} : {s} : @{x}", .{ symbol.esym_index, symbol.fmtName(ctx.elf_file), symbol.value });329 try writer.print("%{d} : {s} : @{x}", .{
330 symbol.esym_index,
331 symbol.fmtName(ctx.elf_file),
332 symbol.address(.{}, ctx.elf_file),
333 });
327 if (symbol.file(ctx.elf_file)) |file_ptr| {334 if (symbol.file(ctx.elf_file)) |file_ptr| {
328 if (symbol.isAbs(ctx.elf_file)) {335 if (symbol.isAbs(ctx.elf_file)) {
329 if (symbol.elfSym(ctx.elf_file).st_shndx == elf.SHN_UNDEF) {336 if (symbol.elfSym(ctx.elf_file).st_shndx == elf.SHN_UNDEF) {
src/link/Elf/ZigObject.zig+24-35
...@@ -401,19 +401,6 @@ pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void {...@@ -401,19 +401,6 @@ pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void {
401 }401 }
402}402}
403403
404pub fn allocateTlvAtoms(self: ZigObject, elf_file: *Elf) void {
405 for (self.tls_variables.keys(), self.tls_variables.values()) |atom_index, tlv| {
406 const atom = elf_file.atom(atom_index) orelse continue;
407 if (!atom.flags.alive) continue;
408 const local = elf_file.symbol(tlv.symbol_index);
409 const shdr = elf_file.shdrs.items[atom.output_section_index];
410 atom.value += shdr.sh_addr;
411 local.value = atom.value;
412
413 // TODO exported TLS vars
414 }
415}
416
417pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void {404pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void {
418 const gpa = elf_file.base.comp.gpa;405 const gpa = elf_file.base.comp.gpa;
419 for (self.atoms.items) |atom_index| {406 for (self.atoms.items) |atom_index| {
...@@ -644,7 +631,7 @@ pub fn codeAlloc(self: ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8...@@ -644,7 +631,7 @@ pub fn codeAlloc(self: ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8
644 return code;631 return code;
645 }632 }
646633
647 const file_offset = shdr.sh_offset + atom.value - shdr.sh_addr;634 const file_offset = shdr.sh_offset + atom.value;
648 const size = std.math.cast(usize, atom.size) orelse return error.Overflow;635 const size = std.math.cast(usize, atom.size) orelse return error.Overflow;
649 const code = try gpa.alloc(u8, size);636 const code = try gpa.alloc(u8, size);
650 errdefer gpa.free(code);637 errdefer gpa.free(code);
...@@ -664,7 +651,7 @@ pub fn getDeclVAddr(...@@ -664,7 +651,7 @@ pub fn getDeclVAddr(
664) !u64 {651) !u64 {
665 const this_sym_index = try self.getOrCreateMetadataForDecl(elf_file, decl_index);652 const this_sym_index = try self.getOrCreateMetadataForDecl(elf_file, decl_index);
666 const this_sym = elf_file.symbol(this_sym_index);653 const this_sym = elf_file.symbol(this_sym_index);
667 const vaddr = this_sym.value;654 const vaddr = this_sym.address(.{}, elf_file);
668 const parent_atom = elf_file.symbol(reloc_info.parent_atom_index).atom(elf_file).?;655 const parent_atom = elf_file.symbol(reloc_info.parent_atom_index).atom(elf_file).?;
669 try parent_atom.addReloc(elf_file, .{656 try parent_atom.addReloc(elf_file, .{
670 .r_offset = reloc_info.offset,657 .r_offset = reloc_info.offset,
...@@ -682,7 +669,7 @@ pub fn getAnonDeclVAddr(...@@ -682,7 +669,7 @@ pub fn getAnonDeclVAddr(
682) !u64 {669) !u64 {
683 const sym_index = self.anon_decls.get(decl_val).?.symbol_index;670 const sym_index = self.anon_decls.get(decl_val).?.symbol_index;
684 const sym = elf_file.symbol(sym_index);671 const sym = elf_file.symbol(sym_index);
685 const vaddr = sym.value;672 const vaddr = sym.address(.{}, elf_file);
686 const parent_atom = elf_file.symbol(reloc_info.parent_atom_index).atom(elf_file).?;673 const parent_atom = elf_file.symbol(reloc_info.parent_atom_index).atom(elf_file).?;
687 try parent_atom.addReloc(elf_file, .{674 try parent_atom.addReloc(elf_file, .{
688 .r_offset = reloc_info.offset,675 .r_offset = reloc_info.offset,
...@@ -853,7 +840,7 @@ fn getDeclShdrIndex(...@@ -853,7 +840,7 @@ fn getDeclShdrIndex(
853 elf_file: *Elf,840 elf_file: *Elf,
854 decl: *const Module.Decl,841 decl: *const Module.Decl,
855 code: []const u8,842 code: []const u8,
856) error{OutOfMemory}!u16 {843) error{OutOfMemory}!u32 {
857 _ = self;844 _ = self;
858 const mod = elf_file.base.comp.module.?;845 const mod = elf_file.base.comp.module.?;
859 const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded;846 const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded;
...@@ -907,7 +894,7 @@ fn updateDeclCode(...@@ -907,7 +894,7 @@ fn updateDeclCode(
907 elf_file: *Elf,894 elf_file: *Elf,
908 decl_index: InternPool.DeclIndex,895 decl_index: InternPool.DeclIndex,
909 sym_index: Symbol.Index,896 sym_index: Symbol.Index,
910 shdr_index: u16,897 shdr_index: u32,
911 code: []const u8,898 code: []const u8,
912 stt_bits: u8,899 stt_bits: u8,
913) !void {900) !void {
...@@ -941,13 +928,13 @@ fn updateDeclCode(...@@ -941,13 +928,13 @@ fn updateDeclCode(
941928
942 if (old_size > 0 and elf_file.base.child_pid == null) {929 if (old_size > 0 and elf_file.base.child_pid == null) {
943 const capacity = atom_ptr.capacity(elf_file);930 const capacity = atom_ptr.capacity(elf_file);
944 const need_realloc = code.len > capacity or !required_alignment.check(sym.value);931 const need_realloc = code.len > capacity or !required_alignment.check(atom_ptr.value);
945 if (need_realloc) {932 if (need_realloc) {
946 try atom_ptr.grow(elf_file);933 try atom_ptr.grow(elf_file);
947 log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl_name, old_vaddr, atom_ptr.value });934 log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl_name, old_vaddr, atom_ptr.value });
948 if (old_vaddr != atom_ptr.value) {935 if (old_vaddr != atom_ptr.value) {
949 sym.value = atom_ptr.value;936 sym.value = 0;
950 esym.st_value = atom_ptr.value;937 esym.st_value = 0;
951938
952 if (!elf_file.base.isRelocatable()) {939 if (!elf_file.base.isRelocatable()) {
953 log.debug(" (writing new offset table entry)", .{});940 log.debug(" (writing new offset table entry)", .{});
...@@ -963,9 +950,9 @@ fn updateDeclCode(...@@ -963,9 +950,9 @@ fn updateDeclCode(
963 try atom_ptr.allocate(elf_file);950 try atom_ptr.allocate(elf_file);
964 errdefer self.freeDeclMetadata(elf_file, sym_index);951 errdefer self.freeDeclMetadata(elf_file, sym_index);
965952
966 sym.value = atom_ptr.value;953 sym.value = 0;
967 sym.flags.needs_zig_got = true;954 sym.flags.needs_zig_got = true;
968 esym.st_value = atom_ptr.value;955 esym.st_value = 0;
969956
970 if (!elf_file.base.isRelocatable()) {957 if (!elf_file.base.isRelocatable()) {
971 const gop = try sym.getOrCreateZigGotEntry(sym_index, elf_file);958 const gop = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
...@@ -981,7 +968,7 @@ fn updateDeclCode(...@@ -981,7 +968,7 @@ fn updateDeclCode(
981 .iov_len = code.len,968 .iov_len = code.len,
982 }};969 }};
983 var remote_vec: [1]std.os.iovec_const = .{.{970 var remote_vec: [1]std.os.iovec_const = .{.{
984 .iov_base = @as([*]u8, @ptrFromInt(@as(usize, @intCast(sym.value)))),971 .iov_base = @as([*]u8, @ptrFromInt(@as(usize, @intCast(sym.address(.{}, elf_file))))),
985 .iov_len = code.len,972 .iov_len = code.len,
986 }};973 }};
987 const rc = std.os.linux.process_vm_writev(pid, &code_vec, &remote_vec, 0);974 const rc = std.os.linux.process_vm_writev(pid, &code_vec, &remote_vec, 0);
...@@ -996,7 +983,7 @@ fn updateDeclCode(...@@ -996,7 +983,7 @@ fn updateDeclCode(
996983
997 const shdr = elf_file.shdrs.items[shdr_index];984 const shdr = elf_file.shdrs.items[shdr_index];
998 if (shdr.sh_type != elf.SHT_NOBITS) {985 if (shdr.sh_type != elf.SHT_NOBITS) {
999 const file_offset = shdr.sh_offset + sym.value - shdr.sh_addr;986 const file_offset = shdr.sh_offset + atom_ptr.value;
1000 try elf_file.base.file.?.pwriteAll(code, file_offset);987 try elf_file.base.file.?.pwriteAll(code, file_offset);
1001 }988 }
1002}989}
...@@ -1006,7 +993,7 @@ fn updateTlv(...@@ -1006,7 +993,7 @@ fn updateTlv(
1006 elf_file: *Elf,993 elf_file: *Elf,
1007 decl_index: InternPool.DeclIndex,994 decl_index: InternPool.DeclIndex,
1008 sym_index: Symbol.Index,995 sym_index: Symbol.Index,
1009 shndx: u16,996 shndx: u32,
1010 code: []const u8,997 code: []const u8,
1011) !void {998) !void {
1012 const gpa = elf_file.base.comp.gpa;999 const gpa = elf_file.base.comp.gpa;
...@@ -1022,12 +1009,14 @@ fn updateTlv(...@@ -1022,12 +1009,14 @@ fn updateTlv(
1022 const esym = &self.local_esyms.items(.elf_sym)[sym.esym_index];1009 const esym = &self.local_esyms.items(.elf_sym)[sym.esym_index];
1023 const atom_ptr = sym.atom(elf_file).?;1010 const atom_ptr = sym.atom(elf_file).?;
10241011
1012 sym.value = 0;
1025 sym.output_section_index = shndx;1013 sym.output_section_index = shndx;
1026 atom_ptr.output_section_index = shndx;1014 atom_ptr.output_section_index = shndx;
10271015
1028 sym.name_offset = try self.strtab.insert(gpa, decl_name);1016 sym.name_offset = try self.strtab.insert(gpa, decl_name);
1029 atom_ptr.flags.alive = true;1017 atom_ptr.flags.alive = true;
1030 atom_ptr.name_offset = sym.name_offset;1018 atom_ptr.name_offset = sym.name_offset;
1019 esym.st_value = 0;
1031 esym.st_name = sym.name_offset;1020 esym.st_name = sym.name_offset;
1032 esym.st_info = elf.STT_TLS;1021 esym.st_info = elf.STT_TLS;
1033 esym.st_size = code.len;1022 esym.st_size = code.len;
...@@ -1117,7 +1106,7 @@ pub fn updateFunc(...@@ -1117,7 +1106,7 @@ pub fn updateFunc(
1117 try self.dwarf.?.commitDeclState(1106 try self.dwarf.?.commitDeclState(
1118 mod,1107 mod,
1119 decl_index,1108 decl_index,
1120 sym.value,1109 sym.address(.{}, elf_file),
1121 sym.atom(elf_file).?.size,1110 sym.atom(elf_file).?.size,
1122 ds,1111 ds,
1123 );1112 );
...@@ -1202,7 +1191,7 @@ pub fn updateDecl(...@@ -1202,7 +1191,7 @@ pub fn updateDecl(
1202 try self.dwarf.?.commitDeclState(1191 try self.dwarf.?.commitDeclState(
1203 mod,1192 mod,
1204 decl_index,1193 decl_index,
1205 sym.value,1194 sym.address(.{}, elf_file),
1206 sym.atom(elf_file).?.size,1195 sym.atom(elf_file).?.size,
1207 ds,1196 ds,
1208 );1197 );
...@@ -1281,9 +1270,9 @@ fn updateLazySymbol(...@@ -1281,9 +1270,9 @@ fn updateLazySymbol(
1281 try atom_ptr.allocate(elf_file);1270 try atom_ptr.allocate(elf_file);
1282 errdefer self.freeDeclMetadata(elf_file, symbol_index);1271 errdefer self.freeDeclMetadata(elf_file, symbol_index);
12831272
1284 local_sym.value = atom_ptr.value;1273 local_sym.value = 0;
1285 local_sym.flags.needs_zig_got = true;1274 local_sym.flags.needs_zig_got = true;
1286 local_esym.st_value = atom_ptr.value;1275 local_esym.st_value = 0;
12871276
1288 if (!elf_file.base.isRelocatable()) {1277 if (!elf_file.base.isRelocatable()) {
1289 const gop = try local_sym.getOrCreateZigGotEntry(symbol_index, elf_file);1278 const gop = try local_sym.getOrCreateZigGotEntry(symbol_index, elf_file);
...@@ -1291,7 +1280,7 @@ fn updateLazySymbol(...@@ -1291,7 +1280,7 @@ fn updateLazySymbol(
1291 }1280 }
12921281
1293 const shdr = elf_file.shdrs.items[output_section_index];1282 const shdr = elf_file.shdrs.items[output_section_index];
1294 const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr;1283 const file_offset = shdr.sh_offset + atom_ptr.value;
1295 try elf_file.base.file.?.pwriteAll(code, file_offset);1284 try elf_file.base.file.?.pwriteAll(code, file_offset);
1296}1285}
12971286
...@@ -1345,7 +1334,7 @@ fn lowerConst(...@@ -1345,7 +1334,7 @@ fn lowerConst(
1345 name: []const u8,1334 name: []const u8,
1346 tv: TypedValue,1335 tv: TypedValue,
1347 required_alignment: InternPool.Alignment,1336 required_alignment: InternPool.Alignment,
1348 output_section_index: u16,1337 output_section_index: u32,
1349 src_loc: Module.SrcLoc,1338 src_loc: Module.SrcLoc,
1350) !LowerConstResult {1339) !LowerConstResult {
1351 const gpa = elf_file.base.comp.gpa;1340 const gpa = elf_file.base.comp.gpa;
...@@ -1384,11 +1373,11 @@ fn lowerConst(...@@ -1384,11 +1373,11 @@ fn lowerConst(
1384 // TODO rename and re-audit this method1373 // TODO rename and re-audit this method
1385 errdefer self.freeDeclMetadata(elf_file, sym_index);1374 errdefer self.freeDeclMetadata(elf_file, sym_index);
13861375
1387 local_sym.value = atom_ptr.value;1376 local_sym.value = 0;
1388 local_esym.st_value = atom_ptr.value;1377 local_esym.st_value = 0;
13891378
1390 const shdr = elf_file.shdrs.items[output_section_index];1379 const shdr = elf_file.shdrs.items[output_section_index];
1391 const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr;1380 const file_offset = shdr.sh_offset + atom_ptr.value;
1392 try elf_file.base.file.?.pwriteAll(code, file_offset);1381 try elf_file.base.file.?.pwriteAll(code, file_offset);
13931382
1394 return .{ .ok = sym_index };1383 return .{ .ok = sym_index };
src/link/Elf/eh_frame.zig+1-1
...@@ -409,7 +409,7 @@ fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Re...@@ -409,7 +409,7 @@ fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Re
409 var r_sym: u32 = 0;409 var r_sym: u32 = 0;
410 switch (sym.type(elf_file)) {410 switch (sym.type(elf_file)) {
411 elf.STT_SECTION => {411 elf.STT_SECTION => {
412 r_addend += @intCast(sym.value);412 r_addend += @intCast(sym.address(.{}, elf_file));
413 r_sym = elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx().?);413 r_sym = elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx().?);
414 },414 },
415 else => {415 else => {
src/link/Elf/relocatable.zig-1
...@@ -195,7 +195,6 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const...@@ -195,7 +195,6 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const
195195
196 try allocateAllocSections(elf_file);196 try allocateAllocSections(elf_file);
197 try elf_file.allocateNonAllocSections();197 try elf_file.allocateNonAllocSections();
198 elf_file.allocateAtoms();
199198
200 if (build_options.enable_logging) {199 if (build_options.enable_logging) {
201 state_log.debug("{}", .{elf_file.dumpState()});200 state_log.debug("{}", .{elf_file.dumpState()});
src/link/Elf/synthetic_sections.zig+7-7
...@@ -297,7 +297,7 @@ pub const ZigGotSection = struct {...@@ -297,7 +297,7 @@ pub const ZigGotSection = struct {
297 const off = zig_got.entryOffset(index, elf_file);297 const off = zig_got.entryOffset(index, elf_file);
298 const vaddr = zig_got.entryAddress(index, elf_file);298 const vaddr = zig_got.entryAddress(index, elf_file);
299 const entry = zig_got.entries.items[index];299 const entry = zig_got.entries.items[index];
300 const value = elf_file.symbol(entry).value;300 const value = elf_file.symbol(entry).address(.{}, elf_file);
301 switch (entry_size) {301 switch (entry_size) {
302 2 => {302 2 => {
303 var buf: [2]u8 = undefined;303 var buf: [2]u8 = undefined;
...@@ -388,7 +388,7 @@ pub const ZigGotSection = struct {...@@ -388,7 +388,7 @@ pub const ZigGotSection = struct {
388 .st_name = st_name,388 .st_name = st_name,
389 .st_info = elf.STT_OBJECT,389 .st_info = elf.STT_OBJECT,
390 .st_other = 0,390 .st_other = 0,
391 .st_shndx = elf_file.zig_got_section_index.?,391 .st_shndx = @intCast(elf_file.zig_got_section_index.?),
392 .st_value = st_value,392 .st_value = st_value,
393 .st_size = st_size,393 .st_size = st_size,
394 };394 };
...@@ -813,7 +813,7 @@ pub const GotSection = struct {...@@ -813,7 +813,7 @@ pub const GotSection = struct {
813 .st_name = st_name,813 .st_name = st_name,
814 .st_info = elf.STT_OBJECT,814 .st_info = elf.STT_OBJECT,
815 .st_other = 0,815 .st_other = 0,
816 .st_shndx = elf_file.got_section_index.?,816 .st_shndx = @intCast(elf_file.got_section_index.?),
817 .st_value = st_value,817 .st_value = st_value,
818 .st_size = st_size,818 .st_size = st_size,
819 };819 };
...@@ -953,7 +953,7 @@ pub const PltSection = struct {...@@ -953,7 +953,7 @@ pub const PltSection = struct {
953 .st_name = st_name,953 .st_name = st_name,
954 .st_info = elf.STT_FUNC,954 .st_info = elf.STT_FUNC,
955 .st_other = 0,955 .st_other = 0,
956 .st_shndx = elf_file.plt_section_index.?,956 .st_shndx = @intCast(elf_file.plt_section_index.?),
957 .st_value = sym.pltAddress(elf_file),957 .st_value = sym.pltAddress(elf_file),
958 .st_size = 16,958 .st_size = 16,
959 };959 };
...@@ -1004,7 +1004,7 @@ pub const GotPltSection = struct {...@@ -1004,7 +1004,7 @@ pub const GotPltSection = struct {
1004 {1004 {
1005 // [0]: _DYNAMIC1005 // [0]: _DYNAMIC
1006 const symbol = elf_file.symbol(elf_file.dynamic_index.?);1006 const symbol = elf_file.symbol(elf_file.dynamic_index.?);
1007 try writer.writeInt(u64, symbol.value, .little);1007 try writer.writeInt(u64, symbol.address(.{}, elf_file), .little);
1008 }1008 }
1009 // [1]: 0x01009 // [1]: 0x0
1010 // [2]: 0x01010 // [2]: 0x0
...@@ -1082,7 +1082,7 @@ pub const PltGotSection = struct {...@@ -1082,7 +1082,7 @@ pub const PltGotSection = struct {
1082 .st_name = st_name,1082 .st_name = st_name,
1083 .st_info = elf.STT_FUNC,1083 .st_info = elf.STT_FUNC,
1084 .st_other = 0,1084 .st_other = 0,
1085 .st_shndx = elf_file.plt_got_section_index.?,1085 .st_shndx = @intCast(elf_file.plt_got_section_index.?),
1086 .st_value = sym.pltGotAddress(elf_file),1086 .st_value = sym.pltGotAddress(elf_file),
1087 .st_size = 16,1087 .st_size = 16,
1088 };1088 };
...@@ -1132,7 +1132,7 @@ pub const CopyRelSection = struct {...@@ -1132,7 +1132,7 @@ pub const CopyRelSection = struct {
1132 }1132 }
1133 }1133 }
11341134
1135 pub fn updateSectionSize(copy_rel: CopyRelSection, shndx: u16, elf_file: *Elf) !void {1135 pub fn updateSectionSize(copy_rel: CopyRelSection, shndx: u32, elf_file: *Elf) !void {
1136 const shdr = &elf_file.shdrs.items[shndx];1136 const shdr = &elf_file.shdrs.items[shndx];
1137 for (copy_rel.symbols.items) |sym_index| {1137 for (copy_rel.symbols.items) |sym_index| {
1138 const symbol = elf_file.symbol(sym_index);1138 const symbol = elf_file.symbol(sym_index);