authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-02 11:45:22+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-04 09:10:43+01:00
log7c5c59191ec1d8879b70c47c54577e23f6262cc4
treede7a265c3ac3b909c63dbc17295fb4064bda0d50
parentdbe13200f1b5a20367b9e5ec288a8ec27fa2d505

elf: claim unresolved dangling symbols as undef externs when emitting object


2 files changed, 97 insertions(+), 12 deletions(-)

src/link/Elf.zig+8
......@@ -1523,6 +1523,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
15231523
15241524pub fn flushObject(self: *Elf, comp: *Compilation) link.File.FlushError!void {
15251525 _ = comp;
1526 self.claimUnresolvedObject();
1527
15261528 try self.initSections();
15271529 try self.sortShdrs();
15281530 try self.updateSectionSizes();
......@@ -1924,6 +1926,12 @@ fn claimUnresolved(self: *Elf) void {
19241926 }
19251927}
19261928
1929fn claimUnresolvedObject(self: *Elf) void {
1930 if (self.zigObjectPtr()) |zig_object| {
1931 zig_object.claimUnresolvedObject(self);
1932 }
1933}
1934
19271935/// In scanRelocs we will go over all live atoms and scan their relocs.
19281936/// This will help us work out what synthetics to emit, GOT indirection, etc.
19291937/// This is also the point where we will report undefined symbols for any
src/link/Elf/ZigObject.zig+89-12
......@@ -210,6 +210,8 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf) !void {
210210 self.saveDebugSectionsSizes(elf_file);
211211 }
212212
213 try self.sortSymbols(elf_file);
214
213215 // The point of flushModule() is to commit changes, so in theory, nothing should
214216 // be dirty after this. However, it is possible for some things to remain
215217 // dirty because they fail to be written in the event of compile errors,
......@@ -353,7 +355,7 @@ pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) void {
353355 }
354356}
355357
356pub fn claimUnresolved(self: *ZigObject, elf_file: *Elf) void {
358pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void {
357359 for (self.globals(), 0..) |index, i| {
358360 const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit;
359361 const esym = self.global_esyms.items(.elf_sym)[i];
......@@ -381,6 +383,26 @@ pub fn claimUnresolved(self: *ZigObject, elf_file: *Elf) void {
381383 }
382384}
383385
386pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void {
387 for (self.globals(), 0..) |index, i| {
388 const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit;
389 const esym = self.global_esyms.items(.elf_sym)[i];
390
391 if (esym.st_shndx != elf.SHN_UNDEF) continue;
392
393 const global = elf_file.symbol(index);
394 if (global.file(elf_file)) |file| {
395 if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF or
396 file.index() <= self.index) continue;
397 }
398
399 global.value = 0;
400 global.atom_index = 0;
401 global.esym_index = esym_index;
402 global.file_index = self.index;
403 }
404}
405
384406pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void {
385407 for (self.atoms.items) |atom_index| {
386408 const atom = elf_file.atom(atom_index) orelse continue;
......@@ -414,6 +436,72 @@ pub fn markLive(self: *ZigObject, elf_file: *Elf) void {
414436 }
415437}
416438
439fn sortSymbols(self: *ZigObject, elf_file: *Elf) error{OutOfMemory}!void {
440 _ = self;
441 _ = elf_file;
442 // const Entry = struct {
443 // index: Symbol.Index,
444
445 // const Ctx = struct {
446 // zobj: ZigObject,
447 // efile: *Elf,
448 // };
449
450 // pub fn lessThan(ctx: Ctx, lhs: @This(), rhs: @This()) bool {
451 // const lhs_sym = ctx.efile.symbol(zobj.symbol(lhs.index));
452 // const rhs_sym = ctx.efile.symbol(zobj.symbol(rhs.index));
453 // if (lhs_sym.outputShndx() != null and rhs_sym.outputShndx() != null) {
454 // if (lhs_sym.output_section_index == rhs_sym.output_section_index) {
455 // if (lhs_sym.value == rhs_sym.value) {
456 // return lhs_sym.name_offset < rhs_sym.name_offset;
457 // }
458 // return lhs_sym.value < rhs_sym.value;
459 // }
460 // return lhs_sym.output_section_index < rhs_sym.output_section_index;
461 // }
462 // if (lhs_sym.outputShndx() != null) {
463 // if (rhs_sym.isAbs(ctx.efile)) return false;
464 // return true;
465 // }
466 // return false;
467 // }
468 // };
469
470 // const gpa = elf_file.base.allocator;
471
472 // {
473 // const sorted = try gpa.alloc(Entry, self.local_symbols.items.len);
474 // defer gpa.free(sorted);
475 // for (0..self.local_symbols.items.len) |index| {
476 // sorted[i] = .{ .index = @as(Symbol.Index, @intCast(index)) };
477 // }
478 // mem.sort(Entry, sorted, .{ .zobj = self, .efile = elf_file }, Entry.lessThan);
479
480 // const backlinks = try gpa.alloc(Symbol.Index, sorted.len);
481 // defer gpa.free(backlinks);
482 // for (sorted, 0..) |entry, i| {
483 // backlinks[entry.index] = @as(Symbol.Index, @intCast(i));
484 // }
485
486 // const local_symbols = try self.local_symbols.toOwnedSlice(gpa);
487 // defer gpa.free(local_symbols);
488
489 // try self.local_symbols.ensureTotalCapacityPrecise(gpa, local_symbols.len);
490 // for (sorted) |entry| {
491 // self.local_symbols.appendAssumeCapacity(local_symbols[entry.index]);
492 // }
493
494 // for (self.)
495 // }
496
497 // const sorted_globals = try gpa.alloc(Entry, self.global_symbols.items.len);
498 // defer gpa.free(sorted_globals);
499 // for (self.global_symbols.items, 0..) |index, i| {
500 // sorted_globals[i] = .{ .index = index };
501 // }
502 // mem.sort(Entry, sorted_globals, elf_file, Entry.lessThan);
503}
504
417505pub fn updateRelaSectionSizes(self: ZigObject, elf_file: *Elf) void {
418506 _ = self;
419507
......@@ -451,16 +539,6 @@ pub fn updateRelaSectionSizes(self: ZigObject, elf_file: *Elf) void {
451539pub fn writeRelaSections(self: ZigObject, elf_file: *Elf) !void {
452540 const gpa = elf_file.base.allocator;
453541
454 // const getSectionSymbol = struct {
455 // fn getSectionSymbol(zig_object: ZigObject, shndx: u16, ctx: *Elf) Symbol.Index {
456 // for (zig_object.locals()) |local_index| {
457 // const local = ctx.symbol(local_index);
458 // if (local.type(ctx) == elf.STT_SECTION and local.output_section_index == shndx)
459 // return local.esym_index;
460 // } else unreachable;
461 // }
462 // }.getSectionSymbol;
463
464542 for (&[_]?u16{
465543 elf_file.zig_text_rela_section_index,
466544 elf_file.zig_data_rel_ro_rela_section_index,
......@@ -485,7 +563,6 @@ pub fn writeRelaSections(self: ZigObject, elf_file: *Elf) !void {
485563 (target.esym_index & symbol_mask) + @as(u32, @intCast(self.local_esyms.slice().len))
486564 else
487565 target.esym_index;
488 // getSectionSymbol(self, target.outputShndx().?, elf_file);
489566 const r_type = switch (rel.r_type()) {
490567 Elf.R_X86_64_ZIG_GOT32,
491568 Elf.R_X86_64_ZIG_GOTPCREL,