authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-01 08:50:01+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-07 10:21:02+02:00
logdeeaa1bb0cb8a8c7ccebb23cc68be64e4b013ab2
tree0b1e93cb77cff05de14485b646e985f7dcba9ecf
parentde80e4fec2a29c5aac70c8d72b11a90cb96feeaf

elf: redo symbol mgmt and ownership in ZigObject


7 files changed, 335 insertions(+), 278 deletions(-)

src/link/Elf.zig+17-61
......@@ -173,11 +173,7 @@ shstrtab_section_index: ?u32 = null,
173173strtab_section_index: ?u32 = null,
174174symtab_section_index: ?u32 = null,
175175
176/// An array of symbols parsed across all input files.
177symbols: std.ArrayListUnmanaged(Symbol) = .{},
178symbols_extra: std.ArrayListUnmanaged(u32) = .{},
179
180resolver: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{},
176resolver: SymbolResolver = .{},
181177
182178has_text_reloc: bool = false,
183179num_ifunc_dynrelocs: usize = 0,
......@@ -191,10 +187,6 @@ merge_sections: std.ArrayListUnmanaged(MergeSection) = .{},
191187/// Table of last atom index in a section and matching atom free list if any.
192188last_atom_and_free_list_table: LastAtomAndFreeListTable = .{},
193189
194/// Global string table used to provide quick access to global symbol resolvers
195/// such as `resolver`.
196strings: StringTable = .{},
197
198190first_eflags: ?elf.Elf64_Word = null,
199191
200192/// When allocating, the ideal_capacity is calculated by
......@@ -455,8 +447,6 @@ pub fn deinit(self: *Elf) void {
455447 self.shstrtab.deinit(gpa);
456448 self.symtab.deinit(gpa);
457449 self.strtab.deinit(gpa);
458 self.symbols.deinit(gpa);
459 self.symbols_extra.deinit(gpa);
460450 self.resolver.deinit(gpa);
461451
462452 for (self.thunks.items) |*th| {
......@@ -472,8 +462,6 @@ pub fn deinit(self: *Elf) void {
472462 }
473463 self.last_atom_and_free_list_table.deinit(gpa);
474464
475 self.strings.deinit(gpa);
476
477465 self.got.deinit(gpa);
478466 self.plt.deinit(gpa);
479467 self.plt_got.deinit(gpa);
......@@ -1916,20 +1904,17 @@ fn accessLibPath(
19161904/// 6. Re-run symbol resolution on pruned objects and shared objects sets.
19171905pub fn resolveSymbols(self: *Elf) !void {
19181906 // Resolve symbols in the ZigObject. For now, we assume that it's always live.
1919 if (self.zigObjectPtr()) |zig_object| zig_object.asFile().resolveSymbols(self);
1907 if (self.zigObjectPtr()) |zo| try zo.asFile().resolveSymbols(self);
19201908 // Resolve symbols on the set of all objects and shared objects (even if some are unneeded).
1921 for (self.objects.items) |index| self.file(index).?.resolveSymbols(self);
1922 for (self.shared_objects.items) |index| self.file(index).?.resolveSymbols(self);
1923 if (self.linkerDefinedPtr()) |obj| obj.asFile().resolveSymbols(self);
1909 for (self.objects.items) |index| try self.file(index).?.resolveSymbols(self);
1910 for (self.shared_objects.items) |index| try self.file(index).?.resolveSymbols(self);
1911 if (self.linkerDefinedPtr()) |obj| try obj.asFile().resolveSymbols(self);
19241912
19251913 // Mark live objects.
19261914 self.markLive();
19271915
19281916 // Reset state of all globals after marking live objects.
1929 if (self.zigObjectPtr()) |zig_object| zig_object.asFile().resetGlobals(self);
1930 for (self.objects.items) |index| self.file(index).?.resetGlobals(self);
1931 for (self.shared_objects.items) |index| self.file(index).?.resetGlobals(self);
1932 if (self.linkerDefinedPtr()) |obj| obj.asFile().resetGlobals(self);
1917 self.resolver.reset();
19331918
19341919 // Prune dead objects and shared objects.
19351920 var i: usize = 0;
......@@ -1962,10 +1947,10 @@ pub fn resolveSymbols(self: *Elf) !void {
19621947 }
19631948
19641949 // Re-resolve the symbols.
1965 if (self.zigObjectPtr()) |zig_object| zig_object.asFile().resolveSymbols(self);
1966 for (self.objects.items) |index| self.file(index).?.resolveSymbols(self);
1967 for (self.shared_objects.items) |index| self.file(index).?.resolveSymbols(self);
1968 if (self.linkerDefinedPtr()) |obj| obj.asFile().resolveSymbols(self);
1950 if (self.zigObjectPtr()) |zo| try zo.asFile().resolveSymbols(self);
1951 for (self.objects.items) |index| try self.file(index).?.resolveSymbols(self);
1952 for (self.shared_objects.items) |index| try self.file(index).?.resolveSymbols(self);
1953 if (self.linkerDefinedPtr()) |obj| try obj.asFile().resolveSymbols(self);
19691954}
19701955
19711956/// Traverses all objects and shared objects marking any object referenced by
......@@ -1999,46 +1984,17 @@ fn convertCommonSymbols(self: *Elf) !void {
19991984}
20001985
20011986fn markImportsExports(self: *Elf) void {
2002 const mark = struct {
2003 fn mark(elf_file: *Elf, file_index: File.Index) void {
2004 for (elf_file.file(file_index).?.globals()) |global_index| {
2005 const global = elf_file.symbol(global_index);
2006 if (global.version_index == elf.VER_NDX_LOCAL) continue;
2007 const file_ptr = global.file(elf_file) orelse continue;
2008 const vis = @as(elf.STV, @enumFromInt(global.elfSym(elf_file).st_other));
2009 if (vis == .HIDDEN) continue;
2010 if (file_ptr == .shared_object and !global.isAbs(elf_file)) {
2011 global.flags.import = true;
2012 continue;
2013 }
2014 if (file_ptr.index() == file_index) {
2015 global.flags.@"export" = true;
2016 if (elf_file.isEffectivelyDynLib() and vis != .PROTECTED) {
2017 global.flags.import = true;
2018 }
2019 }
2020 }
2021 }
2022 }.mark;
2023
1987 if (self.zigObjectPtr()) |zo| {
1988 zo.markImportsExports(self);
1989 }
1990 for (self.objects.items) |index| {
1991 self.file(index).?.object.markImportsExports(self);
1992 }
20241993 if (!self.isEffectivelyDynLib()) {
20251994 for (self.shared_objects.items) |index| {
2026 for (self.file(index).?.globals()) |global_index| {
2027 const global = self.symbol(global_index);
2028 const file_ptr = global.file(self) orelse continue;
2029 const vis = @as(elf.STV, @enumFromInt(global.elfSym(self).st_other));
2030 if (file_ptr != .shared_object and vis != .HIDDEN) global.flags.@"export" = true;
2031 }
1995 self.file(index).?.shared_object.markImportExports(self);
20321996 }
20331997 }
2034
2035 if (self.zig_object_index) |index| {
2036 mark(self, index);
2037 }
2038
2039 for (self.objects.items) |index| {
2040 mark(self, index);
2041 }
20421998}
20431999
20442000fn claimUnresolved(self: *Elf) void {
src/link/Elf/LinkerDefined.zig+2-6
......@@ -302,12 +302,8 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
302302 }
303303}
304304
305pub fn globals(self: *LinkerDefined) []Symbol {
306 return self.symbols.items;
307}
308
309305pub fn updateSymtabSize(self: *LinkerDefined, elf_file: *Elf) void {
310 for (self.globals(), self.symbols_resolver.items) |*global, resolv| {
306 for (self.symbols.items, self.symbols_resolver.items) |*global, resolv| {
311307 const ref = elf_file.resolver.get(resolv).?;
312308 const ref_sym = elf_file.symbol(ref) orelse continue;
313309 if (ref_sym.file(elf_file).?.index() != self.index) continue;
......@@ -324,7 +320,7 @@ pub fn updateSymtabSize(self: *LinkerDefined, elf_file: *Elf) void {
324320}
325321
326322pub fn writeSymtab(self: *LinkerDefined, elf_file: *Elf) void {
327 for (self.globals(), self.symbols_resolver.items) |global, resolv| {
323 for (self.symbols.items, self.symbols_resolver.items) |global, resolv| {
328324 const ref = elf_file.resolver.get(resolv).?;
329325 const ref_sym = elf_file.symbol(ref) orelse continue;
330326 if (ref_sym.file(elf_file).?.index() != self.index) continue;
src/link/Elf/Object.zig+25-2
......@@ -676,6 +676,29 @@ pub fn markEhFrameAtomsDead(self: *Object, elf_file: *Elf) void {
676676 }
677677}
678678
679pub fn markImportsExports(self: *Object, elf_file: *Elf) void {
680 const first_global = self.first_global orelse return;
681 for (0..self.globals().len) |i| {
682 const idx = first_global + i;
683 const ref = self.resolveSymbol(@intCast(idx), elf_file);
684 const sym = elf_file.symbol(ref) orelse continue;
685 const file = sym.file(elf_file).?;
686 if (sym.version_index == elf.VER_NDX_LOCAL) continue;
687 const vis = @as(elf.STV, @enumFromInt(sym.elfSym(elf_file).st_other));
688 if (vis == .HIDDEN) continue;
689 if (file == .shared_object and !sym.isAbs(elf_file)) {
690 sym.flags.import = true;
691 continue;
692 }
693 if (file.index() == self.index) {
694 sym.flags.@"export" = true;
695 if (elf_file.isEffectivelyDynLib() and vis != .PROTECTED) {
696 sym.flags.import = true;
697 }
698 }
699 }
700}
701
679702pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void {
680703 const first_global = self.first_global orelse return;
681704 for (0..self.globals().len) |i| {
......@@ -1169,14 +1192,14 @@ pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index
11691192 return data;
11701193}
11711194
1172pub fn locals(self: *Object) []Symbol {
1195fn locals(self: *Object) []Symbol {
11731196 if (self.symbols.items.len == 0) return &[0]Symbol{};
11741197 assert(self.symbols.items.len >= self.symtab.items.len);
11751198 const end = self.first_global orelse self.symtab.items.len;
11761199 return self.symbols.items[0..end];
11771200}
11781201
1179pub fn globals(self: *Object) []Symbol {
1202fn globals(self: *Object) []Symbol {
11801203 if (self.symbols.items.len == 0) return &[0]Symbol{};
11811204 assert(self.symbols.items.len >= self.symtab.items.len);
11821205 const start = self.first_global orelse self.symtab.items.len;
src/link/Elf/SharedObject.zig+11-5
......@@ -282,12 +282,18 @@ pub fn markLive(self: *SharedObject, elf_file: *Elf) void {
282282 }
283283}
284284
285pub fn globals(self: *SharedObject) []Symbol {
286 return self.symbols.items;
285pub fn markImportExports(self: *SharedObject, elf_file: *Elf) void {
286 for (0..self.symbols.items.len) |i| {
287 const ref = self.resolveSymbol(@intCast(i), elf_file);
288 const ref_sym = elf_file.symbol(ref) orelse continue;
289 const ref_file = ref_sym.file(self).?;
290 const vis = @as(elf.STV, @enumFromInt(ref_sym.elfSym(self).st_other));
291 if (ref_file != .shared_object and vis != .HIDDEN) ref_sym.flags.@"export" = true;
292 }
287293}
288294
289295pub fn updateSymtabSize(self: *SharedObject, elf_file: *Elf) void {
290 for (self.globals(), self.symbols_resolver.items) |*global, resolv| {
296 for (self.symbols.items, self.symbols_resolver.items) |*global, resolv| {
291297 const ref = elf_file.resolver.get(resolv).?;
292298 const ref_sym = elf_file.symbol(ref) orelse continue;
293299 if (ref_sym.file(elf_file).?.index() != self.index) continue;
......@@ -300,7 +306,7 @@ pub fn updateSymtabSize(self: *SharedObject, elf_file: *Elf) void {
300306}
301307
302308pub fn writeSymtab(self: *SharedObject, elf_file: *Elf) void {
303 for (self.globals(), self.symbols_resolver.items) |global, resolv| {
309 for (self.symbols.items, self.symbols_resolver.items) |global, resolv| {
304310 const ref = elf_file.resolver.get(resolv).?;
305311 const ref_sym = elf_file.symbol(ref) orelse continue;
306312 if (ref_sym.file(elf_file).?.index() != self.index) continue;
......@@ -354,7 +360,7 @@ pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void {
354360 const gpa = comp.gpa;
355361 var aliases = std.ArrayList(Symbol.Index).init(gpa);
356362 defer aliases.deinit();
357 try aliases.ensureTotalCapacityPrecise(self.globals().len);
363 try aliases.ensureTotalCapacityPrecise(self.symbols.items.len);
358364
359365 for (self.symbols_resolvers.items, 0..) |resolv, index| {
360366 const ref = elf_file.resolver.get(resolv).?;
src/link/Elf/Symbol.zig+2-12
......@@ -63,9 +63,7 @@ pub fn @"type"(symbol: Symbol, elf_file: *Elf) u4 {
6363}
6464
6565pub fn name(symbol: Symbol, elf_file: *Elf) [:0]const u8 {
66 if (symbol.flags.global) return elf_file.strings.getAssumeExists(symbol.name_offset);
67 const file_ptr = symbol.file(elf_file).?;
68 return switch (file_ptr) {
66 return switch (symbol.file(elf_file).?) {
6967 inline else => |x| x.getString(symbol.name_offset),
7068 };
7169}
......@@ -87,9 +85,7 @@ pub fn file(symbol: Symbol, elf_file: *Elf) ?File {
8785}
8886
8987pub fn elfSym(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym {
90 const file_ptr = symbol.file(elf_file).?;
91 return switch (file_ptr) {
92 .zig_object => |x| x.elfSym(symbol.esym_index).*,
88 return switch (symbol.file(elf_file).?) {
9389 inline else => |x| x.symtab.items[symbol.esym_index],
9490 };
9591}
......@@ -423,12 +419,6 @@ pub const Flags = packed struct {
423419 /// Whether this symbol is weak.
424420 weak: bool = false,
425421
426 /// Whether the symbol has its name interned in global symbol
427 /// resolver table.
428 /// This happens for any symbol that is considered a global
429 /// symbol, but is not necessarily an import or export.
430 global: bool = false,
431
432422 /// Whether the symbol makes into the output symtab.
433423 output_symtab: bool = false,
434424
src/link/Elf/ZigObject.zig+278-179
......@@ -8,9 +8,11 @@ data: std.ArrayListUnmanaged(u8) = .{},
88path: []const u8,
99index: File.Index,
1010
11local_esyms: std.MultiArrayList(ElfSym) = .{},
12global_esyms: std.MultiArrayList(ElfSym) = .{},
11symtab: std.MultiArrayList(ElfSym) = .{},
1312strtab: StringTable = .{},
13symbols: std.ArrayListUnmanaged(Symbol) = .{},
14symbols_extra: std.ArrayListUnmanaged(u32) = .{},
15symbols_resolver: std.ArrayListUnmanaged(Elf.SymbolResolver.Index) = .{},
1416local_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
1517global_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
1618globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},
......@@ -113,9 +115,11 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {
113115
114116pub fn deinit(self: *ZigObject, allocator: Allocator) void {
115117 self.data.deinit(allocator);
116 self.local_esyms.deinit(allocator);
117 self.global_esyms.deinit(allocator);
118 self.symtab.deinit(allocator);
118119 self.strtab.deinit(allocator);
120 self.symbols.deinit(allocator);
121 self.symbols_extra.deinit(allocator);
122 self.symbols_resolver.deinit(allocator);
119123 self.local_symbols.deinit(allocator);
120124 self.global_symbols.deinit(allocator);
121125 self.globals_lookup.deinit(allocator);
......@@ -263,51 +267,73 @@ fn saveDebugSectionsSizes(self: *ZigObject, elf_file: *Elf) void {
263267 }
264268}
265269
266pub fn addLocalEsym(self: *ZigObject, allocator: Allocator) !Symbol.Index {
267 try self.local_esyms.ensureUnusedCapacity(allocator, 1);
268 const index = @as(Symbol.Index, @intCast(self.local_esyms.addOneAssumeCapacity()));
269 var esym = ElfSym{ .elf_sym = Elf.null_sym };
270 esym.elf_sym.st_info = elf.STB_LOCAL << 4;
271 self.local_esyms.set(index, esym);
270fn newSymbol(self: *ZigObject, allocator: Allocator, name_off: u32, st_bind: u4) !Symbol.Index {
271 try self.symtab.ensureUnusedCapacity(allocator, 1);
272 try self.symbols.ensureUnusedCapacity(allocator, 1);
273 try self.symbols_extra.ensureUnusedCapacity(allocator, @sizeOf(Symbol.Extra));
274
275 const index = self.addSymbolAssumeCapacity();
276 const sym = &self.symbols.items[index];
277 sym.name_offset = name_off;
278 sym.extra = self.addSymbolExtraAssumeCapacity(.{});
279
280 const esym_idx: u32 = @intCast(self.symtab.addOneAssumeCapacity());
281 const esym = ElfSym{ .elf_sym = .{
282 .st_value = 0,
283 .st_name = name_off,
284 .st_info = @as(u8, @intCast(st_bind)) << 4,
285 .st_other = 0,
286 .st_size = 0,
287 .st_shndx = 0,
288 } };
289 self.symtab.set(index, esym);
290 sym.esym_index = esym_idx;
291
272292 return index;
273293}
274294
275pub fn addGlobalEsym(self: *ZigObject, allocator: Allocator) !Symbol.Index {
276 try self.global_esyms.ensureUnusedCapacity(allocator, 1);
277 const index = @as(Symbol.Index, @intCast(self.global_esyms.addOneAssumeCapacity()));
278 var esym = ElfSym{ .elf_sym = Elf.null_sym };
279 esym.elf_sym.st_info = elf.STB_GLOBAL << 4;
280 self.global_esyms.set(index, esym);
281 return index | global_symbol_bit;
295fn newLocalSymbol(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index {
296 try self.local_symbols.ensureUnusedCapacity(allocator, 1);
297 const fake_index: Symbol.Index = @intCast(self.local_symbols.items.len);
298 const index = try self.newSymbol(allocator, name_off, elf.STB_LOCAL);
299 self.local_symbols.appendAssumeCapacity(index);
300 return fake_index;
282301}
283302
284pub fn newAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index {
285 const gpa = elf_file.base.comp.gpa;
286 const atom_index = try self.addAtom(gpa);
287 const symbol_index = try elf_file.addSymbol();
288 const esym_index = try self.addLocalEsym(gpa);
289
290 try self.atoms_indexes.append(gpa, atom_index);
291 try self.local_symbols.append(gpa, symbol_index);
292
293 const symbol_ptr = elf_file.symbol(symbol_index);
294 symbol_ptr.file_index = self.index;
295 symbol_ptr.ref = .{ .index = atom_index, .file = self.index };
296 symbol_ptr.extra_index = try elf_file.addSymbolExtra(.{});
303fn newGlobalSymbol(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index {
304 try self.global_symbols.ensureUnusedCapacity(allocator, 1);
305 const fake_index: Symbol.Index = @intCast(self.global_symbols.items.len);
306 const index = try self.newSymbol(allocator, name_off, elf.STB_GLOBAL);
307 self.global_symbols.appendAssumeCapacity(index);
308 return fake_index | global_symbol_bit;
309}
297310
298 self.local_esyms.items(.shndx)[esym_index] = atom_index;
299 self.local_esyms.items(.elf_sym)[esym_index].st_shndx = SHN_ATOM;
300 symbol_ptr.esym_index = esym_index;
311fn newAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Atom.Index {
312 try self.atoms.ensureUnusedCapacity(allocator, 1);
313 try self.atoms_extra.ensureUnusedCapacity(allocator, @sizeOf(Atom.Extra));
314 try self.atoms_indexes.ensureUnusedCapacity(allocator, 1);
315 try self.relocs.ensureUnusedCapacity(allocator, 1);
301316
302 // TODO I'm thinking that maybe we shouldn' set this value unless it's actually needed?
303 const relocs_index = @as(u32, @intCast(self.relocs.items.len));
304 const relocs = try self.relocs.addOne(gpa);
305 relocs.* = .{};
317 const index = self.addAtomAssumeCapacity();
318 self.atoms_indexes.appendAssumeCapacity(index);
319 const atom_ptr = self.atom(index).?;
320 atom_ptr.name_offset = name_off;
306321
307 const atom_ptr = self.atom(atom_index).?;
322 const relocs_index: u32 = @intCast(self.relocs.items.len);
323 self.relocs.addOneAssumeCapacity().* = .{};
308324 atom_ptr.relocs_section_index = relocs_index;
309325
310 return symbol_index;
326 return index;
327}
328
329fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index {
330 const atom_index = try self.newAtom(allocator, name_off);
331 const sym_index = try self.newLocalSymbol(allocator, name_off);
332 const sym = self.symbol(sym_index);
333 sym.ref = .{ .index = atom_index, .file = self.index };
334 self.symtab.items(.shndx)[sym.esym_index] = atom_index;
335 self.symtab.items(.elf_sym)[sym.esym_index].st_shndx = SHN_ATOM;
336 return sym_index;
311337}
312338
313339/// 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
322348 return shdr;
323349}
324350
325pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) void {
326 for (self.globals(), 0..) |index, i| {
327 const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit;
328 const esym = self.global_esyms.items(.elf_sym)[i];
329 const shndx = self.global_esyms.items(.shndx)[i];
330
331 if (esym.st_shndx == elf.SHN_UNDEF) continue;
351pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) !void {
352 const gpa = elf_file.base.comp.gpa;
332353
354 for (self.global_symbols.items, 0..) |index, i| {
355 const global = &self.symbols.items[index];
356 const esym = global.elfSym(elf_file);
357 const shndx = self.symtab.items(.shndx)[global.esym_index];
333358 if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) {
334359 assert(esym.st_shndx == SHN_ATOM);
335360 const atom_ptr = self.atom(shndx) orelse continue;
336361 if (!atom_ptr.alive) continue;
337362 }
338363
339 const global = elf_file.symbol(index);
340 if (self.asFile().symbolRank(esym, false) < global.symbolRank(elf_file)) {
341 const atom_index = switch (esym.st_shndx) {
342 elf.SHN_ABS, elf.SHN_COMMON => 0,
343 SHN_ATOM => shndx,
344 else => unreachable,
345 };
346 global.value = @intCast(esym.st_value);
347 global.ref = .{ .index = atom_index, .file = self.index };
348 global.esym_index = esym_index;
349 global.file_index = self.index;
350 global.version_index = elf_file.default_sym_version;
351 if (esym.st_bind() == elf.STB_WEAK) global.flags.weak = true;
364 const resolv = &self.symbols_resolver.items[i];
365 const gop = try elf_file.resolver.getOrPut(gpa, .{
366 .index = @intCast(i | global_symbol_bit),
367 .file = self.index,
368 }, elf_file);
369 if (!gop.found_existing) {
370 gop.ref.* = .{ .index = 0, .file = 0 };
371 }
372 resolv.* = gop.index;
373
374 if (esym.st_shndx == elf.SHN_UNDEF) continue;
375 if (elf_file.symbol(gop.ref.*) == null) {
376 gop.ref.* = .{ .index = @intCast(i | global_symbol_bit), .file = self.index };
377 continue;
378 }
379
380 if (self.asFile().symbolRank(esym, !self.alive) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) {
381 gop.ref.* = .{ .index = @intCast(i | global_symbol_bit), .file = self.index };
352382 }
353383 }
354384}
355385
356pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void {
357 for (self.globals(), 0..) |index, i| {
358 const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit;
359 const esym = self.global_esyms.items(.elf_sym)[i];
360
386pub fn claimUnresolved(self: *ZigObject, elf_file: *Elf) void {
387 for (self.global_symbols.items, 0..) |index, i| {
388 const global = &self.symbols.items[index];
389 const esym = self.symtab.items(.elf_sym)[index];
361390 if (esym.st_shndx != elf.SHN_UNDEF) continue;
362
363 const global = elf_file.symbol(index);
364 if (global.file(elf_file)) |_| {
365 if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF) continue;
366 }
391 if (elf_file.symbol(self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file)) != null) continue;
367392
368393 const is_import = blk: {
369394 if (!elf_file.isEffectivelyDynLib()) break :blk false;
......@@ -374,29 +399,36 @@ pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void {
374399
375400 global.value = 0;
376401 global.ref = .{ .index = 0, .file = 0 };
377 global.esym_index = esym_index;
402 global.esym_index = @intCast(index);
378403 global.file_index = self.index;
379404 global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;
380405 global.flags.import = is_import;
406
407 const idx = self.symbols_resolver.items[i];
408 elf_file.resolver.values.items[idx - 1] = .{ .index = @intCast(i | global_symbol_bit), .file = self.index };
381409 }
382410}
383411
384412pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void {
385 for (self.globals(), 0..) |index, i| {
386 const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit;
387 const esym = self.global_esyms.items(.elf_sym)[i];
388
413 for (self.global_symbols.items, 0..) |index, i| {
414 const global = &self.symbols.items[index];
415 const esym = self.symtab.items(.elf_sym)[index];
389416 if (esym.st_shndx != elf.SHN_UNDEF) continue;
417 if (elf_file.symbol(self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file)) != null) continue;
390418
391 const global = elf_file.symbol(index);
392 if (global.file(elf_file)) |file| {
393 if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF or file.index() <= self.index) continue;
394 }
419 // TODO: audit this
420 // const global = elf_file.symbol(index);
421 // if (global.file(elf_file)) |file| {
422 // if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF or file.index() <= self.index) continue;
423 // }
395424
396425 global.value = 0;
397426 global.ref = .{ .index = 0, .file = 0 };
398 global.esym_index = esym_index;
427 global.esym_index = @intCast(index);
399428 global.file_index = self.index;
429
430 const idx = self.symbols_resolver.items[i];
431 elf_file.resolver.items[idx - 1] = .{ .index = @intCast(i | global_symbol_bit), .file = self.index };
400432 }
401433}
402434
......@@ -419,12 +451,14 @@ pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void {
419451}
420452
421453pub fn markLive(self: *ZigObject, elf_file: *Elf) void {
422 for (self.globals(), 0..) |index, i| {
423 const esym = self.global_esyms.items(.elf_sym)[i];
454 for (self.global_symbols.items, 0..) |index, i| {
455 const global = self.symbols.items[index];
456 const esym = self.symtab.items(.elf_sym)[index];
424457 if (esym.st_bind() == elf.STB_WEAK) continue;
425458
426 const global = elf_file.symbol(index);
427 const file = global.file(elf_file) orelse continue;
459 const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file);
460 const sym = elf_file.symbol(ref) orelse continue;
461 const file = sym.file(elf_file).?;
428462 const should_keep = esym.st_shndx == elf.SHN_UNDEF or
429463 (esym.st_shndx == elf.SHN_COMMON and global.elfSym(elf_file).st_shndx != elf.SHN_COMMON);
430464 if (should_keep and !file.isAlive()) {
......@@ -434,14 +468,36 @@ pub fn markLive(self: *ZigObject, elf_file: *Elf) void {
434468 }
435469}
436470
437pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void {
438 for (self.globals(), 0..) |index, i| {
439 const esym = self.global_esyms.items(.elf_sym)[i];
440 const shndx = self.global_esyms.items(.shndx)[i];
441 const global = elf_file.symbol(index);
442 const global_file = global.file(elf_file) orelse continue;
471pub fn markImportsExports(self: *Object, elf_file: *Elf) void {
472 for (0..self.global_symbols.items.len) |i| {
473 const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file);
474 const sym = elf_file.symbol(ref) orelse continue;
475 const file = sym.file(elf_file).?;
476 if (sym.version_index == elf.VER_NDX_LOCAL) continue;
477 const vis = @as(elf.STV, @enumFromInt(sym.elfSym(elf_file).st_other));
478 if (vis == .HIDDEN) continue;
479 if (file == .shared_object and !sym.isAbs(elf_file)) {
480 sym.flags.import = true;
481 continue;
482 }
483 if (file.index() == self.index) {
484 sym.flags.@"export" = true;
485 if (elf_file.isEffectivelyDynLib() and vis != .PROTECTED) {
486 sym.flags.import = true;
487 }
488 }
489 }
490}
443491
444 if (self.index == global_file.index() or
492pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void {
493 for (self.global_symbols.items, 0..) |index, i| {
494 const esym = self.symtab.items(.elf_sym)[index];
495 const shndx = self.symtab.items(.shndx)[index];
496 const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file);
497 const ref_sym = elf_file.symbol(ref) orelse continue;
498 const ref_file = ref_sym.file(elf_file).?;
499
500 if (self.index == ref_file.index() or
445501 esym.st_shndx == elf.SHN_UNDEF or
446502 esym.st_bind() == elf.STB_WEAK or
447503 esym.st_shndx == elf.SHN_COMMON) continue;
......@@ -451,7 +507,7 @@ pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{O
451507 if (!atom_ptr.alive) continue;
452508 }
453509
454 const gop = try dupes.getOrPut(index);
510 const gop = try dupes.getOrPut(self.symbols_resolver.items[i]);
455511 if (!gop.found_existing) {
456512 gop.value_ptr.* = .{};
457513 }
......@@ -483,12 +539,13 @@ pub fn readFileContents(self: *ZigObject, elf_file: *Elf) !void {
483539pub fn updateArSymtab(self: ZigObject, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) error{OutOfMemory}!void {
484540 const gpa = elf_file.base.comp.gpa;
485541
486 try ar_symtab.symtab.ensureUnusedCapacity(gpa, self.globals().len);
542 try ar_symtab.symtab.ensureUnusedCapacity(gpa, self.global_symbols.items.len);
487543
488 for (self.globals()) |global_index| {
489 const global = elf_file.symbol(global_index);
490 const file_ptr = global.file(elf_file).?;
491 assert(file_ptr.index() == self.index);
544 for (self.global_symbols.items, 0..) |index, i| {
545 const global = self.symbols.items[index];
546 const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file);
547 const sym = elf_file.symbol(ref).?;
548 assert(sym.file(elf_file).?.index() == self.index);
492549 if (global.outputShndx(elf_file) == null) continue;
493550
494551 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 {
530587 }
531588}
532589
533inline fn isGlobal(index: Symbol.Index) bool {
534 return index & global_symbol_bit != 0;
535}
536
537pub fn symbol(self: ZigObject, index: Symbol.Index) Symbol.Index {
538 const actual_index = index & symbol_mask;
539 if (isGlobal(index)) return self.globals()[actual_index];
540 return self.locals()[actual_index];
541}
542
543pub fn elfSym(self: *ZigObject, index: Symbol.Index) *elf.Elf64_Sym {
544 const actual_index = index & symbol_mask;
545 if (isGlobal(index)) return &self.global_esyms.items(.elf_sym)[actual_index];
546 return &self.local_esyms.items(.elf_sym)[actual_index];
547}
548
549pub fn locals(self: ZigObject) []const Symbol.Index {
550 return self.local_symbols.items;
551}
552
553pub fn globals(self: ZigObject) []const Symbol.Index {
554 return self.global_symbols.items;
555}
556
557590pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void {
558 for (self.locals()) |local_index| {
559 const local = elf_file.symbol(local_index);
591 for (self.local_symbols.items) |index| {
592 const local = &self.symbols.items[index];
560593 if (local.atom(elf_file)) |atom_ptr| if (!atom_ptr.alive) continue;
561594 const esym = local.elfSym(elf_file);
562595 switch (esym.st_type()) {
......@@ -564,22 +597,23 @@ pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void {
564597 else => {},
565598 }
566599 local.flags.output_symtab = true;
567 try local.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file);
600 local.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file);
568601 self.output_symtab_ctx.nlocals += 1;
569602 self.output_symtab_ctx.strsize += @as(u32, @intCast(local.name(elf_file).len)) + 1;
570603 }
571604
572 for (self.globals()) |global_index| {
573 const global = elf_file.symbol(global_index);
574 const file_ptr = global.file(elf_file) orelse continue;
575 if (file_ptr.index() != self.index) continue;
605 for (self.global_symbols.items, self.symbols_resolver.items) |index, resolv| {
606 const global = &self.symbols.items[index];
607 const ref = elf_file.resolver.items[resolv];
608 const ref_sym = elf_file.symbol(ref) orelse continue;
609 if (ref_sym.file(elf_file).?.index() != self.index) continue;
576610 if (global.atom(elf_file)) |atom_ptr| if (!atom_ptr.alive) continue;
577611 global.flags.output_symtab = true;
578612 if (global.isLocal(elf_file)) {
579 try global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file);
613 global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file);
580614 self.output_symtab_ctx.nlocals += 1;
581615 } else {
582 try global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file);
616 global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file);
583617 self.output_symtab_ctx.nglobals += 1;
584618 }
585619 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 {
587621}
588622
589623pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void {
590 for (self.locals()) |local_index| {
591 const local = elf_file.symbol(local_index);
624 for (self.local_symbols.items) |index| {
625 const local = &self.symbols.items[index];
592626 const idx = local.outputSymtabIndex(elf_file) orelse continue;
593627 const out_sym = &elf_file.symtab.items[idx];
594628 out_sym.st_name = @intCast(elf_file.strtab.items.len);
......@@ -597,10 +631,11 @@ pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void {
597631 local.setOutputSym(elf_file, out_sym);
598632 }
599633
600 for (self.globals()) |global_index| {
601 const global = elf_file.symbol(global_index);
602 const file_ptr = global.file(elf_file) orelse continue;
603 if (file_ptr.index() != self.index) continue;
634 for (self.global_symbols.items, self.symbols_resolver.items) |index, resolv| {
635 const global = self.symbols.items[index];
636 const ref = elf_file.resolver.items[resolv];
637 const ref_sym = elf_file.symbol(ref) orelse continue;
638 if (ref_sym.file(elf_file).?.index() != self.index) continue;
604639 const idx = global.outputSymtabIndex(elf_file) orelse continue;
605640 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
606641 elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file));
......@@ -611,10 +646,6 @@ pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void {
611646 }
612647}
613648
614pub fn asFile(self: *ZigObject) File {
615 return .{ .zig_object = self };
616}
617
618649/// Returns atom's code.
619650/// Caller owns the memory.
620651pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 {
......@@ -755,8 +786,8 @@ pub fn getOrCreateMetadataForLazySymbol(
755786 };
756787 switch (metadata.state.*) {
757788 .unused => {
758 const symbol_index = try self.newAtom(elf_file);
759 const sym = elf_file.symbol(symbol_index);
789 const symbol_index = try self.newSymbolWithAtom(gpa, 0);
790 const sym = self.symbol(symbol_index);
760791 sym.flags.needs_zig_got = true;
761792 metadata.symbol_index.* = symbol_index;
762793 },
......@@ -817,10 +848,10 @@ pub fn getOrCreateMetadataForDecl(
817848 const gop = try self.decls.getOrPut(gpa, decl_index);
818849 if (!gop.found_existing) {
819850 const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded;
820 const symbol_index = try self.newAtom(elf_file);
851 const symbol_index = try self.newSymbolWithAtom(gpa, 0);
821852 const mod = elf_file.base.comp.module.?;
822853 const decl = mod.declPtr(decl_index);
823 const sym = elf_file.symbol(symbol_index);
854 const sym = self.symbol(symbol_index);
824855 if (decl.getOwnedVariable(mod)) |variable| {
825856 if (variable.is_threadlocal and any_non_single_threaded) {
826857 sym.flags.is_tls = true;
......@@ -1064,7 +1095,7 @@ pub fn updateFunc(
10641095
10651096 const sym_index = try self.getOrCreateMetadataForDecl(elf_file, decl_index);
10661097 self.freeUnnamedConsts(elf_file, decl_index);
1067 elf_file.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file);
1098 self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file);
10681099
10691100 var code_buffer = std.ArrayList(u8).init(gpa);
10701101 defer code_buffer.deinit();
......@@ -1096,7 +1127,7 @@ pub fn updateFunc(
10961127 try self.updateDeclCode(elf_file, pt, decl_index, sym_index, shndx, code, elf.STT_FUNC);
10971128
10981129 if (decl_state) |*ds| {
1099 const sym = elf_file.symbol(sym_index);
1130 const sym = self.symbol(sym_index);
11001131 try self.dwarf.?.commitDeclState(
11011132 pt,
11021133 decl_index,
......@@ -1130,13 +1161,13 @@ pub fn updateDecl(
11301161 const variable = decl.getOwnedVariable(mod).?;
11311162 const name = decl.name.toSlice(&mod.intern_pool);
11321163 const lib_name = variable.lib_name.toSlice(&mod.intern_pool);
1133 const esym_index = try self.getGlobalSymbol(elf_file, name, lib_name);
1134 elf_file.symbol(self.symbol(esym_index)).flags.needs_got = true;
1164 const sym_index = try self.getGlobalSymbol(elf_file, name, lib_name);
1165 self.symbol(sym_index).flags.needs_got = true;
11351166 return;
11361167 }
11371168
11381169 const sym_index = try self.getOrCreateMetadataForDecl(elf_file, decl_index);
1139 elf_file.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file);
1170 self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file);
11401171
11411172 const gpa = elf_file.base.comp.gpa;
11421173 var code_buffer = std.ArrayList(u8).init(gpa);
......@@ -1174,7 +1205,7 @@ pub fn updateDecl(
11741205 try self.updateDeclCode(elf_file, pt, decl_index, sym_index, shndx, code, elf.STT_OBJECT);
11751206
11761207 if (decl_state) |*ds| {
1177 const sym = elf_file.symbol(sym_index);
1208 const sym = self.symbol(sym_index);
11781209 try self.dwarf.?.commitDeclState(
11791210 pt,
11801211 decl_index,
......@@ -1323,7 +1354,8 @@ fn lowerConst(
13231354 var code_buffer = std.ArrayList(u8).init(gpa);
13241355 defer code_buffer.deinit();
13251356
1326 const sym_index = try self.newAtom(elf_file);
1357 const name_off = try self.addString(gpa, name);
1358 const sym_index = try self.newSymbolWithAtom(gpa, name_off);
13271359
13281360 const res = try codegen.generateSymbol(
13291361 &elf_file.base,
......@@ -1339,27 +1371,19 @@ fn lowerConst(
13391371 .fail => |em| return .{ .fail = em },
13401372 };
13411373
1342 const local_sym = elf_file.symbol(sym_index);
1343 const name_str_index = try self.strtab.insert(gpa, name);
1344 local_sym.name_offset = name_str_index;
1345 const local_esym = &self.local_esyms.items(.elf_sym)[local_sym.esym_index];
1346 local_esym.st_name = name_str_index;
1374 const local_sym = self.symbol(sym_index);
1375 const local_esym = local_sym.elfSym(elf_file);
13471376 local_esym.st_info |= elf.STT_OBJECT;
13481377 local_esym.st_size = code.len;
13491378 const atom_ptr = local_sym.atom(elf_file).?;
13501379 atom_ptr.alive = true;
1351 atom_ptr.name_offset = name_str_index;
13521380 atom_ptr.alignment = required_alignment;
13531381 atom_ptr.size = code.len;
13541382 atom_ptr.output_section_index = output_section_index;
13551383
13561384 try atom_ptr.allocate(elf_file);
1357 // TODO rename and re-audit this method
13581385 errdefer self.freeDeclMetadata(elf_file, sym_index);
13591386
1360 local_sym.value = 0;
1361 local_esym.st_value = 0;
1362
13631387 const shdr = elf_file.shdrs.items[output_section_index];
13641388 const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value));
13651389 try elf_file.base.file.?.pwriteAll(code, file_offset);
......@@ -1401,9 +1425,9 @@ pub fn updateExports(
14011425 },
14021426 };
14031427 const sym_index = metadata.symbol_index;
1404 const esym_index = elf_file.symbol(sym_index).esym_index;
1405 const esym = self.local_esyms.items(.elf_sym)[esym_index];
1406 const esym_shndx = self.local_esyms.items(.shndx)[esym_index];
1428 const esym_index = self.symbol(sym_index).esym_index;
1429 const esym = self.symtab.items(.elf_sym)[esym_index];
1430 const esym_shndx = self.symtab.items(.shndx)[esym_index];
14071431
14081432 for (export_indices) |export_idx| {
14091433 const exp = mod.all_exports.items[export_idx];
......@@ -1437,22 +1461,27 @@ pub fn updateExports(
14371461 const stt_bits: u8 = @as(u4, @truncate(esym.st_info));
14381462 const exp_name = exp.opts.name.toSlice(&mod.intern_pool);
14391463 const name_off = try self.strtab.insert(gpa, exp_name);
1440 const global_esym_index = if (metadata.@"export"(self, exp_name)) |exp_index|
1464 const global_sym_index = if (metadata.@"export"(self, exp_name)) |exp_index|
14411465 exp_index.*
14421466 else blk: {
1443 const global_esym_index = try self.getGlobalSymbol(elf_file, exp_name, null);
1444 try metadata.exports.append(gpa, global_esym_index);
1445 break :blk global_esym_index;
1467 const global_sym_index = try self.getGlobalSymbol(elf_file, exp_name, null);
1468 try metadata.exports.append(gpa, global_sym_index);
1469 break :blk global_sym_index;
14461470 };
14471471
1448 const actual_esym_index = global_esym_index & symbol_mask;
1449 const global_esym = &self.global_esyms.items(.elf_sym)[actual_esym_index];
1450 global_esym.st_value = @intCast(elf_file.symbol(sym_index).value);
1472 const value = self.symbol(sym_index).value;
1473 const global_sym = self.symbol(global_sym_index);
1474 global_sym.value = value;
1475 global_sym.flags.weak = exp.opts.linkage == .weak;
1476 global_sym.version_index = elf_file.default_version_index;
1477 global_sym.ref = .{ .index = esym_shndx, .file = self.index };
1478 const global_esym = global_sym.elfSym(elf_file);
1479 global_esym.st_value = @intCast(value);
14511480 global_esym.st_shndx = esym.st_shndx;
14521481 global_esym.st_info = (stb_bits << 4) | stt_bits;
14531482 global_esym.st_name = name_off;
14541483 global_esym.st_size = esym.st_size;
1455 self.global_esyms.items(.shndx)[actual_esym_index] = esym_shndx;
1484 self.symtab.items(.shndx)[global_sym.esym_index] = esym_shndx;
14561485 }
14571486}
14581487
......@@ -1506,16 +1535,19 @@ pub fn getGlobalSymbol(self: *ZigObject, elf_file: *Elf, name: []const u8, lib_n
15061535 const off = try self.strtab.insert(gpa, name);
15071536 const lookup_gop = try self.globals_lookup.getOrPut(gpa, off);
15081537 if (!lookup_gop.found_existing) {
1509 const esym_index = try self.addGlobalEsym(gpa);
1510 const esym = self.elfSym(esym_index);
1511 esym.st_name = off;
1512 lookup_gop.value_ptr.* = esym_index;
1513 const gop = try elf_file.getOrPutGlobal(name);
1514 try self.global_symbols.append(gpa, gop.index);
1538 lookup_gop.value_ptr.* = try self.newSymbol(gpa, off);
15151539 }
15161540 return lookup_gop.value_ptr.*;
15171541}
15181542
1543pub fn asFile(self: *ZigObject) File {
1544 return .{ .zig_object = self };
1545}
1546
1547fn addString(self: *ZigObject, allocator: Allocator, string: []const u8) !u32 {
1548 return self.strtab.insert(allocator, string);
1549}
1550
15191551pub fn getString(self: ZigObject, off: u32) [:0]const u8 {
15201552 return self.strtab.getAssumeExists(off);
15211553}
......@@ -1586,6 +1618,73 @@ pub fn setAtomExtra(self: *ZigObject, index: u32, extra: Atom.Extra) void {
15861618 }
15871619}
15881620
1621inline fn isGlobal(index: Symbol.Index) bool {
1622 return index & global_symbol_bit != 0;
1623}
1624
1625pub fn symbol(self: *ZigObject, index: Symbol.Index) *Symbol {
1626 const actual_index = index & symbol_mask;
1627 if (isGlobal(index)) return &self.symbols.items[self.global_symbols.items[actual_index]];
1628 return &self.symbols.items[self.local_symbols.items[actual_index]];
1629}
1630
1631pub fn resolveSymbol(self: ZigObject, index: Symbol.Index, elf_file: *Elf) Elf.Ref {
1632 if (isGlobal(index)) {
1633 const resolv = self.symbols_resolver.items[index & symbol_mask];
1634 return elf_file.resolver.get(resolv).?;
1635 }
1636 return .{ .index = index, .file = self.index };
1637}
1638
1639pub fn addSymbol(self: *ZigObject, allocator: Allocator) !Symbol.Index {
1640 try self.symbols.ensureUnusedCapacity(allocator, 1);
1641 const index: Symbol.Index = @intCast(self.symbols.items.len);
1642 self.symbols.appendAssumeCapacity(.{ .file_index = self.index });
1643 return index;
1644}
1645
1646pub fn addSymbolExtra(self: *ZigObject, allocator: Allocator, extra: Symbol.Extra) !u32 {
1647 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1648 try self.symbols_extra.ensureUnusedCapacity(allocator, fields.len);
1649 return self.addSymbolExtraAssumeCapacity(extra);
1650}
1651
1652pub fn addSymbolExtraAssumeCapacity(self: *ZigObject, extra: Symbol.Extra) u32 {
1653 const index = @as(u32, @intCast(self.symbols_extra.items.len));
1654 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1655 inline for (fields) |field| {
1656 self.symbols_extra.appendAssumeCapacity(switch (field.type) {
1657 u32 => @field(extra, field.name),
1658 else => @compileError("bad field type"),
1659 });
1660 }
1661 return index;
1662}
1663
1664pub fn symbolExtra(self: *ZigObject, index: u32) Symbol.Extra {
1665 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1666 var i: usize = index;
1667 var result: Symbol.Extra = undefined;
1668 inline for (fields) |field| {
1669 @field(result, field.name) = switch (field.type) {
1670 u32 => self.symbols_extra.items[i],
1671 else => @compileError("bad field type"),
1672 };
1673 i += 1;
1674 }
1675 return result;
1676}
1677
1678pub fn setSymbolExtra(self: *ZigObject, index: u32, extra: Symbol.Extra) void {
1679 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1680 inline for (fields, 0..) |field, i| {
1681 self.symbols_extra.items[index + i] = switch (field.type) {
1682 u32 => @field(extra, field.name),
1683 else => @compileError("bad field type"),
1684 };
1685 }
1686}
1687
15891688pub fn fmtSymtab(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(formatSymtab) {
15901689 return .{ .data = .{
15911690 .self = self,
......@@ -1658,9 +1757,9 @@ const DeclMetadata = struct {
16581757 /// A list of all exports aliases of this Decl.
16591758 exports: std.ArrayListUnmanaged(Symbol.Index) = .{},
16601759
1661 fn @"export"(m: DeclMetadata, zig_object: *ZigObject, name: []const u8) ?*u32 {
1760 fn @"export"(m: DeclMetadata, zo: *ZigObject, name: []const u8) ?*u32 {
16621761 for (m.exports.items) |*exp| {
1663 const exp_name = zig_object.getString(zig_object.elfSym(exp.*).st_name);
1762 const exp_name = zo.getString(zo.symbol(exp.*).name_off);
16641763 if (mem.eql(u8, name, exp_name)) return exp;
16651764 }
16661765 return null;
src/link/Elf/file.zig-13
......@@ -153,19 +153,6 @@ pub const File = union(enum) {
153153 };
154154 }
155155
156 pub fn locals(file: File) []const Symbol.Index {
157 return switch (file) {
158 .linker_defined, .shared_object => &[0]Symbol.Index{},
159 inline else => |x| x.locals(),
160 };
161 }
162
163 pub fn globals(file: File) []const Symbol.Index {
164 return switch (file) {
165 inline else => |x| x.globals(),
166 };
167 }
168
169156 pub fn getString(file: File, off: u32) [:0]const u8 {
170157 return switch (file) {
171158 inline else => |x| x.getString(off),