elf: start fixing symbol resolution
This commit is contained in:
@@ -836,14 +836,20 @@ pub fn populateMissingMetadata(self: *Elf) !void {
|
||||
} });
|
||||
self.zig_module_index = index;
|
||||
const zig_module = self.file(index).?.zig_module;
|
||||
const sym_index = try zig_module.addLocal(self);
|
||||
const sym = self.symbol(sym_index);
|
||||
const esym = zig_module.sourceSymbol(sym_index, self);
|
||||
|
||||
const name_off = try self.strtab.insert(gpa, std.fs.path.stem(module.main_pkg.root_src_path));
|
||||
sym.name_offset = name_off;
|
||||
const symbol_index = try self.addSymbol();
|
||||
try zig_module.local_symbols.append(gpa, symbol_index);
|
||||
const symbol_ptr = self.symbol(symbol_index);
|
||||
symbol_ptr.file_index = zig_module.index;
|
||||
symbol_ptr.name_offset = name_off;
|
||||
|
||||
const esym_index = try zig_module.addLocalEsym(gpa);
|
||||
const esym = &zig_module.local_esyms.items[esym_index];
|
||||
esym.st_name = name_off;
|
||||
esym.st_info |= elf.STT_FILE;
|
||||
esym.st_shndx = elf.SHN_ABS;
|
||||
symbol_ptr.esym_index = esym_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2194,7 +2200,7 @@ pub fn getOrCreateMetadataForLazySymbol(self: *Elf, sym: link.File.LazySymbol) !
|
||||
};
|
||||
const zig_module = self.file(self.zig_module_index.?).?.zig_module;
|
||||
switch (metadata.state.*) {
|
||||
.unused => metadata.symbol_index.* = try zig_module.createAtom(switch (sym.kind) {
|
||||
.unused => metadata.symbol_index.* = try zig_module.addAtom(switch (sym.kind) {
|
||||
.code => self.text_section_index.?,
|
||||
.const_data => self.rodata_section_index.?,
|
||||
}, self),
|
||||
@@ -2213,7 +2219,7 @@ pub fn getOrCreateMetadataForDecl(self: *Elf, decl_index: Module.Decl.Index) !Sy
|
||||
if (!gop.found_existing) {
|
||||
const zig_module = self.file(self.zig_module_index.?).?.zig_module;
|
||||
gop.value_ptr.* = .{
|
||||
.symbol_index = try zig_module.createAtom(self.getDeclShdrIndex(decl_index), self),
|
||||
.symbol_index = try zig_module.addAtom(self.getDeclShdrIndex(decl_index), self),
|
||||
.exports = .{},
|
||||
};
|
||||
}
|
||||
@@ -2264,7 +2270,7 @@ fn updateDeclCode(
|
||||
const required_alignment = decl.getAlignment(mod);
|
||||
|
||||
const sym = self.symbol(sym_index);
|
||||
const esym = zig_module.sourceSymbol(sym_index, self);
|
||||
const esym = &zig_module.local_esyms.items[sym.esym_index];
|
||||
const atom_ptr = sym.atom(self).?;
|
||||
const shdr_index = sym.output_section_index;
|
||||
|
||||
@@ -2521,7 +2527,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol.
|
||||
const local_sym = self.symbol(symbol_index);
|
||||
const phdr_index = self.phdr_to_shdr_table.get(local_sym.output_section_index).?;
|
||||
local_sym.name_offset = name_str_index;
|
||||
const local_esym = zig_module.sourceSymbol(symbol_index, self);
|
||||
const local_esym = &zig_module.local_esyms.items[local_sym.esym_index];
|
||||
local_esym.st_name = name_str_index;
|
||||
local_esym.st_info |= elf.STT_OBJECT;
|
||||
local_esym.st_size = code.len;
|
||||
@@ -2575,7 +2581,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
|
||||
const name = self.strtab.get(name_str_index).?;
|
||||
|
||||
const zig_module = self.file(self.zig_module_index.?).?.zig_module;
|
||||
const sym_index = try zig_module.createAtom(self.rodata_section_index.?, self);
|
||||
const sym_index = try zig_module.addAtom(self.rodata_section_index.?, self);
|
||||
|
||||
const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), typed_value, &code_buffer, .{
|
||||
.none = {},
|
||||
@@ -2597,7 +2603,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
|
||||
const phdr_index = self.phdr_to_shdr_table.get(shdr_index).?;
|
||||
const local_sym = self.symbol(sym_index);
|
||||
local_sym.name_offset = name_str_index;
|
||||
const local_esym = zig_module.sourceSymbol(sym_index, self);
|
||||
const local_esym = &zig_module.local_esyms.items[local_sym.esym_index];
|
||||
local_esym.st_name = name_str_index;
|
||||
local_esym.st_info |= elf.STT_OBJECT;
|
||||
local_esym.st_size = code.len;
|
||||
@@ -2642,10 +2648,11 @@ pub fn updateDeclExports(
|
||||
|
||||
const gpa = self.base.allocator;
|
||||
|
||||
const zig_module = self.file(self.zig_module_index.?).?.zig_module;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const decl_sym_index = try self.getOrCreateMetadataForDecl(decl_index);
|
||||
const decl_sym = self.symbol(decl_sym_index);
|
||||
const decl_esym = decl_sym.sourceSymbol(self);
|
||||
const decl_esym = zig_module.local_esyms.items[decl_sym.esym_index];
|
||||
const decl_metadata = self.decls.getPtr(decl_index).?;
|
||||
|
||||
for (exports) |exp| {
|
||||
@@ -2681,21 +2688,21 @@ pub fn updateDeclExports(
|
||||
};
|
||||
const stt_bits: u8 = @as(u4, @truncate(decl_esym.st_info));
|
||||
|
||||
const zig_module = self.file(self.zig_module_index.?).?.zig_module;
|
||||
const sym_index = if (decl_metadata.@"export"(self, exp_name)) |exp_index| exp_index.* else blk: {
|
||||
const sym_index = try zig_module.addGlobal(exp_name, self);
|
||||
const sym_index = try zig_module.addGlobalEsym(gpa);
|
||||
_ = try zig_module.global_symbols.addOne(gpa);
|
||||
try decl_metadata.exports.append(gpa, sym_index);
|
||||
break :blk sym_index;
|
||||
};
|
||||
const sym = self.symbol(sym_index);
|
||||
sym.flags.@"export" = true;
|
||||
sym.value = decl_sym.value;
|
||||
sym.atom_index = decl_sym.atom_index;
|
||||
sym.output_section_index = decl_sym.output_section_index;
|
||||
const esym = zig_module.sourceSymbol(sym_index, self);
|
||||
esym.* = decl_esym;
|
||||
const name_off = try self.strtab.insert(gpa, exp_name);
|
||||
const esym = &zig_module.global_esyms.items[sym_index];
|
||||
esym.st_value = decl_sym.value;
|
||||
esym.st_shndx = decl_sym.output_section_index;
|
||||
esym.st_info = (stb_bits << 4) | stt_bits;
|
||||
_ = self.unresolved.swapRemove(sym_index);
|
||||
esym.st_name = name_off;
|
||||
|
||||
const gop = try self.getOrPutGlobal(name_off);
|
||||
zig_module.global_symbols.items[sym_index] = gop.index;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2722,20 +2729,20 @@ pub fn deleteDeclExport(
|
||||
) void {
|
||||
if (self.llvm_object) |_| return;
|
||||
const metadata = self.decls.getPtr(decl_index) orelse return;
|
||||
const gpa = self.base.allocator;
|
||||
const mod = self.base.options.module.?;
|
||||
const zig_module = self.file(self.zig_module_index.?).?.zig_module;
|
||||
const exp_name = mod.intern_pool.stringToSlice(name);
|
||||
const sym_index = metadata.@"export"(self, exp_name) orelse return;
|
||||
const esym_index = metadata.@"export"(self, exp_name) orelse return;
|
||||
log.debug("deleting export '{s}'", .{exp_name});
|
||||
const sym = self.symbol(sym_index.*);
|
||||
const esym = zig_module.sourceSymbol(sym_index.*, self);
|
||||
assert(self.resolver.fetchSwapRemove(sym.name_offset) != null); // TODO don't delete it if it's not dominant
|
||||
sym.* = .{};
|
||||
// TODO free list for esym!
|
||||
const esym = &zig_module.global_esyms.items[esym_index.*];
|
||||
_ = zig_module.globals_lookup.remove(esym.st_name);
|
||||
const sym_index = self.resolver.get(esym.st_name).?;
|
||||
const sym = self.symbol(sym_index);
|
||||
if (sym.file_index == zig_module.index) {
|
||||
_ = self.resolver.swapRemove(esym.st_name);
|
||||
sym.* = .{};
|
||||
}
|
||||
esym.* = null_sym;
|
||||
self.symbols_free_list.append(gpa, sym_index.*) catch {};
|
||||
sym_index.* = 0;
|
||||
}
|
||||
|
||||
fn addLinkerDefinedSymbols(self: *Elf) !void {
|
||||
@@ -3468,8 +3475,18 @@ pub fn globalByName(self: *Elf, name: []const u8) ?Symbol.Index {
|
||||
|
||||
pub fn getGlobalSymbol(self: *Elf, name: []const u8, lib_name: ?[]const u8) !u32 {
|
||||
_ = lib_name;
|
||||
const gpa = self.base.allocator;
|
||||
const off = try self.strtab.insert(gpa, name);
|
||||
const gop = try self.getOrPutGlobal(off);
|
||||
const zig_module = self.file(self.zig_module_index.?).?.zig_module;
|
||||
return zig_module.addGlobal(name, self);
|
||||
const lookup_gop = try zig_module.globals_lookup.getOrPut(gpa, off);
|
||||
if (!lookup_gop.found_existing) {
|
||||
const esym_index = try zig_module.addGlobalEsym(gpa);
|
||||
const esym = &zig_module.global_esyms.items[esym_index];
|
||||
esym.st_name = off;
|
||||
lookup_gop.value_ptr.* = esym_index;
|
||||
}
|
||||
return gop.index;
|
||||
}
|
||||
|
||||
const GetOrCreateComdatGroupOwnerResult = struct {
|
||||
@@ -3753,8 +3770,10 @@ const DeclMetadata = struct {
|
||||
exports: std.ArrayListUnmanaged(Symbol.Index) = .{},
|
||||
|
||||
fn @"export"(m: DeclMetadata, elf_file: *Elf, name: []const u8) ?*u32 {
|
||||
const zig_module = elf_file.file(elf_file.zig_module_index.?).?.zig_module;
|
||||
for (m.exports.items) |*exp| {
|
||||
if (mem.eql(u8, name, elf_file.symbol(exp.*).name(elf_file))) return exp;
|
||||
const exp_name = elf_file.strtab.getAssumeExists(zig_module.global_esyms.items[exp.*].st_name);
|
||||
if (mem.eql(u8, name, exp_name)) return exp;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@ shdrs: std.ArrayListUnmanaged(elf.Elf64_Shdr) = .{},
|
||||
strings: StringTable(.object_strings) = .{},
|
||||
symtab: []align(1) const elf.Elf64_Sym = &[0]elf.Elf64_Sym{},
|
||||
strtab: []const u8 = &[0]u8{},
|
||||
first_global: ?u32 = null,
|
||||
first_global: ?Symbol.Index = null,
|
||||
|
||||
symbols: std.ArrayListUnmanaged(u32) = .{},
|
||||
symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
|
||||
atoms: std.ArrayListUnmanaged(Atom.Index) = .{},
|
||||
comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup.Index) = .{},
|
||||
|
||||
|
||||
@@ -69,9 +69,13 @@ pub fn file(symbol: Symbol, elf_file: *Elf) ?File {
|
||||
pub fn sourceSymbol(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym {
|
||||
const file_ptr = symbol.file(elf_file).?;
|
||||
switch (file_ptr) {
|
||||
.zig_module => return file_ptr.zig_module.sourceSymbol(symbol.index, elf_file).*,
|
||||
.linker_defined => return file_ptr.linker_defined.symtab.items[symbol.esym_index],
|
||||
.object => return file_ptr.object.symtab[symbol.esym_index],
|
||||
.zig_module => |x| {
|
||||
const is_global = x.globals_lookup.contains(symbol.name_offset);
|
||||
if (is_global) return x.global_esyms.items[symbol.esym_index];
|
||||
return x.local_esyms.items[symbol.esym_index];
|
||||
},
|
||||
.linker_defined => |x| return x.symtab.items[symbol.esym_index],
|
||||
.object => |x| return x.symtab[symbol.esym_index],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +168,10 @@ pub fn setExtra(symbol: Symbol, extras: Extra, elf_file: *Elf) void {
|
||||
}
|
||||
|
||||
pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
|
||||
const file_ptr = symbol.file(elf_file).?;
|
||||
const file_ptr = symbol.file(elf_file) orelse {
|
||||
out.* = Elf.null_sym;
|
||||
return;
|
||||
};
|
||||
const s_sym = symbol.sourceSymbol(elf_file);
|
||||
const st_type = symbol.type(elf_file);
|
||||
const st_bind: u8 = blk: {
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
path: []const u8,
|
||||
index: File.Index,
|
||||
|
||||
elf_local_symbols: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
|
||||
local_symbols: std.AutoArrayHashMapUnmanaged(Symbol.Index, void) = .{},
|
||||
|
||||
elf_global_symbols: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
|
||||
global_symbols: std.AutoArrayHashMapUnmanaged(Symbol.Index, void) = .{},
|
||||
local_esyms: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
|
||||
global_esyms: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
|
||||
local_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
|
||||
global_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
|
||||
globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},
|
||||
|
||||
atoms: std.AutoArrayHashMapUnmanaged(Atom.Index, void) = .{},
|
||||
relocs: std.ArrayListUnmanaged(std.ArrayListUnmanaged(elf.Elf64_Rela)) = .{},
|
||||
@@ -14,10 +14,11 @@ relocs: std.ArrayListUnmanaged(std.ArrayListUnmanaged(elf.Elf64_Rela)) = .{},
|
||||
output_symtab_size: Elf.SymtabSize = .{},
|
||||
|
||||
pub fn deinit(self: *ZigModule, allocator: Allocator) void {
|
||||
self.elf_local_symbols.deinit(allocator);
|
||||
self.local_esyms.deinit(allocator);
|
||||
self.global_esyms.deinit(allocator);
|
||||
self.local_symbols.deinit(allocator);
|
||||
self.elf_global_symbols.deinit(allocator);
|
||||
self.global_symbols.deinit(allocator);
|
||||
self.globals_lookup.deinit(allocator);
|
||||
self.atoms.deinit(allocator);
|
||||
for (self.relocs.items) |*list| {
|
||||
list.deinit(allocator);
|
||||
@@ -25,58 +26,57 @@ pub fn deinit(self: *ZigModule, allocator: Allocator) void {
|
||||
self.relocs.deinit(allocator);
|
||||
}
|
||||
|
||||
pub fn createAtom(self: *ZigModule, output_section_index: u16, elf_file: *Elf) !Symbol.Index {
|
||||
pub fn addLocalEsym(self: *ZigModule, allocator: Allocator) !Symbol.Index {
|
||||
try self.local_esyms.ensureUnusedCapacity(allocator, 1);
|
||||
const index = @as(Symbol.Index, @intCast(self.local_esyms.items.len));
|
||||
const esym = self.local_esyms.addOneAssumeCapacity();
|
||||
esym.* = Elf.null_sym;
|
||||
esym.st_info = elf.STB_LOCAL << 4;
|
||||
return index;
|
||||
}
|
||||
|
||||
pub fn addGlobalEsym(self: *ZigModule, allocator: Allocator) !Symbol.Index {
|
||||
try self.global_esyms.ensureUnusedCapacity(allocator, 1);
|
||||
const index = @as(Symbol.Index, @intCast(self.global_esyms.items.len));
|
||||
const esym = self.global_esyms.addOneAssumeCapacity();
|
||||
esym.* = Elf.null_sym;
|
||||
esym.st_info = elf.STB_GLOBAL << 4;
|
||||
return index;
|
||||
}
|
||||
|
||||
pub fn addAtom(self: *ZigModule, output_section_index: u16, elf_file: *Elf) !Symbol.Index {
|
||||
const gpa = elf_file.base.allocator;
|
||||
|
||||
const atom_index = try elf_file.addAtom();
|
||||
const symbol_index = try self.addLocal(elf_file);
|
||||
try self.atoms.putNoClobber(gpa, atom_index, {});
|
||||
const atom_ptr = elf_file.atom(atom_index).?;
|
||||
atom_ptr.file_index = self.index;
|
||||
atom_ptr.output_section_index = output_section_index;
|
||||
|
||||
const symbol_index = try elf_file.addSymbol();
|
||||
try self.local_symbols.append(gpa, symbol_index);
|
||||
const symbol_ptr = elf_file.symbol(symbol_index);
|
||||
symbol_ptr.file_index = self.index;
|
||||
symbol_ptr.atom_index = atom_index;
|
||||
symbol_ptr.output_section_index = output_section_index;
|
||||
const local_esym = self.sourceSymbol(symbol_ptr.index, elf_file);
|
||||
local_esym.st_shndx = output_section_index;
|
||||
|
||||
const esym_index = try self.addLocalEsym(gpa);
|
||||
const esym = &self.local_esyms.items[esym_index];
|
||||
esym.st_shndx = output_section_index;
|
||||
symbol_ptr.esym_index = esym_index;
|
||||
|
||||
const relocs_index = @as(Atom.Index, @intCast(self.relocs.items.len));
|
||||
const relocs = try self.relocs.addOne(gpa);
|
||||
relocs.* = .{};
|
||||
atom_ptr.relocs_section_index = relocs_index;
|
||||
try self.atoms.putNoClobber(gpa, atom_index, {});
|
||||
|
||||
return symbol_index;
|
||||
}
|
||||
|
||||
pub fn addLocal(self: *ZigModule, elf_file: *Elf) !Symbol.Index {
|
||||
const gpa = elf_file.base.allocator;
|
||||
const symbol_index = try elf_file.addSymbol();
|
||||
const symbol_ptr = elf_file.symbol(symbol_index);
|
||||
symbol_ptr.file_index = self.index;
|
||||
symbol_ptr.esym_index = @as(Symbol.Index, @intCast(self.elf_local_symbols.items.len));
|
||||
const local_esym = try self.elf_local_symbols.addOne(gpa);
|
||||
local_esym.* = Elf.null_sym;
|
||||
local_esym.st_info = elf.STB_LOCAL << 4;
|
||||
try self.local_symbols.putNoClobber(gpa, symbol_index, {});
|
||||
return symbol_index;
|
||||
}
|
||||
|
||||
pub fn addGlobal(self: *ZigModule, name: []const u8, elf_file: *Elf) !Symbol.Index {
|
||||
const gpa = elf_file.base.allocator;
|
||||
try self.elf_global_symbols.ensureUnusedCapacity(gpa, 1);
|
||||
try self.global_symbols.ensureUnusedCapacity(gpa, 1);
|
||||
const off = try elf_file.strtab.insert(gpa, name);
|
||||
const esym_index = @as(Symbol.Index, @intCast(self.elf_global_symbols.items.len));
|
||||
const esym = self.elf_global_symbols.addOneAssumeCapacity();
|
||||
esym.* = Elf.null_sym;
|
||||
esym.st_name = off;
|
||||
esym.st_info = elf.STB_GLOBAL << 4;
|
||||
const gop = try elf_file.getOrPutGlobal(off);
|
||||
if (!gop.found_existing) {
|
||||
try elf_file.unresolved.putNoClobber(gpa, gop.index, {});
|
||||
}
|
||||
const sym = elf_file.symbol(gop.index);
|
||||
sym.file_index = self.index;
|
||||
sym.esym_index = esym_index;
|
||||
self.global_symbols.putAssumeCapacityNoClobber(gop.index, {});
|
||||
return gop.index;
|
||||
pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void {
|
||||
_ = self;
|
||||
_ = elf_file;
|
||||
@panic("TODO");
|
||||
}
|
||||
|
||||
pub fn updateSymtabSize(self: *ZigModule, elf_file: *Elf) void {
|
||||
@@ -133,19 +133,12 @@ pub fn writeSymtab(self: *ZigModule, elf_file: *Elf, ctx: anytype) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sourceSymbol(self: *ZigModule, symbol_index: Symbol.Index, elf_file: *Elf) *elf.Elf64_Sym {
|
||||
const sym = elf_file.symbol(symbol_index);
|
||||
if (self.local_symbols.get(symbol_index)) |_| return &self.elf_local_symbols.items[sym.esym_index];
|
||||
assert(self.global_symbols.get(symbol_index) != null);
|
||||
return &self.elf_global_symbols.items[sym.esym_index];
|
||||
}
|
||||
|
||||
pub fn locals(self: *ZigModule) []const Symbol.Index {
|
||||
return self.local_symbols.keys();
|
||||
return self.local_symbols.items;
|
||||
}
|
||||
|
||||
pub fn globals(self: *ZigModule) []const Symbol.Index {
|
||||
return self.global_symbols.keys();
|
||||
return self.global_symbols.items;
|
||||
}
|
||||
|
||||
pub fn asFile(self: *ZigModule) File {
|
||||
|
||||
@@ -32,7 +32,6 @@ pub const File = union(enum) {
|
||||
|
||||
pub fn resolveSymbols(file: File, elf_file: *Elf) void {
|
||||
switch (file) {
|
||||
.zig_module => unreachable, // handled separately
|
||||
inline else => |x| x.resolveSymbols(elf_file),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user