diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 02b463ff16..b1051a7fe4 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -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; } diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index aff1fa9182..868ccb33c4 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -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) = .{}, diff --git a/src/link/Elf/Symbol.zig b/src/link/Elf/Symbol.zig index a6901d9ab7..0f9c574555 100644 --- a/src/link/Elf/Symbol.zig +++ b/src/link/Elf/Symbol.zig @@ -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: { diff --git a/src/link/Elf/ZigModule.zig b/src/link/Elf/ZigModule.zig index cf14fcc169..8951894638 100644 --- a/src/link/Elf/ZigModule.zig +++ b/src/link/Elf/ZigModule.zig @@ -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 { diff --git a/src/link/Elf/file.zig b/src/link/Elf/file.zig index 0d7e62da67..828d4f4c1f 100644 --- a/src/link/Elf/file.zig +++ b/src/link/Elf/file.zig @@ -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), } }