elf: move symbol ownership to SharedObject

This commit is contained in:
Jakub Konka 2024-07-31 15:45:36 +02:00
parent d0367b0219
commit 9fe69cc0b5
2 changed files with 197 additions and 128 deletions

View File

@ -562,7 +562,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void {
}
}
pub fn resolveSymbols(self: *Object, elf_file: *Elf) void {
pub fn resolveSymbols(self: *Object, elf_file: *Elf) !void {
const gpa = elf_file.base.comp.gpa;
const first_global = self.first_global orelse return;
@ -585,12 +585,12 @@ pub fn resolveSymbols(self: *Object, elf_file: *Elf) void {
resolv.* = gop.index;
if (esym.st_shndx == elf.SHN_UNDEF) continue;
if (elf_file.symbol(gop.ref) == null) {
if (elf_file.symbol(gop.ref.*) == null) {
gop.ref.* = .{ .index = @intCast(i), .file = self.index };
continue;
}
if (self.asFile().symbolRank(esym, !self.alive) < elf_file.symbol(gop.ref).?.symbolRank(elf_file)) {
if (self.asFile().symbolRank(esym, !self.alive) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) {
gop.ref.* = .{ .index = @intCast(i), .file = self.index };
}
}
@ -625,34 +625,40 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void {
pub fn claimUnresolvedObject(self: *Object, elf_file: *Elf) void {
const first_global = self.first_global orelse return;
for (self.globals(), 0..) |index, i| {
for (self.globals(), 0..) |*sym, i| {
const esym_index = @as(u32, @intCast(first_global + i));
const esym = self.symtab.items[esym_index];
if (esym.st_shndx != elf.SHN_UNDEF) continue;
if (elf_file.symbol(self.resolveSymbol(esym_index, elf_file)) != null) continue;
const global = elf_file.symbol(index);
if (global.file(elf_file)) |file| {
if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF or file.index() <= self.index) continue;
}
// TODO: audit this
// const global = elf_file.symbol(index);
// if (global.file(elf_file)) |file| {
// if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF or file.index() <= self.index) continue;
// }
global.value = 0;
global.ref = .{ .index = 0, .file = 0 };
global.esym_index = esym_index;
global.file_index = self.index;
sym.value = 0;
sym.ref = .{ .index = 0, .file = 0 };
sym.esym_index = esym_index;
sym.file_index = self.index;
const idx = self.symbols_resolver.items[i];
elf_file.resolver.items[idx - 1] = .{ .index = esym_index, .file = self.index };
}
}
pub fn markLive(self: *Object, elf_file: *Elf) void {
const first_global = self.first_global orelse return;
for (self.globals(), 0..) |index, i| {
const sym_idx = first_global + i;
const sym = self.symtab.items[sym_idx];
if (sym.st_bind() == elf.STB_WEAK) continue;
for (0..self.globals().len) |i| {
const esym_idx = first_global + i;
const esym = self.symtab.items[esym_idx];
if (esym.st_bind() == elf.STB_WEAK) continue;
const global = elf_file.symbol(index);
const file = global.file(elf_file) orelse continue;
const should_keep = sym.st_shndx == elf.SHN_UNDEF or
(sym.st_shndx == elf.SHN_COMMON and global.elfSym(elf_file).st_shndx != elf.SHN_COMMON);
const ref = self.resolveSymbol(@intCast(esym_idx), elf_file);
const sym = elf_file.symbol(ref) orelse continue;
const file = sym.file(elf_file).?;
const should_keep = esym.st_shndx == elf.SHN_UNDEF or
(esym.st_shndx == elf.SHN_COMMON and sym.elfSym(elf_file).st_shndx != elf.SHN_COMMON);
if (should_keep and !file.isAlive()) {
file.setAlive();
file.markLive(elf_file);
@ -672,24 +678,25 @@ pub fn markEhFrameAtomsDead(self: *Object, elf_file: *Elf) void {
pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void {
const first_global = self.first_global orelse return;
for (self.globals(), 0..) |index, i| {
const sym_idx = first_global + i;
const sym = self.symtab.items[sym_idx];
const global = elf_file.symbol(index);
const global_file = global.file(elf_file) orelse continue;
for (0..self.globals().len) |i| {
const esym_idx = first_global + i;
const esym = self.symtab.items[esym_idx];
const ref = self.resolveSymbol(@intCast(esym_idx), elf_file);
const ref_sym = elf_file.symbol(ref) orelse continue;
const ref_file = ref_sym.file(elf_file).?;
if (self.index == global_file.index() or
sym.st_shndx == elf.SHN_UNDEF or
sym.st_bind() == elf.STB_WEAK or
sym.st_shndx == elf.SHN_COMMON) continue;
if (self.index == ref_file.index() or
esym.st_shndx == elf.SHN_UNDEF or
esym.st_bind() == elf.STB_WEAK or
esym.st_shndx == elf.SHN_COMMON) continue;
if (sym.st_shndx != elf.SHN_ABS) {
const atom_index = self.atoms_indexes.items[sym.st_shndx];
if (esym.st_shndx != elf.SHN_ABS) {
const atom_index = self.atoms_indexes.items[esym.st_shndx];
const atom_ptr = self.atom(atom_index) orelse continue;
if (!atom_ptr.alive) continue;
}
const gop = try dupes.getOrPut(index);
const gop = try dupes.getOrPut(self.symbols_resolver.items[i]);
if (!gop.found_existing) {
gop.value_ptr.* = .{};
}
@ -819,8 +826,8 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {
}
for (self.symtab.items, 0..) |*esym, idx| {
const sym_index = self.symbols.items[idx];
const sym = elf_file.symbol(sym_index);
const sym = &self.symbols.items[idx];
// TODO: do we need ref here?
if (esym.st_shndx == elf.SHN_COMMON or esym.st_shndx == elf.SHN_UNDEF or esym.st_shndx == elf.SHN_ABS) continue;
@ -860,23 +867,20 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {
return error.MalformedObject;
};
const out_sym_idx: u64 = @intCast(self.symbols.items.len);
try self.symbols.ensureUnusedCapacity(gpa, 1);
const sym_index = try self.addSymbol(gpa);
const sym = &self.symbols.items[sym_index];
const name = try std.fmt.allocPrint(gpa, "{s}$subsection{d}", .{ msec.name(elf_file), res.msub_index });
defer gpa.free(name);
const sym_index = try elf_file.addSymbol();
const sym = elf_file.symbol(sym_index);
sym.* = .{
.value = @bitCast(@as(i64, @intCast(res.offset)) - rel.r_addend),
.name_offset = try self.addString(gpa, name),
.esym_index = rel.r_sym(),
.file_index = self.index,
.extra_index = try elf_file.addSymbolExtra(.{}),
.extra_index = try self.addSymbolExtra(gpa, .{}),
};
sym.ref = .{ .index = res.msub_index, .file = imsec.merge_section_index };
sym.flags.merge_subsection = true;
self.symbols.addOneAssumeCapacity().* = sym_index;
rel.r_info = (out_sym_idx << 32) | rel.r_type();
rel.r_info = (@as(u64, @intCast(sym_index)) << 32) | rel.r_type();
}
}
}
@ -885,27 +889,16 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {
/// play nicely with the rest of the system.
pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
const first_global = self.first_global orelse return;
for (self.globals(), 0..) |index, i| {
const sym_idx = @as(u32, @intCast(first_global + i));
const this_sym = self.symtab.items[sym_idx];
if (this_sym.st_shndx != elf.SHN_COMMON) continue;
const global = elf_file.symbol(index);
const global_file = global.file(elf_file).?;
if (global_file.index() != self.index) {
// if (elf_file.options.warn_common) {
// elf_file.base.warn("{}: multiple common symbols: {s}", .{
// self.fmtPath(),
// global.getName(elf_file),
// });
// }
continue;
}
for (self.globals(), self.symbols_resolver.items, 0..) |*sym, resolv, i| {
const esym_idx = @as(u32, @intCast(first_global + i));
const esym = self.symtab.items[esym_idx];
if (esym.st_shndx != elf.SHN_COMMON) continue;
if (elf_file.resolver.get(resolv).?.file != self.index) continue;
const comp = elf_file.base.comp;
const gpa = comp.gpa;
const is_tls = global.type(elf_file) == elf.STT_TLS;
const is_tls = sym.type(elf_file) == elf.STT_TLS;
const name = if (is_tls) ".tls_common" else ".common";
const name_offset = @as(u32, @intCast(self.strtab.items.len));
try self.strtab.writer(gpa).print("{s}\x00", .{name});
@ -914,7 +907,7 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
if (is_tls) sh_flags |= elf.SHF_TLS;
const shndx = @as(u32, @intCast(self.shdrs.items.len));
const shdr = try self.shdrs.addOne(gpa);
const sh_size = math.cast(usize, this_sym.st_size) orelse return error.Overflow;
const sh_size = math.cast(usize, esym.st_size) orelse return error.Overflow;
shdr.* = .{
.sh_name = name_offset,
.sh_type = elf.SHT_NOBITS,
@ -924,21 +917,21 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
.sh_size = sh_size,
.sh_link = 0,
.sh_info = 0,
.sh_addralign = this_sym.st_value,
.sh_addralign = esym.st_value,
.sh_entsize = 0,
};
const atom_index = try self.addAtom(gpa, .{
.name = name_offset,
.shndx = shndx,
.size = this_sym.st_size,
.alignment = Alignment.fromNonzeroByteUnits(this_sym.st_value),
.size = esym.st_size,
.alignment = Alignment.fromNonzeroByteUnits(esym.st_value),
});
try self.atoms_indexes.append(gpa, atom_index);
global.value = 0;
global.ref = .{ .index = atom_index, .file = self.index };
global.flags.weak = false;
sym.value = 0;
sym.ref = .{ .index = atom_index, .file = self.index };
sym.flags.weak = false;
}
}
@ -1080,7 +1073,7 @@ pub fn writeAr(self: Object, elf_file: *Elf, writer: anytype) !void {
try writer.writeAll(data);
}
pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void {
pub fn updateSymtabSize(self: *Object, elf_file: *Elf) void {
const isAlive = struct {
fn isAlive(sym: *const Symbol, ctx: *Elf) bool {
if (sym.mergeSubsection(ctx)) |msub| return msub.alive;
@ -1089,8 +1082,7 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void {
}
}.isAlive;
for (self.locals()) |local_index| {
const local = elf_file.symbol(local_index);
for (self.locals()) |*local| {
if (!isAlive(local, elf_file)) continue;
const esym = local.elfSym(elf_file);
switch (esym.st_type()) {
@ -1099,22 +1091,22 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void {
else => {},
}
local.flags.output_symtab = true;
try local.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file);
local.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file);
self.output_symtab_ctx.nlocals += 1;
self.output_symtab_ctx.strsize += @as(u32, @intCast(local.name(elf_file).len)) + 1;
}
for (self.globals()) |global_index| {
const global = elf_file.symbol(global_index);
const file_ptr = global.file(elf_file) orelse continue;
if (file_ptr.index() != self.index) continue;
for (self.globals(), self.symbols_resolver.items) |*global, resolv| {
const ref = elf_file.resolver.items[resolv];
const ref_sym = elf_file.symbol(ref) orelse continue;
if (ref_sym.file(elf_file).?.index() != self.index) continue;
if (!isAlive(global, elf_file)) continue;
global.flags.output_symtab = true;
if (global.isLocal(elf_file)) {
try global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file);
global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file);
self.output_symtab_ctx.nlocals += 1;
} else {
try global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file);
global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file);
self.output_symtab_ctx.nglobals += 1;
}
self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1;
@ -1122,8 +1114,7 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void {
}
pub fn writeSymtab(self: Object, elf_file: *Elf) void {
for (self.locals()) |local_index| {
const local = elf_file.symbol(local_index);
for (self.locals()) |local| {
const idx = local.outputSymtabIndex(elf_file) orelse continue;
const out_sym = &elf_file.symtab.items[idx];
out_sym.st_name = @intCast(elf_file.strtab.items.len);
@ -1132,10 +1123,10 @@ pub fn writeSymtab(self: Object, elf_file: *Elf) void {
local.setOutputSym(elf_file, out_sym);
}
for (self.globals()) |global_index| {
const global = elf_file.symbol(global_index);
const file_ptr = global.file(elf_file) orelse continue;
if (file_ptr.index() != self.index) continue;
for (self.globals(), self.symbols_resolver.items) |global, resolv| {
const ref = elf_file.resolver.items[resolv];
const ref_sym = elf_file.symbol(ref) orelse continue;
if (ref_sym.file(elf_file).?.index() != self.index) continue;
const idx = global.outputSymtabIndex(elf_file) orelse continue;
const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file));

View File

@ -10,7 +10,10 @@ strtab: std.ArrayListUnmanaged(u8) = .{},
versyms: std.ArrayListUnmanaged(elf.Elf64_Versym) = .{},
verstrings: std.ArrayListUnmanaged(u32) = .{},
symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
symbols: std.ArrayListUnmanaged(Symbol) = .{},
symbols_extra: std.ArrayListUnmanaged(u32) = .{},
symbols_resolver: std.ArrayListUnmanaged(Elf.SymbolResolver.Index) = .{},
aliases: ?std.ArrayListUnmanaged(u32) = null,
dynamic_table: std.ArrayListUnmanaged(elf.Elf64_Dyn) = .{},
@ -38,6 +41,8 @@ pub fn deinit(self: *SharedObject, allocator: Allocator) void {
self.versyms.deinit(allocator);
self.verstrings.deinit(allocator);
self.symbols.deinit(allocator);
self.symbols_extra.deinit(allocator);
self.symbols_resolver.deinit(allocator);
if (self.aliases) |*aliases| aliases.deinit(allocator);
self.dynamic_table.deinit(allocator);
}
@ -129,7 +134,7 @@ pub fn parse(self: *SharedObject, elf_file: *Elf, handle: std.fs.File) !void {
.versym_sect_index = versym_sect_index,
});
try self.initSymtab(elf_file, .{
try self.initSymbols(elf_file, .{
.symtab = symtab,
.strtab = strtab,
});
@ -188,16 +193,20 @@ fn parseVersions(self: *SharedObject, elf_file: *Elf, handle: std.fs.File, opts:
}
}
fn initSymtab(self: *SharedObject, elf_file: *Elf, opts: struct {
fn initSymbols(self: *SharedObject, elf_file: *Elf, opts: struct {
symtab: []align(1) const elf.Elf64_Sym,
strtab: []const u8,
}) !void {
const comp = elf_file.base.comp;
const gpa = comp.gpa;
const gpa = elf_file.base.comp.gpa;
const nsyms = opts.symtab.len;
try self.strtab.appendSlice(gpa, opts.strtab);
try self.symtab.ensureTotalCapacityPrecise(gpa, opts.symtab.len);
try self.symbols.ensureTotalCapacityPrecise(gpa, opts.symtab.len);
try self.symtab.ensureTotalCapacityPrecise(gpa, nsyms);
try self.symbols.ensureTotalCapacityPrecise(gpa, nsyms);
try self.symbols_extra.ensureTotalCapacityPrecise(gpa, nsyms * @sizeOf(Symbol.Extra));
try self.symbols_resolver.ensureTotalCapacityPrecise(gpa, nsyms);
self.symbols_resolver.resize(gpa, nsyms) catch unreachable;
@memset(self.symbols_resolver.items, 0);
for (opts.symtab, 0..) |sym, i| {
const hidden = self.versyms.items[i] & elf.VERSYM_HIDDEN != 0;
@ -214,41 +223,56 @@ fn initSymtab(self: *SharedObject, elf_file: *Elf, opts: struct {
try self.strtab.writer(gpa).print("{s}\x00", .{mangled});
break :blk name_off;
} else sym.st_name;
const out_sym = self.symtab.addOneAssumeCapacity();
out_sym.* = sym;
out_sym.st_name = name_off;
const gop = try elf_file.getOrPutGlobal(self.getString(name_off));
self.symbols.addOneAssumeCapacity().* = gop.index;
const out_esym_index: u32 = @intCast(self.symtab.items.len);
const out_esym = self.symtab.addOneAssumeCapacity();
out_esym.* = sym;
out_esym.st_name = name_off;
const out_sym_index = self.addSymbolAssumeCapacity();
const out_sym = &self.symbols.items[out_sym_index];
out_sym.* = .{
.value = @intCast(out_esym.st_value),
.ref = .{ .index = 0, .file = 0 },
.esym_index = out_esym_index,
.version_index = self.versyms.items[out_esym_index],
.extra_index = self.addSymbolExtraAssumeCapacity(.{}),
};
}
}
pub fn resolveSymbols(self: *SharedObject, elf_file: *Elf) void {
for (self.globals(), 0..) |index, i| {
const esym_index = @as(u32, @intCast(i));
const this_sym = self.symtab.items[esym_index];
pub fn resolveSymbols(self: *SharedObject, elf_file: *Elf) !void {
const gpa = elf_file.base.comp.gpa;
if (this_sym.st_shndx == elf.SHN_UNDEF) continue;
for (self.symtab.items, self.symbols_resolver.items, 0..) |esym, *resolv, i| {
const gop = try elf_file.resolver.getOrPut(gpa, .{
.index = @intCast(i),
.file = self.index,
}, elf_file);
if (!gop.found_existing) {
gop.ref.* = .{ .index = 0, .file = 0 };
}
resolv.* = gop.index;
const global = elf_file.symbol(index);
if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) {
global.value = @intCast(this_sym.st_value);
global.ref = .{ .index = 0, .file = 0 };
global.esym_index = esym_index;
global.version_index = self.versyms.items[esym_index];
global.file_index = self.index;
if (esym.st_shndx == elf.SHN_UNDEF) continue;
if (elf_file.symbol(gop.ref.*) == null) {
gop.ref.* = .{ .index = @intCast(i), .file = self.index };
continue;
}
if (self.asFile().symbolRank(esym, false) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) {
gop.ref.* = .{ .index = @intCast(i), .file = self.index };
}
}
}
pub fn markLive(self: *SharedObject, elf_file: *Elf) void {
for (self.globals(), 0..) |index, i| {
const sym = self.symtab.items[i];
if (sym.st_shndx != elf.SHN_UNDEF) continue;
for (self.symtab.items, 0..) |esym, i| {
if (esym.st_shndx != elf.SHN_UNDEF) continue;
const global = elf_file.symbol(index);
const file = global.file(elf_file) orelse continue;
const ref = self.resolveSymbol(@intCast(i), elf_file);
const sym = elf_file.symbol(ref) orelse continue;
const file = sym.file(elf_file).?;
const should_drop = switch (file) {
.shared_object => |sh| !sh.needed and sym.st_bind() == elf.STB_WEAK,
.shared_object => |sh| !sh.needed and esym.st_bind() == elf.STB_WEAK,
else => false,
};
if (!should_drop and !file.isAlive()) {
@ -262,24 +286,24 @@ pub fn globals(self: SharedObject) []const Symbol.Index {
return self.symbols.items;
}
pub fn updateSymtabSize(self: *SharedObject, elf_file: *Elf) !void {
for (self.globals()) |global_index| {
const global = elf_file.symbol(global_index);
const file_ptr = global.file(elf_file) orelse continue;
if (file_ptr.index() != self.index) continue;
pub fn updateSymtabSize(self: *SharedObject, elf_file: *Elf) void {
for (self.globals(), self.symbols_resolver.items) |*global, resolv| {
const ref = elf_file.resolver.get(resolv).?;
const ref_sym = elf_file.symbol(ref) orelse continue;
if (ref_sym.file(elf_file).?.index() != self.index) continue;
if (global.isLocal(elf_file)) continue;
global.flags.output_symtab = true;
try global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file);
global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file);
self.output_symtab_ctx.nglobals += 1;
self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1;
}
}
pub fn writeSymtab(self: SharedObject, elf_file: *Elf) void {
for (self.globals()) |global_index| {
const global = elf_file.symbol(global_index);
const file_ptr = global.file(elf_file) orelse continue;
if (file_ptr.index() != self.index) continue;
for (self.globals(), self.symbols_resolver.items) |global, resolv| {
const ref = elf_file.resolver.get(resolv).?;
const ref_sym = elf_file.symbol(ref) orelse continue;
if (ref_sym.file(elf_file).?.index() != self.index) continue;
const idx = global.outputSymtabIndex(elf_file) orelse continue;
const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file));
@ -332,10 +356,10 @@ pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void {
defer aliases.deinit();
try aliases.ensureTotalCapacityPrecise(self.globals().len);
for (self.globals()) |index| {
const global = elf_file.symbol(index);
const global_file = global.file(elf_file) orelse continue;
if (global_file.index() != self.index) continue;
for (self.symbols_resolvers.items, 0..) |resolv, index| {
const ref = elf_file.resolver.get(resolv).?;
const ref_sym = elf_file.symbol(ref) orelse continue;
if (ref_sym.file(elf_file).?.index() != self.index) continue;
aliases.appendAssumeCapacity(index);
}
@ -347,16 +371,16 @@ pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void {
pub fn symbolAliases(self: *SharedObject, index: u32, elf_file: *Elf) []const u32 {
assert(self.aliases != null);
const symbol = elf_file.symbol(index).elfSym(elf_file);
const symbol = self.symbol(index).elfSym(elf_file);
const aliases = self.aliases.?;
const start = for (aliases.items, 0..) |alias, i| {
const alias_sym = elf_file.symbol(alias).elfSym(elf_file);
const alias_sym = self.symbol(alias).elfSym(elf_file);
if (symbol.st_value == alias_sym.st_value) break i;
} else aliases.items.len;
const end = for (aliases.items[start..], 0..) |alias, i| {
const alias_sym = elf_file.symbol(alias).elfSym(elf_file);
const alias_sym = self.symbol(alias).elfSym(elf_file);
if (symbol.st_value < alias_sym.st_value) break i + start;
} else aliases.items.len;
@ -368,6 +392,60 @@ pub fn getString(self: SharedObject, off: u32) [:0]const u8 {
return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.items.ptr + off)), 0);
}
pub fn resolveSymbol(self: SharedObject, index: Symbol.Index, elf_file: *Elf) Elf.Ref {
const resolv = self.symbols_resolver.items[index];
return elf_file.resolver.get(resolv).?;
}
pub fn addSymbol(self: *SharedObject, allocator: Allocator) !Symbol.Index {
try self.symbols.ensureUnusedCapacity(allocator, 1);
const index: Symbol.Index = @intCast(self.symbols.items.len);
self.symbols.appendAssumeCapacity(.{ .file_index = self.index });
return index;
}
pub fn addSymbolExtra(self: *SharedObject, allocator: Allocator, extra: Symbol.Extra) !u32 {
const fields = @typeInfo(Symbol.Extra).Struct.fields;
try self.symbols_extra.ensureUnusedCapacity(allocator, fields.len);
return self.addSymbolExtraAssumeCapacity(extra);
}
pub fn addSymbolExtraAssumeCapacity(self: *SharedObject, extra: Symbol.Extra) u32 {
const index = @as(u32, @intCast(self.symbols_extra.items.len));
const fields = @typeInfo(Symbol.Extra).Struct.fields;
inline for (fields) |field| {
self.symbols_extra.appendAssumeCapacity(switch (field.type) {
u32 => @field(extra, field.name),
else => @compileError("bad field type"),
});
}
return index;
}
pub fn symbolExtra(self: *SharedObject, index: u32) Symbol.Extra {
const fields = @typeInfo(Symbol.Extra).Struct.fields;
var i: usize = index;
var result: Symbol.Extra = undefined;
inline for (fields) |field| {
@field(result, field.name) = switch (field.type) {
u32 => self.symbols_extra.items[i],
else => @compileError("bad field type"),
};
i += 1;
}
return result;
}
pub fn setSymbolExtra(self: *SharedObject, index: u32, extra: Symbol.Extra) void {
const fields = @typeInfo(Symbol.Extra).Struct.fields;
inline for (fields, 0..) |field, i| {
self.symbols_extra.items[index + i] = switch (field.type) {
u32 => @field(extra, field.name),
else => @compileError("bad field type"),
};
}
}
pub fn format(
self: SharedObject,
comptime unused_fmt_string: []const u8,