authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-04-15 19:54:53+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-04-20 23:36:41+02:00
log700644d35dd674c7381c4794d566e0e64f45c174
treee2d985e943b977ac4d0d1f8a1e85cfa713e9cbb8
parentc7ffdbcd41f45d23328f1b40d90420ff29ed66af

link/elf: introduce Atom extras for out-of-band storage


3 files changed, 92 insertions(+), 8 deletions(-)

src/link/Elf.zig+50
......@@ -205,6 +205,7 @@ num_ifunc_dynrelocs: usize = 0,
205205
206206/// List of atoms that are owned directly by the linker.
207207atoms: std.ArrayListUnmanaged(Atom) = .{},
208atoms_extra: std.ArrayListUnmanaged(u32) = .{},
208209
209210/// List of range extension thunks.
210211thunks: std.ArrayListUnmanaged(Thunk) = .{},
......@@ -369,6 +370,7 @@ pub fn createEmpty(
369370 try self.symbols_extra.append(gpa, 0);
370371 // Allocate atom index 0 to null atom
371372 try self.atoms.append(gpa, .{});
373 try self.atoms_extra.append(gpa, 0);
372374 // Append null file at index 0
373375 try self.files.append(gpa, .null);
374376 // Append null byte to string tables
......@@ -491,6 +493,10 @@ pub fn deinit(self: *Elf) void {
491493 self.start_stop_indexes.deinit(gpa);
492494
493495 self.atoms.deinit(gpa);
496 self.atoms_extra.deinit(gpa);
497 for (self.thunks.items) |*th| {
498 th.deinit(gpa);
499 }
494500 self.thunks.deinit(gpa);
495501 for (self.last_atom_and_free_list_table.values()) |*value| {
496502 value.free_list.deinit(gpa);
......@@ -5458,6 +5464,50 @@ pub fn addAtom(self: *Elf) !Atom.Index {
54585464 return index;
54595465}
54605466
5467pub fn addAtomExtra(self: *Elf, extra: Atom.Extra) !u32 {
5468 const fields = @typeInfo(Atom.Extra).Struct.fields;
5469 try self.atoms_extra.ensureUnusedCapacity(self.base.comp.gpa, fields.len);
5470 return self.addAtomExtraAssumeCapacity(extra);
5471}
5472
5473pub fn addAtomExtraAssumeCapacity(self: *Elf, extra: Atom.Extra) u32 {
5474 const index = @as(u32, @intCast(self.atoms_extra.items.len));
5475 const fields = @typeInfo(Atom.Extra).Struct.fields;
5476 inline for (fields) |field| {
5477 self.atoms_extra.appendAssumeCapacity(switch (field.type) {
5478 u32 => @field(extra, field.name),
5479 else => @compileError("bad field type"),
5480 });
5481 }
5482 return index;
5483}
5484
5485pub fn atomExtra(self: *Elf, index: u32) ?Atom.Extra {
5486 if (index == 0) return null;
5487 const fields = @typeInfo(Atom.Extra).Struct.fields;
5488 var i: usize = index;
5489 var result: Atom.Extra = undefined;
5490 inline for (fields) |field| {
5491 @field(result, field.name) = switch (field.type) {
5492 u32 => self.atoms_extra.items[i],
5493 else => @compileError("bad field type"),
5494 };
5495 i += 1;
5496 }
5497 return result;
5498}
5499
5500pub fn setAtomExtra(self: *Elf, index: u32, extra: Atom.Extra) void {
5501 assert(index > 0);
5502 const fields = @typeInfo(Atom.Extra).Struct.fields;
5503 inline for (fields, 0..) |field, i| {
5504 self.atoms_extra.items[index + i] = switch (field.type) {
5505 u32 => @field(extra, field.name),
5506 else => @compileError("bad field type"),
5507 };
5508 }
5509}
5510
54615511pub fn addThunk(self: *Elf) !Thunk.Index {
54625512 const index = @as(Thunk.Index, @intCast(self.thunks.items.len));
54635513 const th = try self.thunks.addOne(self.base.comp.gpa);
src/link/Elf/Atom.zig+40-7
......@@ -31,12 +31,6 @@ rel_num: u32 = 0,
3131/// Index of this atom in the linker's atoms table.
3232atom_index: Index = 0,
3333
34/// Index of the thunk for this atom.
35thunk_index: Thunk.Index = 0,
36
37/// Flags we use for state tracking.
38flags: Flags = .{},
39
4034/// Start index of FDEs referencing this atom.
4135fde_start: u32 = 0,
4236
......@@ -48,6 +42,11 @@ fde_end: u32 = 0,
4842prev_index: Index = 0,
4943next_index: Index = 0,
5044
45/// Flags we use for state tracking.
46flags: Flags = .{},
47
48extra_index: u32 = 0,
49
5150pub const Alignment = @import("../../InternPool.zig").Alignment;
5251
5352pub fn name(self: Atom, elf_file: *Elf) []const u8 {
......@@ -68,7 +67,9 @@ pub fn file(self: Atom, elf_file: *Elf) ?File {
6867}
6968
7069pub fn thunk(self: Atom, elf_file: *Elf) *Thunk {
71 return elf_file.thunk(self.thunk_index);
70 assert(self.flags.thunk);
71 const extras = self.extra(elf_file).?;
72 return elf_file.thunk(extras.thunk);
7273}
7374
7475pub fn inputShdr(self: Atom, elf_file: *Elf) elf.Elf64_Shdr {
......@@ -981,6 +982,31 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
981982 if (has_reloc_errors) return error.RelocFailure;
982983}
983984
985const AddExtraOpts = struct {
986 thunk: ?u32 = null,
987};
988
989pub fn addExtra(atom: *Atom, opts: AddExtraOpts, elf_file: *Elf) !void {
990 if (atom.extra(elf_file) == null) {
991 atom.extra_index = try elf_file.addAtomExtra(.{});
992 }
993 var extras = atom.extra(elf_file).?;
994 inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| {
995 if (@field(opts, field.name)) |x| {
996 @field(extras, field.name) = x;
997 }
998 }
999 atom.setExtra(extras, elf_file);
1000}
1001
1002pub inline fn extra(atom: Atom, elf_file: *Elf) ?Extra {
1003 return elf_file.atomExtra(atom.extra_index);
1004}
1005
1006pub inline fn setExtra(atom: Atom, extras: Extra, elf_file: *Elf) void {
1007 elf_file.setAtomExtra(atom.extra_index, extras);
1008}
1009
9841010pub fn format(
9851011 atom: Atom,
9861012 comptime unused_fmt_string: []const u8,
......@@ -1042,6 +1068,9 @@ pub const Flags = packed struct {
10421068
10431069 /// Specifies if the atom has been visited during garbage collection.
10441070 visited: bool = false,
1071
1072 /// Whether this symbol has a range extension thunk.
1073 thunk: bool = false,
10451074};
10461075
10471076const x86_64 = struct {
......@@ -2167,6 +2196,10 @@ const RelocsIterator = struct {
21672196 }
21682197};
21692198
2199pub const Extra = struct {
2200 thunk: u32 = 0,
2201};
2202
21702203const std = @import("std");
21712204const assert = std.debug.assert;
21722205const elf = std.elf;
src/link/Elf/thunks.zig+2-1
......@@ -50,7 +50,8 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void {
5050 };
5151 try thunk.symbols.put(gpa, target, {});
5252 }
53 atom.thunk_index = thunk_index;
53 try atom.addExtra(.{ .thunk = thunk_index }, elf_file);
54 atom.flags.thunk = true;
5455 }
5556
5657 thunk.value = try advance(shdr, thunk.size(elf_file), Atom.Alignment.fromNonzeroByteUnits(2));