diff --git a/src/link/Elf.zig b/src/link/Elf.zig index f31df0dcba..4f0312fd27 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -331,7 +331,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option symbol_ptr.name_offset = name_off; const esym_index = try zig_module.addLocalEsym(allocator); - const esym = &zig_module.local_esyms.items[esym_index]; + const esym = &zig_module.local_esyms.items(.elf_sym)[esym_index]; esym.st_name = name_off; esym.st_info |= elf.STT_FILE; esym.st_shndx = elf.SHN_ABS; @@ -3172,7 +3172,7 @@ fn updateDeclCode( const required_alignment = decl.getAlignment(mod); const sym = self.symbol(sym_index); - const esym = &zig_module.local_esyms.items[sym.esym_index]; + const esym = &zig_module.local_esyms.items(.elf_sym)[sym.esym_index]; const atom_ptr = sym.atom(self).?; const shdr_index = self.getDeclShdrIndex(decl_index, code); @@ -3438,7 +3438,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol. const phdr_index = self.phdr_to_shdr_table.get(output_section_index).?; local_sym.name_offset = name_str_index; local_sym.output_section_index = output_section_index; - const local_esym = &zig_module.local_esyms.items[local_sym.esym_index]; + const local_esym = &zig_module.local_esyms.items(.elf_sym)[local_sym.esym_index]; local_esym.st_name = name_str_index; local_esym.st_info |= elf.STT_OBJECT; local_esym.st_size = code.len; @@ -3527,7 +3527,7 @@ fn lowerConst( const name_str_index = try self.strtab.insert(gpa, name); local_sym.name_offset = name_str_index; local_sym.output_section_index = output_section_index; - const local_esym = &zig_module.local_esyms.items[local_sym.esym_index]; + const local_esym = &zig_module.local_esyms.items(.elf_sym)[local_sym.esym_index]; local_esym.st_name = name_str_index; local_esym.st_info |= elf.STT_OBJECT; local_esym.st_size = code.len; @@ -3573,7 +3573,9 @@ pub fn updateDeclExports( 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_esym = zig_module.local_esyms.items[self.symbol(decl_sym_index).esym_index]; + const decl_esym_index = self.symbol(decl_sym_index).esym_index; + const decl_esym = zig_module.local_esyms.items(.elf_sym)[decl_esym_index]; + const decl_esym_shndx = zig_module.local_esyms.items(.shndx)[decl_esym_index]; const decl_metadata = self.decls.getPtr(decl_index).?; for (exports) |exp| { @@ -3615,11 +3617,13 @@ pub fn updateDeclExports( try zig_module.global_symbols.append(gpa, gop.index); break :blk sym_index; }; - const esym = &zig_module.global_esyms.items[sym_index & 0x0fffffff]; - esym.st_value = self.symbol(decl_sym_index).value; - esym.st_shndx = decl_esym.st_shndx; - esym.st_info = (stb_bits << 4) | stt_bits; - esym.st_name = name_off; + const global_esym_index = sym_index & ZigModule.symbol_mask; + const global_esym = &zig_module.global_esyms.items(.elf_sym)[global_esym_index]; + global_esym.st_value = self.symbol(decl_sym_index).value; + global_esym.st_shndx = decl_esym.st_shndx; + global_esym.st_info = (stb_bits << 4) | stt_bits; + global_esym.st_name = name_off; + zig_module.global_esyms.items(.shndx)[global_esym_index] = decl_esym_shndx; } } @@ -3651,7 +3655,7 @@ pub fn deleteDeclExport( const exp_name = mod.intern_pool.stringToSlice(name); const esym_index = metadata.@"export"(self, exp_name) orelse return; log.debug("deleting export '{s}'", .{exp_name}); - const esym = &zig_module.global_esyms.items[esym_index.*]; + const esym = &zig_module.global_esyms.items(.elf_sym)[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); @@ -3660,6 +3664,7 @@ pub fn deleteDeclExport( sym.* = .{}; } esym.* = null_sym; + zig_module.global_esyms.items(.shndx)[esym_index.*] = elf.SHN_UNDEF; } fn addLinkerDefinedSymbols(self: *Elf) !void { diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig index a876a4d16c..6201bd1644 100644 --- a/src/link/Elf/Atom.zig +++ b/src/link/Elf/Atom.zig @@ -14,13 +14,13 @@ size: u64 = 0, alignment: Alignment = .@"1", /// Index of the input section. -input_section_index: u16 = 0, +input_section_index: u32 = 0, /// Index of the output section. output_section_index: u16 = 0, /// Index of the input section containing this atom's relocs. -relocs_section_index: u16 = 0, +relocs_section_index: u32 = 0, /// Index of this atom in the linker's atoms table. atom_index: Index = 0, diff --git a/src/link/Elf/ZigModule.zig b/src/link/Elf/ZigModule.zig index 4532d7b448..15f82113d9 100644 --- a/src/link/Elf/ZigModule.zig +++ b/src/link/Elf/ZigModule.zig @@ -7,8 +7,8 @@ path: []const u8, index: File.Index, -local_esyms: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{}, -global_esyms: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{}, +local_esyms: std.MultiArrayList(ElfSym) = .{}, +global_esyms: std.MultiArrayList(ElfSym) = .{}, local_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, global_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{}, @@ -20,6 +20,10 @@ num_dynrelocs: u32 = 0, output_symtab_size: Elf.SymtabSize = .{}, +pub const global_symbol_bit: u32 = 0x80000000; +pub const symbol_mask: u32 = 0x7fffffff; +pub const SHN_ATOM: u16 = 0x100; + pub fn deinit(self: *ZigModule, allocator: Allocator) void { self.local_esyms.deinit(allocator); self.global_esyms.deinit(allocator); @@ -35,20 +39,20 @@ pub fn deinit(self: *ZigModule, allocator: Allocator) void { 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; + 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); 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 | 0x10000000; + 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; } pub fn addAtom(self: *ZigModule, elf_file: *Elf) !Symbol.Index { @@ -58,7 +62,7 @@ pub fn addAtom(self: *ZigModule, elf_file: *Elf) !Symbol.Index { const symbol_index = try elf_file.addSymbol(); const esym_index = try self.addLocalEsym(gpa); - const shndx = @as(u16, @intCast(self.atoms.items.len)); + const shndx = @as(u32, @intCast(self.atoms.items.len)); try self.atoms.append(gpa, atom_index); try self.local_symbols.append(gpa, symbol_index); @@ -69,11 +73,11 @@ pub fn addAtom(self: *ZigModule, elf_file: *Elf) !Symbol.Index { symbol_ptr.file_index = self.index; symbol_ptr.atom_index = atom_index; - const esym = &self.local_esyms.items[esym_index]; - esym.st_shndx = shndx; + self.local_esyms.items(.shndx)[esym_index] = shndx; + self.local_esyms.items(.elf_sym)[esym_index].st_shndx = SHN_ATOM; symbol_ptr.esym_index = esym_index; - const relocs_index = @as(u16, @intCast(self.relocs.items.len)); + const relocs_index = @as(u32, @intCast(self.relocs.items.len)); const relocs = try self.relocs.addOne(gpa); relocs.* = .{}; atom_ptr.relocs_section_index = relocs_index; @@ -99,13 +103,15 @@ pub fn inputShdr(self: ZigModule, atom_index: Atom.Index, elf_file: *Elf) Object pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void { for (self.globals(), 0..) |index, i| { - const esym_index = @as(Symbol.Index, @intCast(i)) | 0x10000000; - const esym = self.global_esyms.items[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; if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) { - const atom_index = self.atoms.items[esym.st_shndx]; + assert(esym.st_shndx == SHN_ATOM); + const atom_index = self.atoms.items[shndx]; const atom = elf_file.atom(atom_index) orelse continue; if (!atom.flags.alive) continue; } @@ -114,7 +120,8 @@ pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void { if (self.asFile().symbolRank(esym, false) < global.symbolRank(elf_file)) { const atom_index = switch (esym.st_shndx) { elf.SHN_ABS, elf.SHN_COMMON => 0, - else => self.atoms.items[esym.st_shndx], + SHN_ATOM => self.atoms.items[shndx], + else => unreachable, }; const output_section_index = if (elf_file.atom(atom_index)) |atom| atom.outputShndx().? @@ -133,8 +140,8 @@ pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void { pub fn claimUnresolved(self: *ZigModule, elf_file: *Elf) void { for (self.globals(), 0..) |index, i| { - const esym_index = @as(Symbol.Index, @intCast(i)) | 0x10000000; - const esym = self.global_esyms.items[i]; + const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit; + const esym = self.global_esyms.items(.elf_sym)[i]; if (esym.st_shndx != elf.SHN_UNDEF) continue; @@ -187,7 +194,7 @@ pub fn resetGlobals(self: *ZigModule, elf_file: *Elf) void { pub fn markLive(self: *ZigModule, elf_file: *Elf) void { for (self.globals(), 0..) |index, i| { - const esym = self.global_esyms.items[i]; + const esym = self.global_esyms.items(.elf_sym)[i]; if (esym.st_bind() == elf.STB_WEAK) continue; const global = elf_file.symbol(index); @@ -256,17 +263,17 @@ pub fn writeSymtab(self: *ZigModule, elf_file: *Elf, ctx: anytype) void { } pub fn symbol(self: *ZigModule, index: Symbol.Index) Symbol.Index { - const is_global = index & 0x10000000 != 0; - const actual_index = index & 0x0fffffff; + const is_global = index & global_symbol_bit != 0; + const actual_index = index & symbol_mask; if (is_global) return self.global_symbols.items[actual_index]; return self.local_symbols.items[actual_index]; } pub fn elfSym(self: *ZigModule, index: Symbol.Index) *elf.Elf64_Sym { - const is_global = index & 0x10000000 != 0; - const actual_index = index & 0x0fffffff; - if (is_global) return &self.global_esyms.items[actual_index]; - return &self.local_esyms.items[actual_index]; + const is_global = index & global_symbol_bit != 0; + const actual_index = index & symbol_mask; + if (is_global) return &self.global_esyms.items(.elf_sym)[actual_index]; + return &self.local_esyms.items(.elf_sym)[actual_index]; } pub fn locals(self: *ZigModule) []const Symbol.Index { @@ -354,6 +361,11 @@ fn formatAtoms( } } +const ElfSym = struct { + elf_sym: elf.Elf64_Sym, + shndx: u32 = elf.SHN_UNDEF, +}; + const assert = std.debug.assert; const std = @import("std"); const elf = std.elf;