mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 13:30:45 +00:00
link/elf: introduce Atom extras for out-of-band storage
This commit is contained in:
parent
c7ffdbcd41
commit
700644d35d
@ -205,6 +205,7 @@ num_ifunc_dynrelocs: usize = 0,
|
||||
|
||||
/// List of atoms that are owned directly by the linker.
|
||||
atoms: std.ArrayListUnmanaged(Atom) = .{},
|
||||
atoms_extra: std.ArrayListUnmanaged(u32) = .{},
|
||||
|
||||
/// List of range extension thunks.
|
||||
thunks: std.ArrayListUnmanaged(Thunk) = .{},
|
||||
@ -369,6 +370,7 @@ pub fn createEmpty(
|
||||
try self.symbols_extra.append(gpa, 0);
|
||||
// Allocate atom index 0 to null atom
|
||||
try self.atoms.append(gpa, .{});
|
||||
try self.atoms_extra.append(gpa, 0);
|
||||
// Append null file at index 0
|
||||
try self.files.append(gpa, .null);
|
||||
// Append null byte to string tables
|
||||
@ -491,6 +493,10 @@ pub fn deinit(self: *Elf) void {
|
||||
self.start_stop_indexes.deinit(gpa);
|
||||
|
||||
self.atoms.deinit(gpa);
|
||||
self.atoms_extra.deinit(gpa);
|
||||
for (self.thunks.items) |*th| {
|
||||
th.deinit(gpa);
|
||||
}
|
||||
self.thunks.deinit(gpa);
|
||||
for (self.last_atom_and_free_list_table.values()) |*value| {
|
||||
value.free_list.deinit(gpa);
|
||||
@ -5458,6 +5464,50 @@ pub fn addAtom(self: *Elf) !Atom.Index {
|
||||
return index;
|
||||
}
|
||||
|
||||
pub fn addAtomExtra(self: *Elf, extra: Atom.Extra) !u32 {
|
||||
const fields = @typeInfo(Atom.Extra).Struct.fields;
|
||||
try self.atoms_extra.ensureUnusedCapacity(self.base.comp.gpa, fields.len);
|
||||
return self.addAtomExtraAssumeCapacity(extra);
|
||||
}
|
||||
|
||||
pub fn addAtomExtraAssumeCapacity(self: *Elf, extra: Atom.Extra) u32 {
|
||||
const index = @as(u32, @intCast(self.atoms_extra.items.len));
|
||||
const fields = @typeInfo(Atom.Extra).Struct.fields;
|
||||
inline for (fields) |field| {
|
||||
self.atoms_extra.appendAssumeCapacity(switch (field.type) {
|
||||
u32 => @field(extra, field.name),
|
||||
else => @compileError("bad field type"),
|
||||
});
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
pub fn atomExtra(self: *Elf, index: u32) ?Atom.Extra {
|
||||
if (index == 0) return null;
|
||||
const fields = @typeInfo(Atom.Extra).Struct.fields;
|
||||
var i: usize = index;
|
||||
var result: Atom.Extra = undefined;
|
||||
inline for (fields) |field| {
|
||||
@field(result, field.name) = switch (field.type) {
|
||||
u32 => self.atoms_extra.items[i],
|
||||
else => @compileError("bad field type"),
|
||||
};
|
||||
i += 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn setAtomExtra(self: *Elf, index: u32, extra: Atom.Extra) void {
|
||||
assert(index > 0);
|
||||
const fields = @typeInfo(Atom.Extra).Struct.fields;
|
||||
inline for (fields, 0..) |field, i| {
|
||||
self.atoms_extra.items[index + i] = switch (field.type) {
|
||||
u32 => @field(extra, field.name),
|
||||
else => @compileError("bad field type"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addThunk(self: *Elf) !Thunk.Index {
|
||||
const index = @as(Thunk.Index, @intCast(self.thunks.items.len));
|
||||
const th = try self.thunks.addOne(self.base.comp.gpa);
|
||||
|
||||
@ -31,12 +31,6 @@ rel_num: u32 = 0,
|
||||
/// Index of this atom in the linker's atoms table.
|
||||
atom_index: Index = 0,
|
||||
|
||||
/// Index of the thunk for this atom.
|
||||
thunk_index: Thunk.Index = 0,
|
||||
|
||||
/// Flags we use for state tracking.
|
||||
flags: Flags = .{},
|
||||
|
||||
/// Start index of FDEs referencing this atom.
|
||||
fde_start: u32 = 0,
|
||||
|
||||
@ -48,6 +42,11 @@ fde_end: u32 = 0,
|
||||
prev_index: Index = 0,
|
||||
next_index: Index = 0,
|
||||
|
||||
/// Flags we use for state tracking.
|
||||
flags: Flags = .{},
|
||||
|
||||
extra_index: u32 = 0,
|
||||
|
||||
pub const Alignment = @import("../../InternPool.zig").Alignment;
|
||||
|
||||
pub fn name(self: Atom, elf_file: *Elf) []const u8 {
|
||||
@ -68,7 +67,9 @@ pub fn file(self: Atom, elf_file: *Elf) ?File {
|
||||
}
|
||||
|
||||
pub fn thunk(self: Atom, elf_file: *Elf) *Thunk {
|
||||
return elf_file.thunk(self.thunk_index);
|
||||
assert(self.flags.thunk);
|
||||
const extras = self.extra(elf_file).?;
|
||||
return elf_file.thunk(extras.thunk);
|
||||
}
|
||||
|
||||
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
|
||||
if (has_reloc_errors) return error.RelocFailure;
|
||||
}
|
||||
|
||||
const AddExtraOpts = struct {
|
||||
thunk: ?u32 = null,
|
||||
};
|
||||
|
||||
pub fn addExtra(atom: *Atom, opts: AddExtraOpts, elf_file: *Elf) !void {
|
||||
if (atom.extra(elf_file) == null) {
|
||||
atom.extra_index = try elf_file.addAtomExtra(.{});
|
||||
}
|
||||
var extras = atom.extra(elf_file).?;
|
||||
inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| {
|
||||
if (@field(opts, field.name)) |x| {
|
||||
@field(extras, field.name) = x;
|
||||
}
|
||||
}
|
||||
atom.setExtra(extras, elf_file);
|
||||
}
|
||||
|
||||
pub inline fn extra(atom: Atom, elf_file: *Elf) ?Extra {
|
||||
return elf_file.atomExtra(atom.extra_index);
|
||||
}
|
||||
|
||||
pub inline fn setExtra(atom: Atom, extras: Extra, elf_file: *Elf) void {
|
||||
elf_file.setAtomExtra(atom.extra_index, extras);
|
||||
}
|
||||
|
||||
pub fn format(
|
||||
atom: Atom,
|
||||
comptime unused_fmt_string: []const u8,
|
||||
@ -1042,6 +1068,9 @@ pub const Flags = packed struct {
|
||||
|
||||
/// Specifies if the atom has been visited during garbage collection.
|
||||
visited: bool = false,
|
||||
|
||||
/// Whether this symbol has a range extension thunk.
|
||||
thunk: bool = false,
|
||||
};
|
||||
|
||||
const x86_64 = struct {
|
||||
@ -2167,6 +2196,10 @@ const RelocsIterator = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const Extra = struct {
|
||||
thunk: u32 = 0,
|
||||
};
|
||||
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const elf = std.elf;
|
||||
|
||||
@ -50,7 +50,8 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void {
|
||||
};
|
||||
try thunk.symbols.put(gpa, target, {});
|
||||
}
|
||||
atom.thunk_index = thunk_index;
|
||||
try atom.addExtra(.{ .thunk = thunk_index }, elf_file);
|
||||
atom.flags.thunk = true;
|
||||
}
|
||||
|
||||
thunk.value = try advance(shdr, thunk.size(elf_file), Atom.Alignment.fromNonzeroByteUnits(2));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user