authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-12 14:36:55+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-12 14:36:55+02:00
log962b46148d573f62146a2752a0ab8cfd5f8da132
treec7c0328dd00321ebdd6f727e9fca8e250148dd97
parent53c3757c007bc48e5db1b933b0713df099499d2c

elf: add simplistic symbol resolution


6 files changed, 63 insertions(+), 45 deletions(-)

src/link/Elf.zig+16-1
...@@ -1045,6 +1045,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1045,6 +1045,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
10451045
1046 try self.addLinkerDefinedSymbols();1046 try self.addLinkerDefinedSymbols();
10471047
1048 // Resolve symbols
1049 self.resolveSymbols();
1050
1048 if (self.unresolved.keys().len > 0) try self.reportUndefined();1051 if (self.unresolved.keys().len > 0) try self.reportUndefined();
10491052
1050 self.allocateLinkerDefinedSymbols();1053 self.allocateLinkerDefinedSymbols();
...@@ -1321,6 +1324,18 @@ fn parseObject(self: *Elf, in_file: std.fs.File, path: []const u8, ctx: *ParseEr...@@ -1321,6 +1324,18 @@ fn parseObject(self: *Elf, in_file: std.fs.File, path: []const u8, ctx: *ParseEr
1321 if (ctx.detected_cpu_arch != self.base.options.target.cpu.arch) return error.InvalidCpuArch;1324 if (ctx.detected_cpu_arch != self.base.options.target.cpu.arch) return error.InvalidCpuArch;
1322}1325}
13231326
1327fn resolveSymbols(self: *Elf) void {
1328 if (self.zig_module_index) |index| {
1329 const zig_module = self.file(index).?.zig_module;
1330 zig_module.resolveSymbols(self);
1331 }
1332
1333 for (self.objects.items) |index| {
1334 const object = self.file(index).?.object;
1335 object.resolveSymbols(self);
1336 }
1337}
1338
1324fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {1339fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {
1325 const tracy = trace(@src());1340 const tracy = trace(@src());
1326 defer tracy.end();1341 defer tracy.end();
...@@ -2697,7 +2712,7 @@ pub fn updateDeclExports(...@@ -2697,7 +2712,7 @@ pub fn updateDeclExports(
2697 const name_off = try self.strtab.insert(gpa, exp_name);2712 const name_off = try self.strtab.insert(gpa, exp_name);
2698 const esym = &zig_module.global_esyms.items[sym_index];2713 const esym = &zig_module.global_esyms.items[sym_index];
2699 esym.st_value = decl_sym.value;2714 esym.st_value = decl_sym.value;
2700 esym.st_shndx = decl_sym.output_section_index;2715 esym.st_shndx = decl_sym.atom_index;
2701 esym.st_info = (stb_bits << 4) | stt_bits;2716 esym.st_info = (stb_bits << 4) | stt_bits;
2702 esym.st_name = name_off;2717 esym.st_name = name_off;
27032718
src/link/Elf/Atom.zig+2-2
...@@ -17,7 +17,7 @@ alignment: u8 = 0,...@@ -17,7 +17,7 @@ alignment: u8 = 0,
17input_section_index: Index = 0,17input_section_index: Index = 0,
1818
19/// Index of the output section.19/// Index of the output section.
20output_section_index: u16 = 0,20output_section_index: Index = 0,
2121
22/// Index of the input section containing this atom's relocs.22/// Index of the input section containing this atom's relocs.
23relocs_section_index: Index = 0,23relocs_section_index: Index = 0,
...@@ -484,7 +484,7 @@ fn format2(...@@ -484,7 +484,7 @@ fn format2(
484 }484 }
485}485}
486486
487pub const Index = u32;487pub const Index = u16;
488488
489const std = @import("std");489const std = @import("std");
490const assert = std.debug.assert;490const assert = std.debug.assert;
src/link/Elf/Object.zig+14-23
...@@ -245,10 +245,6 @@ fn initSymtab(self: *Object, elf_file: *Elf) !void {...@@ -245,10 +245,6 @@ fn initSymtab(self: *Object, elf_file: *Elf) !void {
245 const off = try elf_file.strtab.insert(gpa, name);245 const off = try elf_file.strtab.insert(gpa, name);
246 const gop = try elf_file.getOrPutGlobal(off);246 const gop = try elf_file.getOrPutGlobal(off);
247 self.symbols.addOneAssumeCapacity().* = gop.index;247 self.symbols.addOneAssumeCapacity().* = gop.index;
248
249 if (sym.st_shndx == elf.SHN_UNDEF) {
250 try elf_file.unresolved.put(gpa, gop.index, {});
251 }
252 }248 }
253}249}
254250
...@@ -388,34 +384,29 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf) !void {...@@ -388,34 +384,29 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf) !void {
388pub fn resolveSymbols(self: *Object, elf_file: *Elf) void {384pub fn resolveSymbols(self: *Object, elf_file: *Elf) void {
389 const first_global = self.first_global orelse return;385 const first_global = self.first_global orelse return;
390 for (self.globals(), 0..) |index, i| {386 for (self.globals(), 0..) |index, i| {
391 const sym_idx = @as(u32, @intCast(first_global + i));387 const esym_index = @as(Symbol.Index, @intCast(first_global + i));
392 const this_sym = self.symtab[sym_idx];388 const esym = self.symtab[esym_index];
393389
394 if (this_sym.st_shndx == elf.SHN_UNDEF) continue;390 if (esym.st_shndx == elf.SHN_UNDEF) continue;
395391
396 if (this_sym.st_shndx != elf.SHN_ABS and this_sym.st_shndx != elf.SHN_COMMON) {392 if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) {
397 const atom_index = self.atoms.items[this_sym.st_shndx];393 const atom_index = self.atoms.items[esym.st_shndx];
398 const atom = elf_file.atom(atom_index) orelse continue;394 const atom = elf_file.atom(atom_index) orelse continue;
399 if (!atom.alive) continue;395 if (!atom.alive) continue;
400 }396 }
401397
402 _ = elf_file.unresolved.swapRemove(index);
403
404 const global = elf_file.symbol(index);398 const global = elf_file.symbol(index);
405 if (self.asFile().symbolRank(this_sym, !self.alive) < global.symbolRank(elf_file)) {399 if (self.asFile().symbolRank(esym, !self.alive) < global.symbolRank(elf_file)) {
406 const atom = switch (this_sym.st_shndx) {400 const atom_index = switch (esym.st_shndx) {
407 elf.SHN_ABS, elf.SHN_COMMON => 0,401 elf.SHN_ABS, elf.SHN_COMMON => 0,
408 else => self.atoms.items[this_sym.st_shndx],402 else => self.atoms.items[esym.st_shndx],
409 };
410 global.* = .{
411 .value = this_sym.st_value,
412 .name = global.name,
413 .atom = atom,
414 .sym_idx = sym_idx,
415 .file = self.index,
416 .ver_idx = elf_file.default_sym_version,
417 };403 };
418 if (this_sym.st_bind() == elf.STB_WEAK) global.flags.weak = true;404 global.value = esym.st_value;
405 global.atom_index = atom_index;
406 global.esym_index = esym_index;
407 global.file_index = self.index;
408 global.version_index = elf_file.default_sym_version;
409 if (esym.st_bind() == elf.STB_WEAK) global.flags.weak = true;
419 }410 }
420 }411 }
421}412}
src/link/Elf/Symbol.zig+4-3
...@@ -70,9 +70,10 @@ pub fn sourceSymbol(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym {...@@ -70,9 +70,10 @@ pub fn sourceSymbol(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym {
70 const file_ptr = symbol.file(elf_file).?;70 const file_ptr = symbol.file(elf_file).?;
71 switch (file_ptr) {71 switch (file_ptr) {
72 .zig_module => |x| {72 .zig_module => |x| {
73 const is_global = x.globals_lookup.contains(symbol.name_offset);73 const is_global = symbol.esym_index & 0x10000000 != 0;
74 if (is_global) return x.global_esyms.items[symbol.esym_index];74 const esym_index = symbol.esym_index & 0x0fffffff;
75 return x.local_esyms.items[symbol.esym_index];75 if (is_global) return x.global_esyms.items[esym_index];
76 return x.local_esyms.items[esym_index];
76 },77 },
77 .linker_defined => |x| return x.symtab.items[symbol.esym_index],78 .linker_defined => |x| return x.symtab.items[symbol.esym_index],
78 .object => |x| return x.symtab[symbol.esym_index],79 .object => |x| return x.symtab[symbol.esym_index],
src/link/Elf/ZigModule.zig+27-4
...@@ -62,7 +62,7 @@ pub fn addAtom(self: *ZigModule, output_section_index: u16, elf_file: *Elf) !Sym...@@ -62,7 +62,7 @@ pub fn addAtom(self: *ZigModule, output_section_index: u16, elf_file: *Elf) !Sym
6262
63 const esym_index = try self.addLocalEsym(gpa);63 const esym_index = try self.addLocalEsym(gpa);
64 const esym = &self.local_esyms.items[esym_index];64 const esym = &self.local_esyms.items[esym_index];
65 esym.st_shndx = output_section_index;65 esym.st_shndx = atom_index;
66 symbol_ptr.esym_index = esym_index;66 symbol_ptr.esym_index = esym_index;
6767
68 const relocs_index = @as(Atom.Index, @intCast(self.relocs.items.len));68 const relocs_index = @as(Atom.Index, @intCast(self.relocs.items.len));
...@@ -74,9 +74,32 @@ pub fn addAtom(self: *ZigModule, output_section_index: u16, elf_file: *Elf) !Sym...@@ -74,9 +74,32 @@ pub fn addAtom(self: *ZigModule, output_section_index: u16, elf_file: *Elf) !Sym
74}74}
7575
76pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void {76pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void {
77 _ = self;77 for (self.globals(), 0..) |index, i| {
78 _ = elf_file;78 const esym_index = @as(Symbol.Index, @intCast(i)) | 0x10000000;
79 @panic("TODO");79 const esym = self.global_esyms.items[i];
80
81 if (esym.st_shndx == elf.SHN_UNDEF) continue;
82
83 if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) {
84 const atom_index = self.atoms.keys()[esym.st_shndx];
85 const atom = elf_file.atom(atom_index) orelse continue;
86 if (!atom.alive) continue;
87 }
88
89 const global = elf_file.symbol(index);
90 if (self.asFile().symbolRank(esym, false) < global.symbolRank(elf_file)) {
91 const atom_index = switch (esym.st_shndx) {
92 elf.SHN_ABS, elf.SHN_COMMON => 0,
93 else => self.atoms.keys()[esym.st_shndx],
94 };
95 global.value = esym.st_value;
96 global.atom_index = atom_index;
97 global.esym_index = esym_index;
98 global.file_index = self.index;
99 global.version_index = elf_file.default_sym_version;
100 if (esym.st_bind() == elf.STB_WEAK) global.flags.weak = true;
101 }
102 }
80}103}
81104
82pub fn updateSymtabSize(self: *ZigModule, elf_file: *Elf) void {105pub fn updateSymtabSize(self: *ZigModule, elf_file: *Elf) void {
src/link/Elf/file.zig-12
...@@ -30,18 +30,6 @@ pub const File = union(enum) {...@@ -30,18 +30,6 @@ pub const File = union(enum) {
30 }30 }
31 }31 }
3232
33 pub fn resolveSymbols(file: File, elf_file: *Elf) void {
34 switch (file) {
35 inline else => |x| x.resolveSymbols(elf_file),
36 }
37 }
38
39 // pub fn resetGlobals(file: File, elf_file: *Elf) void {
40 // switch (file) {
41 // inline else => |x| x.resetGlobals(elf_file),
42 // }
43 // }
44
45 pub fn isAlive(file: File) bool {33 pub fn isAlive(file: File) bool {
46 return switch (file) {34 return switch (file) {
47 .zig_module => true,35 .zig_module => true,