authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-12 13:58:18+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-12 14:02:15+02:00
log53c3757c007bc48e5db1b933b0713df099499d2c
tree1d1544f7aff60e0c55dae0d2e5740066b9a68f07
parent00787885f4f99a92d85b496ff9e03993d69b1cf6

elf: start fixing symbol resolution


5 files changed, 109 insertions(+), 91 deletions(-)

src/link/Elf.zig+51-32
......@@ -836,14 +836,20 @@ pub fn populateMissingMetadata(self: *Elf) !void {
836836 } });
837837 self.zig_module_index = index;
838838 const zig_module = self.file(index).?.zig_module;
839 const sym_index = try zig_module.addLocal(self);
840 const sym = self.symbol(sym_index);
841 const esym = zig_module.sourceSymbol(sym_index, self);
839
842840 const name_off = try self.strtab.insert(gpa, std.fs.path.stem(module.main_pkg.root_src_path));
843 sym.name_offset = name_off;
841 const symbol_index = try self.addSymbol();
842 try zig_module.local_symbols.append(gpa, symbol_index);
843 const symbol_ptr = self.symbol(symbol_index);
844 symbol_ptr.file_index = zig_module.index;
845 symbol_ptr.name_offset = name_off;
846
847 const esym_index = try zig_module.addLocalEsym(gpa);
848 const esym = &zig_module.local_esyms.items[esym_index];
844849 esym.st_name = name_off;
845850 esym.st_info |= elf.STT_FILE;
846851 esym.st_shndx = elf.SHN_ABS;
852 symbol_ptr.esym_index = esym_index;
847853 }
848854 }
849855}
......@@ -2194,7 +2200,7 @@ pub fn getOrCreateMetadataForLazySymbol(self: *Elf, sym: link.File.LazySymbol) !
21942200 };
21952201 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
21962202 switch (metadata.state.*) {
2197 .unused => metadata.symbol_index.* = try zig_module.createAtom(switch (sym.kind) {
2203 .unused => metadata.symbol_index.* = try zig_module.addAtom(switch (sym.kind) {
21982204 .code => self.text_section_index.?,
21992205 .const_data => self.rodata_section_index.?,
22002206 }, self),
......@@ -2213,7 +2219,7 @@ pub fn getOrCreateMetadataForDecl(self: *Elf, decl_index: Module.Decl.Index) !Sy
22132219 if (!gop.found_existing) {
22142220 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
22152221 gop.value_ptr.* = .{
2216 .symbol_index = try zig_module.createAtom(self.getDeclShdrIndex(decl_index), self),
2222 .symbol_index = try zig_module.addAtom(self.getDeclShdrIndex(decl_index), self),
22172223 .exports = .{},
22182224 };
22192225 }
......@@ -2264,7 +2270,7 @@ fn updateDeclCode(
22642270 const required_alignment = decl.getAlignment(mod);
22652271
22662272 const sym = self.symbol(sym_index);
2267 const esym = zig_module.sourceSymbol(sym_index, self);
2273 const esym = &zig_module.local_esyms.items[sym.esym_index];
22682274 const atom_ptr = sym.atom(self).?;
22692275 const shdr_index = sym.output_section_index;
22702276
......@@ -2521,7 +2527,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol.
25212527 const local_sym = self.symbol(symbol_index);
25222528 const phdr_index = self.phdr_to_shdr_table.get(local_sym.output_section_index).?;
25232529 local_sym.name_offset = name_str_index;
2524 const local_esym = zig_module.sourceSymbol(symbol_index, self);
2530 const local_esym = &zig_module.local_esyms.items[local_sym.esym_index];
25252531 local_esym.st_name = name_str_index;
25262532 local_esym.st_info |= elf.STT_OBJECT;
25272533 local_esym.st_size = code.len;
......@@ -2575,7 +2581,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
25752581 const name = self.strtab.get(name_str_index).?;
25762582
25772583 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
2578 const sym_index = try zig_module.createAtom(self.rodata_section_index.?, self);
2584 const sym_index = try zig_module.addAtom(self.rodata_section_index.?, self);
25792585
25802586 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), typed_value, &code_buffer, .{
25812587 .none = {},
......@@ -2597,7 +2603,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
25972603 const phdr_index = self.phdr_to_shdr_table.get(shdr_index).?;
25982604 const local_sym = self.symbol(sym_index);
25992605 local_sym.name_offset = name_str_index;
2600 const local_esym = zig_module.sourceSymbol(sym_index, self);
2606 const local_esym = &zig_module.local_esyms.items[local_sym.esym_index];
26012607 local_esym.st_name = name_str_index;
26022608 local_esym.st_info |= elf.STT_OBJECT;
26032609 local_esym.st_size = code.len;
......@@ -2642,10 +2648,11 @@ pub fn updateDeclExports(
26422648
26432649 const gpa = self.base.allocator;
26442650
2651 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
26452652 const decl = mod.declPtr(decl_index);
26462653 const decl_sym_index = try self.getOrCreateMetadataForDecl(decl_index);
26472654 const decl_sym = self.symbol(decl_sym_index);
2648 const decl_esym = decl_sym.sourceSymbol(self);
2655 const decl_esym = zig_module.local_esyms.items[decl_sym.esym_index];
26492656 const decl_metadata = self.decls.getPtr(decl_index).?;
26502657
26512658 for (exports) |exp| {
......@@ -2681,21 +2688,21 @@ pub fn updateDeclExports(
26812688 };
26822689 const stt_bits: u8 = @as(u4, @truncate(decl_esym.st_info));
26832690
2684 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
26852691 const sym_index = if (decl_metadata.@"export"(self, exp_name)) |exp_index| exp_index.* else blk: {
2686 const sym_index = try zig_module.addGlobal(exp_name, self);
2692 const sym_index = try zig_module.addGlobalEsym(gpa);
2693 _ = try zig_module.global_symbols.addOne(gpa);
26872694 try decl_metadata.exports.append(gpa, sym_index);
26882695 break :blk sym_index;
26892696 };
2690 const sym = self.symbol(sym_index);
2691 sym.flags.@"export" = true;
2692 sym.value = decl_sym.value;
2693 sym.atom_index = decl_sym.atom_index;
2694 sym.output_section_index = decl_sym.output_section_index;
2695 const esym = zig_module.sourceSymbol(sym_index, self);
2696 esym.* = decl_esym;
2697 const name_off = try self.strtab.insert(gpa, exp_name);
2698 const esym = &zig_module.global_esyms.items[sym_index];
2699 esym.st_value = decl_sym.value;
2700 esym.st_shndx = decl_sym.output_section_index;
26972701 esym.st_info = (stb_bits << 4) | stt_bits;
2698 _ = self.unresolved.swapRemove(sym_index);
2702 esym.st_name = name_off;
2703
2704 const gop = try self.getOrPutGlobal(name_off);
2705 zig_module.global_symbols.items[sym_index] = gop.index;
26992706 }
27002707}
27012708
......@@ -2722,20 +2729,20 @@ pub fn deleteDeclExport(
27222729) void {
27232730 if (self.llvm_object) |_| return;
27242731 const metadata = self.decls.getPtr(decl_index) orelse return;
2725 const gpa = self.base.allocator;
27262732 const mod = self.base.options.module.?;
27272733 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
27282734 const exp_name = mod.intern_pool.stringToSlice(name);
2729 const sym_index = metadata.@"export"(self, exp_name) orelse return;
2735 const esym_index = metadata.@"export"(self, exp_name) orelse return;
27302736 log.debug("deleting export '{s}'", .{exp_name});
2731 const sym = self.symbol(sym_index.*);
2732 const esym = zig_module.sourceSymbol(sym_index.*, self);
2733 assert(self.resolver.fetchSwapRemove(sym.name_offset) != null); // TODO don't delete it if it's not dominant
2734 sym.* = .{};
2735 // TODO free list for esym!
2737 const esym = &zig_module.global_esyms.items[esym_index.*];
2738 _ = zig_module.globals_lookup.remove(esym.st_name);
2739 const sym_index = self.resolver.get(esym.st_name).?;
2740 const sym = self.symbol(sym_index);
2741 if (sym.file_index == zig_module.index) {
2742 _ = self.resolver.swapRemove(esym.st_name);
2743 sym.* = .{};
2744 }
27362745 esym.* = null_sym;
2737 self.symbols_free_list.append(gpa, sym_index.*) catch {};
2738 sym_index.* = 0;
27392746}
27402747
27412748fn addLinkerDefinedSymbols(self: *Elf) !void {
......@@ -3468,8 +3475,18 @@ pub fn globalByName(self: *Elf, name: []const u8) ?Symbol.Index {
34683475
34693476pub fn getGlobalSymbol(self: *Elf, name: []const u8, lib_name: ?[]const u8) !u32 {
34703477 _ = lib_name;
3478 const gpa = self.base.allocator;
3479 const off = try self.strtab.insert(gpa, name);
3480 const gop = try self.getOrPutGlobal(off);
34713481 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
3472 return zig_module.addGlobal(name, self);
3482 const lookup_gop = try zig_module.globals_lookup.getOrPut(gpa, off);
3483 if (!lookup_gop.found_existing) {
3484 const esym_index = try zig_module.addGlobalEsym(gpa);
3485 const esym = &zig_module.global_esyms.items[esym_index];
3486 esym.st_name = off;
3487 lookup_gop.value_ptr.* = esym_index;
3488 }
3489 return gop.index;
34733490}
34743491
34753492const GetOrCreateComdatGroupOwnerResult = struct {
......@@ -3753,8 +3770,10 @@ const DeclMetadata = struct {
37533770 exports: std.ArrayListUnmanaged(Symbol.Index) = .{},
37543771
37553772 fn @"export"(m: DeclMetadata, elf_file: *Elf, name: []const u8) ?*u32 {
3773 const zig_module = elf_file.file(elf_file.zig_module_index.?).?.zig_module;
37563774 for (m.exports.items) |*exp| {
3757 if (mem.eql(u8, name, elf_file.symbol(exp.*).name(elf_file))) return exp;
3775 const exp_name = elf_file.strtab.getAssumeExists(zig_module.global_esyms.items[exp.*].st_name);
3776 if (mem.eql(u8, name, exp_name)) return exp;
37583777 }
37593778 return null;
37603779 }
src/link/Elf/Object.zig+2-2
......@@ -8,9 +8,9 @@ shdrs: std.ArrayListUnmanaged(elf.Elf64_Shdr) = .{},
88strings: StringTable(.object_strings) = .{},
99symtab: []align(1) const elf.Elf64_Sym = &[0]elf.Elf64_Sym{},
1010strtab: []const u8 = &[0]u8{},
11first_global: ?u32 = null,
11first_global: ?Symbol.Index = null,
1212
13symbols: std.ArrayListUnmanaged(u32) = .{},
13symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
1414atoms: std.ArrayListUnmanaged(Atom.Index) = .{},
1515comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup.Index) = .{},
1616
src/link/Elf/Symbol.zig+11-4
......@@ -69,9 +69,13 @@ pub fn file(symbol: Symbol, elf_file: *Elf) ?File {
6969pub fn sourceSymbol(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym {
7070 const file_ptr = symbol.file(elf_file).?;
7171 switch (file_ptr) {
72 .zig_module => return file_ptr.zig_module.sourceSymbol(symbol.index, elf_file).*,
73 .linker_defined => return file_ptr.linker_defined.symtab.items[symbol.esym_index],
74 .object => return file_ptr.object.symtab[symbol.esym_index],
72 .zig_module => |x| {
73 const is_global = x.globals_lookup.contains(symbol.name_offset);
74 if (is_global) return x.global_esyms.items[symbol.esym_index];
75 return x.local_esyms.items[symbol.esym_index];
76 },
77 .linker_defined => |x| return x.symtab.items[symbol.esym_index],
78 .object => |x| return x.symtab[symbol.esym_index],
7579 }
7680}
7781
......@@ -164,7 +168,10 @@ pub fn setExtra(symbol: Symbol, extras: Extra, elf_file: *Elf) void {
164168}
165169
166170pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
167 const file_ptr = symbol.file(elf_file).?;
171 const file_ptr = symbol.file(elf_file) orelse {
172 out.* = Elf.null_sym;
173 return;
174 };
168175 const s_sym = symbol.sourceSymbol(elf_file);
169176 const st_type = symbol.type(elf_file);
170177 const st_bind: u8 = blk: {
src/link/Elf/ZigModule.zig+45-52
......@@ -2,11 +2,11 @@
22path: []const u8,
33index: File.Index,
44
5elf_local_symbols: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
6local_symbols: std.AutoArrayHashMapUnmanaged(Symbol.Index, void) = .{},
7
8elf_global_symbols: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
9global_symbols: std.AutoArrayHashMapUnmanaged(Symbol.Index, void) = .{},
5local_esyms: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
6global_esyms: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
7local_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
8global_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
9globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},
1010
1111atoms: std.AutoArrayHashMapUnmanaged(Atom.Index, void) = .{},
1212relocs: std.ArrayListUnmanaged(std.ArrayListUnmanaged(elf.Elf64_Rela)) = .{},
......@@ -14,10 +14,11 @@ relocs: std.ArrayListUnmanaged(std.ArrayListUnmanaged(elf.Elf64_Rela)) = .{},
1414output_symtab_size: Elf.SymtabSize = .{},
1515
1616pub fn deinit(self: *ZigModule, allocator: Allocator) void {
17 self.elf_local_symbols.deinit(allocator);
17 self.local_esyms.deinit(allocator);
18 self.global_esyms.deinit(allocator);
1819 self.local_symbols.deinit(allocator);
19 self.elf_global_symbols.deinit(allocator);
2020 self.global_symbols.deinit(allocator);
21 self.globals_lookup.deinit(allocator);
2122 self.atoms.deinit(allocator);
2223 for (self.relocs.items) |*list| {
2324 list.deinit(allocator);
......@@ -25,58 +26,57 @@ pub fn deinit(self: *ZigModule, allocator: Allocator) void {
2526 self.relocs.deinit(allocator);
2627}
2728
28pub fn createAtom(self: *ZigModule, output_section_index: u16, elf_file: *Elf) !Symbol.Index {
29pub fn addLocalEsym(self: *ZigModule, allocator: Allocator) !Symbol.Index {
30 try self.local_esyms.ensureUnusedCapacity(allocator, 1);
31 const index = @as(Symbol.Index, @intCast(self.local_esyms.items.len));
32 const esym = self.local_esyms.addOneAssumeCapacity();
33 esym.* = Elf.null_sym;
34 esym.st_info = elf.STB_LOCAL << 4;
35 return index;
36}
37
38pub fn addGlobalEsym(self: *ZigModule, allocator: Allocator) !Symbol.Index {
39 try self.global_esyms.ensureUnusedCapacity(allocator, 1);
40 const index = @as(Symbol.Index, @intCast(self.global_esyms.items.len));
41 const esym = self.global_esyms.addOneAssumeCapacity();
42 esym.* = Elf.null_sym;
43 esym.st_info = elf.STB_GLOBAL << 4;
44 return index;
45}
46
47pub fn addAtom(self: *ZigModule, output_section_index: u16, elf_file: *Elf) !Symbol.Index {
2948 const gpa = elf_file.base.allocator;
49
3050 const atom_index = try elf_file.addAtom();
31 const symbol_index = try self.addLocal(elf_file);
51 try self.atoms.putNoClobber(gpa, atom_index, {});
3252 const atom_ptr = elf_file.atom(atom_index).?;
3353 atom_ptr.file_index = self.index;
3454 atom_ptr.output_section_index = output_section_index;
55
56 const symbol_index = try elf_file.addSymbol();
57 try self.local_symbols.append(gpa, symbol_index);
3558 const symbol_ptr = elf_file.symbol(symbol_index);
59 symbol_ptr.file_index = self.index;
3660 symbol_ptr.atom_index = atom_index;
3761 symbol_ptr.output_section_index = output_section_index;
38 const local_esym = self.sourceSymbol(symbol_ptr.index, elf_file);
39 local_esym.st_shndx = output_section_index;
62
63 const esym_index = try self.addLocalEsym(gpa);
64 const esym = &self.local_esyms.items[esym_index];
65 esym.st_shndx = output_section_index;
66 symbol_ptr.esym_index = esym_index;
67
4068 const relocs_index = @as(Atom.Index, @intCast(self.relocs.items.len));
4169 const relocs = try self.relocs.addOne(gpa);
4270 relocs.* = .{};
4371 atom_ptr.relocs_section_index = relocs_index;
44 try self.atoms.putNoClobber(gpa, atom_index, {});
45 return symbol_index;
46}
4772
48pub fn addLocal(self: *ZigModule, elf_file: *Elf) !Symbol.Index {
49 const gpa = elf_file.base.allocator;
50 const symbol_index = try elf_file.addSymbol();
51 const symbol_ptr = elf_file.symbol(symbol_index);
52 symbol_ptr.file_index = self.index;
53 symbol_ptr.esym_index = @as(Symbol.Index, @intCast(self.elf_local_symbols.items.len));
54 const local_esym = try self.elf_local_symbols.addOne(gpa);
55 local_esym.* = Elf.null_sym;
56 local_esym.st_info = elf.STB_LOCAL << 4;
57 try self.local_symbols.putNoClobber(gpa, symbol_index, {});
5873 return symbol_index;
5974}
6075
61pub fn addGlobal(self: *ZigModule, name: []const u8, elf_file: *Elf) !Symbol.Index {
62 const gpa = elf_file.base.allocator;
63 try self.elf_global_symbols.ensureUnusedCapacity(gpa, 1);
64 try self.global_symbols.ensureUnusedCapacity(gpa, 1);
65 const off = try elf_file.strtab.insert(gpa, name);
66 const esym_index = @as(Symbol.Index, @intCast(self.elf_global_symbols.items.len));
67 const esym = self.elf_global_symbols.addOneAssumeCapacity();
68 esym.* = Elf.null_sym;
69 esym.st_name = off;
70 esym.st_info = elf.STB_GLOBAL << 4;
71 const gop = try elf_file.getOrPutGlobal(off);
72 if (!gop.found_existing) {
73 try elf_file.unresolved.putNoClobber(gpa, gop.index, {});
74 }
75 const sym = elf_file.symbol(gop.index);
76 sym.file_index = self.index;
77 sym.esym_index = esym_index;
78 self.global_symbols.putAssumeCapacityNoClobber(gop.index, {});
79 return gop.index;
76pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void {
77 _ = self;
78 _ = elf_file;
79 @panic("TODO");
8080}
8181
8282pub fn updateSymtabSize(self: *ZigModule, elf_file: *Elf) void {
......@@ -133,19 +133,12 @@ pub fn writeSymtab(self: *ZigModule, elf_file: *Elf, ctx: anytype) void {
133133 }
134134}
135135
136pub fn sourceSymbol(self: *ZigModule, symbol_index: Symbol.Index, elf_file: *Elf) *elf.Elf64_Sym {
137 const sym = elf_file.symbol(symbol_index);
138 if (self.local_symbols.get(symbol_index)) |_| return &self.elf_local_symbols.items[sym.esym_index];
139 assert(self.global_symbols.get(symbol_index) != null);
140 return &self.elf_global_symbols.items[sym.esym_index];
141}
142
143136pub fn locals(self: *ZigModule) []const Symbol.Index {
144 return self.local_symbols.keys();
137 return self.local_symbols.items;
145138}
146139
147140pub fn globals(self: *ZigModule) []const Symbol.Index {
148 return self.global_symbols.keys();
141 return self.global_symbols.items;
149142}
150143
151144pub fn asFile(self: *ZigModule) File {
src/link/Elf/file.zig-1
......@@ -32,7 +32,6 @@ pub const File = union(enum) {
3232
3333 pub fn resolveSymbols(file: File, elf_file: *Elf) void {
3434 switch (file) {
35 .zig_module => unreachable, // handled separately
3635 inline else => |x| x.resolveSymbols(elf_file),
3736 }
3837 }