authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-12 15:44:16+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-12 15:44:16+02:00
logc654f3b0ee8d02d809bb458e1e006b4aa7c3cbc6
tree841df34409500529095b45be843bd0332c99aab0
parentb478a0dd1ab6acab92e2b1a4198fdf6428caad8d

elf: claim unresolved dangling symbols that can be claimed


4 files changed, 101 insertions(+), 37 deletions(-)

src/link/Elf.zig+37-35
...@@ -1048,6 +1048,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1048,6 +1048,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1048 // Resolve symbols1048 // Resolve symbols
1049 self.resolveSymbols();1049 self.resolveSymbols();
1050 self.markImportsExports();1050 self.markImportsExports();
1051 self.claimUnresolved();
10511052
1052 if (self.unresolved.keys().len > 0) try self.reportUndefined();1053 if (self.unresolved.keys().len > 0) try self.reportUndefined();
10531054
...@@ -1338,48 +1339,45 @@ fn resolveSymbols(self: *Elf) void {...@@ -1338,48 +1339,45 @@ fn resolveSymbols(self: *Elf) void {
1338}1339}
13391340
1340fn markImportsExports(self: *Elf) void {1341fn markImportsExports(self: *Elf) void {
1341 const is_dyn_lib = self.base.options.output_mode == .Lib and self.base.options.link_mode == .Dynamic;1342 const mark = struct {
13421343 fn mark(elf_file: *Elf, file_index: File.Index) void {
1343 if (self.zig_module_index) |index| {1344 for (elf_file.file(file_index).?.globals()) |global_index| {
1344 const zig_module = self.file(index).?.zig_module;1345 const global = elf_file.symbol(global_index);
1345 for (zig_module.globals()) |global_index| {1346 if (global.version_index == elf.VER_NDX_LOCAL) continue;
1346 const global = self.symbol(global_index);1347 const file_ptr = global.file(elf_file) orelse continue;
1347 if (global.version_index == elf.VER_NDX_LOCAL) continue;1348 const vis = @as(elf.STV, @enumFromInt(global.elfSym(elf_file).st_other));
1348 const file_ptr = global.file(self) orelse continue;1349 if (vis == .HIDDEN) continue;
1349 const vis = @as(elf.STV, @enumFromInt(global.elfSym(self).st_other));1350 // if (file == .shared and !global.isAbs(self)) {
1350 if (vis == .HIDDEN) continue;1351 // global.flags.import = true;
1351 // if (file == .shared and !global.isAbs(self)) {1352 // continue;
1352 // global.flags.import = true;1353 // }
1353 // continue;1354 if (file_ptr.index() == file_index) {
1354 // }1355 global.flags.@"export" = true;
1355 if (file_ptr.index() == index) {1356 if (elf_file.isDynLib() and vis != .PROTECTED) {
1356 global.flags.@"export" = true;1357 global.flags.import = true;
1357 if (is_dyn_lib and vis != .PROTECTED) {1358 }
1358 global.flags.import = true;
1359 }1359 }
1360 }1360 }
1361 }1361 }
1362 }.mark;
1363
1364 if (self.zig_module_index) |index| {
1365 mark(self, index);
1366 }
1367
1368 for (self.objects.items) |index| {
1369 mark(self, index);
1362 }1370 }
1371}
13631372
1373fn claimUnresolved(self: *Elf) void {
1374 if (self.zig_module_index) |index| {
1375 const zig_module = self.file(index).?.zig_module;
1376 zig_module.claimUnresolved(self);
1377 }
1364 for (self.objects.items) |index| {1378 for (self.objects.items) |index| {
1365 const object = self.file(index).?.object;1379 const object = self.file(index).?.object;
1366 for (object.globals()) |global_index| {1380 object.claimUnresolved(self);
1367 const global = self.symbol(global_index);
1368 if (global.version_index == elf.VER_NDX_LOCAL) continue;
1369 const file_ptr = global.file(self) orelse continue;
1370 const vis = @as(elf.STV, @enumFromInt(global.elfSym(self).st_other));
1371 if (vis == .HIDDEN) continue;
1372 // if (file == .shared and !global.isAbs(self)) {
1373 // global.flags.import = true;
1374 // continue;
1375 // }
1376 if (file_ptr.index() == index) {
1377 global.flags.@"export" = true;
1378 if (is_dyn_lib and vis != .PROTECTED) {
1379 global.flags.import = true;
1380 }
1381 }
1382 }
1383 }1381 }
1384}1382}
13851383
...@@ -3423,6 +3421,10 @@ pub fn defaultEntryAddress(self: Elf) u64 {...@@ -3423,6 +3421,10 @@ pub fn defaultEntryAddress(self: Elf) u64 {
3423 };3421 };
3424}3422}
34253423
3424pub fn isDynLib(self: Elf) bool {
3425 return self.base.options.output_mode == .Lib and self.base.options.link_mode == .Dynamic;
3426}
3427
3426pub fn sectionByName(self: *Elf, name: [:0]const u8) ?u16 {3428pub fn sectionByName(self: *Elf, name: [:0]const u8) ?u16 {
3427 for (self.shdrs.items, 0..) |*shdr, i| {3429 for (self.shdrs.items, 0..) |*shdr, i| {
3428 const this_name = self.shstrtab.getAssumeExists(shdr.sh_name);3430 const this_name = self.shstrtab.getAssumeExists(shdr.sh_name);
src/link/Elf/Object.zig+30-2
...@@ -411,6 +411,34 @@ pub fn resolveSymbols(self: *Object, elf_file: *Elf) void {...@@ -411,6 +411,34 @@ pub fn resolveSymbols(self: *Object, elf_file: *Elf) void {
411 }411 }
412}412}
413413
414pub fn claimUnresolved(self: *Object, elf_file: *Elf) void {
415 const first_global = self.first_global orelse return;
416 for (self.globals(), 0..) |index, i| {
417 const esym_index = @as(u32, @intCast(first_global + i));
418 const esym = self.symtab[esym_index];
419 if (esym.st_shndx != elf.SHN_UNDEF) continue;
420
421 const global = elf_file.symbol(index);
422 if (global.file(elf_file)) |_| {
423 if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF) continue;
424 }
425
426 const is_import = blk: {
427 if (!elf_file.isDynLib()) break :blk false;
428 const vis = @as(elf.STV, @enumFromInt(esym.st_other));
429 if (vis == .HIDDEN) break :blk false;
430 break :blk true;
431 };
432
433 global.value = 0;
434 global.atom_index = 0;
435 global.esym_index = esym_index;
436 global.file_index = self.index;
437 global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;
438 global.flags.import = is_import;
439 }
440}
441
414pub fn resetGlobals(self: *Object, elf_file: *Elf) void {442pub fn resetGlobals(self: *Object, elf_file: *Elf) void {
415 for (self.globals()) |index| {443 for (self.globals()) |index| {
416 const global = elf_file.symbol(index);444 const global = elf_file.symbol(index);
...@@ -576,12 +604,12 @@ pub fn writeSymtab(self: *Object, elf_file: *Elf, ctx: anytype) void {...@@ -576,12 +604,12 @@ pub fn writeSymtab(self: *Object, elf_file: *Elf, ctx: anytype) void {
576 }604 }
577}605}
578606
579pub fn locals(self: *Object) []const u32 {607pub fn locals(self: *Object) []const Symbol.Index {
580 const end = self.first_global orelse self.symbols.items.len;608 const end = self.first_global orelse self.symbols.items.len;
581 return self.symbols.items[0..end];609 return self.symbols.items[0..end];
582}610}
583611
584pub fn globals(self: *Object) []const u32 {612pub fn globals(self: *Object) []const Symbol.Index {
585 const start = self.first_global orelse self.symbols.items.len;613 const start = self.first_global orelse self.symbols.items.len;
586 return self.symbols.items[start..];614 return self.symbols.items[start..];
587}615}
src/link/Elf/ZigModule.zig+28
...@@ -102,6 +102,34 @@ pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void {...@@ -102,6 +102,34 @@ pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void {
102 }102 }
103}103}
104104
105pub fn claimUnresolved(self: *ZigModule, elf_file: *Elf) void {
106 for (self.globals(), 0..) |index, i| {
107 const esym_index = @as(Symbol.Index, @intCast(i)) | 0x10000000;
108 const esym = self.global_esyms.items[i];
109
110 if (esym.st_shndx != elf.SHN_UNDEF) continue;
111
112 const global = elf_file.symbol(index);
113 if (global.file(elf_file)) |_| {
114 if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF) continue;
115 }
116
117 const is_import = blk: {
118 if (!elf_file.isDynLib()) break :blk false;
119 const vis = @as(elf.STV, @enumFromInt(esym.st_other));
120 if (vis == .HIDDEN) break :blk false;
121 break :blk true;
122 };
123
124 global.value = 0;
125 global.atom_index = 0;
126 global.esym_index = esym_index;
127 global.file_index = self.index;
128 global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;
129 global.flags.import = is_import;
130 }
131}
132
105pub fn updateSymtabSize(self: *ZigModule, elf_file: *Elf) void {133pub fn updateSymtabSize(self: *ZigModule, elf_file: *Elf) void {
106 for (self.locals()) |local_index| {134 for (self.locals()) |local_index| {
107 const local = elf_file.symbol(local_index);135 const local = elf_file.symbol(local_index);
src/link/Elf/file.zig+6
...@@ -76,6 +76,12 @@ pub const File = union(enum) {...@@ -76,6 +76,12 @@ pub const File = union(enum) {
76 }76 }
77 }77 }
7878
79 pub fn globals(file: File) []const Symbol.Index {
80 return switch (file) {
81 inline else => |x| x.globals(),
82 };
83 }
84
79 pub const Index = u32;85 pub const Index = u32;
8086
81 pub const Entry = union(enum) {87 pub const Entry = union(enum) {