authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-02 01:33:06+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-04 09:10:30+01:00
logdbe13200f1b5a20367b9e5ec288a8ec27fa2d505
tree3cb3e4f6b460bb2616134a3f577d30374cc0a3f8
parent8055f687659de87ce0101cb3e459699b4541a8b7

elf: emit STT_SECTION symbols


4 files changed, 54 insertions(+), 21 deletions(-)

src/link/Elf.zig+8-8
...@@ -494,6 +494,7 @@ pub fn initMetadata(self: *Elf) !void {...@@ -494,6 +494,7 @@ pub fn initMetadata(self: *Elf) !void {
494 const ptr_size = self.ptrWidthBytes();494 const ptr_size = self.ptrWidthBytes();
495 const ptr_bit_width = self.base.options.target.ptrBitWidth();495 const ptr_bit_width = self.base.options.target.ptrBitWidth();
496 const is_linux = self.base.options.target.os.tag == .linux;496 const is_linux = self.base.options.target.os.tag == .linux;
497 const zig_object = self.zigObjectPtr().?;
497498
498 const fillSection = struct {499 const fillSection = struct {
499 fn fillSection(elf_file: *Elf, shdr: *elf.Elf64_Shdr, size: u64, phndx: ?u16) void {500 fn fillSection(elf_file: *Elf, shdr: *elf.Elf64_Shdr, size: u64, phndx: ?u16) void {
...@@ -597,6 +598,7 @@ pub fn initMetadata(self: *Elf) !void {...@@ -597,6 +598,7 @@ pub fn initMetadata(self: *Elf) !void {
597 const shdr = &self.shdrs.items[self.zig_text_section_index.?];598 const shdr = &self.shdrs.items[self.zig_text_section_index.?];
598 fillSection(self, shdr, self.base.options.program_code_size_hint, self.phdr_zig_load_re_index);599 fillSection(self, shdr, self.base.options.program_code_size_hint, self.phdr_zig_load_re_index);
599 if (self.isObject()) {600 if (self.isObject()) {
601 try zig_object.addSectionSymbol(self.zig_text_section_index.?, self);
600 self.zig_text_rela_section_index = try self.addRelaShdr(602 self.zig_text_rela_section_index = try self.addRelaShdr(
601 ".rela.text.zig",603 ".rela.text.zig",
602 self.zig_text_section_index.?,604 self.zig_text_section_index.?,
...@@ -643,6 +645,7 @@ pub fn initMetadata(self: *Elf) !void {...@@ -643,6 +645,7 @@ pub fn initMetadata(self: *Elf) !void {
643 const shdr = &self.shdrs.items[self.zig_data_rel_ro_section_index.?];645 const shdr = &self.shdrs.items[self.zig_data_rel_ro_section_index.?];
644 fillSection(self, shdr, 1024, self.phdr_zig_load_ro_index);646 fillSection(self, shdr, 1024, self.phdr_zig_load_ro_index);
645 if (self.isObject()) {647 if (self.isObject()) {
648 try zig_object.addSectionSymbol(self.zig_data_rel_ro_section_index.?, self);
646 self.zig_data_rel_ro_rela_section_index = try self.addRelaShdr(649 self.zig_data_rel_ro_rela_section_index = try self.addRelaShdr(
647 ".rela.data.rel.ro.zig",650 ".rela.data.rel.ro.zig",
648 self.zig_data_rel_ro_section_index.?,651 self.zig_data_rel_ro_section_index.?,
...@@ -668,6 +671,7 @@ pub fn initMetadata(self: *Elf) !void {...@@ -668,6 +671,7 @@ pub fn initMetadata(self: *Elf) !void {
668 const shdr = &self.shdrs.items[self.zig_data_section_index.?];671 const shdr = &self.shdrs.items[self.zig_data_section_index.?];
669 fillSection(self, shdr, 1024, self.phdr_zig_load_rw_index);672 fillSection(self, shdr, 1024, self.phdr_zig_load_rw_index);
670 if (self.isObject()) {673 if (self.isObject()) {
674 try zig_object.addSectionSymbol(self.zig_data_section_index.?, self);
671 self.zig_data_rela_section_index = try self.addRelaShdr(675 self.zig_data_rela_section_index = try self.addRelaShdr(
672 ".rela.data.zig",676 ".rela.data.zig",
673 self.zig_data_section_index.?,677 self.zig_data_section_index.?,
...@@ -697,12 +701,12 @@ pub fn initMetadata(self: *Elf) !void {...@@ -697,12 +701,12 @@ pub fn initMetadata(self: *Elf) !void {
697 shdr.sh_size = phdr.p_memsz;701 shdr.sh_size = phdr.p_memsz;
698 try self.phdr_to_shdr_table.putNoClobber(gpa, self.zig_bss_section_index.?, phndx);702 try self.phdr_to_shdr_table.putNoClobber(gpa, self.zig_bss_section_index.?, phndx);
699 } else {703 } else {
704 try zig_object.addSectionSymbol(self.zig_bss_section_index.?, self);
700 shdr.sh_size = 1024;705 shdr.sh_size = 1024;
701 }706 }
702 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_bss_section_index.?, .{});707 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_bss_section_index.?, .{});
703 }708 }
704709
705 const zig_object = self.zigObjectPtr().?;
706 if (zig_object.dwarf) |*dw| {710 if (zig_object.dwarf) |*dw| {
707 if (self.debug_str_section_index == null) {711 if (self.debug_str_section_index == null) {
708 assert(dw.strtab.buffer.items.len == 0);712 assert(dw.strtab.buffer.items.len == 0);
...@@ -3801,23 +3805,19 @@ fn sortShdrs(self: *Elf) !void {...@@ -3801,23 +3805,19 @@ fn sortShdrs(self: *Elf) !void {
3801 if (self.zigObjectPtr()) |zig_object| {3805 if (self.zigObjectPtr()) |zig_object| {
3802 for (zig_object.atoms.items) |atom_index| {3806 for (zig_object.atoms.items) |atom_index| {
3803 const atom_ptr = self.atom(atom_index) orelse continue;3807 const atom_ptr = self.atom(atom_index) orelse continue;
3804 if (!atom_ptr.flags.alive) continue;3808 atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index];
3805 const out_shndx = atom_ptr.outputShndx() orelse continue;
3806 atom_ptr.output_section_index = backlinks[out_shndx];
3807 }3809 }
38083810
3809 for (zig_object.locals()) |local_index| {3811 for (zig_object.locals()) |local_index| {
3810 const local = self.symbol(local_index);3812 const local = self.symbol(local_index);
3811 const atom_ptr = local.atom(self) orelse continue;3813 local.output_section_index = backlinks[local.output_section_index];
3812 if (!atom_ptr.flags.alive) continue;
3813 const out_shndx = local.outputShndx() orelse continue;
3814 local.output_section_index = backlinks[out_shndx];
3815 }3814 }
38163815
3817 for (zig_object.globals()) |global_index| {3816 for (zig_object.globals()) |global_index| {
3818 const global = self.symbol(global_index);3817 const global = self.symbol(global_index);
3819 const atom_ptr = global.atom(self) orelse continue;3818 const atom_ptr = global.atom(self) orelse continue;
3820 if (!atom_ptr.flags.alive) continue;3819 if (!atom_ptr.flags.alive) continue;
3820 // TODO claim unresolved for objects
3821 if (global.file(self).?.index() != zig_object.index) continue;3821 if (global.file(self).?.index() != zig_object.index) continue;
3822 const out_shndx = global.outputShndx() orelse continue;3822 const out_shndx = global.outputShndx() orelse continue;
3823 global.output_section_index = backlinks[out_shndx];3823 global.output_section_index = backlinks[out_shndx];
src/link/Elf/Symbol.zig+2
...@@ -223,6 +223,8 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {...@@ -223,6 +223,8 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
223 const st_shndx = blk: {223 const st_shndx = blk: {
224 if (symbol.flags.has_copy_rel) break :blk elf_file.copy_rel_section_index.?;224 if (symbol.flags.has_copy_rel) break :blk elf_file.copy_rel_section_index.?;
225 if (file_ptr == .shared_object or esym.st_shndx == elf.SHN_UNDEF) break :blk elf.SHN_UNDEF;225 if (file_ptr == .shared_object or esym.st_shndx == elf.SHN_UNDEF) break :blk elf.SHN_UNDEF;
226 // TODO I think this is wrong and obsolete
227 if (elf_file.isObject() and st_type == elf.STT_SECTION) break :blk symbol.outputShndx().?;
226 if (symbol.atom(elf_file) == null and file_ptr != .linker_defined)228 if (symbol.atom(elf_file) == null and file_ptr != .linker_defined)
227 break :blk elf.SHN_ABS;229 break :blk elf.SHN_ABS;
228 break :blk symbol.outputShndx() orelse elf.SHN_UNDEF;230 break :blk symbol.outputShndx() orelse elf.SHN_UNDEF;
src/link/Elf/ZigObject.zig+42-12
...@@ -87,7 +87,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {...@@ -87,7 +87,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {
87 const esym_index = try self.addLocalEsym(gpa);87 const esym_index = try self.addLocalEsym(gpa);
88 const esym = &self.local_esyms.items(.elf_sym)[esym_index];88 const esym = &self.local_esyms.items(.elf_sym)[esym_index];
89 esym.st_name = name_off;89 esym.st_name = name_off;
90 esym.st_info |= elf.STT_FILE;90 esym.st_info = elf.STT_FILE;
91 esym.st_shndx = elf.SHN_ABS;91 esym.st_shndx = elf.SHN_ABS;
92 symbol_ptr.esym_index = esym_index;92 symbol_ptr.esym_index = esym_index;
9393
...@@ -284,6 +284,22 @@ pub fn addAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index {...@@ -284,6 +284,22 @@ pub fn addAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index {
284 return symbol_index;284 return symbol_index;
285}285}
286286
287pub fn addSectionSymbol(self: *ZigObject, shndx: u16, elf_file: *Elf) !void {
288 assert(elf_file.isObject());
289 const gpa = elf_file.base.allocator;
290 const symbol_index = try elf_file.addSymbol();
291 try self.local_symbols.append(gpa, symbol_index);
292 const symbol_ptr = elf_file.symbol(symbol_index);
293 symbol_ptr.file_index = self.index;
294 symbol_ptr.output_section_index = shndx;
295
296 const esym_index = try self.addLocalEsym(gpa);
297 const esym = &self.local_esyms.items(.elf_sym)[esym_index];
298 esym.st_info = elf.STT_SECTION;
299 esym.st_shndx = shndx;
300 symbol_ptr.esym_index = esym_index;
301}
302
287/// TODO actually create fake input shdrs and return that instead.303/// TODO actually create fake input shdrs and return that instead.
288pub fn inputShdr(self: ZigObject, atom_index: Atom.Index, elf_file: *Elf) Object.ElfShdr {304pub fn inputShdr(self: ZigObject, atom_index: Atom.Index, elf_file: *Elf) Object.ElfShdr {
289 _ = self;305 _ = self;
...@@ -435,6 +451,16 @@ pub fn updateRelaSectionSizes(self: ZigObject, elf_file: *Elf) void {...@@ -435,6 +451,16 @@ pub fn updateRelaSectionSizes(self: ZigObject, elf_file: *Elf) void {
435pub fn writeRelaSections(self: ZigObject, elf_file: *Elf) !void {451pub fn writeRelaSections(self: ZigObject, elf_file: *Elf) !void {
436 const gpa = elf_file.base.allocator;452 const gpa = elf_file.base.allocator;
437453
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
438 for (&[_]?u16{464 for (&[_]?u16{
439 elf_file.zig_text_rela_section_index,465 elf_file.zig_text_rela_section_index,
440 elf_file.zig_data_rel_ro_rela_section_index,466 elf_file.zig_data_rel_ro_rela_section_index,
...@@ -453,8 +479,13 @@ pub fn writeRelaSections(self: ZigObject, elf_file: *Elf) !void {...@@ -453,8 +479,13 @@ pub fn writeRelaSections(self: ZigObject, elf_file: *Elf) !void {
453479
454 while (true) {480 while (true) {
455 for (atom.relocs(elf_file)) |rel| {481 for (atom.relocs(elf_file)) |rel| {
456 var r_sym = rel.r_sym() & symbol_mask;482 const target = elf_file.symbol(self.symbol(rel.r_sym()));
457 if (self.isGlobal(rel.r_sym())) r_sym += @intCast(self.local_esyms.slice().len + 1);483 const r_offset = target.value + rel.r_offset;
484 const r_sym: u32 = if (target.flags.global)
485 (target.esym_index & symbol_mask) + @as(u32, @intCast(self.local_esyms.slice().len))
486 else
487 target.esym_index;
488 // getSectionSymbol(self, target.outputShndx().?, elf_file);
458 const r_type = switch (rel.r_type()) {489 const r_type = switch (rel.r_type()) {
459 Elf.R_X86_64_ZIG_GOT32,490 Elf.R_X86_64_ZIG_GOT32,
460 Elf.R_X86_64_ZIG_GOTPCREL,491 Elf.R_X86_64_ZIG_GOTPCREL,
...@@ -462,9 +493,9 @@ pub fn writeRelaSections(self: ZigObject, elf_file: *Elf) !void {...@@ -462,9 +493,9 @@ pub fn writeRelaSections(self: ZigObject, elf_file: *Elf) !void {
462 else => |r_type| r_type,493 else => |r_type| r_type,
463 };494 };
464 relocs.appendAssumeCapacity(.{495 relocs.appendAssumeCapacity(.{
465 .r_offset = rel.r_offset,496 .r_offset = r_offset,
466 .r_addend = rel.r_addend,497 .r_addend = rel.r_addend,
467 .r_info = (@as(u64, @intCast(r_sym)) << 32) | r_type,498 .r_info = (@as(u64, @intCast(r_sym + 1)) << 32) | r_type,
468 });499 });
469 }500 }
470 if (elf_file.atom(atom.prev_index)) |prev| {501 if (elf_file.atom(atom.prev_index)) |prev| {
...@@ -485,28 +516,27 @@ pub fn writeRelaSections(self: ZigObject, elf_file: *Elf) !void {...@@ -485,28 +516,27 @@ pub fn writeRelaSections(self: ZigObject, elf_file: *Elf) !void {
485 }516 }
486}517}
487518
488pub fn isGlobal(self: ZigObject, index: Symbol.Index) bool {519inline fn isGlobal(index: Symbol.Index) bool {
489 _ = self;
490 return index & global_symbol_bit != 0;520 return index & global_symbol_bit != 0;
491}521}
492522
493pub fn symbol(self: *ZigObject, index: Symbol.Index) Symbol.Index {523pub fn symbol(self: ZigObject, index: Symbol.Index) Symbol.Index {
494 const actual_index = index & symbol_mask;524 const actual_index = index & symbol_mask;
495 if (self.isGlobal(index)) return self.global_symbols.items[actual_index];525 if (isGlobal(index)) return self.global_symbols.items[actual_index];
496 return self.local_symbols.items[actual_index];526 return self.local_symbols.items[actual_index];
497}527}
498528
499pub fn elfSym(self: *ZigObject, index: Symbol.Index) *elf.Elf64_Sym {529pub fn elfSym(self: *ZigObject, index: Symbol.Index) *elf.Elf64_Sym {
500 const actual_index = index & symbol_mask;530 const actual_index = index & symbol_mask;
501 if (self.isGlobal(index)) return &self.global_esyms.items(.elf_sym)[actual_index];531 if (isGlobal(index)) return &self.global_esyms.items(.elf_sym)[actual_index];
502 return &self.local_esyms.items(.elf_sym)[actual_index];532 return &self.local_esyms.items(.elf_sym)[actual_index];
503}533}
504534
505pub fn locals(self: *ZigObject) []const Symbol.Index {535pub fn locals(self: ZigObject) []const Symbol.Index {
506 return self.local_symbols.items;536 return self.local_symbols.items;
507}537}
508538
509pub fn globals(self: *ZigObject) []const Symbol.Index {539pub fn globals(self: ZigObject) []const Symbol.Index {
510 return self.global_symbols.items;540 return self.global_symbols.items;
511}541}
512542
src/link/Elf/file.zig+2-1
...@@ -136,7 +136,8 @@ pub const File = union(enum) {...@@ -136,7 +136,8 @@ pub const File = union(enum) {
136 if (local.atom(elf_file)) |atom| if (!atom.flags.alive) continue;136 if (local.atom(elf_file)) |atom| if (!atom.flags.alive) continue;
137 const esym = local.elfSym(elf_file);137 const esym = local.elfSym(elf_file);
138 switch (esym.st_type()) {138 switch (esym.st_type()) {
139 elf.STT_SECTION, elf.STT_NOTYPE => continue,139 elf.STT_SECTION => if (!elf_file.isObject()) continue,
140 elf.STT_NOTYPE => continue,
140 else => {},141 else => {},
141 }142 }
142 local.flags.output_symtab = true;143 local.flags.output_symtab = true;