mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 16:45:27 +00:00
elf: move symbol ownership to SharedObject
This commit is contained in:
parent
d0367b0219
commit
9fe69cc0b5
@ -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));
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user