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...@@ -1523,6 +1523,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
15231523
1524pub fn flushObject(self: *Elf, comp: *Compilation) link.File.FlushError!void {1524pub fn flushObject(self: *Elf, comp: *Compilation) link.File.FlushError!void {
1525 _ = comp;1525 _ = comp;
1526 self.claimUnresolvedObject();
1527
1526 try self.initSections();1528 try self.initSections();
1527 try self.sortShdrs();1529 try self.sortShdrs();
1528 try self.updateSectionSizes();1530 try self.updateSectionSizes();
...@@ -1924,6 +1926,12 @@ fn claimUnresolved(self: *Elf) void {...@@ -1924,6 +1926,12 @@ fn claimUnresolved(self: *Elf) void {
1924 }1926 }
1925}1927}
19261928
1929fn claimUnresolvedObject(self: *Elf) void {
1930 if (self.zigObjectPtr()) |zig_object| {
1931 zig_object.claimUnresolvedObject(self);
1932 }
1933}
1934
1927/// In scanRelocs we will go over all live atoms and scan their relocs.1935/// In scanRelocs we will go over all live atoms and scan their relocs.
1928/// This will help us work out what synthetics to emit, GOT indirection, etc.1936/// This will help us work out what synthetics to emit, GOT indirection, etc.
1929/// This is also the point where we will report undefined symbols for any1937/// 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 {...@@ -210,6 +210,8 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf) !void {
210 self.saveDebugSectionsSizes(elf_file);210 self.saveDebugSectionsSizes(elf_file);
211 }211 }
212212
213 try self.sortSymbols(elf_file);
214
213 // The point of flushModule() is to commit changes, so in theory, nothing should215 // The point of flushModule() is to commit changes, so in theory, nothing should
214 // be dirty after this. However, it is possible for some things to remain216 // be dirty after this. However, it is possible for some things to remain
215 // dirty because they fail to be written in the event of compile errors,217 // 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 {...@@ -353,7 +355,7 @@ pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) void {
353 }355 }
354}356}
355357
356pub fn claimUnresolved(self: *ZigObject, elf_file: *Elf) void {358pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void {
357 for (self.globals(), 0..) |index, i| {359 for (self.globals(), 0..) |index, i| {
358 const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit;360 const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit;
359 const esym = self.global_esyms.items(.elf_sym)[i];361 const esym = self.global_esyms.items(.elf_sym)[i];
...@@ -381,6 +383,26 @@ pub fn claimUnresolved(self: *ZigObject, elf_file: *Elf) void {...@@ -381,6 +383,26 @@ pub fn claimUnresolved(self: *ZigObject, elf_file: *Elf) void {
381 }383 }
382}384}
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
384pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void {406pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void {
385 for (self.atoms.items) |atom_index| {407 for (self.atoms.items) |atom_index| {
386 const atom = elf_file.atom(atom_index) orelse continue;408 const atom = elf_file.atom(atom_index) orelse continue;
...@@ -414,6 +436,72 @@ pub fn markLive(self: *ZigObject, elf_file: *Elf) void {...@@ -414,6 +436,72 @@ pub fn markLive(self: *ZigObject, elf_file: *Elf) void {
414 }436 }
415}437}
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
417pub fn updateRelaSectionSizes(self: ZigObject, elf_file: *Elf) void {505pub fn updateRelaSectionSizes(self: ZigObject, elf_file: *Elf) void {
418 _ = self;506 _ = self;
419507
...@@ -451,16 +539,6 @@ pub fn updateRelaSectionSizes(self: ZigObject, elf_file: *Elf) void {...@@ -451,16 +539,6 @@ pub fn updateRelaSectionSizes(self: ZigObject, elf_file: *Elf) void {
451pub fn writeRelaSections(self: ZigObject, elf_file: *Elf) !void {539pub fn writeRelaSections(self: ZigObject, elf_file: *Elf) !void {
452 const gpa = elf_file.base.allocator;540 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
464 for (&[_]?u16{542 for (&[_]?u16{
465 elf_file.zig_text_rela_section_index,543 elf_file.zig_text_rela_section_index,
466 elf_file.zig_data_rel_ro_rela_section_index,544 elf_file.zig_data_rel_ro_rela_section_index,
...@@ -485,7 +563,6 @@ pub fn writeRelaSections(self: ZigObject, elf_file: *Elf) !void {...@@ -485,7 +563,6 @@ pub fn writeRelaSections(self: ZigObject, elf_file: *Elf) !void {
485 (target.esym_index & symbol_mask) + @as(u32, @intCast(self.local_esyms.slice().len))563 (target.esym_index & symbol_mask) + @as(u32, @intCast(self.local_esyms.slice().len))
486 else564 else
487 target.esym_index;565 target.esym_index;
488 // getSectionSymbol(self, target.outputShndx().?, elf_file);
489 const r_type = switch (rel.r_type()) {566 const r_type = switch (rel.r_type()) {
490 Elf.R_X86_64_ZIG_GOT32,567 Elf.R_X86_64_ZIG_GOT32,
491 Elf.R_X86_64_ZIG_GOTPCREL,568 Elf.R_X86_64_ZIG_GOTPCREL,