| author | |
| committer | |
| log | 700644d35dd674c7381c4794d566e0e64f45c174 |
| tree | e2d985e943b977ac4d0d1f8a1e85cfa713e9cbb8 |
| parent | c7ffdbcd41f45d23328f1b40d90420ff29ed66af |
3 files changed, 92 insertions(+), 8 deletions(-)
src/link/Elf.zig+50| ... | @@ -205,6 +205,7 @@ num_ifunc_dynrelocs: usize = 0, | ... | @@ -205,6 +205,7 @@ num_ifunc_dynrelocs: usize = 0, |
| 205 | 205 | ||
| 206 | /// List of atoms that are owned directly by the linker. | 206 | /// List of atoms that are owned directly by the linker. |
| 207 | atoms: std.ArrayListUnmanaged(Atom) = .{}, | 207 | atoms: std.ArrayListUnmanaged(Atom) = .{}, |
| 208 | atoms_extra: std.ArrayListUnmanaged(u32) = .{}, | ||
| 208 | 209 | ||
| 209 | /// List of range extension thunks. | 210 | /// List of range extension thunks. |
| 210 | thunks: std.ArrayListUnmanaged(Thunk) = .{}, | 211 | thunks: std.ArrayListUnmanaged(Thunk) = .{}, |
| ... | @@ -369,6 +370,7 @@ pub fn createEmpty( | ... | @@ -369,6 +370,7 @@ pub fn createEmpty( |
| 369 | try self.symbols_extra.append(gpa, 0); | 370 | try self.symbols_extra.append(gpa, 0); |
| 370 | // Allocate atom index 0 to null atom | 371 | // Allocate atom index 0 to null atom |
| 371 | try self.atoms.append(gpa, .{}); | 372 | try self.atoms.append(gpa, .{}); |
| 373 | try self.atoms_extra.append(gpa, 0); | ||
| 372 | // Append null file at index 0 | 374 | // Append null file at index 0 |
| 373 | try self.files.append(gpa, .null); | 375 | try self.files.append(gpa, .null); |
| 374 | // Append null byte to string tables | 376 | // Append null byte to string tables |
| ... | @@ -491,6 +493,10 @@ pub fn deinit(self: *Elf) void { | ... | @@ -491,6 +493,10 @@ pub fn deinit(self: *Elf) void { |
| 491 | self.start_stop_indexes.deinit(gpa); | 493 | self.start_stop_indexes.deinit(gpa); |
| 492 | 494 | ||
| 493 | self.atoms.deinit(gpa); | 495 | self.atoms.deinit(gpa); |
| 496 | self.atoms_extra.deinit(gpa); | ||
| 497 | for (self.thunks.items) |*th| { | ||
| 498 | th.deinit(gpa); | ||
| 499 | } | ||
| 494 | self.thunks.deinit(gpa); | 500 | self.thunks.deinit(gpa); |
| 495 | for (self.last_atom_and_free_list_table.values()) |*value| { | 501 | for (self.last_atom_and_free_list_table.values()) |*value| { |
| 496 | value.free_list.deinit(gpa); | 502 | value.free_list.deinit(gpa); |
| ... | @@ -5458,6 +5464,50 @@ pub fn addAtom(self: *Elf) !Atom.Index { | ... | @@ -5458,6 +5464,50 @@ pub fn addAtom(self: *Elf) !Atom.Index { |
| 5458 | return index; | 5464 | return index; |
| 5459 | } | 5465 | } |
| 5460 | 5466 | ||
| 5467 | pub 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 | |||
| 5473 | pub 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 | |||
| 5485 | pub 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 | |||
| 5500 | pub 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 | |||
| 5461 | pub fn addThunk(self: *Elf) !Thunk.Index { | 5511 | pub fn addThunk(self: *Elf) !Thunk.Index { |
| 5462 | const index = @as(Thunk.Index, @intCast(self.thunks.items.len)); | 5512 | const index = @as(Thunk.Index, @intCast(self.thunks.items.len)); |
| 5463 | const th = try self.thunks.addOne(self.base.comp.gpa); | 5513 | 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, | ... | @@ -31,12 +31,6 @@ rel_num: u32 = 0, |
| 31 | /// Index of this atom in the linker's atoms table. | 31 | /// Index of this atom in the linker's atoms table. |
| 32 | atom_index: Index = 0, | 32 | atom_index: Index = 0, |
| 33 | 33 | ||
| 34 | /// Index of the thunk for this atom. | ||
| 35 | thunk_index: Thunk.Index = 0, | ||
| 36 | |||
| 37 | /// Flags we use for state tracking. | ||
| 38 | flags: Flags = .{}, | ||
| 39 | |||
| 40 | /// Start index of FDEs referencing this atom. | 34 | /// Start index of FDEs referencing this atom. |
| 41 | fde_start: u32 = 0, | 35 | fde_start: u32 = 0, |
| 42 | 36 | ||
| ... | @@ -48,6 +42,11 @@ fde_end: u32 = 0, | ... | @@ -48,6 +42,11 @@ fde_end: u32 = 0, |
| 48 | prev_index: Index = 0, | 42 | prev_index: Index = 0, |
| 49 | next_index: Index = 0, | 43 | next_index: Index = 0, |
| 50 | 44 | ||
| 45 | /// Flags we use for state tracking. | ||
| 46 | flags: Flags = .{}, | ||
| 47 | |||
| 48 | extra_index: u32 = 0, | ||
| 49 | |||
| 51 | pub const Alignment = @import("../../InternPool.zig").Alignment; | 50 | pub const Alignment = @import("../../InternPool.zig").Alignment; |
| 52 | 51 | ||
| 53 | pub fn name(self: Atom, elf_file: *Elf) []const u8 { | 52 | pub fn name(self: Atom, elf_file: *Elf) []const u8 { |
| ... | @@ -68,7 +67,9 @@ pub fn file(self: Atom, elf_file: *Elf) ?File { | ... | @@ -68,7 +67,9 @@ pub fn file(self: Atom, elf_file: *Elf) ?File { |
| 68 | } | 67 | } |
| 69 | 68 | ||
| 70 | pub fn thunk(self: Atom, elf_file: *Elf) *Thunk { | 69 | pub 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); | ||
| 72 | } | 73 | } |
| 73 | 74 | ||
| 74 | pub fn inputShdr(self: Atom, elf_file: *Elf) elf.Elf64_Shdr { | 75 | pub 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 | ... | @@ -981,6 +982,31 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any |
| 981 | if (has_reloc_errors) return error.RelocFailure; | 982 | if (has_reloc_errors) return error.RelocFailure; |
| 982 | } | 983 | } |
| 983 | 984 | ||
| 985 | const AddExtraOpts = struct { | ||
| 986 | thunk: ?u32 = null, | ||
| 987 | }; | ||
| 988 | |||
| 989 | pub 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 | |||
| 1002 | pub inline fn extra(atom: Atom, elf_file: *Elf) ?Extra { | ||
| 1003 | return elf_file.atomExtra(atom.extra_index); | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | pub inline fn setExtra(atom: Atom, extras: Extra, elf_file: *Elf) void { | ||
| 1007 | elf_file.setAtomExtra(atom.extra_index, extras); | ||
| 1008 | } | ||
| 1009 | |||
| 984 | pub fn format( | 1010 | pub fn format( |
| 985 | atom: Atom, | 1011 | atom: Atom, |
| 986 | comptime unused_fmt_string: []const u8, | 1012 | comptime unused_fmt_string: []const u8, |
| ... | @@ -1042,6 +1068,9 @@ pub const Flags = packed struct { | ... | @@ -1042,6 +1068,9 @@ pub const Flags = packed struct { |
| 1042 | 1068 | ||
| 1043 | /// Specifies if the atom has been visited during garbage collection. | 1069 | /// Specifies if the atom has been visited during garbage collection. |
| 1044 | visited: bool = false, | 1070 | visited: bool = false, |
| 1071 | |||
| 1072 | /// Whether this symbol has a range extension thunk. | ||
| 1073 | thunk: bool = false, | ||
| 1045 | }; | 1074 | }; |
| 1046 | 1075 | ||
| 1047 | const x86_64 = struct { | 1076 | const x86_64 = struct { |
| ... | @@ -2167,6 +2196,10 @@ const RelocsIterator = struct { | ... | @@ -2167,6 +2196,10 @@ const RelocsIterator = struct { |
| 2167 | } | 2196 | } |
| 2168 | }; | 2197 | }; |
| 2169 | 2198 | ||
| 2199 | pub const Extra = struct { | ||
| 2200 | thunk: u32 = 0, | ||
| 2201 | }; | ||
| 2202 | |||
| 2170 | const std = @import("std"); | 2203 | const std = @import("std"); |
| 2171 | const assert = std.debug.assert; | 2204 | const assert = std.debug.assert; |
| 2172 | const elf = std.elf; | 2205 | const elf = std.elf; |
src/link/Elf/thunks.zig+2-1| ... | @@ -50,7 +50,8 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void { | ... | @@ -50,7 +50,8 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void { |
| 50 | }; | 50 | }; |
| 51 | try thunk.symbols.put(gpa, target, {}); | 51 | try thunk.symbols.put(gpa, target, {}); |
| 52 | } | 52 | } |
| 53 | atom.thunk_index = thunk_index; | 53 | try atom.addExtra(.{ .thunk = thunk_index }, elf_file); |
| 54 | atom.flags.thunk = true; | ||
| 54 | } | 55 | } |
| 55 | 56 | ||
| 56 | thunk.value = try advance(shdr, thunk.size(elf_file), Atom.Alignment.fromNonzeroByteUnits(2)); | 57 | thunk.value = try advance(shdr, thunk.size(elf_file), Atom.Alignment.fromNonzeroByteUnits(2)); |