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
10481048 // Resolve symbols
10491049 self.resolveSymbols();
10501050 self.markImportsExports();
1051 self.claimUnresolved();
10511052
10521053 if (self.unresolved.keys().len > 0) try self.reportUndefined();
10531054
......@@ -1338,48 +1339,45 @@ fn resolveSymbols(self: *Elf) void {
13381339}
13391340
13401341fn markImportsExports(self: *Elf) void {
1341 const is_dyn_lib = self.base.options.output_mode == .Lib and self.base.options.link_mode == .Dynamic;
1342
1343 if (self.zig_module_index) |index| {
1344 const zig_module = self.file(index).?.zig_module;
1345 for (zig_module.globals()) |global_index| {
1346 const global = self.symbol(global_index);
1347 if (global.version_index == elf.VER_NDX_LOCAL) continue;
1348 const file_ptr = global.file(self) orelse continue;
1349 const vis = @as(elf.STV, @enumFromInt(global.elfSym(self).st_other));
1350 if (vis == .HIDDEN) continue;
1351 // if (file == .shared and !global.isAbs(self)) {
1352 // global.flags.import = true;
1353 // continue;
1354 // }
1355 if (file_ptr.index() == index) {
1356 global.flags.@"export" = true;
1357 if (is_dyn_lib and vis != .PROTECTED) {
1358 global.flags.import = true;
1342 const mark = struct {
1343 fn mark(elf_file: *Elf, file_index: File.Index) void {
1344 for (elf_file.file(file_index).?.globals()) |global_index| {
1345 const global = elf_file.symbol(global_index);
1346 if (global.version_index == elf.VER_NDX_LOCAL) continue;
1347 const file_ptr = global.file(elf_file) orelse continue;
1348 const vis = @as(elf.STV, @enumFromInt(global.elfSym(elf_file).st_other));
1349 if (vis == .HIDDEN) continue;
1350 // if (file == .shared and !global.isAbs(self)) {
1351 // global.flags.import = true;
1352 // continue;
1353 // }
1354 if (file_ptr.index() == file_index) {
1355 global.flags.@"export" = true;
1356 if (elf_file.isDynLib() and vis != .PROTECTED) {
1357 global.flags.import = true;
1358 }
13591359 }
13601360 }
13611361 }
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);
13621370 }
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 }
13641378 for (self.objects.items) |index| {
13651379 const object = self.file(index).?.object;
1366 for (object.globals()) |global_index| {
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 }
1380 object.claimUnresolved(self);
13831381 }
13841382}
13851383
......@@ -3423,6 +3421,10 @@ pub fn defaultEntryAddress(self: Elf) u64 {
34233421 };
34243422}
34253423
3424pub fn isDynLib(self: Elf) bool {
3425 return self.base.options.output_mode == .Lib and self.base.options.link_mode == .Dynamic;
3426}
3427
34263428pub fn sectionByName(self: *Elf, name: [:0]const u8) ?u16 {
34273429 for (self.shdrs.items, 0..) |*shdr, i| {
34283430 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 {
411411 }
412412}
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
414442pub fn resetGlobals(self: *Object, elf_file: *Elf) void {
415443 for (self.globals()) |index| {
416444 const global = elf_file.symbol(index);
......@@ -576,12 +604,12 @@ pub fn writeSymtab(self: *Object, elf_file: *Elf, ctx: anytype) void {
576604 }
577605}
578606
579pub fn locals(self: *Object) []const u32 {
607pub fn locals(self: *Object) []const Symbol.Index {
580608 const end = self.first_global orelse self.symbols.items.len;
581609 return self.symbols.items[0..end];
582610}
583611
584pub fn globals(self: *Object) []const u32 {
612pub fn globals(self: *Object) []const Symbol.Index {
585613 const start = self.first_global orelse self.symbols.items.len;
586614 return self.symbols.items[start..];
587615}
src/link/Elf/ZigModule.zig+28
......@@ -102,6 +102,34 @@ pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void {
102102 }
103103}
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
105133pub fn updateSymtabSize(self: *ZigModule, elf_file: *Elf) void {
106134 for (self.locals()) |local_index| {
107135 const local = elf_file.symbol(local_index);
src/link/Elf/file.zig+6
......@@ -76,6 +76,12 @@ pub const File = union(enum) {
7676 }
7777 }
7878
79 pub fn globals(file: File) []const Symbol.Index {
80 return switch (file) {
81 inline else => |x| x.globals(),
82 };
83 }
84
7985 pub const Index = u32;
8086
8187 pub const Entry = union(enum) {