mirror of
https://github.com/ziglang/zig.git
synced 2025-12-30 01:53:16 +00:00
elf: redo symbol mgmt and ownership in ZigObject
This commit is contained in:
parent
de80e4fec2
commit
deeaa1bb0c
@ -173,11 +173,7 @@ shstrtab_section_index: ?u32 = null,
|
||||
strtab_section_index: ?u32 = null,
|
||||
symtab_section_index: ?u32 = null,
|
||||
|
||||
/// An array of symbols parsed across all input files.
|
||||
symbols: std.ArrayListUnmanaged(Symbol) = .{},
|
||||
symbols_extra: std.ArrayListUnmanaged(u32) = .{},
|
||||
|
||||
resolver: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{},
|
||||
resolver: SymbolResolver = .{},
|
||||
|
||||
has_text_reloc: bool = false,
|
||||
num_ifunc_dynrelocs: usize = 0,
|
||||
@ -191,10 +187,6 @@ merge_sections: std.ArrayListUnmanaged(MergeSection) = .{},
|
||||
/// Table of last atom index in a section and matching atom free list if any.
|
||||
last_atom_and_free_list_table: LastAtomAndFreeListTable = .{},
|
||||
|
||||
/// Global string table used to provide quick access to global symbol resolvers
|
||||
/// such as `resolver`.
|
||||
strings: StringTable = .{},
|
||||
|
||||
first_eflags: ?elf.Elf64_Word = null,
|
||||
|
||||
/// When allocating, the ideal_capacity is calculated by
|
||||
@ -455,8 +447,6 @@ pub fn deinit(self: *Elf) void {
|
||||
self.shstrtab.deinit(gpa);
|
||||
self.symtab.deinit(gpa);
|
||||
self.strtab.deinit(gpa);
|
||||
self.symbols.deinit(gpa);
|
||||
self.symbols_extra.deinit(gpa);
|
||||
self.resolver.deinit(gpa);
|
||||
|
||||
for (self.thunks.items) |*th| {
|
||||
@ -472,8 +462,6 @@ pub fn deinit(self: *Elf) void {
|
||||
}
|
||||
self.last_atom_and_free_list_table.deinit(gpa);
|
||||
|
||||
self.strings.deinit(gpa);
|
||||
|
||||
self.got.deinit(gpa);
|
||||
self.plt.deinit(gpa);
|
||||
self.plt_got.deinit(gpa);
|
||||
@ -1916,20 +1904,17 @@ fn accessLibPath(
|
||||
/// 6. Re-run symbol resolution on pruned objects and shared objects sets.
|
||||
pub fn resolveSymbols(self: *Elf) !void {
|
||||
// Resolve symbols in the ZigObject. For now, we assume that it's always live.
|
||||
if (self.zigObjectPtr()) |zig_object| zig_object.asFile().resolveSymbols(self);
|
||||
if (self.zigObjectPtr()) |zo| try zo.asFile().resolveSymbols(self);
|
||||
// Resolve symbols on the set of all objects and shared objects (even if some are unneeded).
|
||||
for (self.objects.items) |index| self.file(index).?.resolveSymbols(self);
|
||||
for (self.shared_objects.items) |index| self.file(index).?.resolveSymbols(self);
|
||||
if (self.linkerDefinedPtr()) |obj| obj.asFile().resolveSymbols(self);
|
||||
for (self.objects.items) |index| try self.file(index).?.resolveSymbols(self);
|
||||
for (self.shared_objects.items) |index| try self.file(index).?.resolveSymbols(self);
|
||||
if (self.linkerDefinedPtr()) |obj| try obj.asFile().resolveSymbols(self);
|
||||
|
||||
// Mark live objects.
|
||||
self.markLive();
|
||||
|
||||
// Reset state of all globals after marking live objects.
|
||||
if (self.zigObjectPtr()) |zig_object| zig_object.asFile().resetGlobals(self);
|
||||
for (self.objects.items) |index| self.file(index).?.resetGlobals(self);
|
||||
for (self.shared_objects.items) |index| self.file(index).?.resetGlobals(self);
|
||||
if (self.linkerDefinedPtr()) |obj| obj.asFile().resetGlobals(self);
|
||||
self.resolver.reset();
|
||||
|
||||
// Prune dead objects and shared objects.
|
||||
var i: usize = 0;
|
||||
@ -1962,10 +1947,10 @@ pub fn resolveSymbols(self: *Elf) !void {
|
||||
}
|
||||
|
||||
// Re-resolve the symbols.
|
||||
if (self.zigObjectPtr()) |zig_object| zig_object.asFile().resolveSymbols(self);
|
||||
for (self.objects.items) |index| self.file(index).?.resolveSymbols(self);
|
||||
for (self.shared_objects.items) |index| self.file(index).?.resolveSymbols(self);
|
||||
if (self.linkerDefinedPtr()) |obj| obj.asFile().resolveSymbols(self);
|
||||
if (self.zigObjectPtr()) |zo| try zo.asFile().resolveSymbols(self);
|
||||
for (self.objects.items) |index| try self.file(index).?.resolveSymbols(self);
|
||||
for (self.shared_objects.items) |index| try self.file(index).?.resolveSymbols(self);
|
||||
if (self.linkerDefinedPtr()) |obj| try obj.asFile().resolveSymbols(self);
|
||||
}
|
||||
|
||||
/// Traverses all objects and shared objects marking any object referenced by
|
||||
@ -1999,46 +1984,17 @@ fn convertCommonSymbols(self: *Elf) !void {
|
||||
}
|
||||
|
||||
fn markImportsExports(self: *Elf) void {
|
||||
const mark = struct {
|
||||
fn mark(elf_file: *Elf, file_index: File.Index) void {
|
||||
for (elf_file.file(file_index).?.globals()) |global_index| {
|
||||
const global = elf_file.symbol(global_index);
|
||||
if (global.version_index == elf.VER_NDX_LOCAL) continue;
|
||||
const file_ptr = global.file(elf_file) orelse continue;
|
||||
const vis = @as(elf.STV, @enumFromInt(global.elfSym(elf_file).st_other));
|
||||
if (vis == .HIDDEN) continue;
|
||||
if (file_ptr == .shared_object and !global.isAbs(elf_file)) {
|
||||
global.flags.import = true;
|
||||
continue;
|
||||
}
|
||||
if (file_ptr.index() == file_index) {
|
||||
global.flags.@"export" = true;
|
||||
if (elf_file.isEffectivelyDynLib() and vis != .PROTECTED) {
|
||||
global.flags.import = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}.mark;
|
||||
|
||||
if (self.zigObjectPtr()) |zo| {
|
||||
zo.markImportsExports(self);
|
||||
}
|
||||
for (self.objects.items) |index| {
|
||||
self.file(index).?.object.markImportsExports(self);
|
||||
}
|
||||
if (!self.isEffectivelyDynLib()) {
|
||||
for (self.shared_objects.items) |index| {
|
||||
for (self.file(index).?.globals()) |global_index| {
|
||||
const global = self.symbol(global_index);
|
||||
const file_ptr = global.file(self) orelse continue;
|
||||
const vis = @as(elf.STV, @enumFromInt(global.elfSym(self).st_other));
|
||||
if (file_ptr != .shared_object and vis != .HIDDEN) global.flags.@"export" = true;
|
||||
}
|
||||
self.file(index).?.shared_object.markImportExports(self);
|
||||
}
|
||||
}
|
||||
|
||||
if (self.zig_object_index) |index| {
|
||||
mark(self, index);
|
||||
}
|
||||
|
||||
for (self.objects.items) |index| {
|
||||
mark(self, index);
|
||||
}
|
||||
}
|
||||
|
||||
fn claimUnresolved(self: *Elf) void {
|
||||
|
||||
@ -302,12 +302,8 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn globals(self: *LinkerDefined) []Symbol {
|
||||
return self.symbols.items;
|
||||
}
|
||||
|
||||
pub fn updateSymtabSize(self: *LinkerDefined, elf_file: *Elf) void {
|
||||
for (self.globals(), self.symbols_resolver.items) |*global, resolv| {
|
||||
for (self.symbols.items, 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;
|
||||
@ -324,7 +320,7 @@ pub fn updateSymtabSize(self: *LinkerDefined, elf_file: *Elf) void {
|
||||
}
|
||||
|
||||
pub fn writeSymtab(self: *LinkerDefined, elf_file: *Elf) void {
|
||||
for (self.globals(), self.symbols_resolver.items) |global, resolv| {
|
||||
for (self.symbols.items, 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;
|
||||
|
||||
@ -676,6 +676,29 @@ pub fn markEhFrameAtomsDead(self: *Object, elf_file: *Elf) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn markImportsExports(self: *Object, elf_file: *Elf) void {
|
||||
const first_global = self.first_global orelse return;
|
||||
for (0..self.globals().len) |i| {
|
||||
const idx = first_global + i;
|
||||
const ref = self.resolveSymbol(@intCast(idx), elf_file);
|
||||
const sym = elf_file.symbol(ref) orelse continue;
|
||||
const file = sym.file(elf_file).?;
|
||||
if (sym.version_index == elf.VER_NDX_LOCAL) continue;
|
||||
const vis = @as(elf.STV, @enumFromInt(sym.elfSym(elf_file).st_other));
|
||||
if (vis == .HIDDEN) continue;
|
||||
if (file == .shared_object and !sym.isAbs(elf_file)) {
|
||||
sym.flags.import = true;
|
||||
continue;
|
||||
}
|
||||
if (file.index() == self.index) {
|
||||
sym.flags.@"export" = true;
|
||||
if (elf_file.isEffectivelyDynLib() and vis != .PROTECTED) {
|
||||
sym.flags.import = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void {
|
||||
const first_global = self.first_global orelse return;
|
||||
for (0..self.globals().len) |i| {
|
||||
@ -1169,14 +1192,14 @@ pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index
|
||||
return data;
|
||||
}
|
||||
|
||||
pub fn locals(self: *Object) []Symbol {
|
||||
fn locals(self: *Object) []Symbol {
|
||||
if (self.symbols.items.len == 0) return &[0]Symbol{};
|
||||
assert(self.symbols.items.len >= self.symtab.items.len);
|
||||
const end = self.first_global orelse self.symtab.items.len;
|
||||
return self.symbols.items[0..end];
|
||||
}
|
||||
|
||||
pub fn globals(self: *Object) []Symbol {
|
||||
fn globals(self: *Object) []Symbol {
|
||||
if (self.symbols.items.len == 0) return &[0]Symbol{};
|
||||
assert(self.symbols.items.len >= self.symtab.items.len);
|
||||
const start = self.first_global orelse self.symtab.items.len;
|
||||
|
||||
@ -282,12 +282,18 @@ pub fn markLive(self: *SharedObject, elf_file: *Elf) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn globals(self: *SharedObject) []Symbol {
|
||||
return self.symbols.items;
|
||||
pub fn markImportExports(self: *SharedObject, elf_file: *Elf) void {
|
||||
for (0..self.symbols.items.len) |i| {
|
||||
const ref = self.resolveSymbol(@intCast(i), elf_file);
|
||||
const ref_sym = elf_file.symbol(ref) orelse continue;
|
||||
const ref_file = ref_sym.file(self).?;
|
||||
const vis = @as(elf.STV, @enumFromInt(ref_sym.elfSym(self).st_other));
|
||||
if (ref_file != .shared_object and vis != .HIDDEN) ref_sym.flags.@"export" = true;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn updateSymtabSize(self: *SharedObject, elf_file: *Elf) void {
|
||||
for (self.globals(), self.symbols_resolver.items) |*global, resolv| {
|
||||
for (self.symbols.items, 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;
|
||||
@ -300,7 +306,7 @@ pub fn updateSymtabSize(self: *SharedObject, elf_file: *Elf) void {
|
||||
}
|
||||
|
||||
pub fn writeSymtab(self: *SharedObject, elf_file: *Elf) void {
|
||||
for (self.globals(), self.symbols_resolver.items) |global, resolv| {
|
||||
for (self.symbols.items, 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;
|
||||
@ -354,7 +360,7 @@ pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void {
|
||||
const gpa = comp.gpa;
|
||||
var aliases = std.ArrayList(Symbol.Index).init(gpa);
|
||||
defer aliases.deinit();
|
||||
try aliases.ensureTotalCapacityPrecise(self.globals().len);
|
||||
try aliases.ensureTotalCapacityPrecise(self.symbols.items.len);
|
||||
|
||||
for (self.symbols_resolvers.items, 0..) |resolv, index| {
|
||||
const ref = elf_file.resolver.get(resolv).?;
|
||||
|
||||
@ -63,9 +63,7 @@ pub fn @"type"(symbol: Symbol, elf_file: *Elf) u4 {
|
||||
}
|
||||
|
||||
pub fn name(symbol: Symbol, elf_file: *Elf) [:0]const u8 {
|
||||
if (symbol.flags.global) return elf_file.strings.getAssumeExists(symbol.name_offset);
|
||||
const file_ptr = symbol.file(elf_file).?;
|
||||
return switch (file_ptr) {
|
||||
return switch (symbol.file(elf_file).?) {
|
||||
inline else => |x| x.getString(symbol.name_offset),
|
||||
};
|
||||
}
|
||||
@ -87,9 +85,7 @@ pub fn file(symbol: Symbol, elf_file: *Elf) ?File {
|
||||
}
|
||||
|
||||
pub fn elfSym(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym {
|
||||
const file_ptr = symbol.file(elf_file).?;
|
||||
return switch (file_ptr) {
|
||||
.zig_object => |x| x.elfSym(symbol.esym_index).*,
|
||||
return switch (symbol.file(elf_file).?) {
|
||||
inline else => |x| x.symtab.items[symbol.esym_index],
|
||||
};
|
||||
}
|
||||
@ -423,12 +419,6 @@ pub const Flags = packed struct {
|
||||
/// Whether this symbol is weak.
|
||||
weak: bool = false,
|
||||
|
||||
/// Whether the symbol has its name interned in global symbol
|
||||
/// resolver table.
|
||||
/// This happens for any symbol that is considered a global
|
||||
/// symbol, but is not necessarily an import or export.
|
||||
global: bool = false,
|
||||
|
||||
/// Whether the symbol makes into the output symtab.
|
||||
output_symtab: bool = false,
|
||||
|
||||
|
||||
@ -8,9 +8,11 @@ data: std.ArrayListUnmanaged(u8) = .{},
|
||||
path: []const u8,
|
||||
index: File.Index,
|
||||
|
||||
local_esyms: std.MultiArrayList(ElfSym) = .{},
|
||||
global_esyms: std.MultiArrayList(ElfSym) = .{},
|
||||
symtab: std.MultiArrayList(ElfSym) = .{},
|
||||
strtab: StringTable = .{},
|
||||
symbols: std.ArrayListUnmanaged(Symbol) = .{},
|
||||
symbols_extra: std.ArrayListUnmanaged(u32) = .{},
|
||||
symbols_resolver: std.ArrayListUnmanaged(Elf.SymbolResolver.Index) = .{},
|
||||
local_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
|
||||
global_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
|
||||
globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},
|
||||
@ -113,9 +115,11 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {
|
||||
|
||||
pub fn deinit(self: *ZigObject, allocator: Allocator) void {
|
||||
self.data.deinit(allocator);
|
||||
self.local_esyms.deinit(allocator);
|
||||
self.global_esyms.deinit(allocator);
|
||||
self.symtab.deinit(allocator);
|
||||
self.strtab.deinit(allocator);
|
||||
self.symbols.deinit(allocator);
|
||||
self.symbols_extra.deinit(allocator);
|
||||
self.symbols_resolver.deinit(allocator);
|
||||
self.local_symbols.deinit(allocator);
|
||||
self.global_symbols.deinit(allocator);
|
||||
self.globals_lookup.deinit(allocator);
|
||||
@ -263,51 +267,73 @@ fn saveDebugSectionsSizes(self: *ZigObject, elf_file: *Elf) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addLocalEsym(self: *ZigObject, allocator: Allocator) !Symbol.Index {
|
||||
try self.local_esyms.ensureUnusedCapacity(allocator, 1);
|
||||
const index = @as(Symbol.Index, @intCast(self.local_esyms.addOneAssumeCapacity()));
|
||||
var esym = ElfSym{ .elf_sym = Elf.null_sym };
|
||||
esym.elf_sym.st_info = elf.STB_LOCAL << 4;
|
||||
self.local_esyms.set(index, esym);
|
||||
fn newSymbol(self: *ZigObject, allocator: Allocator, name_off: u32, st_bind: u4) !Symbol.Index {
|
||||
try self.symtab.ensureUnusedCapacity(allocator, 1);
|
||||
try self.symbols.ensureUnusedCapacity(allocator, 1);
|
||||
try self.symbols_extra.ensureUnusedCapacity(allocator, @sizeOf(Symbol.Extra));
|
||||
|
||||
const index = self.addSymbolAssumeCapacity();
|
||||
const sym = &self.symbols.items[index];
|
||||
sym.name_offset = name_off;
|
||||
sym.extra = self.addSymbolExtraAssumeCapacity(.{});
|
||||
|
||||
const esym_idx: u32 = @intCast(self.symtab.addOneAssumeCapacity());
|
||||
const esym = ElfSym{ .elf_sym = .{
|
||||
.st_value = 0,
|
||||
.st_name = name_off,
|
||||
.st_info = @as(u8, @intCast(st_bind)) << 4,
|
||||
.st_other = 0,
|
||||
.st_size = 0,
|
||||
.st_shndx = 0,
|
||||
} };
|
||||
self.symtab.set(index, esym);
|
||||
sym.esym_index = esym_idx;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
pub fn addGlobalEsym(self: *ZigObject, allocator: Allocator) !Symbol.Index {
|
||||
try self.global_esyms.ensureUnusedCapacity(allocator, 1);
|
||||
const index = @as(Symbol.Index, @intCast(self.global_esyms.addOneAssumeCapacity()));
|
||||
var esym = ElfSym{ .elf_sym = Elf.null_sym };
|
||||
esym.elf_sym.st_info = elf.STB_GLOBAL << 4;
|
||||
self.global_esyms.set(index, esym);
|
||||
return index | global_symbol_bit;
|
||||
fn newLocalSymbol(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index {
|
||||
try self.local_symbols.ensureUnusedCapacity(allocator, 1);
|
||||
const fake_index: Symbol.Index = @intCast(self.local_symbols.items.len);
|
||||
const index = try self.newSymbol(allocator, name_off, elf.STB_LOCAL);
|
||||
self.local_symbols.appendAssumeCapacity(index);
|
||||
return fake_index;
|
||||
}
|
||||
|
||||
pub fn newAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index {
|
||||
const gpa = elf_file.base.comp.gpa;
|
||||
const atom_index = try self.addAtom(gpa);
|
||||
const symbol_index = try elf_file.addSymbol();
|
||||
const esym_index = try self.addLocalEsym(gpa);
|
||||
fn newGlobalSymbol(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index {
|
||||
try self.global_symbols.ensureUnusedCapacity(allocator, 1);
|
||||
const fake_index: Symbol.Index = @intCast(self.global_symbols.items.len);
|
||||
const index = try self.newSymbol(allocator, name_off, elf.STB_GLOBAL);
|
||||
self.global_symbols.appendAssumeCapacity(index);
|
||||
return fake_index | global_symbol_bit;
|
||||
}
|
||||
|
||||
try self.atoms_indexes.append(gpa, atom_index);
|
||||
try self.local_symbols.append(gpa, symbol_index);
|
||||
fn newAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Atom.Index {
|
||||
try self.atoms.ensureUnusedCapacity(allocator, 1);
|
||||
try self.atoms_extra.ensureUnusedCapacity(allocator, @sizeOf(Atom.Extra));
|
||||
try self.atoms_indexes.ensureUnusedCapacity(allocator, 1);
|
||||
try self.relocs.ensureUnusedCapacity(allocator, 1);
|
||||
|
||||
const symbol_ptr = elf_file.symbol(symbol_index);
|
||||
symbol_ptr.file_index = self.index;
|
||||
symbol_ptr.ref = .{ .index = atom_index, .file = self.index };
|
||||
symbol_ptr.extra_index = try elf_file.addSymbolExtra(.{});
|
||||
const index = self.addAtomAssumeCapacity();
|
||||
self.atoms_indexes.appendAssumeCapacity(index);
|
||||
const atom_ptr = self.atom(index).?;
|
||||
atom_ptr.name_offset = name_off;
|
||||
|
||||
self.local_esyms.items(.shndx)[esym_index] = atom_index;
|
||||
self.local_esyms.items(.elf_sym)[esym_index].st_shndx = SHN_ATOM;
|
||||
symbol_ptr.esym_index = esym_index;
|
||||
|
||||
// TODO I'm thinking that maybe we shouldn' set this value unless it's actually needed?
|
||||
const relocs_index = @as(u32, @intCast(self.relocs.items.len));
|
||||
const relocs = try self.relocs.addOne(gpa);
|
||||
relocs.* = .{};
|
||||
|
||||
const atom_ptr = self.atom(atom_index).?;
|
||||
const relocs_index: u32 = @intCast(self.relocs.items.len);
|
||||
self.relocs.addOneAssumeCapacity().* = .{};
|
||||
atom_ptr.relocs_section_index = relocs_index;
|
||||
|
||||
return symbol_index;
|
||||
return index;
|
||||
}
|
||||
|
||||
fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index {
|
||||
const atom_index = try self.newAtom(allocator, name_off);
|
||||
const sym_index = try self.newLocalSymbol(allocator, name_off);
|
||||
const sym = self.symbol(sym_index);
|
||||
sym.ref = .{ .index = atom_index, .file = self.index };
|
||||
self.symtab.items(.shndx)[sym.esym_index] = atom_index;
|
||||
self.symtab.items(.elf_sym)[sym.esym_index].st_shndx = SHN_ATOM;
|
||||
return sym_index;
|
||||
}
|
||||
|
||||
/// TODO actually create fake input shdrs and return that instead.
|
||||
@ -322,48 +348,47 @@ pub fn inputShdr(self: *ZigObject, atom_index: Atom.Index, elf_file: *Elf) elf.E
|
||||
return shdr;
|
||||
}
|
||||
|
||||
pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) void {
|
||||
for (self.globals(), 0..) |index, i| {
|
||||
const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit;
|
||||
const esym = self.global_esyms.items(.elf_sym)[i];
|
||||
const shndx = self.global_esyms.items(.shndx)[i];
|
||||
|
||||
if (esym.st_shndx == elf.SHN_UNDEF) continue;
|
||||
pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) !void {
|
||||
const gpa = elf_file.base.comp.gpa;
|
||||
|
||||
for (self.global_symbols.items, 0..) |index, i| {
|
||||
const global = &self.symbols.items[index];
|
||||
const esym = global.elfSym(elf_file);
|
||||
const shndx = self.symtab.items(.shndx)[global.esym_index];
|
||||
if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) {
|
||||
assert(esym.st_shndx == SHN_ATOM);
|
||||
const atom_ptr = self.atom(shndx) orelse continue;
|
||||
if (!atom_ptr.alive) continue;
|
||||
}
|
||||
|
||||
const global = elf_file.symbol(index);
|
||||
if (self.asFile().symbolRank(esym, false) < global.symbolRank(elf_file)) {
|
||||
const atom_index = switch (esym.st_shndx) {
|
||||
elf.SHN_ABS, elf.SHN_COMMON => 0,
|
||||
SHN_ATOM => shndx,
|
||||
else => unreachable,
|
||||
};
|
||||
global.value = @intCast(esym.st_value);
|
||||
global.ref = .{ .index = atom_index, .file = self.index };
|
||||
global.esym_index = esym_index;
|
||||
global.file_index = self.index;
|
||||
global.version_index = elf_file.default_sym_version;
|
||||
if (esym.st_bind() == elf.STB_WEAK) global.flags.weak = true;
|
||||
const resolv = &self.symbols_resolver.items[i];
|
||||
const gop = try elf_file.resolver.getOrPut(gpa, .{
|
||||
.index = @intCast(i | global_symbol_bit),
|
||||
.file = self.index,
|
||||
}, elf_file);
|
||||
if (!gop.found_existing) {
|
||||
gop.ref.* = .{ .index = 0, .file = 0 };
|
||||
}
|
||||
resolv.* = gop.index;
|
||||
|
||||
if (esym.st_shndx == elf.SHN_UNDEF) continue;
|
||||
if (elf_file.symbol(gop.ref.*) == null) {
|
||||
gop.ref.* = .{ .index = @intCast(i | global_symbol_bit), .file = self.index };
|
||||
continue;
|
||||
}
|
||||
|
||||
if (self.asFile().symbolRank(esym, !self.alive) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) {
|
||||
gop.ref.* = .{ .index = @intCast(i | global_symbol_bit), .file = self.index };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void {
|
||||
for (self.globals(), 0..) |index, i| {
|
||||
const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit;
|
||||
const esym = self.global_esyms.items(.elf_sym)[i];
|
||||
|
||||
pub fn claimUnresolved(self: *ZigObject, elf_file: *Elf) void {
|
||||
for (self.global_symbols.items, 0..) |index, i| {
|
||||
const global = &self.symbols.items[index];
|
||||
const esym = self.symtab.items(.elf_sym)[index];
|
||||
if (esym.st_shndx != elf.SHN_UNDEF) continue;
|
||||
|
||||
const global = elf_file.symbol(index);
|
||||
if (global.file(elf_file)) |_| {
|
||||
if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF) continue;
|
||||
}
|
||||
if (elf_file.symbol(self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file)) != null) continue;
|
||||
|
||||
const is_import = blk: {
|
||||
if (!elf_file.isEffectivelyDynLib()) break :blk false;
|
||||
@ -374,29 +399,36 @@ pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void {
|
||||
|
||||
global.value = 0;
|
||||
global.ref = .{ .index = 0, .file = 0 };
|
||||
global.esym_index = esym_index;
|
||||
global.esym_index = @intCast(index);
|
||||
global.file_index = self.index;
|
||||
global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;
|
||||
global.flags.import = is_import;
|
||||
|
||||
const idx = self.symbols_resolver.items[i];
|
||||
elf_file.resolver.values.items[idx - 1] = .{ .index = @intCast(i | global_symbol_bit), .file = self.index };
|
||||
}
|
||||
}
|
||||
|
||||
pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void {
|
||||
for (self.globals(), 0..) |index, i| {
|
||||
const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit;
|
||||
const esym = self.global_esyms.items(.elf_sym)[i];
|
||||
|
||||
for (self.global_symbols.items, 0..) |index, i| {
|
||||
const global = &self.symbols.items[index];
|
||||
const esym = self.symtab.items(.elf_sym)[index];
|
||||
if (esym.st_shndx != elf.SHN_UNDEF) continue;
|
||||
if (elf_file.symbol(self.resolveSymbol(@intCast(i | global_symbol_bit), 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.esym_index = @intCast(index);
|
||||
global.file_index = self.index;
|
||||
|
||||
const idx = self.symbols_resolver.items[i];
|
||||
elf_file.resolver.items[idx - 1] = .{ .index = @intCast(i | global_symbol_bit), .file = self.index };
|
||||
}
|
||||
}
|
||||
|
||||
@ -419,12 +451,14 @@ pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void {
|
||||
}
|
||||
|
||||
pub fn markLive(self: *ZigObject, elf_file: *Elf) void {
|
||||
for (self.globals(), 0..) |index, i| {
|
||||
const esym = self.global_esyms.items(.elf_sym)[i];
|
||||
for (self.global_symbols.items, 0..) |index, i| {
|
||||
const global = self.symbols.items[index];
|
||||
const esym = self.symtab.items(.elf_sym)[index];
|
||||
if (esym.st_bind() == elf.STB_WEAK) continue;
|
||||
|
||||
const global = elf_file.symbol(index);
|
||||
const file = global.file(elf_file) orelse continue;
|
||||
const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), 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 global.elfSym(elf_file).st_shndx != elf.SHN_COMMON);
|
||||
if (should_keep and !file.isAlive()) {
|
||||
@ -434,14 +468,36 @@ pub fn markLive(self: *ZigObject, elf_file: *Elf) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void {
|
||||
for (self.globals(), 0..) |index, i| {
|
||||
const esym = self.global_esyms.items(.elf_sym)[i];
|
||||
const shndx = self.global_esyms.items(.shndx)[i];
|
||||
const global = elf_file.symbol(index);
|
||||
const global_file = global.file(elf_file) orelse continue;
|
||||
pub fn markImportsExports(self: *Object, elf_file: *Elf) void {
|
||||
for (0..self.global_symbols.items.len) |i| {
|
||||
const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file);
|
||||
const sym = elf_file.symbol(ref) orelse continue;
|
||||
const file = sym.file(elf_file).?;
|
||||
if (sym.version_index == elf.VER_NDX_LOCAL) continue;
|
||||
const vis = @as(elf.STV, @enumFromInt(sym.elfSym(elf_file).st_other));
|
||||
if (vis == .HIDDEN) continue;
|
||||
if (file == .shared_object and !sym.isAbs(elf_file)) {
|
||||
sym.flags.import = true;
|
||||
continue;
|
||||
}
|
||||
if (file.index() == self.index) {
|
||||
sym.flags.@"export" = true;
|
||||
if (elf_file.isEffectivelyDynLib() and vis != .PROTECTED) {
|
||||
sym.flags.import = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (self.index == global_file.index() or
|
||||
pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void {
|
||||
for (self.global_symbols.items, 0..) |index, i| {
|
||||
const esym = self.symtab.items(.elf_sym)[index];
|
||||
const shndx = self.symtab.items(.shndx)[index];
|
||||
const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), 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;
|
||||
@ -451,7 +507,7 @@ pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{O
|
||||
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.* = .{};
|
||||
}
|
||||
@ -483,12 +539,13 @@ pub fn readFileContents(self: *ZigObject, elf_file: *Elf) !void {
|
||||
pub fn updateArSymtab(self: ZigObject, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) error{OutOfMemory}!void {
|
||||
const gpa = elf_file.base.comp.gpa;
|
||||
|
||||
try ar_symtab.symtab.ensureUnusedCapacity(gpa, self.globals().len);
|
||||
try ar_symtab.symtab.ensureUnusedCapacity(gpa, self.global_symbols.items.len);
|
||||
|
||||
for (self.globals()) |global_index| {
|
||||
const global = elf_file.symbol(global_index);
|
||||
const file_ptr = global.file(elf_file).?;
|
||||
assert(file_ptr.index() == self.index);
|
||||
for (self.global_symbols.items, 0..) |index, i| {
|
||||
const global = self.symbols.items[index];
|
||||
const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file);
|
||||
const sym = elf_file.symbol(ref).?;
|
||||
assert(sym.file(elf_file).?.index() == self.index);
|
||||
if (global.outputShndx(elf_file) == null) continue;
|
||||
|
||||
const off = try ar_symtab.strtab.insert(gpa, global.name(elf_file));
|
||||
@ -530,33 +587,9 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void {
|
||||
}
|
||||
}
|
||||
|
||||
inline fn isGlobal(index: Symbol.Index) bool {
|
||||
return index & global_symbol_bit != 0;
|
||||
}
|
||||
|
||||
pub fn symbol(self: ZigObject, index: Symbol.Index) Symbol.Index {
|
||||
const actual_index = index & symbol_mask;
|
||||
if (isGlobal(index)) return self.globals()[actual_index];
|
||||
return self.locals()[actual_index];
|
||||
}
|
||||
|
||||
pub fn elfSym(self: *ZigObject, index: Symbol.Index) *elf.Elf64_Sym {
|
||||
const actual_index = index & symbol_mask;
|
||||
if (isGlobal(index)) return &self.global_esyms.items(.elf_sym)[actual_index];
|
||||
return &self.local_esyms.items(.elf_sym)[actual_index];
|
||||
}
|
||||
|
||||
pub fn locals(self: ZigObject) []const Symbol.Index {
|
||||
return self.local_symbols.items;
|
||||
}
|
||||
|
||||
pub fn globals(self: ZigObject) []const Symbol.Index {
|
||||
return self.global_symbols.items;
|
||||
}
|
||||
|
||||
pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void {
|
||||
for (self.locals()) |local_index| {
|
||||
const local = elf_file.symbol(local_index);
|
||||
for (self.local_symbols.items) |index| {
|
||||
const local = &self.symbols.items[index];
|
||||
if (local.atom(elf_file)) |atom_ptr| if (!atom_ptr.alive) continue;
|
||||
const esym = local.elfSym(elf_file);
|
||||
switch (esym.st_type()) {
|
||||
@ -564,22 +597,23 @@ pub fn updateSymtabSize(self: *ZigObject, 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.global_symbols.items, self.symbols_resolver.items) |index, resolv| {
|
||||
const global = &self.symbols.items[index];
|
||||
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 (global.atom(elf_file)) |atom_ptr| if (!atom_ptr.alive) 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;
|
||||
@ -587,8 +621,8 @@ pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void {
|
||||
}
|
||||
|
||||
pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void {
|
||||
for (self.locals()) |local_index| {
|
||||
const local = elf_file.symbol(local_index);
|
||||
for (self.local_symbols.items) |index| {
|
||||
const local = &self.symbols.items[index];
|
||||
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);
|
||||
@ -597,10 +631,11 @@ pub fn writeSymtab(self: ZigObject, 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.global_symbols.items, self.symbols_resolver.items) |index, resolv| {
|
||||
const global = self.symbols.items[index];
|
||||
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));
|
||||
@ -611,10 +646,6 @@ pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn asFile(self: *ZigObject) File {
|
||||
return .{ .zig_object = self };
|
||||
}
|
||||
|
||||
/// Returns atom's code.
|
||||
/// Caller owns the memory.
|
||||
pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 {
|
||||
@ -755,8 +786,8 @@ pub fn getOrCreateMetadataForLazySymbol(
|
||||
};
|
||||
switch (metadata.state.*) {
|
||||
.unused => {
|
||||
const symbol_index = try self.newAtom(elf_file);
|
||||
const sym = elf_file.symbol(symbol_index);
|
||||
const symbol_index = try self.newSymbolWithAtom(gpa, 0);
|
||||
const sym = self.symbol(symbol_index);
|
||||
sym.flags.needs_zig_got = true;
|
||||
metadata.symbol_index.* = symbol_index;
|
||||
},
|
||||
@ -817,10 +848,10 @@ pub fn getOrCreateMetadataForDecl(
|
||||
const gop = try self.decls.getOrPut(gpa, decl_index);
|
||||
if (!gop.found_existing) {
|
||||
const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded;
|
||||
const symbol_index = try self.newAtom(elf_file);
|
||||
const symbol_index = try self.newSymbolWithAtom(gpa, 0);
|
||||
const mod = elf_file.base.comp.module.?;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const sym = elf_file.symbol(symbol_index);
|
||||
const sym = self.symbol(symbol_index);
|
||||
if (decl.getOwnedVariable(mod)) |variable| {
|
||||
if (variable.is_threadlocal and any_non_single_threaded) {
|
||||
sym.flags.is_tls = true;
|
||||
@ -1064,7 +1095,7 @@ pub fn updateFunc(
|
||||
|
||||
const sym_index = try self.getOrCreateMetadataForDecl(elf_file, decl_index);
|
||||
self.freeUnnamedConsts(elf_file, decl_index);
|
||||
elf_file.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file);
|
||||
self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file);
|
||||
|
||||
var code_buffer = std.ArrayList(u8).init(gpa);
|
||||
defer code_buffer.deinit();
|
||||
@ -1096,7 +1127,7 @@ pub fn updateFunc(
|
||||
try self.updateDeclCode(elf_file, pt, decl_index, sym_index, shndx, code, elf.STT_FUNC);
|
||||
|
||||
if (decl_state) |*ds| {
|
||||
const sym = elf_file.symbol(sym_index);
|
||||
const sym = self.symbol(sym_index);
|
||||
try self.dwarf.?.commitDeclState(
|
||||
pt,
|
||||
decl_index,
|
||||
@ -1130,13 +1161,13 @@ pub fn updateDecl(
|
||||
const variable = decl.getOwnedVariable(mod).?;
|
||||
const name = decl.name.toSlice(&mod.intern_pool);
|
||||
const lib_name = variable.lib_name.toSlice(&mod.intern_pool);
|
||||
const esym_index = try self.getGlobalSymbol(elf_file, name, lib_name);
|
||||
elf_file.symbol(self.symbol(esym_index)).flags.needs_got = true;
|
||||
const sym_index = try self.getGlobalSymbol(elf_file, name, lib_name);
|
||||
self.symbol(sym_index).flags.needs_got = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const sym_index = try self.getOrCreateMetadataForDecl(elf_file, decl_index);
|
||||
elf_file.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file);
|
||||
self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file);
|
||||
|
||||
const gpa = elf_file.base.comp.gpa;
|
||||
var code_buffer = std.ArrayList(u8).init(gpa);
|
||||
@ -1174,7 +1205,7 @@ pub fn updateDecl(
|
||||
try self.updateDeclCode(elf_file, pt, decl_index, sym_index, shndx, code, elf.STT_OBJECT);
|
||||
|
||||
if (decl_state) |*ds| {
|
||||
const sym = elf_file.symbol(sym_index);
|
||||
const sym = self.symbol(sym_index);
|
||||
try self.dwarf.?.commitDeclState(
|
||||
pt,
|
||||
decl_index,
|
||||
@ -1323,7 +1354,8 @@ fn lowerConst(
|
||||
var code_buffer = std.ArrayList(u8).init(gpa);
|
||||
defer code_buffer.deinit();
|
||||
|
||||
const sym_index = try self.newAtom(elf_file);
|
||||
const name_off = try self.addString(gpa, name);
|
||||
const sym_index = try self.newSymbolWithAtom(gpa, name_off);
|
||||
|
||||
const res = try codegen.generateSymbol(
|
||||
&elf_file.base,
|
||||
@ -1339,27 +1371,19 @@ fn lowerConst(
|
||||
.fail => |em| return .{ .fail = em },
|
||||
};
|
||||
|
||||
const local_sym = elf_file.symbol(sym_index);
|
||||
const name_str_index = try self.strtab.insert(gpa, name);
|
||||
local_sym.name_offset = name_str_index;
|
||||
const local_esym = &self.local_esyms.items(.elf_sym)[local_sym.esym_index];
|
||||
local_esym.st_name = name_str_index;
|
||||
const local_sym = self.symbol(sym_index);
|
||||
const local_esym = local_sym.elfSym(elf_file);
|
||||
local_esym.st_info |= elf.STT_OBJECT;
|
||||
local_esym.st_size = code.len;
|
||||
const atom_ptr = local_sym.atom(elf_file).?;
|
||||
atom_ptr.alive = true;
|
||||
atom_ptr.name_offset = name_str_index;
|
||||
atom_ptr.alignment = required_alignment;
|
||||
atom_ptr.size = code.len;
|
||||
atom_ptr.output_section_index = output_section_index;
|
||||
|
||||
try atom_ptr.allocate(elf_file);
|
||||
// TODO rename and re-audit this method
|
||||
errdefer self.freeDeclMetadata(elf_file, sym_index);
|
||||
|
||||
local_sym.value = 0;
|
||||
local_esym.st_value = 0;
|
||||
|
||||
const shdr = elf_file.shdrs.items[output_section_index];
|
||||
const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value));
|
||||
try elf_file.base.file.?.pwriteAll(code, file_offset);
|
||||
@ -1401,9 +1425,9 @@ pub fn updateExports(
|
||||
},
|
||||
};
|
||||
const sym_index = metadata.symbol_index;
|
||||
const esym_index = elf_file.symbol(sym_index).esym_index;
|
||||
const esym = self.local_esyms.items(.elf_sym)[esym_index];
|
||||
const esym_shndx = self.local_esyms.items(.shndx)[esym_index];
|
||||
const esym_index = self.symbol(sym_index).esym_index;
|
||||
const esym = self.symtab.items(.elf_sym)[esym_index];
|
||||
const esym_shndx = self.symtab.items(.shndx)[esym_index];
|
||||
|
||||
for (export_indices) |export_idx| {
|
||||
const exp = mod.all_exports.items[export_idx];
|
||||
@ -1437,22 +1461,27 @@ pub fn updateExports(
|
||||
const stt_bits: u8 = @as(u4, @truncate(esym.st_info));
|
||||
const exp_name = exp.opts.name.toSlice(&mod.intern_pool);
|
||||
const name_off = try self.strtab.insert(gpa, exp_name);
|
||||
const global_esym_index = if (metadata.@"export"(self, exp_name)) |exp_index|
|
||||
const global_sym_index = if (metadata.@"export"(self, exp_name)) |exp_index|
|
||||
exp_index.*
|
||||
else blk: {
|
||||
const global_esym_index = try self.getGlobalSymbol(elf_file, exp_name, null);
|
||||
try metadata.exports.append(gpa, global_esym_index);
|
||||
break :blk global_esym_index;
|
||||
const global_sym_index = try self.getGlobalSymbol(elf_file, exp_name, null);
|
||||
try metadata.exports.append(gpa, global_sym_index);
|
||||
break :blk global_sym_index;
|
||||
};
|
||||
|
||||
const actual_esym_index = global_esym_index & symbol_mask;
|
||||
const global_esym = &self.global_esyms.items(.elf_sym)[actual_esym_index];
|
||||
global_esym.st_value = @intCast(elf_file.symbol(sym_index).value);
|
||||
const value = self.symbol(sym_index).value;
|
||||
const global_sym = self.symbol(global_sym_index);
|
||||
global_sym.value = value;
|
||||
global_sym.flags.weak = exp.opts.linkage == .weak;
|
||||
global_sym.version_index = elf_file.default_version_index;
|
||||
global_sym.ref = .{ .index = esym_shndx, .file = self.index };
|
||||
const global_esym = global_sym.elfSym(elf_file);
|
||||
global_esym.st_value = @intCast(value);
|
||||
global_esym.st_shndx = esym.st_shndx;
|
||||
global_esym.st_info = (stb_bits << 4) | stt_bits;
|
||||
global_esym.st_name = name_off;
|
||||
global_esym.st_size = esym.st_size;
|
||||
self.global_esyms.items(.shndx)[actual_esym_index] = esym_shndx;
|
||||
self.symtab.items(.shndx)[global_sym.esym_index] = esym_shndx;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1506,16 +1535,19 @@ pub fn getGlobalSymbol(self: *ZigObject, elf_file: *Elf, name: []const u8, lib_n
|
||||
const off = try self.strtab.insert(gpa, name);
|
||||
const lookup_gop = try self.globals_lookup.getOrPut(gpa, off);
|
||||
if (!lookup_gop.found_existing) {
|
||||
const esym_index = try self.addGlobalEsym(gpa);
|
||||
const esym = self.elfSym(esym_index);
|
||||
esym.st_name = off;
|
||||
lookup_gop.value_ptr.* = esym_index;
|
||||
const gop = try elf_file.getOrPutGlobal(name);
|
||||
try self.global_symbols.append(gpa, gop.index);
|
||||
lookup_gop.value_ptr.* = try self.newSymbol(gpa, off);
|
||||
}
|
||||
return lookup_gop.value_ptr.*;
|
||||
}
|
||||
|
||||
pub fn asFile(self: *ZigObject) File {
|
||||
return .{ .zig_object = self };
|
||||
}
|
||||
|
||||
fn addString(self: *ZigObject, allocator: Allocator, string: []const u8) !u32 {
|
||||
return self.strtab.insert(allocator, string);
|
||||
}
|
||||
|
||||
pub fn getString(self: ZigObject, off: u32) [:0]const u8 {
|
||||
return self.strtab.getAssumeExists(off);
|
||||
}
|
||||
@ -1586,6 +1618,73 @@ pub fn setAtomExtra(self: *ZigObject, index: u32, extra: Atom.Extra) void {
|
||||
}
|
||||
}
|
||||
|
||||
inline fn isGlobal(index: Symbol.Index) bool {
|
||||
return index & global_symbol_bit != 0;
|
||||
}
|
||||
|
||||
pub fn symbol(self: *ZigObject, index: Symbol.Index) *Symbol {
|
||||
const actual_index = index & symbol_mask;
|
||||
if (isGlobal(index)) return &self.symbols.items[self.global_symbols.items[actual_index]];
|
||||
return &self.symbols.items[self.local_symbols.items[actual_index]];
|
||||
}
|
||||
|
||||
pub fn resolveSymbol(self: ZigObject, index: Symbol.Index, elf_file: *Elf) Elf.Ref {
|
||||
if (isGlobal(index)) {
|
||||
const resolv = self.symbols_resolver.items[index & symbol_mask];
|
||||
return elf_file.resolver.get(resolv).?;
|
||||
}
|
||||
return .{ .index = index, .file = self.index };
|
||||
}
|
||||
|
||||
pub fn addSymbol(self: *ZigObject, 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: *ZigObject, 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: *ZigObject, 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: *ZigObject, 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: *ZigObject, 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 fmtSymtab(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(formatSymtab) {
|
||||
return .{ .data = .{
|
||||
.self = self,
|
||||
@ -1658,9 +1757,9 @@ const DeclMetadata = struct {
|
||||
/// A list of all exports aliases of this Decl.
|
||||
exports: std.ArrayListUnmanaged(Symbol.Index) = .{},
|
||||
|
||||
fn @"export"(m: DeclMetadata, zig_object: *ZigObject, name: []const u8) ?*u32 {
|
||||
fn @"export"(m: DeclMetadata, zo: *ZigObject, name: []const u8) ?*u32 {
|
||||
for (m.exports.items) |*exp| {
|
||||
const exp_name = zig_object.getString(zig_object.elfSym(exp.*).st_name);
|
||||
const exp_name = zo.getString(zo.symbol(exp.*).name_off);
|
||||
if (mem.eql(u8, name, exp_name)) return exp;
|
||||
}
|
||||
return null;
|
||||
|
||||
@ -153,19 +153,6 @@ pub const File = union(enum) {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn locals(file: File) []const Symbol.Index {
|
||||
return switch (file) {
|
||||
.linker_defined, .shared_object => &[0]Symbol.Index{},
|
||||
inline else => |x| x.locals(),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn globals(file: File) []const Symbol.Index {
|
||||
return switch (file) {
|
||||
inline else => |x| x.globals(),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getString(file: File, off: u32) [:0]const u8 {
|
||||
return switch (file) {
|
||||
inline else => |x| x.getString(off),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user