commit 9fe69cc0b588ff96075854d687f3fce3d4457258 (tree)
parent d0367b02199417c10b2cde6d0deae4242689d127
Author: Jakub Konka <kubkon@jakubkonka.com>
Date: Wed, 31 Jul 2024 15:45:36 +0200
elf: move symbol ownership to SharedObject
Diffstat:
2 files changed, 200 insertions(+), 131 deletions(-)
diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig
@@ -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;
-
- 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);
+ 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 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;
-
- 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 (sym.st_shndx != elf.SHN_ABS) {
- const atom_index = self.atoms_indexes.items[sym.st_shndx];
+ 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 == 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 (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));
diff --git a/src/link/Elf/SharedObject.zig b/src/link/Elf/SharedObject.zig
@@ -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;
+
+ 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;
- if (this_sym.st_shndx == elf.SHN_UNDEF) continue;
+ if (esym.st_shndx == elf.SHN_UNDEF) continue;
+ if (elf_file.symbol(gop.ref.*) == null) {
+ gop.ref.* = .{ .index = @intCast(i), .file = self.index };
+ continue;
+ }
- 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 (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,