authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-24 16:03:29+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-30 10:00:50+02:00
log669f28594393e90e4d1aacd0d28f67ebe015b922
tree08f6d4e19a0b8dfc431171214fffdb6e6d956883
parentf1fedb3a51d4d9a37e4568ce1a80149bb5a610f7

elf: move ownership of atoms into objects


15 files changed, 464 insertions(+), 353 deletions(-)

src/link/Elf.zig+39-99
...@@ -54,7 +54,7 @@ phdr_to_shdr_table: std.AutoHashMapUnmanaged(u32, u32) = .{},...@@ -54,7 +54,7 @@ phdr_to_shdr_table: std.AutoHashMapUnmanaged(u32, u32) = .{},
54shdr_table_offset: ?u64 = null,54shdr_table_offset: ?u64 = null,
55/// Table of lists of atoms per output section.55/// Table of lists of atoms per output section.
56/// This table is not used to track incrementally generated atoms.56/// This table is not used to track incrementally generated atoms.
57output_sections: std.AutoArrayHashMapUnmanaged(u32, std.ArrayListUnmanaged(Atom.Index)) = .{},57output_sections: std.AutoArrayHashMapUnmanaged(u32, std.ArrayListUnmanaged(Ref)) = .{},
58output_rela_sections: std.AutoArrayHashMapUnmanaged(u32, RelaSection) = .{},58output_rela_sections: std.AutoArrayHashMapUnmanaged(u32, RelaSection) = .{},
5959
60/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.60/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
...@@ -203,10 +203,6 @@ resolver: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{},...@@ -203,10 +203,6 @@ resolver: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{},
203has_text_reloc: bool = false,203has_text_reloc: bool = false,
204num_ifunc_dynrelocs: usize = 0,204num_ifunc_dynrelocs: usize = 0,
205205
206/// List of atoms that are owned directly by the linker.
207atoms: std.ArrayListUnmanaged(Atom) = .{},
208atoms_extra: std.ArrayListUnmanaged(u32) = .{},
209
210/// List of range extension thunks.206/// List of range extension thunks.
211thunks: std.ArrayListUnmanaged(Thunk) = .{},207thunks: std.ArrayListUnmanaged(Thunk) = .{},
212208
...@@ -375,9 +371,6 @@ pub fn createEmpty(...@@ -375,9 +371,6 @@ pub fn createEmpty(
375 try self.symbols.append(gpa, .{});371 try self.symbols.append(gpa, .{});
376 // Index 0 is always a null symbol.372 // Index 0 is always a null symbol.
377 try self.symbols_extra.append(gpa, 0);373 try self.symbols_extra.append(gpa, 0);
378 // Allocate atom index 0 to null atom
379 try self.atoms.append(gpa, .{});
380 try self.atoms_extra.append(gpa, 0);
381 // Append null file at index 0374 // Append null file at index 0
382 try self.files.append(gpa, .null);375 try self.files.append(gpa, .null);
383 // Append null byte to string tables376 // Append null byte to string tables
...@@ -499,8 +492,6 @@ pub fn deinit(self: *Elf) void {...@@ -499,8 +492,6 @@ pub fn deinit(self: *Elf) void {
499 self.resolver.deinit(gpa);492 self.resolver.deinit(gpa);
500 self.start_stop_indexes.deinit(gpa);493 self.start_stop_indexes.deinit(gpa);
501494
502 self.atoms.deinit(gpa);
503 self.atoms_extra.deinit(gpa);
504 for (self.thunks.items) |*th| {495 for (self.thunks.items) |*th| {
505 th.deinit(gpa);496 th.deinit(gpa);
506 }497 }
...@@ -1305,6 +1296,8 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod...@@ -1305,6 +1296,8 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
1305 const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));1296 const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));
1306 self.files.set(index, .{ .linker_defined = .{ .index = index } });1297 self.files.set(index, .{ .linker_defined = .{ .index = index } });
1307 self.linker_defined_index = index;1298 self.linker_defined_index = index;
1299 const object = self.file(index).?.linker_defined;
1300 try object.init(gpa);
1308 }1301 }
13091302
1310 // Now, we are ready to resolve the symbols across all input files.1303 // Now, we are ready to resolve the symbols across all input files.
...@@ -1379,15 +1372,15 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod...@@ -1379,15 +1372,15 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
13791372
1380 // Beyond this point, everything has been allocated a virtual address and we can resolve1373 // Beyond this point, everything has been allocated a virtual address and we can resolve
1381 // the relocations, and commit objects to file.1374 // the relocations, and commit objects to file.
1382 if (self.zigObjectPtr()) |zig_object| {1375 if (self.zigObjectPtr()) |zo| {
1383 var has_reloc_errors = false;1376 var has_reloc_errors = false;
1384 for (zig_object.atoms.items) |atom_index| {1377 for (zo.atoms_indexes.items) |atom_index| {
1385 const atom_ptr = self.atom(atom_index) orelse continue;1378 const atom_ptr = zo.atom(atom_index) orelse continue;
1386 if (!atom_ptr.flags.alive) continue;1379 if (!atom_ptr.flags.alive) continue;
1387 const out_shndx = atom_ptr.outputShndx() orelse continue;1380 const out_shndx = atom_ptr.outputShndx() orelse continue;
1388 const shdr = &self.shdrs.items[out_shndx];1381 const shdr = &self.shdrs.items[out_shndx];
1389 if (shdr.sh_type == elf.SHT_NOBITS) continue;1382 if (shdr.sh_type == elf.SHT_NOBITS) continue;
1390 const code = try zig_object.codeAlloc(self, atom_index);1383 const code = try zo.codeAlloc(self, atom_index);
1391 defer gpa.free(code);1384 defer gpa.free(code);
1392 const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value));1385 const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value));
1393 atom_ptr.resolveRelocsAlloc(self, code) catch |err| switch (err) {1386 atom_ptr.resolveRelocsAlloc(self, code) catch |err| switch (err) {
...@@ -2012,8 +2005,8 @@ pub fn resolveSymbols(self: *Elf) void {...@@ -2012,8 +2005,8 @@ pub fn resolveSymbols(self: *Elf) void {
2012 const cg_owner = self.comdatGroupOwner(cg.owner);2005 const cg_owner = self.comdatGroupOwner(cg.owner);
2013 if (cg_owner.file != index) {2006 if (cg_owner.file != index) {
2014 for (cg.comdatGroupMembers(self)) |shndx| {2007 for (cg.comdatGroupMembers(self)) |shndx| {
2015 const atom_index = object.atoms.items[shndx];2008 const atom_index = object.atoms_indexes.items[shndx];
2016 if (self.atom(atom_index)) |atom_ptr| {2009 if (object.atom(atom_index)) |atom_ptr| {
2017 atom_ptr.flags.alive = false;2010 atom_ptr.flags.alive = false;
2018 atom_ptr.markFdesDead(self);2011 atom_ptr.markFdesDead(self);
2019 }2012 }
...@@ -2117,7 +2110,7 @@ fn claimUnresolved(self: *Elf) void {...@@ -2117,7 +2110,7 @@ fn claimUnresolved(self: *Elf) void {
2117fn scanRelocs(self: *Elf) !void {2110fn scanRelocs(self: *Elf) !void {
2118 const gpa = self.base.comp.gpa;2111 const gpa = self.base.comp.gpa;
21192112
2120 var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Atom.Index)).init(gpa);2113 var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Ref)).init(gpa);
2121 defer {2114 defer {
2122 var it = undefs.iterator();2115 var it = undefs.iterator();
2123 while (it.next()) |entry| {2116 while (it.next()) |entry| {
...@@ -3721,11 +3714,11 @@ fn sortInitFini(self: *Elf) !void {...@@ -3721,11 +3714,11 @@ fn sortInitFini(self: *Elf) !void {
37213714
3722 const Entry = struct {3715 const Entry = struct {
3723 priority: i32,3716 priority: i32,
3724 atom_index: Atom.Index,3717 atom_ref: Ref,
37253718
3726 pub fn lessThan(ctx: *Elf, lhs: @This(), rhs: @This()) bool {3719 pub fn lessThan(ctx: *Elf, lhs: @This(), rhs: @This()) bool {
3727 if (lhs.priority == rhs.priority) {3720 if (lhs.priority == rhs.priority) {
3728 return ctx.atom(lhs.atom_index).?.priority(ctx) < ctx.atom(rhs.atom_index).?.priority(ctx);3721 return ctx.atom(lhs.atom_ref).?.priority(ctx) < ctx.atom(rhs.atom_ref).?.priority(ctx);
3729 }3722 }
3730 return lhs.priority < rhs.priority;3723 return lhs.priority < rhs.priority;
3731 }3724 }
...@@ -3756,8 +3749,8 @@ fn sortInitFini(self: *Elf) !void {...@@ -3756,8 +3749,8 @@ fn sortInitFini(self: *Elf) !void {
3756 try entries.ensureTotalCapacityPrecise(atom_list.items.len);3749 try entries.ensureTotalCapacityPrecise(atom_list.items.len);
3757 defer entries.deinit();3750 defer entries.deinit();
37583751
3759 for (atom_list.items) |atom_index| {3752 for (atom_list.items) |ref| {
3760 const atom_ptr = self.atom(atom_index).?;3753 const atom_ptr = self.atom(ref).?;
3761 const object = atom_ptr.file(self).?.object;3754 const object = atom_ptr.file(self).?.object;
3762 const priority = blk: {3755 const priority = blk: {
3763 if (is_ctor_dtor) {3756 if (is_ctor_dtor) {
...@@ -3770,14 +3763,14 @@ fn sortInitFini(self: *Elf) !void {...@@ -3770,14 +3763,14 @@ fn sortInitFini(self: *Elf) !void {
3770 const priority = std.fmt.parseUnsigned(u16, it.first(), 10) catch default;3763 const priority = std.fmt.parseUnsigned(u16, it.first(), 10) catch default;
3771 break :blk priority;3764 break :blk priority;
3772 };3765 };
3773 entries.appendAssumeCapacity(.{ .priority = priority, .atom_index = atom_index });3766 entries.appendAssumeCapacity(.{ .priority = priority, .atom_ref = ref });
3774 }3767 }
37753768
3776 mem.sort(Entry, entries.items, self, Entry.lessThan);3769 mem.sort(Entry, entries.items, self, Entry.lessThan);
37773770
3778 atom_list.clearRetainingCapacity();3771 atom_list.clearRetainingCapacity();
3779 for (entries.items) |entry| {3772 for (entries.items) |entry| {
3780 atom_list.appendAssumeCapacity(entry.atom_index);3773 atom_list.appendAssumeCapacity(entry.atom_ref);
3781 }3774 }
3782 }3775 }
3783}3776}
...@@ -4143,23 +4136,23 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) !void {...@@ -4143,23 +4136,23 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) !void {
4143 }4136 }
4144 }4137 }
41454138
4146 if (self.zigObjectPtr()) |zig_object| {4139 if (self.zigObjectPtr()) |zo| {
4147 for (zig_object.atoms.items) |atom_index| {4140 for (zo.atoms_indexes.items) |atom_index| {
4148 const atom_ptr = self.atom(atom_index) orelse continue;4141 const atom_ptr = zo.atom(atom_index) orelse continue;
4149 atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index];4142 atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index];
4150 }4143 }
41514144
4152 for (zig_object.locals()) |local_index| {4145 for (zo.locals()) |local_index| {
4153 const local = self.symbol(local_index);4146 const local = self.symbol(local_index);
4154 local.output_section_index = backlinks[local.output_section_index];4147 local.output_section_index = backlinks[local.output_section_index];
4155 }4148 }
41564149
4157 for (zig_object.globals()) |global_index| {4150 for (zo.globals()) |global_index| {
4158 const global = self.symbol(global_index);4151 const global = self.symbol(global_index);
4159 const atom_ptr = global.atom(self) orelse continue;4152 const atom_ptr = global.atom(self) orelse continue;
4160 if (!atom_ptr.flags.alive) continue;4153 if (!atom_ptr.flags.alive) continue;
4161 // TODO claim unresolved for objects4154 // TODO claim unresolved for objects
4162 if (global.file(self).?.index() != zig_object.index) continue;4155 if (global.file(self).?.index() != zo.index) continue;
4163 const out_shndx = global.outputShndx() orelse continue;4156 const out_shndx = global.outputShndx() orelse continue;
4164 global.output_section_index = backlinks[out_shndx];4157 global.output_section_index = backlinks[out_shndx];
4165 }4158 }
...@@ -4182,8 +4175,8 @@ fn updateSectionSizes(self: *Elf) !void {...@@ -4182,8 +4175,8 @@ fn updateSectionSizes(self: *Elf) !void {
4182 const shdr = &self.shdrs.items[shndx];4175 const shdr = &self.shdrs.items[shndx];
4183 if (atom_list.items.len == 0) continue;4176 if (atom_list.items.len == 0) continue;
4184 if (self.requiresThunks() and shdr.sh_flags & elf.SHF_EXECINSTR != 0) continue;4177 if (self.requiresThunks() and shdr.sh_flags & elf.SHF_EXECINSTR != 0) continue;
4185 for (atom_list.items) |atom_index| {4178 for (atom_list.items) |ref| {
4186 const atom_ptr = self.atom(atom_index) orelse continue;4179 const atom_ptr = self.atom(ref) orelse continue;
4187 if (!atom_ptr.flags.alive) continue;4180 if (!atom_ptr.flags.alive) continue;
4188 const offset = atom_ptr.alignment.forward(shdr.sh_size);4181 const offset = atom_ptr.alignment.forward(shdr.sh_size);
4189 const padding = offset - shdr.sh_size;4182 const padding = offset - shdr.sh_size;
...@@ -4618,7 +4611,7 @@ fn allocateSpecialPhdrs(self: *Elf) void {...@@ -4618,7 +4611,7 @@ fn allocateSpecialPhdrs(self: *Elf) void {
4618fn writeAtoms(self: *Elf) !void {4611fn writeAtoms(self: *Elf) !void {
4619 const gpa = self.base.comp.gpa;4612 const gpa = self.base.comp.gpa;
46204613
4621 var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Atom.Index)).init(gpa);4614 var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Ref)).init(gpa);
4622 defer {4615 defer {
4623 var it = undefs.iterator();4616 var it = undefs.iterator();
4624 while (it.next()) |entry| {4617 while (it.next()) |entry| {
...@@ -4666,21 +4659,21 @@ fn writeAtoms(self: *Elf) !void {...@@ -4666,21 +4659,21 @@ fn writeAtoms(self: *Elf) !void {
4666 0;4659 0;
4667 @memset(buffer, padding_byte);4660 @memset(buffer, padding_byte);
46684661
4669 for (atom_list.items) |atom_index| {4662 for (atom_list.items) |ref| {
4670 const atom_ptr = self.atom(atom_index).?;4663 const atom_ptr = self.atom(ref).?;
4671 assert(atom_ptr.flags.alive);4664 assert(atom_ptr.flags.alive);
46724665
4673 const offset = math.cast(usize, atom_ptr.value - @as(i64, @intCast(base_offset))) orelse4666 const offset = math.cast(usize, atom_ptr.value - @as(i64, @intCast(base_offset))) orelse
4674 return error.Overflow;4667 return error.Overflow;
4675 const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;4668 const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;
46764669
4677 log.debug("writing atom({d}) at 0x{x}", .{ atom_index, sh_offset + offset });4670 log.debug("writing atom({}) at 0x{x}", .{ ref, sh_offset + offset });
46784671
4679 // TODO decompress directly into provided buffer4672 // TODO decompress directly into provided buffer
4680 const out_code = buffer[offset..][0..size];4673 const out_code = buffer[offset..][0..size];
4681 const in_code = switch (atom_ptr.file(self).?) {4674 const in_code = switch (atom_ptr.file(self).?) {
4682 .object => |x| try x.codeDecompressAlloc(self, atom_index),4675 .object => |x| try x.codeDecompressAlloc(self, ref.index),
4683 .zig_object => |x| try x.codeAlloc(self, atom_index),4676 .zig_object => |x| try x.codeAlloc(self, ref.index),
4684 else => unreachable,4677 else => unreachable,
4685 };4678 };
4686 defer gpa.free(in_code);4679 defer gpa.free(in_code);
...@@ -5598,64 +5591,6 @@ fn getStartStopBasename(self: *Elf, shdr: elf.Elf64_Shdr) ?[]const u8 {...@@ -5598,64 +5591,6 @@ fn getStartStopBasename(self: *Elf, shdr: elf.Elf64_Shdr) ?[]const u8 {
5598 return null;5591 return null;
5599}5592}
56005593
5601pub fn atom(self: *Elf, atom_index: Atom.Index) ?*Atom {
5602 if (atom_index == 0) return null;
5603 assert(atom_index < self.atoms.items.len);
5604 return &self.atoms.items[atom_index];
5605}
5606
5607pub fn addAtom(self: *Elf) !Atom.Index {
5608 const gpa = self.base.comp.gpa;
5609 const index = @as(Atom.Index, @intCast(self.atoms.items.len));
5610 const atom_ptr = try self.atoms.addOne(gpa);
5611 atom_ptr.* = .{ .atom_index = index };
5612 return index;
5613}
5614
5615pub fn addAtomExtra(self: *Elf, extra: Atom.Extra) !u32 {
5616 const fields = @typeInfo(Atom.Extra).Struct.fields;
5617 try self.atoms_extra.ensureUnusedCapacity(self.base.comp.gpa, fields.len);
5618 return self.addAtomExtraAssumeCapacity(extra);
5619}
5620
5621pub fn addAtomExtraAssumeCapacity(self: *Elf, extra: Atom.Extra) u32 {
5622 const index = @as(u32, @intCast(self.atoms_extra.items.len));
5623 const fields = @typeInfo(Atom.Extra).Struct.fields;
5624 inline for (fields) |field| {
5625 self.atoms_extra.appendAssumeCapacity(switch (field.type) {
5626 u32 => @field(extra, field.name),
5627 else => @compileError("bad field type"),
5628 });
5629 }
5630 return index;
5631}
5632
5633pub fn atomExtra(self: *Elf, index: u32) ?Atom.Extra {
5634 if (index == 0) return null;
5635 const fields = @typeInfo(Atom.Extra).Struct.fields;
5636 var i: usize = index;
5637 var result: Atom.Extra = undefined;
5638 inline for (fields) |field| {
5639 @field(result, field.name) = switch (field.type) {
5640 u32 => self.atoms_extra.items[i],
5641 else => @compileError("bad field type"),
5642 };
5643 i += 1;
5644 }
5645 return result;
5646}
5647
5648pub fn setAtomExtra(self: *Elf, index: u32, extra: Atom.Extra) void {
5649 assert(index > 0);
5650 const fields = @typeInfo(Atom.Extra).Struct.fields;
5651 inline for (fields, 0..) |field, i| {
5652 self.atoms_extra.items[index + i] = switch (field.type) {
5653 u32 => @field(extra, field.name),
5654 else => @compileError("bad field type"),
5655 };
5656 }
5657}
5658
5659pub fn addThunk(self: *Elf) !Thunk.Index {5594pub fn addThunk(self: *Elf) !Thunk.Index {
5660 const index = @as(Thunk.Index, @intCast(self.thunks.items.len));5595 const index = @as(Thunk.Index, @intCast(self.thunks.items.len));
5661 const th = try self.thunks.addOne(self.base.comp.gpa);5596 const th = try self.thunks.addOne(self.base.comp.gpa);
...@@ -5692,6 +5627,11 @@ pub fn fileHandle(self: Elf, index: File.HandleIndex) File.Handle {...@@ -5692,6 +5627,11 @@ pub fn fileHandle(self: Elf, index: File.HandleIndex) File.Handle {
5692 return self.file_handles.items[index];5627 return self.file_handles.items[index];
5693}5628}
56945629
5630pub fn atom(self: *Elf, ref: Ref) ?*Atom {
5631 const file_ptr = self.file(ref.file) orelse return null;
5632 return file_ptr.atom(ref.index);
5633}
5634
5695/// Returns pointer-to-symbol described at sym_index.5635/// Returns pointer-to-symbol described at sym_index.
5696pub fn symbol(self: *Elf, sym_index: Symbol.Index) *Symbol {5636pub fn symbol(self: *Elf, sym_index: Symbol.Index) *Symbol {
5697 return &self.symbols.items[sym_index];5637 return &self.symbols.items[sym_index];
...@@ -5938,9 +5878,9 @@ fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void {...@@ -5938,9 +5878,9 @@ fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void {
5938 var err = try self.base.addErrorWithNotesAssumeCapacity(nnotes);5878 var err = try self.base.addErrorWithNotesAssumeCapacity(nnotes);
5939 try err.addMsg("undefined symbol: {s}", .{self.symbol(undef_index).name(self)});5879 try err.addMsg("undefined symbol: {s}", .{self.symbol(undef_index).name(self)});
59405880
5941 for (atoms[0..natoms]) |atom_index| {5881 for (atoms[0..natoms]) |ref| {
5942 const atom_ptr = self.atom(atom_index).?;5882 const atom_ptr = self.atom(ref).?;
5943 const file_ptr = self.file(atom_ptr.file_index).?;5883 const file_ptr = self.file(ref.file).?;
5944 try err.addNote("referenced by {s}:{s}", .{ file_ptr.fmtPath(), atom_ptr.name(self) });5884 try err.addNote("referenced by {s}:{s}", .{ file_ptr.fmtPath(), atom_ptr.name(self) });
5945 }5885 }
59465886
...@@ -6401,7 +6341,7 @@ const LastAtomAndFreeListTable = std.AutoArrayHashMapUnmanaged(u32, LastAtomAndF...@@ -6401,7 +6341,7 @@ const LastAtomAndFreeListTable = std.AutoArrayHashMapUnmanaged(u32, LastAtomAndF
64016341
6402const RelaSection = struct {6342const RelaSection = struct {
6403 shndx: u32,6343 shndx: u32,
6404 atom_list: std.ArrayListUnmanaged(Atom.Index) = .{},6344 atom_list: std.ArrayListUnmanaged(Ref) = .{},
6405};6345};
6406const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection);6346const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection);
64076347
src/link/Elf/Atom.zig+29-27
...@@ -68,7 +68,7 @@ pub fn file(self: Atom, elf_file: *Elf) ?File {...@@ -68,7 +68,7 @@ pub fn file(self: Atom, elf_file: *Elf) ?File {
6868
69pub fn thunk(self: Atom, elf_file: *Elf) *Thunk {69pub fn thunk(self: Atom, elf_file: *Elf) *Thunk {
70 assert(self.flags.thunk);70 assert(self.flags.thunk);
71 const extras = self.extra(elf_file).?;71 const extras = self.extra(elf_file);
72 return elf_file.thunk(extras.thunk);72 return elf_file.thunk(extras.thunk);
73}73}
7474
...@@ -99,7 +99,8 @@ pub fn priority(self: Atom, elf_file: *Elf) u64 {...@@ -99,7 +99,8 @@ pub fn priority(self: Atom, elf_file: *Elf) u64 {
99/// File offset relocation happens transparently, so it is not included in99/// File offset relocation happens transparently, so it is not included in
100/// this calculation.100/// this calculation.
101pub fn capacity(self: Atom, elf_file: *Elf) u64 {101pub fn capacity(self: Atom, elf_file: *Elf) u64 {
102 const next_addr = if (elf_file.atom(self.next_index)) |next|102 const zo = elf_file.zigObjectPtr().?;
103 const next_addr = if (zo.atom(self.next_index)) |next|
103 next.address(elf_file)104 next.address(elf_file)
104 else105 else
105 std.math.maxInt(u32);106 std.math.maxInt(u32);
...@@ -107,8 +108,9 @@ pub fn capacity(self: Atom, elf_file: *Elf) u64 {...@@ -107,8 +108,9 @@ pub fn capacity(self: Atom, elf_file: *Elf) u64 {
107}108}
108109
109pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {110pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {
111 const zo = elf_file.zigObjectPtr().?;
110 // No need to keep a free list node for the last block.112 // No need to keep a free list node for the last block.
111 const next = elf_file.atom(self.next_index) orelse return false;113 const next = zo.atom(self.next_index) orelse return false;
112 const cap: u64 = @intCast(next.address(elf_file) - self.address(elf_file));114 const cap: u64 = @intCast(next.address(elf_file) - self.address(elf_file));
113 const ideal_cap = Elf.padToIdeal(self.size);115 const ideal_cap = Elf.padToIdeal(self.size);
114 if (cap <= ideal_cap) return false;116 if (cap <= ideal_cap) return false;
...@@ -117,6 +119,7 @@ pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {...@@ -117,6 +119,7 @@ pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {
117}119}
118120
119pub fn allocate(self: *Atom, elf_file: *Elf) !void {121pub fn allocate(self: *Atom, elf_file: *Elf) !void {
122 const zo = elf_file.zigObjectPtr().?;
120 const shdr = &elf_file.shdrs.items[self.outputShndx().?];123 const shdr = &elf_file.shdrs.items[self.outputShndx().?];
121 const meta = elf_file.last_atom_and_free_list_table.getPtr(self.outputShndx().?).?;124 const meta = elf_file.last_atom_and_free_list_table.getPtr(self.outputShndx().?).?;
122 const free_list = &meta.free_list;125 const free_list = &meta.free_list;
...@@ -137,7 +140,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {...@@ -137,7 +140,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
137 var i: usize = if (elf_file.base.child_pid == null) 0 else free_list.items.len;140 var i: usize = if (elf_file.base.child_pid == null) 0 else free_list.items.len;
138 while (i < free_list.items.len) {141 while (i < free_list.items.len) {
139 const big_atom_index = free_list.items[i];142 const big_atom_index = free_list.items[i];
140 const big_atom = elf_file.atom(big_atom_index).?;143 const big_atom = zo.atom(big_atom_index).?;
141 // We now have a pointer to a live atom that has too much capacity.144 // We now have a pointer to a live atom that has too much capacity.
142 // Is it enough that we could fit this new atom?145 // Is it enough that we could fit this new atom?
143 const cap = big_atom.capacity(elf_file);146 const cap = big_atom.capacity(elf_file);
...@@ -169,7 +172,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {...@@ -169,7 +172,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
169 free_list_removal = i;172 free_list_removal = i;
170 }173 }
171 break :blk @intCast(new_start_vaddr);174 break :blk @intCast(new_start_vaddr);
172 } else if (elf_file.atom(last_atom_index.*)) |last| {175 } else if (zo.atom(last_atom_index.*)) |last| {
173 const ideal_capacity = Elf.padToIdeal(last.size);176 const ideal_capacity = Elf.padToIdeal(last.size);
174 const ideal_capacity_end_vaddr = @as(u64, @intCast(last.value)) + ideal_capacity;177 const ideal_capacity_end_vaddr = @as(u64, @intCast(last.value)) + ideal_capacity;
175 const new_start_vaddr = self.alignment.forward(ideal_capacity_end_vaddr);178 const new_start_vaddr = self.alignment.forward(ideal_capacity_end_vaddr);
...@@ -189,7 +192,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {...@@ -189,7 +192,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
189 });192 });
190193
191 const expand_section = if (atom_placement) |placement_index|194 const expand_section = if (atom_placement) |placement_index|
192 elf_file.atom(placement_index).?.next_index == 0195 zo.atom(placement_index).?.next_index == 0
193 else196 else
194 true;197 true;
195 if (expand_section) {198 if (expand_section) {
...@@ -214,15 +217,15 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {...@@ -214,15 +217,15 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
214 // This function can also reallocate an atom.217 // This function can also reallocate an atom.
215 // In this case we need to "unplug" it from its previous location before218 // In this case we need to "unplug" it from its previous location before
216 // plugging it in to its new location.219 // plugging it in to its new location.
217 if (elf_file.atom(self.prev_index)) |prev| {220 if (zo.atom(self.prev_index)) |prev| {
218 prev.next_index = self.next_index;221 prev.next_index = self.next_index;
219 }222 }
220 if (elf_file.atom(self.next_index)) |next| {223 if (zo.atom(self.next_index)) |next| {
221 next.prev_index = self.prev_index;224 next.prev_index = self.prev_index;
222 }225 }
223226
224 if (atom_placement) |big_atom_index| {227 if (atom_placement) |big_atom_index| {
225 const big_atom = elf_file.atom(big_atom_index).?;228 const big_atom = zo.atom(big_atom_index).?;
226 self.prev_index = big_atom_index;229 self.prev_index = big_atom_index;
227 self.next_index = big_atom.next_index;230 self.next_index = big_atom.next_index;
228 big_atom.next_index = self.atom_index;231 big_atom.next_index = self.atom_index;
...@@ -250,6 +253,7 @@ pub fn grow(self: *Atom, elf_file: *Elf) !void {...@@ -250,6 +253,7 @@ pub fn grow(self: *Atom, elf_file: *Elf) !void {
250pub fn free(self: *Atom, elf_file: *Elf) void {253pub fn free(self: *Atom, elf_file: *Elf) void {
251 log.debug("freeAtom {d} ({s})", .{ self.atom_index, self.name(elf_file) });254 log.debug("freeAtom {d} ({s})", .{ self.atom_index, self.name(elf_file) });
252255
256 const zo = elf_file.zigObjectPtr().?;
253 const comp = elf_file.base.comp;257 const comp = elf_file.base.comp;
254 const gpa = comp.gpa;258 const gpa = comp.gpa;
255 const shndx = self.outputShndx().?;259 const shndx = self.outputShndx().?;
...@@ -272,9 +276,9 @@ pub fn free(self: *Atom, elf_file: *Elf) void {...@@ -272,9 +276,9 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
272 }276 }
273 }277 }
274278
275 if (elf_file.atom(last_atom_index.*)) |last_atom| {279 if (zo.atom(last_atom_index.*)) |last_atom| {
276 if (last_atom.atom_index == self.atom_index) {280 if (last_atom.atom_index == self.atom_index) {
277 if (elf_file.atom(self.prev_index)) |_| {281 if (zo.atom(self.prev_index)) |_| {
278 // TODO shrink the section size here282 // TODO shrink the section size here
279 last_atom_index.* = self.prev_index;283 last_atom_index.* = self.prev_index;
280 } else {284 } else {
...@@ -283,7 +287,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void {...@@ -283,7 +287,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
283 }287 }
284 }288 }
285289
286 if (elf_file.atom(self.prev_index)) |prev| {290 if (zo.atom(self.prev_index)) |prev| {
287 prev.next_index = self.next_index;291 prev.next_index = self.next_index;
288 if (!already_have_free_list_node and prev.*.freeListEligible(elf_file)) {292 if (!already_have_free_list_node and prev.*.freeListEligible(elf_file)) {
289 // The free list is heuristics, it doesn't have to be perfect, so we can293 // The free list is heuristics, it doesn't have to be perfect, so we can
...@@ -294,7 +298,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void {...@@ -294,7 +298,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
294 self.prev_index = 0;298 self.prev_index = 0;
295 }299 }
296300
297 if (elf_file.atom(self.next_index)) |next| {301 if (zo.atom(self.next_index)) |next| {
298 next.prev_index = self.prev_index;302 next.prev_index = self.prev_index;
299 } else {303 } else {
300 self.next_index = 0;304 self.next_index = 0;
...@@ -313,7 +317,7 @@ pub fn relocs(self: Atom, elf_file: *Elf) []const elf.Elf64_Rela {...@@ -313,7 +317,7 @@ pub fn relocs(self: Atom, elf_file: *Elf) []const elf.Elf64_Rela {
313 switch (self.file(elf_file).?) {317 switch (self.file(elf_file).?) {
314 .zig_object => |x| return x.relocs.items[shndx].items,318 .zig_object => |x| return x.relocs.items[shndx].items,
315 .object => |x| {319 .object => |x| {
316 const extras = self.extra(elf_file).?;320 const extras = self.extra(elf_file);
317 return x.relocs.items[extras.rel_index..][0..extras.rel_count];321 return x.relocs.items[extras.rel_index..][0..extras.rel_count];
318 },322 },
319 else => unreachable,323 else => unreachable,
...@@ -367,7 +371,7 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El...@@ -367,7 +371,7 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El
367371
368pub fn fdes(self: Atom, elf_file: *Elf) []Fde {372pub fn fdes(self: Atom, elf_file: *Elf) []Fde {
369 if (!self.flags.fde) return &[0]Fde{};373 if (!self.flags.fde) return &[0]Fde{};
370 const extras = self.extra(elf_file).?;374 const extras = self.extra(elf_file);
371 const object = self.file(elf_file).?.object;375 const object = self.file(elf_file).?.object;
372 return object.fdes.items[extras.fde_start..][0..extras.fde_count];376 return object.fdes.items[extras.fde_start..][0..extras.fde_count];
373}377}
...@@ -712,9 +716,9 @@ fn reportUndefined(...@@ -712,9 +716,9 @@ fn reportUndefined(
712 {716 {
713 const gop = try undefs.getOrPut(sym_index);717 const gop = try undefs.getOrPut(sym_index);
714 if (!gop.found_existing) {718 if (!gop.found_existing) {
715 gop.value_ptr.* = std.ArrayList(Atom.Index).init(gpa);719 gop.value_ptr.* = std.ArrayList(Elf.Ref).init(gpa);
716 }720 }
717 try gop.value_ptr.append(self.atom_index);721 try gop.value_ptr.append(.{ .index = self.atom_index, .file = self.file_index });
718 return true;722 return true;
719 }723 }
720724
...@@ -1001,25 +1005,23 @@ const AddExtraOpts = struct {...@@ -1001,25 +1005,23 @@ const AddExtraOpts = struct {
1001 rel_count: ?u32 = null,1005 rel_count: ?u32 = null,
1002};1006};
10031007
1004pub fn addExtra(atom: *Atom, opts: AddExtraOpts, elf_file: *Elf) !void {1008pub fn addExtra(atom: *Atom, opts: AddExtraOpts, elf_file: *Elf) void {
1005 if (atom.extra(elf_file) == null) {1009 const file_ptr = atom.file(elf_file).?;
1006 atom.extra_index = try elf_file.addAtomExtra(.{});1010 var extras = file_ptr.atomExtra(atom.extra_index);
1007 }
1008 var extras = atom.extra(elf_file).?;
1009 inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| {1011 inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| {
1010 if (@field(opts, field.name)) |x| {1012 if (@field(opts, field.name)) |x| {
1011 @field(extras, field.name) = x;1013 @field(extras, field.name) = x;
1012 }1014 }
1013 }1015 }
1014 atom.setExtra(extras, elf_file);1016 file_ptr.setAtomExtra(atom.extra_index, extras);
1015}1017}
10161018
1017pub inline fn extra(atom: Atom, elf_file: *Elf) ?Extra {1019pub inline fn extra(atom: Atom, elf_file: *Elf) Extra {
1018 return elf_file.atomExtra(atom.extra_index);1020 return atom.file(elf_file).?.atomExtra(atom.extra_index);
1019}1021}
10201022
1021pub inline fn setExtra(atom: Atom, extras: Extra, elf_file: *Elf) void {1023pub inline fn setExtra(atom: Atom, extras: Extra, elf_file: *Elf) void {
1022 elf_file.setAtomExtra(atom.extra_index, extras);1024 atom.file(elf_file).?.setAtomExtra(atom.extra_index, extras);
1023}1025}
10241026
1025pub fn format(1027pub fn format(
...@@ -1063,7 +1065,7 @@ fn format2(...@@ -1063,7 +1065,7 @@ fn format2(
1063 });1065 });
1064 if (atom.flags.fde) {1066 if (atom.flags.fde) {
1065 try writer.writeAll(" : fdes{ ");1067 try writer.writeAll(" : fdes{ ");
1066 const extras = atom.extra(elf_file).?;1068 const extras = atom.extra(elf_file);
1067 for (atom.fdes(elf_file), extras.fde_start..) |fde, i| {1069 for (atom.fdes(elf_file), extras.fde_start..) |fde, i| {
1068 try writer.print("{d}", .{i});1070 try writer.print("{d}", .{i});
1069 if (!fde.alive) try writer.writeAll("([*])");1071 if (!fde.alive) try writer.writeAll("([*])");
src/link/Elf/LinkerDefined.zig+8-1
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1index: File.Index,1index: File.Index,
2
2symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},3symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
3strtab: std.ArrayListUnmanaged(u8) = .{},4strtab: std.ArrayListUnmanaged(u8) = .{},
4symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},5symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
...@@ -11,6 +12,11 @@ pub fn deinit(self: *LinkerDefined, allocator: Allocator) void {...@@ -11,6 +12,11 @@ pub fn deinit(self: *LinkerDefined, allocator: Allocator) void {
11 self.symbols.deinit(allocator);12 self.symbols.deinit(allocator);
12}13}
1314
15pub fn init(self: *LinkerDefined, allocator: Allocator) !void {
16 // Null byte in strtab
17 try self.strtab.append(allocator, 0);
18}
19
14pub fn addGlobal(self: *LinkerDefined, name: [:0]const u8, elf_file: *Elf) !u32 {20pub fn addGlobal(self: *LinkerDefined, name: [:0]const u8, elf_file: *Elf) !u32 {
15 const comp = elf_file.base.comp;21 const comp = elf_file.base.comp;
16 const gpa = comp.gpa;22 const gpa = comp.gpa;
...@@ -41,7 +47,7 @@ pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) void {...@@ -41,7 +47,7 @@ pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) void {
41 const global = elf_file.symbol(index);47 const global = elf_file.symbol(index);
42 if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) {48 if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) {
43 global.value = 0;49 global.value = 0;
44 global.atom_index = 0;50 global.atom_ref = .{ .index = 0, .file = 0 };
45 global.file_index = self.index;51 global.file_index = self.index;
46 global.esym_index = sym_idx;52 global.esym_index = sym_idx;
47 global.version_index = elf_file.default_sym_version;53 global.version_index = elf_file.default_sym_version;
...@@ -127,6 +133,7 @@ const mem = std.mem;...@@ -127,6 +133,7 @@ const mem = std.mem;
127const std = @import("std");133const std = @import("std");
128134
129const Allocator = mem.Allocator;135const Allocator = mem.Allocator;
136const Atom = @import("Atom.zig");
130const Elf = @import("../Elf.zig");137const Elf = @import("../Elf.zig");
131const File = @import("file.zig").File;138const File = @import("file.zig").File;
132const LinkerDefined = @This();139const LinkerDefined = @This();
src/link/Elf/Object.zig+199-123
...@@ -10,9 +10,12 @@ symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},...@@ -10,9 +10,12 @@ symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
10strtab: std.ArrayListUnmanaged(u8) = .{},10strtab: std.ArrayListUnmanaged(u8) = .{},
11first_global: ?Symbol.Index = null,11first_global: ?Symbol.Index = null,
12symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},12symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
13atoms: std.ArrayListUnmanaged(Atom.Index) = .{},
14relocs: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},13relocs: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},
1514
15atoms: std.ArrayListUnmanaged(Atom) = .{},
16atoms_indexes: std.ArrayListUnmanaged(Atom.Index) = .{},
17atoms_extra: std.ArrayListUnmanaged(u32) = .{},
18
16comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup) = .{},19comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup) = .{},
17comdat_group_data: std.ArrayListUnmanaged(u32) = .{},20comdat_group_data: std.ArrayListUnmanaged(u32) = .{},
1821
...@@ -49,6 +52,8 @@ pub fn deinit(self: *Object, allocator: Allocator) void {...@@ -49,6 +52,8 @@ pub fn deinit(self: *Object, allocator: Allocator) void {
49 self.strtab.deinit(allocator);52 self.strtab.deinit(allocator);
50 self.symbols.deinit(allocator);53 self.symbols.deinit(allocator);
51 self.atoms.deinit(allocator);54 self.atoms.deinit(allocator);
55 self.atoms_indexes.deinit(allocator);
56 self.atoms_extra.deinit(allocator);
52 self.comdat_groups.deinit(allocator);57 self.comdat_groups.deinit(allocator);
53 self.comdat_group_data.deinit(allocator);58 self.comdat_group_data.deinit(allocator);
54 self.relocs.deinit(allocator);59 self.relocs.deinit(allocator);
...@@ -71,15 +76,17 @@ pub fn parse(self: *Object, elf_file: *Elf) !void {...@@ -71,15 +76,17 @@ pub fn parse(self: *Object, elf_file: *Elf) !void {
7176
72 // Append null input merge section77 // Append null input merge section
73 try self.input_merge_sections.append(gpa, .{});78 try self.input_merge_sections.append(gpa, .{});
79 // Allocate atom index 0 to null atom
80 try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) });
7481
75 try self.initAtoms(gpa, handle, elf_file);82 try self.initAtoms(gpa, handle, elf_file);
76 try self.initSymtab(gpa, elf_file);83 try self.initSymtab(gpa, elf_file);
7784
78 for (self.shdrs.items, 0..) |shdr, i| {85 for (self.shdrs.items, 0..) |shdr, i| {
79 const atom = elf_file.atom(self.atoms.items[i]) orelse continue;86 const atom_ptr = self.atom(self.atoms_indexes.items[i]) orelse continue;
80 if (!atom.flags.alive) continue;87 if (!atom_ptr.flags.alive) continue;
81 if ((cpu_arch == .x86_64 and shdr.sh_type == elf.SHT_X86_64_UNWIND) or88 if ((cpu_arch == .x86_64 and shdr.sh_type == elf.SHT_X86_64_UNWIND) or
82 mem.eql(u8, atom.name(elf_file), ".eh_frame"))89 mem.eql(u8, atom_ptr.name(elf_file), ".eh_frame"))
83 {90 {
84 try self.parseEhFrame(gpa, handle, @as(u32, @intCast(i)), elf_file);91 try self.parseEhFrame(gpa, handle, @as(u32, @intCast(i)), elf_file);
85 }92 }
...@@ -179,8 +186,11 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil...@@ -179,8 +186,11 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil
179186
180fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: *Elf) !void {187fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: *Elf) !void {
181 const shdrs = self.shdrs.items;188 const shdrs = self.shdrs.items;
182 try self.atoms.resize(allocator, shdrs.len);189 try self.atoms.ensureTotalCapacityPrecise(allocator, shdrs.len);
183 @memset(self.atoms.items, 0);190 try self.atoms_extra.ensureTotalCapacityPrecise(allocator, shdrs.len * @sizeOf(Atom.Extra));
191 try self.atoms_indexes.ensureTotalCapacityPrecise(allocator, shdrs.len);
192 try self.atoms_indexes.resize(allocator, shdrs.len);
193 @memset(self.atoms_indexes.items, 0);
184194
185 for (shdrs, 0..) |shdr, i| {195 for (shdrs, 0..) |shdr, i| {
186 if (shdr.sh_flags & elf.SHF_EXCLUDE != 0 and196 if (shdr.sh_flags & elf.SHF_EXCLUDE != 0 and
...@@ -242,7 +252,19 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:...@@ -242,7 +252,19 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:
242 else => {252 else => {
243 const shndx = @as(u32, @intCast(i));253 const shndx = @as(u32, @intCast(i));
244 if (self.skipShdr(shndx, elf_file)) continue;254 if (self.skipShdr(shndx, elf_file)) continue;
245 try self.addAtom(allocator, handle, shdr, shndx, elf_file);255 const size, const alignment = if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) blk: {
256 const data = try self.preadShdrContentsAlloc(allocator, handle, shndx);
257 defer allocator.free(data);
258 const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*;
259 break :blk .{ chdr.ch_size, Alignment.fromNonzeroByteUnits(chdr.ch_addralign) };
260 } else .{ shdr.sh_size, Alignment.fromNonzeroByteUnits(shdr.sh_addralign) };
261 const atom_index = self.addAtomAssumeCapacity(.{
262 .name = shdr.sh_name,
263 .shndx = shndx,
264 .size = size,
265 .alignment = alignment,
266 });
267 self.atoms_indexes.items[shndx] = atom_index;
246 },268 },
247 }269 }
248 }270 }
...@@ -250,14 +272,14 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:...@@ -250,14 +272,14 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:
250 // Parse relocs sections if any.272 // Parse relocs sections if any.
251 for (shdrs, 0..) |shdr, i| switch (shdr.sh_type) {273 for (shdrs, 0..) |shdr, i| switch (shdr.sh_type) {
252 elf.SHT_REL, elf.SHT_RELA => {274 elf.SHT_REL, elf.SHT_RELA => {
253 const atom_index = self.atoms.items[shdr.sh_info];275 const atom_index = self.atoms_indexes.items[shdr.sh_info];
254 if (elf_file.atom(atom_index)) |atom| {276 if (self.atom(atom_index)) |atom_ptr| {
255 const relocs = try self.preadRelocsAlloc(allocator, handle, @intCast(i));277 const relocs = try self.preadRelocsAlloc(allocator, handle, @intCast(i));
256 defer allocator.free(relocs);278 defer allocator.free(relocs);
257 atom.relocs_section_index = @intCast(i);279 atom_ptr.relocs_section_index = @intCast(i);
258 const rel_index: u32 = @intCast(self.relocs.items.len);280 const rel_index: u32 = @intCast(self.relocs.items.len);
259 const rel_count: u32 = @intCast(relocs.len);281 const rel_count: u32 = @intCast(relocs.len);
260 try atom.addExtra(.{ .rel_index = rel_index, .rel_count = rel_count }, elf_file);282 atom_ptr.addExtra(.{ .rel_index = rel_index, .rel_count = rel_count }, elf_file);
261 try self.relocs.appendUnalignedSlice(allocator, relocs);283 try self.relocs.appendUnalignedSlice(allocator, relocs);
262 if (elf_file.getTarget().cpu.arch == .riscv64) {284 if (elf_file.getTarget().cpu.arch == .riscv64) {
263 sortRelocs(self.relocs.items[rel_index..][0..rel_count]);285 sortRelocs(self.relocs.items[rel_index..][0..rel_count]);
...@@ -268,27 +290,6 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:...@@ -268,27 +290,6 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:
268 };290 };
269}291}
270292
271fn addAtom(self: *Object, allocator: Allocator, handle: std.fs.File, shdr: elf.Elf64_Shdr, shndx: u32, elf_file: *Elf) !void {
272 const atom_index = try elf_file.addAtom();
273 const atom = elf_file.atom(atom_index).?;
274 atom.atom_index = atom_index;
275 atom.name_offset = shdr.sh_name;
276 atom.file_index = self.index;
277 atom.input_section_index = shndx;
278 self.atoms.items[shndx] = atom_index;
279
280 if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) {
281 const data = try self.preadShdrContentsAlloc(allocator, handle, shndx);
282 defer allocator.free(data);
283 const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*;
284 atom.size = chdr.ch_size;
285 atom.alignment = Alignment.fromNonzeroByteUnits(chdr.ch_addralign);
286 } else {
287 atom.size = shdr.sh_size;
288 atom.alignment = Alignment.fromNonzeroByteUnits(shdr.sh_addralign);
289 }
290}
291
292fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{OutOfMemory}!u32 {293fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{OutOfMemory}!u32 {
293 const name = blk: {294 const name = blk: {
294 const name = self.getString(shdr.sh_name);295 const name = self.getString(shdr.sh_name);
...@@ -368,8 +369,10 @@ fn initSymtab(self: *Object, allocator: Allocator, elf_file: *Elf) !void {...@@ -368,8 +369,10 @@ fn initSymtab(self: *Object, allocator: Allocator, elf_file: *Elf) !void {
368 sym_ptr.value = @intCast(sym.st_value);369 sym_ptr.value = @intCast(sym.st_value);
369 sym_ptr.name_offset = sym.st_name;370 sym_ptr.name_offset = sym.st_name;
370 sym_ptr.esym_index = @as(u32, @intCast(i));371 sym_ptr.esym_index = @as(u32, @intCast(i));
371 sym_ptr.atom_index = if (sym.st_shndx == elf.SHN_ABS) 0 else self.atoms.items[sym.st_shndx];
372 sym_ptr.file_index = self.index;372 sym_ptr.file_index = self.index;
373 if (sym.st_shndx != elf.SHN_ABS) {
374 sym_ptr.atom_ref = .{ .index = self.atoms_indexes.items[sym.st_shndx], .file = self.index };
375 }
373 }376 }
374377
375 for (self.symtab.items[first_global..]) |sym| {378 for (self.symtab.items[first_global..]) |sym| {
...@@ -456,15 +459,15 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx:...@@ -456,15 +459,15 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx:
456 var i: u32 = @as(u32, @intCast(fdes_start));459 var i: u32 = @as(u32, @intCast(fdes_start));
457 while (i < self.fdes.items.len) {460 while (i < self.fdes.items.len) {
458 const fde = self.fdes.items[i];461 const fde = self.fdes.items[i];
459 const atom = fde.atom(elf_file);462 const atom_ptr = fde.atom(elf_file);
460 const start = i;463 const start = i;
461 i += 1;464 i += 1;
462 while (i < self.fdes.items.len) : (i += 1) {465 while (i < self.fdes.items.len) : (i += 1) {
463 const next_fde = self.fdes.items[i];466 const next_fde = self.fdes.items[i];
464 if (atom.atom_index != next_fde.atom(elf_file).atom_index) break;467 if (atom_ptr.atom_index != next_fde.atom(elf_file).atom_index) break;
465 }468 }
466 try atom.addExtra(.{ .fde_start = start, .fde_count = i - start }, elf_file);469 atom_ptr.addExtra(.{ .fde_start = start, .fde_count = i - start }, elf_file);
467 atom.flags.fde = true;470 atom_ptr.flags.fde = true;
468 }471 }
469}472}
470473
...@@ -507,19 +510,19 @@ fn filterRelocs(...@@ -507,19 +510,19 @@ fn filterRelocs(
507pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void {510pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void {
508 const comp = elf_file.base.comp;511 const comp = elf_file.base.comp;
509 const gpa = comp.gpa;512 const gpa = comp.gpa;
510 for (self.atoms.items) |atom_index| {513 for (self.atoms_indexes.items) |atom_index| {
511 const atom = elf_file.atom(atom_index) orelse continue;514 const atom_ptr = self.atom(atom_index) orelse continue;
512 if (!atom.flags.alive) continue;515 if (!atom_ptr.flags.alive) continue;
513 const shdr = atom.inputShdr(elf_file);516 const shdr = atom_ptr.inputShdr(elf_file);
514 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;517 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
515 if (shdr.sh_type == elf.SHT_NOBITS) continue;518 if (shdr.sh_type == elf.SHT_NOBITS) continue;
516 if (atom.scanRelocsRequiresCode(elf_file)) {519 if (atom_ptr.scanRelocsRequiresCode(elf_file)) {
517 // TODO ideally, we don't have to decompress at this stage (should already be done)520 // TODO ideally, we don't have to decompress at this stage (should already be done)
518 // and we just fetch the code slice.521 // and we just fetch the code slice.
519 const code = try self.codeDecompressAlloc(elf_file, atom_index);522 const code = try self.codeDecompressAlloc(elf_file, atom_index);
520 defer gpa.free(code);523 defer gpa.free(code);
521 try atom.scanRelocs(elf_file, code, undefs);524 try atom_ptr.scanRelocs(elf_file, code, undefs);
522 } else try atom.scanRelocs(elf_file, null, undefs);525 } else try atom_ptr.scanRelocs(elf_file, null, undefs);
523 }526 }
524527
525 for (self.cies.items) |cie| {528 for (self.cies.items) |cie| {
...@@ -547,19 +550,21 @@ pub fn resolveSymbols(self: *Object, elf_file: *Elf) void {...@@ -547,19 +550,21 @@ pub fn resolveSymbols(self: *Object, elf_file: *Elf) void {
547 if (esym.st_shndx == elf.SHN_UNDEF) continue;550 if (esym.st_shndx == elf.SHN_UNDEF) continue;
548551
549 if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) {552 if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) {
550 const atom_index = self.atoms.items[esym.st_shndx];553 const atom_index = self.atoms_indexes.items[esym.st_shndx];
551 const atom = elf_file.atom(atom_index) orelse continue;554 const atom_ptr = self.atom(atom_index) orelse continue;
552 if (!atom.flags.alive) continue;555 if (!atom_ptr.flags.alive) continue;
553 }556 }
554557
555 const global = elf_file.symbol(index);558 const global = elf_file.symbol(index);
556 if (self.asFile().symbolRank(esym, !self.alive) < global.symbolRank(elf_file)) {559 if (self.asFile().symbolRank(esym, !self.alive) < global.symbolRank(elf_file)) {
557 const atom_index = switch (esym.st_shndx) {560 switch (esym.st_shndx) {
558 elf.SHN_ABS, elf.SHN_COMMON => 0,561 elf.SHN_ABS, elf.SHN_COMMON => {},
559 else => self.atoms.items[esym.st_shndx],562 else => global.atom_ref = .{
560 };563 .index = self.atoms_indexes.items[esym.st_shndx],
564 .file = self.index,
565 },
566 }
561 global.value = @intCast(esym.st_value);567 global.value = @intCast(esym.st_value);
562 global.atom_index = atom_index;
563 global.esym_index = esym_index;568 global.esym_index = esym_index;
564 global.file_index = self.index;569 global.file_index = self.index;
565 global.version_index = elf_file.default_sym_version;570 global.version_index = elf_file.default_sym_version;
...@@ -588,7 +593,7 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void {...@@ -588,7 +593,7 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void {
588 };593 };
589594
590 global.value = 0;595 global.value = 0;
591 global.atom_index = 0;596 global.atom_ref = .{ .index = 0, .file = 0 };
592 global.esym_index = esym_index;597 global.esym_index = esym_index;
593 global.file_index = self.index;598 global.file_index = self.index;
594 global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;599 global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;
...@@ -609,7 +614,7 @@ pub fn claimUnresolvedObject(self: *Object, elf_file: *Elf) void {...@@ -609,7 +614,7 @@ pub fn claimUnresolvedObject(self: *Object, elf_file: *Elf) void {
609 }614 }
610615
611 global.value = 0;616 global.value = 0;
612 global.atom_index = 0;617 global.atom_ref = .{ .index = 0, .file = 0 };
613 global.esym_index = esym_index;618 global.esym_index = esym_index;
614 global.file_index = self.index;619 global.file_index = self.index;
615 }620 }
...@@ -633,13 +638,13 @@ pub fn markLive(self: *Object, elf_file: *Elf) void {...@@ -633,13 +638,13 @@ pub fn markLive(self: *Object, elf_file: *Elf) void {
633 }638 }
634}639}
635640
636pub fn markEhFrameAtomsDead(self: Object, elf_file: *Elf) void {641pub fn markEhFrameAtomsDead(self: *Object, elf_file: *Elf) void {
637 const cpu_arch = elf_file.getTarget().cpu.arch;642 const cpu_arch = elf_file.getTarget().cpu.arch;
638 for (self.atoms.items) |atom_index| {643 for (self.atoms_indexes.items) |atom_index| {
639 const atom = elf_file.atom(atom_index) orelse continue;644 const atom_ptr = self.atom(atom_index) orelse continue;
640 const is_eh_frame = (cpu_arch == .x86_64 and atom.inputShdr(elf_file).sh_type == elf.SHT_X86_64_UNWIND) or645 const is_eh_frame = (cpu_arch == .x86_64 and atom_ptr.inputShdr(elf_file).sh_type == elf.SHT_X86_64_UNWIND) or
641 mem.eql(u8, atom.name(elf_file), ".eh_frame");646 mem.eql(u8, atom_ptr.name(elf_file), ".eh_frame");
642 if (atom.flags.alive and is_eh_frame) atom.flags.alive = false;647 if (atom_ptr.flags.alive and is_eh_frame) atom_ptr.flags.alive = false;
643 }648 }
644}649}
645650
...@@ -657,9 +662,9 @@ pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutO...@@ -657,9 +662,9 @@ pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutO
657 sym.st_shndx == elf.SHN_COMMON) continue;662 sym.st_shndx == elf.SHN_COMMON) continue;
658663
659 if (sym.st_shndx != elf.SHN_ABS) {664 if (sym.st_shndx != elf.SHN_ABS) {
660 const atom_index = self.atoms.items[sym.st_shndx];665 const atom_index = self.atoms_indexes.items[sym.st_shndx];
661 const atom = elf_file.atom(atom_index) orelse continue;666 const atom_ptr = self.atom(atom_index) orelse continue;
662 if (!atom.flags.alive) continue;667 if (!atom_ptr.flags.alive) continue;
663 }668 }
664669
665 const gop = try dupes.getOrPut(index);670 const gop = try dupes.getOrPut(index);
...@@ -680,8 +685,8 @@ pub fn initMergeSections(self: *Object, elf_file: *Elf) !void {...@@ -680,8 +685,8 @@ pub fn initMergeSections(self: *Object, elf_file: *Elf) !void {
680 for (self.shdrs.items, 0..) |shdr, shndx| {685 for (self.shdrs.items, 0..) |shdr, shndx| {
681 if (shdr.sh_flags & elf.SHF_MERGE == 0) continue;686 if (shdr.sh_flags & elf.SHF_MERGE == 0) continue;
682687
683 const atom_index = self.atoms.items[shndx];688 const atom_index = self.atoms_indexes.items[shndx];
684 const atom_ptr = elf_file.atom(atom_index) orelse continue;689 const atom_ptr = self.atom(atom_index) orelse continue;
685 if (!atom_ptr.flags.alive) continue;690 if (!atom_ptr.flags.alive) continue;
686 if (atom_ptr.relocs(elf_file).len > 0) continue;691 if (atom_ptr.relocs(elf_file).len > 0) continue;
687692
...@@ -755,7 +760,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {...@@ -755,7 +760,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {
755 const imsec = self.inputMergeSection(index) orelse continue;760 const imsec = self.inputMergeSection(index) orelse continue;
756 if (imsec.offsets.items.len == 0) continue;761 if (imsec.offsets.items.len == 0) continue;
757 const msec = elf_file.mergeSection(imsec.merge_section_index);762 const msec = elf_file.mergeSection(imsec.merge_section_index);
758 const atom_ptr = elf_file.atom(imsec.atom_index).?;763 const atom_ptr = self.atom(imsec.atom_index).?;
759 const isec = atom_ptr.inputShdr(elf_file);764 const isec = atom_ptr.inputShdr(elf_file);
760765
761 try imsec.subsections.resize(gpa, imsec.strings.items.len);766 try imsec.subsections.resize(gpa, imsec.strings.items.len);
...@@ -802,10 +807,10 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {...@@ -802,10 +807,10 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {
802 sym.value = offset;807 sym.value = offset;
803 }808 }
804809
805 for (self.atoms.items) |atom_index| {810 for (self.atoms_indexes.items) |atom_index| {
806 const atom_ptr = elf_file.atom(atom_index) orelse continue;811 const atom_ptr = self.atom(atom_index) orelse continue;
807 if (!atom_ptr.flags.alive) continue;812 if (!atom_ptr.flags.alive) continue;
808 const extras = atom_ptr.extra(elf_file) orelse continue;813 const extras = atom_ptr.extra(elf_file);
809 const relocs = self.relocs.items[extras.rel_index..][0..extras.rel_count];814 const relocs = self.relocs.items[extras.rel_index..][0..extras.rel_count];
810 for (relocs) |*rel| {815 for (relocs) |*rel| {
811 const esym = self.symtab.items[rel.r_sym()];816 const esym = self.symtab.items[rel.r_sym()];
...@@ -867,21 +872,10 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {...@@ -867,21 +872,10 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
867 const comp = elf_file.base.comp;872 const comp = elf_file.base.comp;
868 const gpa = comp.gpa;873 const gpa = comp.gpa;
869874
870 const atom_index = try elf_file.addAtom();
871 try self.atoms.append(gpa, atom_index);
872
873 const is_tls = global.type(elf_file) == elf.STT_TLS;875 const is_tls = global.type(elf_file) == elf.STT_TLS;
874 const name = if (is_tls) ".tls_common" else ".common";876 const name = if (is_tls) ".tls_common" else ".common";
875
876 const atom = elf_file.atom(atom_index).?;
877 const name_offset = @as(u32, @intCast(self.strtab.items.len));877 const name_offset = @as(u32, @intCast(self.strtab.items.len));
878 try self.strtab.writer(gpa).print("{s}\x00", .{name});878 try self.strtab.writer(gpa).print("{s}\x00", .{name});
879 atom.atom_index = atom_index;
880 atom.name_offset = name_offset;
881 atom.file_index = self.index;
882 atom.size = this_sym.st_size;
883 const alignment = this_sym.st_value;
884 atom.alignment = Alignment.fromNonzeroByteUnits(alignment);
885879
886 var sh_flags: u32 = elf.SHF_ALLOC | elf.SHF_WRITE;880 var sh_flags: u32 = elf.SHF_ALLOC | elf.SHF_WRITE;
887 if (is_tls) sh_flags |= elf.SHF_TLS;881 if (is_tls) sh_flags |= elf.SHF_TLS;
...@@ -897,38 +891,45 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {...@@ -897,38 +891,45 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
897 .sh_size = sh_size,891 .sh_size = sh_size,
898 .sh_link = 0,892 .sh_link = 0,
899 .sh_info = 0,893 .sh_info = 0,
900 .sh_addralign = alignment,894 .sh_addralign = this_sym.st_value,
901 .sh_entsize = 0,895 .sh_entsize = 0,
902 };896 };
903 atom.input_section_index = shndx;897
898 const atom_index = try self.addAtom(gpa, .{
899 .name = name_offset,
900 .shndx = shndx,
901 .size = this_sym.st_size,
902 .alignment = Alignment.fromNonzeroByteUnits(this_sym.st_value),
903 });
904 try self.atoms_indexes.append(gpa, atom_index);
904905
905 global.value = 0;906 global.value = 0;
906 global.atom_index = atom_index;907 global.atom_ref = .{ .index = atom_index, .file = self.index };
907 global.flags.weak = false;908 global.flags.weak = false;
908 }909 }
909}910}
910911
911pub fn initOutputSections(self: Object, elf_file: *Elf) !void {912pub fn initOutputSections(self: *Object, elf_file: *Elf) !void {
912 for (self.atoms.items) |atom_index| {913 for (self.atoms_indexes.items) |atom_index| {
913 const atom = elf_file.atom(atom_index) orelse continue;914 const atom_ptr = self.atom(atom_index) orelse continue;
914 if (!atom.flags.alive) continue;915 if (!atom_ptr.flags.alive) continue;
915 const shdr = atom.inputShdr(elf_file);916 const shdr = atom_ptr.inputShdr(elf_file);
916 _ = try self.initOutputSection(elf_file, shdr);917 _ = try self.initOutputSection(elf_file, shdr);
917 }918 }
918}919}
919920
920pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {921pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {
921 for (self.atoms.items) |atom_index| {922 for (self.atoms_indexes.items) |atom_index| {
922 const atom = elf_file.atom(atom_index) orelse continue;923 const atom_ptr = self.atom(atom_index) orelse continue;
923 if (!atom.flags.alive) continue;924 if (!atom_ptr.flags.alive) continue;
924 const shdr = atom.inputShdr(elf_file);925 const shdr = atom_ptr.inputShdr(elf_file);
925 atom.output_section_index = self.initOutputSection(elf_file, shdr) catch unreachable;926 atom_ptr.output_section_index = self.initOutputSection(elf_file, shdr) catch unreachable;
926927
927 const comp = elf_file.base.comp;928 const comp = elf_file.base.comp;
928 const gpa = comp.gpa;929 const gpa = comp.gpa;
929 const gop = try elf_file.output_sections.getOrPut(gpa, atom.output_section_index);930 const gop = try elf_file.output_sections.getOrPut(gpa, atom_ptr.output_section_index);
930 if (!gop.found_existing) gop.value_ptr.* = .{};931 if (!gop.found_existing) gop.value_ptr.* = .{};
931 try gop.value_ptr.append(gpa, atom_index);932 try gop.value_ptr.append(gpa, .{ .index = atom_index, .file = self.index });
932 }933 }
933934
934 for (self.locals()) |local_index| {935 for (self.locals()) |local_index| {
...@@ -938,9 +939,9 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {...@@ -938,9 +939,9 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {
938 local.output_section_index = msub.mergeSection(elf_file).output_section_index;939 local.output_section_index = msub.mergeSection(elf_file).output_section_index;
939 continue;940 continue;
940 }941 }
941 const atom = local.atom(elf_file) orelse continue;942 const atom_ptr = local.atom(elf_file) orelse continue;
942 if (!atom.flags.alive) continue;943 if (!atom_ptr.flags.alive) continue;
943 local.output_section_index = atom.output_section_index;944 local.output_section_index = atom_ptr.output_section_index;
944 }945 }
945946
946 for (self.globals()) |global_index| {947 for (self.globals()) |global_index| {
...@@ -951,9 +952,9 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {...@@ -951,9 +952,9 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {
951 global.output_section_index = msub.mergeSection(elf_file).output_section_index;952 global.output_section_index = msub.mergeSection(elf_file).output_section_index;
952 continue;953 continue;
953 }954 }
954 const atom = global.atom(elf_file) orelse continue;955 const atom_ptr = global.atom(elf_file) orelse continue;
955 if (!atom.flags.alive) continue;956 if (!atom_ptr.flags.alive) continue;
956 global.output_section_index = atom.output_section_index;957 global.output_section_index = atom_ptr.output_section_index;
957 }958 }
958959
959 for (self.symbols.items[self.symtab.items.len..]) |local_index| {960 for (self.symbols.items[self.symtab.items.len..]) |local_index| {
...@@ -964,11 +965,11 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {...@@ -964,11 +965,11 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {
964 }965 }
965}966}
966967
967pub fn initRelaSections(self: Object, elf_file: *Elf) !void {968pub fn initRelaSections(self: *Object, elf_file: *Elf) !void {
968 for (self.atoms.items) |atom_index| {969 for (self.atoms_indexes.items) |atom_index| {
969 const atom = elf_file.atom(atom_index) orelse continue;970 const atom_ptr = self.atom(atom_index) orelse continue;
970 if (!atom.flags.alive) continue;971 if (!atom_ptr.flags.alive) continue;
971 const shndx = atom.relocsShndx() orelse continue;972 const shndx = atom_ptr.relocsShndx() orelse continue;
972 const shdr = self.shdrs.items[shndx];973 const shdr = self.shdrs.items[shndx];
973 const out_shndx = try self.initOutputSection(elf_file, shdr);974 const out_shndx = try self.initOutputSection(elf_file, shdr);
974 const out_shdr = &elf_file.shdrs.items[out_shndx];975 const out_shdr = &elf_file.shdrs.items[out_shndx];
...@@ -978,24 +979,24 @@ pub fn initRelaSections(self: Object, elf_file: *Elf) !void {...@@ -978,24 +979,24 @@ pub fn initRelaSections(self: Object, elf_file: *Elf) !void {
978 }979 }
979}980}
980981
981pub fn addAtomsToRelaSections(self: Object, elf_file: *Elf) !void {982pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void {
982 for (self.atoms.items) |atom_index| {983 for (self.atoms_indexes.items) |atom_index| {
983 const atom = elf_file.atom(atom_index) orelse continue;984 const atom_ptr = self.atom(atom_index) orelse continue;
984 if (!atom.flags.alive) continue;985 if (!atom_ptr.flags.alive) continue;
985 const shndx = blk: {986 const shndx = blk: {
986 const shndx = atom.relocsShndx() orelse continue;987 const shndx = atom_ptr.relocsShndx() orelse continue;
987 const shdr = self.shdrs.items[shndx];988 const shdr = self.shdrs.items[shndx];
988 break :blk self.initOutputSection(elf_file, shdr) catch unreachable;989 break :blk self.initOutputSection(elf_file, shdr) catch unreachable;
989 };990 };
990 const shdr = &elf_file.shdrs.items[shndx];991 const shdr = &elf_file.shdrs.items[shndx];
991 shdr.sh_info = atom.outputShndx().?;992 shdr.sh_info = atom_ptr.outputShndx().?;
992 shdr.sh_link = elf_file.symtab_section_index.?;993 shdr.sh_link = elf_file.symtab_section_index.?;
993994
994 const comp = elf_file.base.comp;995 const comp = elf_file.base.comp;
995 const gpa = comp.gpa;996 const gpa = comp.gpa;
996 const gop = try elf_file.output_rela_sections.getOrPut(gpa, atom.outputShndx().?);997 const gop = try elf_file.output_rela_sections.getOrPut(gpa, atom_ptr.outputShndx().?);
997 if (!gop.found_existing) gop.value_ptr.* = .{ .shndx = shndx };998 if (!gop.found_existing) gop.value_ptr.* = .{ .shndx = shndx };
998 try gop.value_ptr.atom_list.append(gpa, atom_index);999 try gop.value_ptr.atom_list.append(gpa, .{ .index = atom_index, .file = self.index });
999 }1000 }
1000}1001}
10011002
...@@ -1129,11 +1130,10 @@ pub fn globals(self: Object) []const Symbol.Index {...@@ -1129,11 +1130,10 @@ pub fn globals(self: Object) []const Symbol.Index {
11291130
1130/// Returns atom's code and optionally uncompresses data if required (for compressed sections).1131/// Returns atom's code and optionally uncompresses data if required (for compressed sections).
1131/// Caller owns the memory.1132/// Caller owns the memory.
1132pub fn codeDecompressAlloc(self: Object, elf_file: *Elf, atom_index: Atom.Index) ![]u8 {1133pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index) ![]u8 {
1133 const comp = elf_file.base.comp;1134 const comp = elf_file.base.comp;
1134 const gpa = comp.gpa;1135 const gpa = comp.gpa;
1135 const atom_ptr = elf_file.atom(atom_index).?;1136 const atom_ptr = self.atom(atom_index).?;
1136 assert(atom_ptr.file_index == self.index);
1137 const shdr = atom_ptr.inputShdr(elf_file);1137 const shdr = atom_ptr.inputShdr(elf_file);
1138 const handle = elf_file.fileHandle(self.file_handle);1138 const handle = elf_file.fileHandle(self.file_handle);
1139 const data = try self.preadShdrContentsAlloc(gpa, handle, atom_ptr.input_section_index);1139 const data = try self.preadShdrContentsAlloc(gpa, handle, atom_ptr.input_section_index);
...@@ -1194,6 +1194,82 @@ fn preadRelocsAlloc(self: Object, allocator: Allocator, handle: std.fs.File, shn...@@ -1194,6 +1194,82 @@ fn preadRelocsAlloc(self: Object, allocator: Allocator, handle: std.fs.File, shn
1194 return @as([*]align(1) const elf.Elf64_Rela, @ptrCast(raw.ptr))[0..num];1194 return @as([*]align(1) const elf.Elf64_Rela, @ptrCast(raw.ptr))[0..num];
1195}1195}
11961196
1197const AddAtomArgs = struct {
1198 name: u32,
1199 shndx: u32,
1200 size: u64,
1201 alignment: Alignment,
1202};
1203
1204fn addAtom(self: *Object, allocator: Allocator, args: AddAtomArgs) !Atom.Index {
1205 try self.atoms.ensureUnusedCapacity(allocator, 1);
1206 try self.atoms_extra.ensureUnusedCapacity(allocator, @sizeOf(Atom.Extra));
1207 return self.addAtomAssumeCapacity(args);
1208}
1209
1210fn addAtomAssumeCapacity(self: *Object, args: AddAtomArgs) Atom.Index {
1211 const atom_index: Atom.Index = @intCast(self.atoms.items.len);
1212 const atom_ptr = self.atoms.addOneAssumeCapacity();
1213 atom_ptr.* = .{
1214 .atom_index = atom_index,
1215 .name_offset = args.name,
1216 .file_index = self.index,
1217 .input_section_index = args.shndx,
1218 .extra_index = self.addAtomExtraAssumeCapacity(.{}),
1219 .size = args.size,
1220 .alignment = args.alignment,
1221 };
1222 return atom_index;
1223}
1224
1225pub fn atom(self: *Object, atom_index: Atom.Index) ?*Atom {
1226 if (atom_index == 0) return null;
1227 assert(atom_index < self.atoms.items.len);
1228 return &self.atoms.items[atom_index];
1229}
1230
1231pub fn addAtomExtra(self: *Object, allocator: Allocator, extra: Atom.Extra) !u32 {
1232 const fields = @typeInfo(Atom.Extra).Struct.fields;
1233 try self.atoms_extra.ensureUnusedCapacity(allocator, fields.len);
1234 return self.addAtomExtraAssumeCapacity(extra);
1235}
1236
1237pub fn addAtomExtraAssumeCapacity(self: *Object, extra: Atom.Extra) u32 {
1238 const index = @as(u32, @intCast(self.atoms_extra.items.len));
1239 const fields = @typeInfo(Atom.Extra).Struct.fields;
1240 inline for (fields) |field| {
1241 self.atoms_extra.appendAssumeCapacity(switch (field.type) {
1242 u32 => @field(extra, field.name),
1243 else => @compileError("bad field type"),
1244 });
1245 }
1246 return index;
1247}
1248
1249pub fn atomExtra(self: *Object, index: u32) Atom.Extra {
1250 const fields = @typeInfo(Atom.Extra).Struct.fields;
1251 var i: usize = index;
1252 var result: Atom.Extra = undefined;
1253 inline for (fields) |field| {
1254 @field(result, field.name) = switch (field.type) {
1255 u32 => self.atoms_extra.items[i],
1256 else => @compileError("bad field type"),
1257 };
1258 i += 1;
1259 }
1260 return result;
1261}
1262
1263pub fn setAtomExtra(self: *Object, index: u32, extra: Atom.Extra) void {
1264 const fields = @typeInfo(Atom.Extra).Struct.fields;
1265 inline for (fields, 0..) |field, i| {
1266 self.atoms_extra.items[index + i] = switch (field.type) {
1267 u32 => @field(extra, field.name),
1268 else => @compileError("bad field type"),
1269 };
1270 }
1271}
1272
1197fn addInputMergeSection(self: *Object, allocator: Allocator) !InputMergeSection.Index {1273fn addInputMergeSection(self: *Object, allocator: Allocator) !InputMergeSection.Index {
1198 const index: InputMergeSection.Index = @intCast(self.input_merge_sections.items.len);1274 const index: InputMergeSection.Index = @intCast(self.input_merge_sections.items.len);
1199 const msec = try self.input_merge_sections.addOne(allocator);1275 const msec = try self.input_merge_sections.addOne(allocator);
...@@ -1280,9 +1356,9 @@ fn formatAtoms(...@@ -1280,9 +1356,9 @@ fn formatAtoms(
1280 _ = options;1356 _ = options;
1281 const object = ctx.object;1357 const object = ctx.object;
1282 try writer.writeAll(" atoms\n");1358 try writer.writeAll(" atoms\n");
1283 for (object.atoms.items) |atom_index| {1359 for (object.atoms_indexes.items) |atom_index| {
1284 const atom = ctx.elf_file.atom(atom_index) orelse continue;1360 const atom_ptr = object.atom(atom_index) orelse continue;
1285 try writer.print(" {}\n", .{atom.fmt(ctx.elf_file)});1361 try writer.print(" {}\n", .{atom_ptr.fmt(ctx.elf_file)});
1286 }1362 }
1287}1363}
12881364
...@@ -1354,9 +1430,9 @@ fn formatComdatGroups(...@@ -1354,9 +1430,9 @@ fn formatComdatGroups(
1354 try writer.print(" COMDAT({d})\n", .{cg_index});1430 try writer.print(" COMDAT({d})\n", .{cg_index});
1355 const cg_members = cg.comdatGroupMembers(elf_file);1431 const cg_members = cg.comdatGroupMembers(elf_file);
1356 for (cg_members) |shndx| {1432 for (cg_members) |shndx| {
1357 const atom_index = object.atoms.items[shndx];1433 const atom_index = object.atoms_indexes.items[shndx];
1358 const atom = elf_file.atom(atom_index) orelse continue;1434 const atom_ptr = object.atom(atom_index) orelse continue;
1359 try writer.print(" atom({d}) : {s}\n", .{ atom_index, atom.name(elf_file) });1435 try writer.print(" atom({d}) : {s}\n", .{ atom_index, atom_ptr.name(elf_file) });
1360 }1436 }
1361 }1437 }
1362}1438}
src/link/Elf/SharedObject.zig+1-1
...@@ -232,7 +232,7 @@ pub fn resolveSymbols(self: *SharedObject, elf_file: *Elf) void {...@@ -232,7 +232,7 @@ pub fn resolveSymbols(self: *SharedObject, elf_file: *Elf) void {
232 const global = elf_file.symbol(index);232 const global = elf_file.symbol(index);
233 if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) {233 if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) {
234 global.value = @intCast(this_sym.st_value);234 global.value = @intCast(this_sym.st_value);
235 global.atom_index = 0;235 global.atom_ref = .{ .index = 0, .file = 0 };
236 global.esym_index = esym_index;236 global.esym_index = esym_index;
237 global.version_index = self.versyms.items[esym_index];237 global.version_index = self.versyms.items[esym_index];
238 global.file_index = self.index;238 global.file_index = self.index;
src/link/Elf/Symbol.zig+4-4
...@@ -9,10 +9,9 @@ name_offset: u32 = 0,...@@ -9,10 +9,9 @@ name_offset: u32 = 0,
9/// Index of file where this symbol is defined.9/// Index of file where this symbol is defined.
10file_index: File.Index = 0,10file_index: File.Index = 0,
1111
12/// Index of atom containing this symbol.12/// Reference to Atom containing this symbol if any.
13/// Index of 0 means there is no associated atom with this symbol.
14/// Use `atom` to get the pointer to the atom.13/// Use `atom` to get the pointer to the atom.
15atom_index: Atom.Index = 0,14atom_ref: Elf.Ref = .{ .index = 0, .file = 0 },
1615
17/// Assigned output section index for this symbol.16/// Assigned output section index for this symbol.
18output_section_index: u32 = 0,17output_section_index: u32 = 0,
...@@ -68,7 +67,8 @@ pub fn name(symbol: Symbol, elf_file: *Elf) [:0]const u8 {...@@ -68,7 +67,8 @@ pub fn name(symbol: Symbol, elf_file: *Elf) [:0]const u8 {
68}67}
6968
70pub fn atom(symbol: Symbol, elf_file: *Elf) ?*Atom {69pub fn atom(symbol: Symbol, elf_file: *Elf) ?*Atom {
71 return elf_file.atom(symbol.atom_index);70 const file_ptr = elf_file.file(symbol.atom_ref.file) orelse return null;
71 return file_ptr.atom(symbol.atom_ref.index);
72}72}
7373
74pub fn mergeSubsection(symbol: Symbol, elf_file: *Elf) ?*MergeSubsection {74pub fn mergeSubsection(symbol: Symbol, elf_file: *Elf) ?*MergeSubsection {
src/link/Elf/ZigObject.zig+124-61
...@@ -15,7 +15,9 @@ local_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},...@@ -15,7 +15,9 @@ local_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
15global_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},15global_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
16globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},16globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},
1717
18atoms: std.ArrayListUnmanaged(Atom.Index) = .{},18atoms: std.ArrayListUnmanaged(Atom) = .{},
19atoms_indexes: std.ArrayListUnmanaged(Atom.Index) = .{},
20atoms_extra: std.ArrayListUnmanaged(u32) = .{},
19relocs: std.ArrayListUnmanaged(std.ArrayListUnmanaged(elf.Elf64_Rela)) = .{},21relocs: std.ArrayListUnmanaged(std.ArrayListUnmanaged(elf.Elf64_Rela)) = .{},
2022
21num_dynrelocs: u32 = 0,23num_dynrelocs: u32 = 0,
...@@ -80,7 +82,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {...@@ -80,7 +82,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {
80 const comp = elf_file.base.comp;82 const comp = elf_file.base.comp;
81 const gpa = comp.gpa;83 const gpa = comp.gpa;
8284
83 try self.atoms.append(gpa, 0); // null input section85 try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) }); // null input section
84 try self.relocs.append(gpa, .{}); // null relocs section86 try self.relocs.append(gpa, .{}); // null relocs section
85 try self.strtab.buffer.append(gpa, 0);87 try self.strtab.buffer.append(gpa, 0);
8688
...@@ -117,6 +119,8 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {...@@ -117,6 +119,8 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
117 self.global_symbols.deinit(allocator);119 self.global_symbols.deinit(allocator);
118 self.globals_lookup.deinit(allocator);120 self.globals_lookup.deinit(allocator);
119 self.atoms.deinit(allocator);121 self.atoms.deinit(allocator);
122 self.atoms_indexes.deinit(allocator);
123 self.atoms_extra.deinit(allocator);
120 for (self.relocs.items) |*list| {124 for (self.relocs.items) |*list| {
121 list.deinit(allocator);125 list.deinit(allocator);
122 }126 }
...@@ -276,24 +280,20 @@ pub fn addGlobalEsym(self: *ZigObject, allocator: Allocator) !Symbol.Index {...@@ -276,24 +280,20 @@ pub fn addGlobalEsym(self: *ZigObject, allocator: Allocator) !Symbol.Index {
276 return index | global_symbol_bit;280 return index | global_symbol_bit;
277}281}
278282
279pub fn addAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index {283pub fn newAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index {
280 const gpa = elf_file.base.comp.gpa;284 const gpa = elf_file.base.comp.gpa;
281 const atom_index = try elf_file.addAtom();285 const atom_index = try self.addAtom(gpa);
282 const symbol_index = try elf_file.addSymbol();286 const symbol_index = try elf_file.addSymbol();
283 const esym_index = try self.addLocalEsym(gpa);287 const esym_index = try self.addLocalEsym(gpa);
284288
285 const shndx = @as(u32, @intCast(self.atoms.items.len));289 try self.atoms_indexes.append(gpa, atom_index);
286 try self.atoms.append(gpa, atom_index);
287 try self.local_symbols.append(gpa, symbol_index);290 try self.local_symbols.append(gpa, symbol_index);
288291
289 const atom_ptr = elf_file.atom(atom_index).?;
290 atom_ptr.file_index = self.index;
291
292 const symbol_ptr = elf_file.symbol(symbol_index);292 const symbol_ptr = elf_file.symbol(symbol_index);
293 symbol_ptr.file_index = self.index;293 symbol_ptr.file_index = self.index;
294 symbol_ptr.atom_index = atom_index;294 symbol_ptr.atom_ref = .{ .index = atom_index, .file = self.index };
295295
296 self.local_esyms.items(.shndx)[esym_index] = shndx;296 self.local_esyms.items(.shndx)[esym_index] = atom_index;
297 self.local_esyms.items(.elf_sym)[esym_index].st_shndx = SHN_ATOM;297 self.local_esyms.items(.elf_sym)[esym_index].st_shndx = SHN_ATOM;
298 symbol_ptr.esym_index = esym_index;298 symbol_ptr.esym_index = esym_index;
299299
...@@ -301,21 +301,22 @@ pub fn addAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index {...@@ -301,21 +301,22 @@ pub fn addAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index {
301 const relocs_index = @as(u32, @intCast(self.relocs.items.len));301 const relocs_index = @as(u32, @intCast(self.relocs.items.len));
302 const relocs = try self.relocs.addOne(gpa);302 const relocs = try self.relocs.addOne(gpa);
303 relocs.* = .{};303 relocs.* = .{};
304
305 const atom_ptr = self.atom(atom_index).?;
304 atom_ptr.relocs_section_index = relocs_index;306 atom_ptr.relocs_section_index = relocs_index;
305307
306 return symbol_index;308 return symbol_index;
307}309}
308310
309/// TODO actually create fake input shdrs and return that instead.311/// TODO actually create fake input shdrs and return that instead.
310pub fn inputShdr(self: ZigObject, atom_index: Atom.Index, elf_file: *Elf) elf.Elf64_Shdr {312pub fn inputShdr(self: *ZigObject, atom_index: Atom.Index, elf_file: *Elf) elf.Elf64_Shdr {
311 _ = self;313 const atom_ptr = self.atom(atom_index) orelse return Elf.null_shdr;
312 const atom = elf_file.atom(atom_index) orelse return Elf.null_shdr;314 const shndx = atom_ptr.outputShndx() orelse return Elf.null_shdr;
313 const shndx = atom.outputShndx() orelse return Elf.null_shdr;
314 var shdr = elf_file.shdrs.items[shndx];315 var shdr = elf_file.shdrs.items[shndx];
315 shdr.sh_addr = 0;316 shdr.sh_addr = 0;
316 shdr.sh_offset = 0;317 shdr.sh_offset = 0;
317 shdr.sh_size = atom.size;318 shdr.sh_size = atom_ptr.size;
318 shdr.sh_addralign = atom.alignment.toByteUnits() orelse 1;319 shdr.sh_addralign = atom_ptr.alignment.toByteUnits() orelse 1;
319 return shdr;320 return shdr;
320}321}
321322
...@@ -329,24 +330,23 @@ pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) void {...@@ -329,24 +330,23 @@ pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) void {
329330
330 if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) {331 if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) {
331 assert(esym.st_shndx == SHN_ATOM);332 assert(esym.st_shndx == SHN_ATOM);
332 const atom_index = self.atoms.items[shndx];333 const atom_ptr = self.atom(shndx) orelse continue;
333 const atom = elf_file.atom(atom_index) orelse continue;334 if (!atom_ptr.flags.alive) continue;
334 if (!atom.flags.alive) continue;
335 }335 }
336336
337 const global = elf_file.symbol(index);337 const global = elf_file.symbol(index);
338 if (self.asFile().symbolRank(esym, false) < global.symbolRank(elf_file)) {338 if (self.asFile().symbolRank(esym, false) < global.symbolRank(elf_file)) {
339 const atom_index = switch (esym.st_shndx) {339 const atom_index = switch (esym.st_shndx) {
340 elf.SHN_ABS, elf.SHN_COMMON => 0,340 elf.SHN_ABS, elf.SHN_COMMON => 0,
341 SHN_ATOM => self.atoms.items[shndx],341 SHN_ATOM => shndx,
342 else => unreachable,342 else => unreachable,
343 };343 };
344 const output_section_index = if (elf_file.atom(atom_index)) |atom|344 const output_section_index = if (self.atom(atom_index)) |atom_ptr|
345 atom.outputShndx().?345 atom_ptr.outputShndx().?
346 else346 else
347 elf.SHN_UNDEF;347 elf.SHN_UNDEF;
348 global.value = @intCast(esym.st_value);348 global.value = @intCast(esym.st_value);
349 global.atom_index = atom_index;349 global.atom_ref = .{ .index = atom_index, .file = self.index };
350 global.esym_index = esym_index;350 global.esym_index = esym_index;
351 global.file_index = self.index;351 global.file_index = self.index;
352 global.output_section_index = output_section_index;352 global.output_section_index = output_section_index;
...@@ -376,7 +376,7 @@ pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void {...@@ -376,7 +376,7 @@ pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void {
376 };376 };
377377
378 global.value = 0;378 global.value = 0;
379 global.atom_index = 0;379 global.atom_ref = .{ .index = 0, .file = 0 };
380 global.esym_index = esym_index;380 global.esym_index = esym_index;
381 global.file_index = self.index;381 global.file_index = self.index;
382 global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;382 global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;
...@@ -397,7 +397,7 @@ pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void {...@@ -397,7 +397,7 @@ pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void {
397 }397 }
398398
399 global.value = 0;399 global.value = 0;
400 global.atom_index = 0;400 global.atom_ref = .{ .index = 0, .file = 0 };
401 global.esym_index = esym_index;401 global.esym_index = esym_index;
402 global.file_index = self.index;402 global.file_index = self.index;
403 }403 }
...@@ -405,19 +405,19 @@ pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void {...@@ -405,19 +405,19 @@ pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void {
405405
406pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void {406pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void {
407 const gpa = elf_file.base.comp.gpa;407 const gpa = elf_file.base.comp.gpa;
408 for (self.atoms.items) |atom_index| {408 for (self.atoms_indexes.items) |atom_index| {
409 const atom = elf_file.atom(atom_index) orelse continue;409 const atom_ptr = self.atom(atom_index) orelse continue;
410 if (!atom.flags.alive) continue;410 if (!atom_ptr.flags.alive) continue;
411 const shdr = atom.inputShdr(elf_file);411 const shdr = atom_ptr.inputShdr(elf_file);
412 if (shdr.sh_type == elf.SHT_NOBITS) continue;412 if (shdr.sh_type == elf.SHT_NOBITS) continue;
413 if (atom.scanRelocsRequiresCode(elf_file)) {413 if (atom_ptr.scanRelocsRequiresCode(elf_file)) {
414 // TODO ideally we don't have to fetch the code here.414 // TODO ideally we don't have to fetch the code here.
415 // Perhaps it would make sense to save the code until flushModule where we415 // Perhaps it would make sense to save the code until flushModule where we
416 // would free all of generated code?416 // would free all of generated code?
417 const code = try self.codeAlloc(elf_file, atom_index);417 const code = try self.codeAlloc(elf_file, atom_index);
418 defer gpa.free(code);418 defer gpa.free(code);
419 try atom.scanRelocs(elf_file, code, undefs);419 try atom_ptr.scanRelocs(elf_file, code, undefs);
420 } else try atom.scanRelocs(elf_file, null, undefs);420 } else try atom_ptr.scanRelocs(elf_file, null, undefs);
421 }421 }
422}422}
423423
...@@ -450,9 +450,8 @@ pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{O...@@ -450,9 +450,8 @@ pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{O
450 esym.st_shndx == elf.SHN_COMMON) continue;450 esym.st_shndx == elf.SHN_COMMON) continue;
451451
452 if (esym.st_shndx == SHN_ATOM) {452 if (esym.st_shndx == SHN_ATOM) {
453 const atom_index = self.atoms.items[shndx];453 const atom_ptr = self.atom(shndx) orelse continue;
454 const atom = elf_file.atom(atom_index) orelse continue;454 if (!atom_ptr.flags.alive) continue;
455 if (!atom.flags.alive) continue;
456 }455 }
457456
458 const gop = try dupes.getOrPut(index);457 const gop = try dupes.getOrPut(index);
...@@ -517,20 +516,20 @@ pub fn writeAr(self: ZigObject, writer: anytype) !void {...@@ -517,20 +516,20 @@ pub fn writeAr(self: ZigObject, writer: anytype) !void {
517 try writer.writeAll(self.data.items);516 try writer.writeAll(self.data.items);
518}517}
519518
520pub fn addAtomsToRelaSections(self: ZigObject, elf_file: *Elf) !void {519pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void {
521 for (self.atoms.items) |atom_index| {520 for (self.atoms_indexes.items) |atom_index| {
522 const atom = elf_file.atom(atom_index) orelse continue;521 const atom_ptr = self.atom(atom_index) orelse continue;
523 if (!atom.flags.alive) continue;522 if (!atom_ptr.flags.alive) continue;
524 const rela_shndx = atom.relocsShndx() orelse continue;523 const rela_shndx = atom_ptr.relocsShndx() orelse continue;
525 // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level524 // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level
526 if (self.relocs.items[rela_shndx].items.len == 0) continue;525 if (self.relocs.items[rela_shndx].items.len == 0) continue;
527 const out_shndx = atom.outputShndx().?;526 const out_shndx = atom_ptr.outputShndx().?;
528 const out_shdr = elf_file.shdrs.items[out_shndx];527 const out_shdr = elf_file.shdrs.items[out_shndx];
529 if (out_shdr.sh_type == elf.SHT_NOBITS) continue;528 if (out_shdr.sh_type == elf.SHT_NOBITS) continue;
530529
531 const gpa = elf_file.base.comp.gpa;530 const gpa = elf_file.base.comp.gpa;
532 const sec = elf_file.output_rela_sections.getPtr(out_shndx).?;531 const sec = elf_file.output_rela_sections.getPtr(out_shndx).?;
533 try sec.atom_list.append(gpa, atom_index);532 try sec.atom_list.append(gpa, .{ .index = atom_index, .file = self.index });
534 }533 }
535}534}
536535
...@@ -561,7 +560,7 @@ pub fn globals(self: ZigObject) []const Symbol.Index {...@@ -561,7 +560,7 @@ pub fn globals(self: ZigObject) []const Symbol.Index {
561pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void {560pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void {
562 for (self.locals()) |local_index| {561 for (self.locals()) |local_index| {
563 const local = elf_file.symbol(local_index);562 const local = elf_file.symbol(local_index);
564 if (local.atom(elf_file)) |atom| if (!atom.flags.alive) continue;563 if (local.atom(elf_file)) |atom_ptr| if (!atom_ptr.flags.alive) continue;
565 const esym = local.elfSym(elf_file);564 const esym = local.elfSym(elf_file);
566 switch (esym.st_type()) {565 switch (esym.st_type()) {
567 elf.STT_SECTION, elf.STT_NOTYPE => continue,566 elf.STT_SECTION, elf.STT_NOTYPE => continue,
...@@ -577,7 +576,7 @@ pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void {...@@ -577,7 +576,7 @@ pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void {
577 const global = elf_file.symbol(global_index);576 const global = elf_file.symbol(global_index);
578 const file_ptr = global.file(elf_file) orelse continue;577 const file_ptr = global.file(elf_file) orelse continue;
579 if (file_ptr.index() != self.index) continue;578 if (file_ptr.index() != self.index) continue;
580 if (global.atom(elf_file)) |atom| if (!atom.flags.alive) continue;579 if (global.atom(elf_file)) |atom_ptr| if (!atom_ptr.flags.alive) continue;
581 global.flags.output_symtab = true;580 global.flags.output_symtab = true;
582 if (global.isLocal(elf_file)) {581 if (global.isLocal(elf_file)) {
583 try global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file);582 try global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file);
...@@ -621,11 +620,10 @@ pub fn asFile(self: *ZigObject) File {...@@ -621,11 +620,10 @@ pub fn asFile(self: *ZigObject) File {
621620
622/// Returns atom's code.621/// Returns atom's code.
623/// Caller owns the memory.622/// Caller owns the memory.
624pub fn codeAlloc(self: ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 {623pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 {
625 const gpa = elf_file.base.comp.gpa;624 const gpa = elf_file.base.comp.gpa;
626 const atom = elf_file.atom(atom_index).?;625 const atom_ptr = self.atom(atom_index).?;
627 assert(atom.file_index == self.index);626 const shdr = &elf_file.shdrs.items[atom_ptr.outputShndx().?];
628 const shdr = &elf_file.shdrs.items[atom.outputShndx().?];
629627
630 if (shdr.sh_flags & elf.SHF_TLS != 0) {628 if (shdr.sh_flags & elf.SHF_TLS != 0) {
631 const tlv = self.tls_variables.get(atom_index).?;629 const tlv = self.tls_variables.get(atom_index).?;
...@@ -633,13 +631,13 @@ pub fn codeAlloc(self: ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8...@@ -633,13 +631,13 @@ pub fn codeAlloc(self: ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8
633 return code;631 return code;
634 }632 }
635633
636 const file_offset = shdr.sh_offset + @as(u64, @intCast(atom.value));634 const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value));
637 const size = std.math.cast(usize, atom.size) orelse return error.Overflow;635 const size = std.math.cast(usize, atom_ptr.size) orelse return error.Overflow;
638 const code = try gpa.alloc(u8, size);636 const code = try gpa.alloc(u8, size);
639 errdefer gpa.free(code);637 errdefer gpa.free(code);
640 const amt = try elf_file.base.file.?.preadAll(code, file_offset);638 const amt = try elf_file.base.file.?.preadAll(code, file_offset);
641 if (amt != code.len) {639 if (amt != code.len) {
642 log.err("fetching code for {s} failed", .{atom.name(elf_file)});640 log.err("fetching code for {s} failed", .{atom_ptr.name(elf_file)});
643 return error.InputOutput;641 return error.InputOutput;
644 }642 }
645 return code;643 return code;
...@@ -760,7 +758,7 @@ pub fn getOrCreateMetadataForLazySymbol(...@@ -760,7 +758,7 @@ pub fn getOrCreateMetadataForLazySymbol(
760 };758 };
761 switch (metadata.state.*) {759 switch (metadata.state.*) {
762 .unused => {760 .unused => {
763 const symbol_index = try self.addAtom(elf_file);761 const symbol_index = try self.newAtom(elf_file);
764 const sym = elf_file.symbol(symbol_index);762 const sym = elf_file.symbol(symbol_index);
765 sym.flags.needs_zig_got = true;763 sym.flags.needs_zig_got = true;
766 metadata.symbol_index.* = symbol_index;764 metadata.symbol_index.* = symbol_index;
...@@ -824,7 +822,7 @@ pub fn getOrCreateMetadataForDecl(...@@ -824,7 +822,7 @@ pub fn getOrCreateMetadataForDecl(
824 const gop = try self.decls.getOrPut(gpa, decl_index);822 const gop = try self.decls.getOrPut(gpa, decl_index);
825 if (!gop.found_existing) {823 if (!gop.found_existing) {
826 const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded;824 const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded;
827 const symbol_index = try self.addAtom(elf_file);825 const symbol_index = try self.newAtom(elf_file);
828 const mod = elf_file.base.comp.module.?;826 const mod = elf_file.base.comp.module.?;
829 const decl = mod.declPtr(decl_index);827 const decl = mod.declPtr(decl_index);
830 const sym = elf_file.symbol(symbol_index);828 const sym = elf_file.symbol(symbol_index);
...@@ -1048,7 +1046,7 @@ fn updateTlv(...@@ -1048,7 +1046,7 @@ fn updateTlv(
1048 {1046 {
1049 const gop = try elf_file.output_sections.getOrPut(gpa, atom_ptr.output_section_index);1047 const gop = try elf_file.output_sections.getOrPut(gpa, atom_ptr.output_section_index);
1050 if (!gop.found_existing) gop.value_ptr.* = .{};1048 if (!gop.found_existing) gop.value_ptr.* = .{};
1051 try gop.value_ptr.append(gpa, atom_ptr.atom_index);1049 try gop.value_ptr.append(gpa, .{ .index = atom_ptr.atom_index, .file = self.index });
1052 }1050 }
1053}1051}
10541052
...@@ -1307,8 +1305,7 @@ pub fn lowerUnnamedConst(...@@ -1307,8 +1305,7 @@ pub fn lowerUnnamedConst(
1307 return error.CodegenFail;1305 return error.CodegenFail;
1308 },1306 },
1309 };1307 };
1310 const sym = elf_file.symbol(sym_index);1308 try unnamed_consts.append(gpa, sym_index);
1311 try unnamed_consts.append(gpa, sym.atom_index);
1312 return sym_index;1309 return sym_index;
1313}1310}
13141311
...@@ -1332,7 +1329,7 @@ fn lowerConst(...@@ -1332,7 +1329,7 @@ fn lowerConst(
1332 var code_buffer = std.ArrayList(u8).init(gpa);1329 var code_buffer = std.ArrayList(u8).init(gpa);
1333 defer code_buffer.deinit();1330 defer code_buffer.deinit();
13341331
1335 const sym_index = try self.addAtom(elf_file);1332 const sym_index = try self.newAtom(elf_file);
13361333
1337 const res = try codegen.generateSymbol(1334 const res = try codegen.generateSymbol(
1338 &elf_file.base,1335 &elf_file.base,
...@@ -1530,6 +1527,72 @@ pub fn getString(self: ZigObject, off: u32) [:0]const u8 {...@@ -1530,6 +1527,72 @@ pub fn getString(self: ZigObject, off: u32) [:0]const u8 {
1530 return self.strtab.getAssumeExists(off);1527 return self.strtab.getAssumeExists(off);
1531}1528}
15321529
1530fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index {
1531 try self.atoms.ensureUnusedCapacity(allocator, 1);
1532 try self.atoms_extra.ensureUnusedCapacity(allocator, @sizeOf(Atom.Extra));
1533 return self.addAtomAssumeCapacity();
1534}
1535
1536fn addAtomAssumeCapacity(self: *ZigObject) Atom.Index {
1537 const atom_index: Atom.Index = @intCast(self.atoms.items.len);
1538 const atom_ptr = self.atoms.addOneAssumeCapacity();
1539 atom_ptr.* = .{
1540 .file_index = self.index,
1541 .atom_index = atom_index,
1542 .extra_index = self.addAtomExtraAssumeCapacity(.{}),
1543 };
1544 return atom_index;
1545}
1546
1547pub fn atom(self: *ZigObject, atom_index: Atom.Index) ?*Atom {
1548 if (atom_index == 0) return null;
1549 assert(atom_index < self.atoms.items.len);
1550 return &self.atoms.items[atom_index];
1551}
1552
1553fn addAtomExtra(self: *ZigObject, allocator: Allocator, extra: Atom.Extra) !u32 {
1554 const fields = @typeInfo(Atom.Extra).Struct.fields;
1555 try self.atoms_extra.ensureUnusedCapacity(allocator, fields.len);
1556 return self.addAtomExtraAssumeCapacity(extra);
1557}
1558
1559fn addAtomExtraAssumeCapacity(self: *ZigObject, extra: Atom.Extra) u32 {
1560 const index = @as(u32, @intCast(self.atoms_extra.items.len));
1561 const fields = @typeInfo(Atom.Extra).Struct.fields;
1562 inline for (fields) |field| {
1563 self.atoms_extra.appendAssumeCapacity(switch (field.type) {
1564 u32 => @field(extra, field.name),
1565 else => @compileError("bad field type"),
1566 });
1567 }
1568 return index;
1569}
1570
1571pub fn atomExtra(self: ZigObject, index: u32) Atom.Extra {
1572 const fields = @typeInfo(Atom.Extra).Struct.fields;
1573 var i: usize = index;
1574 var result: Atom.Extra = undefined;
1575 inline for (fields) |field| {
1576 @field(result, field.name) = switch (field.type) {
1577 u32 => self.atoms_extra.items[i],
1578 else => @compileError("bad field type"),
1579 };
1580 i += 1;
1581 }
1582 return result;
1583}
1584
1585pub fn setAtomExtra(self: *ZigObject, index: u32, extra: Atom.Extra) void {
1586 assert(index > 0);
1587 const fields = @typeInfo(Atom.Extra).Struct.fields;
1588 inline for (fields, 0..) |field, i| {
1589 self.atoms_extra.items[index + i] = switch (field.type) {
1590 u32 => @field(extra, field.name),
1591 else => @compileError("bad field type"),
1592 };
1593 }
1594}
1595
1533pub fn fmtSymtab(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(formatSymtab) {1596pub fn fmtSymtab(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(formatSymtab) {
1534 return .{ .data = .{1597 return .{ .data = .{
1535 .self = self,1598 .self = self,
...@@ -1578,9 +1641,9 @@ fn formatAtoms(...@@ -1578,9 +1641,9 @@ fn formatAtoms(
1578 _ = unused_fmt_string;1641 _ = unused_fmt_string;
1579 _ = options;1642 _ = options;
1580 try writer.writeAll(" atoms\n");1643 try writer.writeAll(" atoms\n");
1581 for (ctx.self.atoms.items) |atom_index| {1644 for (ctx.self.atoms_indexes.items) |atom_index| {
1582 const atom = ctx.elf_file.atom(atom_index) orelse continue;1645 const atom_ptr = ctx.self.atom(atom_index) orelse continue;
1583 try writer.print(" {}\n", .{atom.fmt(ctx.elf_file)});1646 try writer.print(" {}\n", .{atom_ptr.fmt(ctx.elf_file)});
1584 }1647 }
1585}1648}
15861649
src/link/Elf/eh_frame.zig+2-2
...@@ -42,8 +42,8 @@ pub const Fde = struct {...@@ -42,8 +42,8 @@ pub const Fde = struct {
42 const object = elf_file.file(fde.file_index).?.object;42 const object = elf_file.file(fde.file_index).?.object;
43 const rel = fde.relocs(elf_file)[0];43 const rel = fde.relocs(elf_file)[0];
44 const sym = object.symtab.items[rel.r_sym()];44 const sym = object.symtab.items[rel.r_sym()];
45 const atom_index = object.atoms.items[sym.st_shndx];45 const atom_index = object.atoms_indexes.items[sym.st_shndx];
46 return elf_file.atom(atom_index).?;46 return object.atom(atom_index).?;
47 }47 }
4848
49 pub fn relocs(fde: Fde, elf_file: *Elf) []align(1) const elf.Elf64_Rela {49 pub fn relocs(fde: Fde, elf_file: *Elf) []align(1) const elf.Elf64_Rela {
src/link/Elf/file.zig+26-3
...@@ -98,11 +98,34 @@ pub const File = union(enum) {...@@ -98,11 +98,34 @@ pub const File = union(enum) {
98 }98 }
99 }99 }
100100
101 pub fn atom(file: File, atom_index: Atom.Index) ?*Atom {
102 return switch (file) {
103 .shared_object => unreachable,
104 .linker_defined => null,
105 inline else => |x| x.atom(atom_index),
106 };
107 }
108
101 pub fn atoms(file: File) []const Atom.Index {109 pub fn atoms(file: File) []const Atom.Index {
102 return switch (file) {110 return switch (file) {
103 .linker_defined, .shared_object => &[0]Atom.Index{},111 .shared_object => unreachable,
104 .zig_object => |x| x.atoms.items,112 .linker_defined => &[0]Atom.Index{},
105 .object => |x| x.atoms.items,113 .zig_object => |x| x.atoms_indexes.items,
114 .object => |x| x.atoms_indexes.items,
115 };
116 }
117
118 pub fn atomExtra(file: File, extra_index: u32) Atom.Extra {
119 return switch (file) {
120 .shared_object, .linker_defined => unreachable,
121 inline else => |x| x.atomExtra(extra_index),
122 };
123 }
124
125 pub fn setAtomExtra(file: File, extra_index: u32, extra: Atom.Extra) void {
126 return switch (file) {
127 .shared_object, .linker_defined => unreachable,
128 inline else => |x| x.setAtomExtra(extra_index, extra),
106 };129 };
107 }130 }
108131
src/link/Elf/gc.zig+7-5
...@@ -35,7 +35,7 @@ fn collectRoots(roots: *std.ArrayList(*Atom), files: []const File.Index, elf_fil...@@ -35,7 +35,7 @@ fn collectRoots(roots: *std.ArrayList(*Atom), files: []const File.Index, elf_fil
35 const file = elf_file.file(index).?;35 const file = elf_file.file(index).?;
3636
37 for (file.atoms()) |atom_index| {37 for (file.atoms()) |atom_index| {
38 const atom = elf_file.atom(atom_index) orelse continue;38 const atom = file.atom(atom_index) orelse continue;
39 if (!atom.flags.alive) continue;39 if (!atom.flags.alive) continue;
4040
41 const shdr = atom.inputShdr(elf_file);41 const shdr = atom.inputShdr(elf_file);
...@@ -120,8 +120,9 @@ fn mark(roots: std.ArrayList(*Atom), elf_file: *Elf) void {...@@ -120,8 +120,9 @@ fn mark(roots: std.ArrayList(*Atom), elf_file: *Elf) void {
120120
121fn prune(files: []const File.Index, elf_file: *Elf) void {121fn prune(files: []const File.Index, elf_file: *Elf) void {
122 for (files) |index| {122 for (files) |index| {
123 for (elf_file.file(index).?.atoms()) |atom_index| {123 const file = elf_file.file(index).?;
124 const atom = elf_file.atom(atom_index) orelse continue;124 for (file.atoms()) |atom_index| {
125 const atom = file.atom(atom_index) orelse continue;
125 if (atom.flags.alive and !atom.flags.visited) {126 if (atom.flags.alive and !atom.flags.visited) {
126 atom.flags.alive = false;127 atom.flags.alive = false;
127 atom.markFdesDead(elf_file);128 atom.markFdesDead(elf_file);
...@@ -133,8 +134,9 @@ fn prune(files: []const File.Index, elf_file: *Elf) void {...@@ -133,8 +134,9 @@ fn prune(files: []const File.Index, elf_file: *Elf) void {
133pub fn dumpPrunedAtoms(elf_file: *Elf) !void {134pub fn dumpPrunedAtoms(elf_file: *Elf) !void {
134 const stderr = std.io.getStdErr().writer();135 const stderr = std.io.getStdErr().writer();
135 for (elf_file.objects.items) |index| {136 for (elf_file.objects.items) |index| {
136 for (elf_file.file(index).?.object.atoms.items) |atom_index| {137 const file = elf_file.file(index).?;
137 const atom = elf_file.atom(atom_index) orelse continue;138 for (file.atoms()) |atom_index| {
139 const atom = file.atom(atom_index) orelse continue;
138 if (!atom.flags.alive)140 if (!atom.flags.alive)
139 // TODO should we simply print to stderr?141 // TODO should we simply print to stderr?
140 try stderr.print("link: removing unused section '{s}' in file '{}'\n", .{142 try stderr.print("link: removing unused section '{s}' in file '{}'\n", .{
src/link/Elf/relocatable.zig+12-12
...@@ -341,8 +341,8 @@ fn initComdatGroups(elf_file: *Elf) !void {...@@ -341,8 +341,8 @@ fn initComdatGroups(elf_file: *Elf) !void {
341fn updateSectionSizes(elf_file: *Elf) !void {341fn updateSectionSizes(elf_file: *Elf) !void {
342 for (elf_file.output_sections.keys(), elf_file.output_sections.values()) |shndx, atom_list| {342 for (elf_file.output_sections.keys(), elf_file.output_sections.values()) |shndx, atom_list| {
343 const shdr = &elf_file.shdrs.items[shndx];343 const shdr = &elf_file.shdrs.items[shndx];
344 for (atom_list.items) |atom_index| {344 for (atom_list.items) |ref| {
345 const atom_ptr = elf_file.atom(atom_index) orelse continue;345 const atom_ptr = elf_file.atom(ref) orelse continue;
346 if (!atom_ptr.flags.alive) continue;346 if (!atom_ptr.flags.alive) continue;
347 const offset = atom_ptr.alignment.forward(shdr.sh_size);347 const offset = atom_ptr.alignment.forward(shdr.sh_size);
348 const padding = offset - shdr.sh_size;348 const padding = offset - shdr.sh_size;
...@@ -354,8 +354,8 @@ fn updateSectionSizes(elf_file: *Elf) !void {...@@ -354,8 +354,8 @@ fn updateSectionSizes(elf_file: *Elf) !void {
354354
355 for (elf_file.output_rela_sections.values()) |sec| {355 for (elf_file.output_rela_sections.values()) |sec| {
356 const shdr = &elf_file.shdrs.items[sec.shndx];356 const shdr = &elf_file.shdrs.items[sec.shndx];
357 for (sec.atom_list.items) |atom_index| {357 for (sec.atom_list.items) |ref| {
358 const atom_ptr = elf_file.atom(atom_index) orelse continue;358 const atom_ptr = elf_file.atom(ref) orelse continue;
359 if (!atom_ptr.flags.alive) continue;359 if (!atom_ptr.flags.alive) continue;
360 const relocs = atom_ptr.relocs(elf_file);360 const relocs = atom_ptr.relocs(elf_file);
361 shdr.sh_size += shdr.sh_entsize * relocs.len;361 shdr.sh_size += shdr.sh_entsize * relocs.len;
...@@ -448,16 +448,16 @@ fn writeAtoms(elf_file: *Elf) !void {...@@ -448,16 +448,16 @@ fn writeAtoms(elf_file: *Elf) !void {
448 0;448 0;
449 @memset(buffer, padding_byte);449 @memset(buffer, padding_byte);
450450
451 for (atom_list.items) |atom_index| {451 for (atom_list.items) |ref| {
452 const atom_ptr = elf_file.atom(atom_index).?;452 const atom_ptr = elf_file.atom(ref).?;
453 assert(atom_ptr.flags.alive);453 assert(atom_ptr.flags.alive);
454454
455 const offset = math.cast(usize, atom_ptr.value - @as(i64, @intCast(shdr.sh_addr - base_offset))) orelse455 const offset = math.cast(usize, atom_ptr.value - @as(i64, @intCast(shdr.sh_addr - base_offset))) orelse
456 return error.Overflow;456 return error.Overflow;
457 const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;457 const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;
458458
459 log.debug("writing atom({d}) from 0x{x} to 0x{x}", .{459 log.debug("writing atom({}) from 0x{x} to 0x{x}", .{
460 atom_index,460 ref,
461 sh_offset + offset,461 sh_offset + offset,
462 sh_offset + offset + size,462 sh_offset + offset + size,
463 });463 });
...@@ -465,8 +465,8 @@ fn writeAtoms(elf_file: *Elf) !void {...@@ -465,8 +465,8 @@ fn writeAtoms(elf_file: *Elf) !void {
465 // TODO decompress directly into provided buffer465 // TODO decompress directly into provided buffer
466 const out_code = buffer[offset..][0..size];466 const out_code = buffer[offset..][0..size];
467 const in_code = switch (atom_ptr.file(elf_file).?) {467 const in_code = switch (atom_ptr.file(elf_file).?) {
468 .object => |x| try x.codeDecompressAlloc(elf_file, atom_index),468 .object => |x| try x.codeDecompressAlloc(elf_file, ref.index),
469 .zig_object => |x| try x.codeAlloc(elf_file, atom_index),469 .zig_object => |x| try x.codeAlloc(elf_file, ref.index),
470 else => unreachable,470 else => unreachable,
471 };471 };
472 defer gpa.free(in_code);472 defer gpa.free(in_code);
...@@ -490,8 +490,8 @@ fn writeSyntheticSections(elf_file: *Elf) !void {...@@ -490,8 +490,8 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
490 var relocs = try std.ArrayList(elf.Elf64_Rela).initCapacity(gpa, num_relocs);490 var relocs = try std.ArrayList(elf.Elf64_Rela).initCapacity(gpa, num_relocs);
491 defer relocs.deinit();491 defer relocs.deinit();
492492
493 for (sec.atom_list.items) |atom_index| {493 for (sec.atom_list.items) |ref| {
494 const atom_ptr = elf_file.atom(atom_index) orelse continue;494 const atom_ptr = elf_file.atom(ref) orelse continue;
495 if (!atom_ptr.flags.alive) continue;495 if (!atom_ptr.flags.alive) continue;
496 try atom_ptr.writeRelocs(elf_file, &relocs);496 try atom_ptr.writeRelocs(elf_file, &relocs);
497 }497 }
src/link/Elf/synthetic_sections.zig+4-4
...@@ -1705,14 +1705,14 @@ pub const ComdatGroupSection = struct {...@@ -1705,14 +1705,14 @@ pub const ComdatGroupSection = struct {
1705 const shdr = object.shdrs.items[shndx];1705 const shdr = object.shdrs.items[shndx];
1706 switch (shdr.sh_type) {1706 switch (shdr.sh_type) {
1707 elf.SHT_RELA => {1707 elf.SHT_RELA => {
1708 const atom_index = object.atoms.items[shdr.sh_info];1708 const atom_index = object.atoms_indexes.items[shdr.sh_info];
1709 const atom = elf_file.atom(atom_index).?;1709 const atom = object.atom(atom_index).?;
1710 const rela = elf_file.output_rela_sections.get(atom.outputShndx().?).?;1710 const rela = elf_file.output_rela_sections.get(atom.outputShndx().?).?;
1711 try writer.writeInt(u32, rela.shndx, .little);1711 try writer.writeInt(u32, rela.shndx, .little);
1712 },1712 },
1713 else => {1713 else => {
1714 const atom_index = object.atoms.items[shndx];1714 const atom_index = object.atoms_indexes.items[shndx];
1715 const atom = elf_file.atom(atom_index).?;1715 const atom = object.atom(atom_index).?;
1716 try writer.writeInt(u32, atom.outputShndx().?, .little);1716 try writer.writeInt(u32, atom.outputShndx().?, .little);
1717 },1717 },
1718 }1718 }
src/link/Elf/thunks.zig+7-8
...@@ -6,8 +6,8 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void {...@@ -6,8 +6,8 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void {
6 const atoms = elf_file.output_sections.get(shndx).?.items;6 const atoms = elf_file.output_sections.get(shndx).?.items;
7 assert(atoms.len > 0);7 assert(atoms.len > 0);
88
9 for (atoms) |atom_index| {9 for (atoms) |ref| {
10 elf_file.atom(atom_index).?.value = -1;10 elf_file.atom(ref).?.value = -1;
11 }11 }
1212
13 var i: usize = 0;13 var i: usize = 0;
...@@ -19,8 +19,7 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void {...@@ -19,8 +19,7 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void {
19 i += 1;19 i += 1;
2020
21 while (i < atoms.len) : (i += 1) {21 while (i < atoms.len) : (i += 1) {
22 const atom_index = atoms[i];22 const atom = elf_file.atom(atoms[i]).?;
23 const atom = elf_file.atom(atom_index).?;
24 assert(atom.flags.alive);23 assert(atom.flags.alive);
25 if (@as(i64, @intCast(atom.alignment.forward(shdr.sh_size))) - start_atom.value >= max_distance)24 if (@as(i64, @intCast(atom.alignment.forward(shdr.sh_size))) - start_atom.value >= max_distance)
26 break;25 break;
...@@ -33,10 +32,10 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void {...@@ -33,10 +32,10 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void {
33 thunk.output_section_index = shndx;32 thunk.output_section_index = shndx;
3433
35 // Scan relocs in the group and create trampolines for any unreachable callsite34 // Scan relocs in the group and create trampolines for any unreachable callsite
36 for (atoms[start..i]) |atom_index| {35 for (atoms[start..i]) |ref| {
37 const atom = elf_file.atom(atom_index).?;36 const atom = elf_file.atom(ref).?;
38 const file = atom.file(elf_file).?;37 const file = atom.file(elf_file).?;
39 log.debug("atom({d}) {s}", .{ atom_index, atom.name(elf_file) });38 log.debug("atom({}) {s}", .{ ref, atom.name(elf_file) });
40 for (atom.relocs(elf_file)) |rel| {39 for (atom.relocs(elf_file)) |rel| {
41 const is_reachable = switch (cpu_arch) {40 const is_reachable = switch (cpu_arch) {
42 .aarch64 => aarch64.isReachable(atom, rel, elf_file),41 .aarch64 => aarch64.isReachable(atom, rel, elf_file),
...@@ -51,7 +50,7 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void {...@@ -51,7 +50,7 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void {
51 };50 };
52 try thunk.symbols.put(gpa, target, {});51 try thunk.symbols.put(gpa, target, {});
53 }52 }
54 try atom.addExtra(.{ .thunk = thunk_index }, elf_file);53 atom.addExtra(.{ .thunk = thunk_index }, elf_file);
55 atom.flags.thunk = true;54 atom.flags.thunk = true;
56 }55 }
5756
src/link/MachO/InternalObject.zig+1-2
...@@ -45,8 +45,7 @@ pub fn deinit(self: *InternalObject, allocator: Allocator) void {...@@ -45,8 +45,7 @@ pub fn deinit(self: *InternalObject, allocator: Allocator) void {
4545
46pub fn init(self: *InternalObject, allocator: Allocator) !void {46pub fn init(self: *InternalObject, allocator: Allocator) !void {
47 // Atom at index 0 is reserved as null atom.47 // Atom at index 0 is reserved as null atom.
48 try self.atoms.append(allocator, .{});48 try self.atoms.append(allocator, .{ .extra = try self.addAtomExtra(allocator, .{}) });
49 try self.atoms_extra.append(allocator, 0);
50 // Null byte in strtab49 // Null byte in strtab
51 try self.strtab.append(allocator, 0);50 try self.strtab.append(allocator, 0);
52}51}
src/link/MachO/ZigObject.zig+1-1
...@@ -1634,7 +1634,7 @@ fn isThreadlocal(macho_file: *MachO, decl_index: InternPool.DeclIndex) bool {...@@ -1634,7 +1634,7 @@ fn isThreadlocal(macho_file: *MachO, decl_index: InternPool.DeclIndex) bool {
16341634
1635fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index {1635fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index {
1636 try self.atoms.ensureUnusedCapacity(allocator, 1);1636 try self.atoms.ensureUnusedCapacity(allocator, 1);
1637 try self.atoms_extra.ensureUnusedCapacity(allocator, 1);1637 try self.atoms_extra.ensureUnusedCapacity(allocator, @sizeOf(Atom.Extra));
1638 return self.addAtomAssumeCapacity();1638 return self.addAtomAssumeCapacity();
1639}1639}
16401640