authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-02 10:32:21+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-02 15:17:44+02:00
logda56727e6a50286992b025ce8ef39bd3dc88c630
tree1b8e982744e65dbc01e6ed3508debcc459b3c0b8
parentcf3a6fe0f539fd07d99701a06d0c3672ef0992c2

elf: write symbol names into .strtab rather than .shstrtab


1 files changed, 64 insertions(+), 22 deletions(-)

src/link/Elf.zig+64-22
...@@ -129,8 +129,10 @@ phdr_load_rw_index: ?u16 = null,...@@ -129,8 +129,10 @@ phdr_load_rw_index: ?u16 = null,
129entry_addr: ?u64 = null,129entry_addr: ?u64 = null,
130page_size: u32,130page_size: u32,
131131
132/// .shstrtab buffer
132shstrtab: StringTable(.strtab) = .{},133shstrtab: StringTable(.strtab) = .{},
133shstrtab_index: ?u16 = null,134/// .strtab buffer
135strtab: StringTable(.strtab) = .{},
134136
135symtab_section_index: ?u16 = null,137symtab_section_index: ?u16 = null,
136text_section_index: ?u16 = null,138text_section_index: ?u16 = null,
...@@ -142,6 +144,8 @@ debug_abbrev_section_index: ?u16 = null,...@@ -142,6 +144,8 @@ debug_abbrev_section_index: ?u16 = null,
142debug_str_section_index: ?u16 = null,144debug_str_section_index: ?u16 = null,
143debug_aranges_section_index: ?u16 = null,145debug_aranges_section_index: ?u16 = null,
144debug_line_section_index: ?u16 = null,146debug_line_section_index: ?u16 = null,
147shstrtab_section_index: ?u16 = null,
148strtab_section_index: ?u16 = null,
145149
146/// The same order as in the file. ELF requires global symbols to all be after the150/// The same order as in the file. ELF requires global symbols to all be after the
147/// local symbols, they cannot be mixed. So we must buffer all the global symbols and151/// local symbols, they cannot be mixed. So we must buffer all the global symbols and
...@@ -158,6 +162,7 @@ got_table: TableSection(u32) = .{},...@@ -158,6 +162,7 @@ got_table: TableSection(u32) = .{},
158phdr_table_dirty: bool = false,162phdr_table_dirty: bool = false,
159shdr_table_dirty: bool = false,163shdr_table_dirty: bool = false,
160shstrtab_dirty: bool = false,164shstrtab_dirty: bool = false,
165strtab_dirty: bool = false,
161got_table_count_dirty: bool = false,166got_table_count_dirty: bool = false,
162167
163debug_strtab_dirty: bool = false,168debug_strtab_dirty: bool = false,
...@@ -323,6 +328,7 @@ pub fn deinit(self: *Elf) void {...@@ -323,6 +328,7 @@ pub fn deinit(self: *Elf) void {
323328
324 self.program_headers.deinit(gpa);329 self.program_headers.deinit(gpa);
325 self.shstrtab.deinit(gpa);330 self.shstrtab.deinit(gpa);
331 self.strtab.deinit(gpa);
326 self.local_symbols.deinit(gpa);332 self.local_symbols.deinit(gpa);
327 self.global_symbols.deinit(gpa);333 self.global_symbols.deinit(gpa);
328 self.global_symbol_free_list.deinit(gpa);334 self.global_symbol_free_list.deinit(gpa);
...@@ -581,12 +587,12 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -581,12 +587,12 @@ pub fn populateMissingMetadata(self: *Elf) !void {
581 self.phdr_table_dirty = true;587 self.phdr_table_dirty = true;
582 }588 }
583589
584 if (self.shstrtab_index == null) {590 if (self.shstrtab_section_index == null) {
585 self.shstrtab_index = @as(u16, @intCast(self.sections.slice().len));591 self.shstrtab_section_index = @as(u16, @intCast(self.sections.slice().len));
586 assert(self.shstrtab.buffer.items.len == 0);592 assert(self.shstrtab.buffer.items.len == 0);
587 try self.shstrtab.buffer.append(gpa, 0); // need a 0 at position 0593 try self.shstrtab.buffer.append(gpa, 0); // need a 0 at position 0
588 const off = self.findFreeSpace(self.shstrtab.buffer.items.len, 1);594 const off = self.findFreeSpace(self.shstrtab.buffer.items.len, 1);
589 log.debug("found shstrtab free space 0x{x} to 0x{x}", .{ off, off + self.shstrtab.buffer.items.len });595 log.debug("found .shstrtab free space 0x{x} to 0x{x}", .{ off, off + self.shstrtab.buffer.items.len });
590 try self.sections.append(gpa, .{596 try self.sections.append(gpa, .{
591 .shdr = .{597 .shdr = .{
592 .sh_name = try self.shstrtab.insert(gpa, ".shstrtab"),598 .sh_name = try self.shstrtab.insert(gpa, ".shstrtab"),
...@@ -606,6 +612,31 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -606,6 +612,31 @@ pub fn populateMissingMetadata(self: *Elf) !void {
606 self.shdr_table_dirty = true;612 self.shdr_table_dirty = true;
607 }613 }
608614
615 if (self.strtab_section_index == null) {
616 self.strtab_section_index = @as(u16, @intCast(self.sections.slice().len));
617 assert(self.strtab.buffer.items.len == 0);
618 try self.strtab.buffer.append(gpa, 0); // need a 0 at position 0
619 const off = self.findFreeSpace(self.strtab.buffer.items.len, 1);
620 log.debug("found .strtab free space 0x{x} to 0x{x}", .{ off, off + self.strtab.buffer.items.len });
621 try self.sections.append(gpa, .{
622 .shdr = .{
623 .sh_name = try self.shstrtab.insert(gpa, ".strtab"),
624 .sh_type = elf.SHT_STRTAB,
625 .sh_flags = 0,
626 .sh_addr = 0,
627 .sh_offset = off,
628 .sh_size = self.strtab.buffer.items.len,
629 .sh_link = 0,
630 .sh_info = 0,
631 .sh_addralign = 1,
632 .sh_entsize = 0,
633 },
634 .phdr_index = undefined,
635 });
636 self.strtab_dirty = true;
637 self.shdr_table_dirty = true;
638 }
639
609 if (self.text_section_index == null) {640 if (self.text_section_index == null) {
610 self.text_section_index = @as(u16, @intCast(self.sections.slice().len));641 self.text_section_index = @as(u16, @intCast(self.sections.slice().len));
611 const phdr = &self.program_headers.items[self.phdr_load_re_index.?];642 const phdr = &self.program_headers.items[self.phdr_load_re_index.?];
...@@ -711,7 +742,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -711,7 +742,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
711 .sh_offset = off,742 .sh_offset = off,
712 .sh_size = file_size,743 .sh_size = file_size,
713 // The section header index of the associated string table.744 // The section header index of the associated string table.
714 .sh_link = self.shstrtab_index.?,745 .sh_link = self.strtab_section_index.?,
715 .sh_info = @as(u32, @intCast(self.local_symbols.items.len)),746 .sh_info = @as(u32, @intCast(self.local_symbols.items.len)),
716 .sh_addralign = min_align,747 .sh_addralign = min_align,
717 .sh_entsize = each_size,748 .sh_entsize = each_size,
...@@ -1076,7 +1107,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1076,7 +1107,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1076 const source_sym = atom.getSymbol(self);1107 const source_sym = atom.getSymbol(self);
1077 const source_shdr = self.sections.items(.shdr)[source_sym.st_shndx];1108 const source_shdr = self.sections.items(.shdr)[source_sym.st_shndx];
10781109
1079 log.debug("relocating '{?s}'", .{self.shstrtab.get(source_sym.st_name)});1110 log.debug("relocating '{?s}'", .{self.strtab.get(source_sym.st_name)});
10801111
1081 for (relocs.items) |*reloc| {1112 for (relocs.items) |*reloc| {
1082 const target_sym = self.local_symbols.items[reloc.target];1113 const target_sym = self.local_symbols.items[reloc.target];
...@@ -1090,7 +1121,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1090,7 +1121,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1090 log.debug(" ({x}: [() => 0x{x}] ({?s}))", .{1121 log.debug(" ({x}: [() => 0x{x}] ({?s}))", .{
1091 reloc.offset,1122 reloc.offset,
1092 target_vaddr,1123 target_vaddr,
1093 self.shstrtab.get(target_sym.st_name),1124 self.strtab.get(target_sym.st_name),
1094 });1125 });
10951126
1096 switch (self.ptr_width) {1127 switch (self.ptr_width) {
...@@ -1212,7 +1243,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1212,7 +1243,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1212 }1243 }
12131244
1214 {1245 {
1215 const shdr_index = self.shstrtab_index.?;1246 const shdr_index = self.shstrtab_section_index.?;
1216 if (self.shstrtab_dirty or self.shstrtab.buffer.items.len != self.sections.items(.shdr)[shdr_index].sh_size) {1247 if (self.shstrtab_dirty or self.shstrtab.buffer.items.len != self.sections.items(.shdr)[shdr_index].sh_size) {
1217 try self.growNonAllocSection(shdr_index, self.shstrtab.buffer.items.len, 1, false);1248 try self.growNonAllocSection(shdr_index, self.shstrtab.buffer.items.len, 1, false);
1218 const shstrtab_sect = self.sections.items(.shdr)[shdr_index];1249 const shstrtab_sect = self.sections.items(.shdr)[shdr_index];
...@@ -1221,6 +1252,16 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1221,6 +1252,16 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1221 }1252 }
1222 }1253 }
12231254
1255 {
1256 const shdr_index = self.strtab_section_index.?;
1257 if (self.strtab_dirty or self.strtab.buffer.items.len != self.sections.items(.shdr)[shdr_index].sh_size) {
1258 try self.growNonAllocSection(shdr_index, self.strtab.buffer.items.len, 1, false);
1259 const strtab_sect = self.sections.items(.shdr)[shdr_index];
1260 try self.base.file.?.pwriteAll(self.strtab.buffer.items, strtab_sect.sh_offset);
1261 self.strtab_dirty = false;
1262 }
1263 }
1264
1224 if (self.dwarf) |dwarf| {1265 if (self.dwarf) |dwarf| {
1225 const shdr_index = self.debug_str_section_index.?;1266 const shdr_index = self.debug_str_section_index.?;
1226 if (self.debug_strtab_dirty or dwarf.strtab.buffer.items.len != self.sections.items(.shdr)[shdr_index].sh_size) {1267 if (self.debug_strtab_dirty or dwarf.strtab.buffer.items.len != self.sections.items(.shdr)[shdr_index].sh_size) {
...@@ -1298,6 +1339,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1298,6 +1339,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1298 assert(!self.phdr_table_dirty);1339 assert(!self.phdr_table_dirty);
1299 assert(!self.shdr_table_dirty);1340 assert(!self.shdr_table_dirty);
1300 assert(!self.shstrtab_dirty);1341 assert(!self.shstrtab_dirty);
1342 assert(!self.strtab_dirty);
1301 assert(!self.debug_strtab_dirty);1343 assert(!self.debug_strtab_dirty);
1302 assert(!self.got_table_count_dirty);1344 assert(!self.got_table_count_dirty);
1303}1345}
...@@ -2115,7 +2157,7 @@ fn writeElfHeader(self: *Elf) !void {...@@ -2115,7 +2157,7 @@ fn writeElfHeader(self: *Elf) !void {
2115 mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian);2157 mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian);
2116 index += 2;2158 index += 2;
21172159
2118 mem.writeInt(u16, hdr_buf[index..][0..2], self.shstrtab_index.?, endian);2160 mem.writeInt(u16, hdr_buf[index..][0..2], self.shstrtab_section_index.?, endian);
2119 index += 2;2161 index += 2;
21202162
2121 assert(index == e_ehsize);2163 assert(index == e_ehsize);
...@@ -2485,7 +2527,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s...@@ -2485,7 +2527,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s
2485 const shdr_index = decl_metadata.shdr;2527 const shdr_index = decl_metadata.shdr;
2486 if (atom.getSymbol(self).st_size != 0 and self.base.child_pid == null) {2528 if (atom.getSymbol(self).st_size != 0 and self.base.child_pid == null) {
2487 const local_sym = atom.getSymbolPtr(self);2529 const local_sym = atom.getSymbolPtr(self);
2488 local_sym.st_name = try self.shstrtab.insert(gpa, decl_name);2530 local_sym.st_name = try self.strtab.insert(gpa, decl_name);
2489 local_sym.st_info = (elf.STB_LOCAL << 4) | stt_bits;2531 local_sym.st_info = (elf.STB_LOCAL << 4) | stt_bits;
2490 local_sym.st_other = 0;2532 local_sym.st_other = 0;
2491 local_sym.st_shndx = shdr_index;2533 local_sym.st_shndx = shdr_index;
...@@ -2515,7 +2557,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s...@@ -2515,7 +2557,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s
2515 } else {2557 } else {
2516 const local_sym = atom.getSymbolPtr(self);2558 const local_sym = atom.getSymbolPtr(self);
2517 local_sym.* = .{2559 local_sym.* = .{
2518 .st_name = try self.shstrtab.insert(gpa, decl_name),2560 .st_name = try self.strtab.insert(gpa, decl_name),
2519 .st_info = (elf.STB_LOCAL << 4) | stt_bits,2561 .st_info = (elf.STB_LOCAL << 4) | stt_bits,
2520 .st_other = 0,2562 .st_other = 0,
2521 .st_shndx = shdr_index,2563 .st_shndx = shdr_index,
...@@ -2716,9 +2758,9 @@ fn updateLazySymbolAtom(...@@ -2716,9 +2758,9 @@ fn updateLazySymbolAtom(
2716 sym.ty.fmt(mod),2758 sym.ty.fmt(mod),
2717 });2759 });
2718 defer gpa.free(name);2760 defer gpa.free(name);
2719 break :blk try self.shstrtab.insert(gpa, name);2761 break :blk try self.strtab.insert(gpa, name);
2720 };2762 };
2721 const name = self.shstrtab.get(name_str_index).?;2763 const name = self.strtab.get(name_str_index).?;
27222764
2723 const atom = self.getAtom(atom_index);2765 const atom = self.getAtom(atom_index);
2724 const local_sym_index = atom.getSymbolIndex().?;2766 const local_sym_index = atom.getSymbolIndex().?;
...@@ -2793,9 +2835,9 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module...@@ -2793,9 +2835,9 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
2793 const index = unnamed_consts.items.len;2835 const index = unnamed_consts.items.len;
2794 const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });2836 const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });
2795 defer gpa.free(name);2837 defer gpa.free(name);
2796 break :blk try self.shstrtab.insert(gpa, name);2838 break :blk try self.strtab.insert(gpa, name);
2797 };2839 };
2798 const name = self.shstrtab.get(name_str_index).?;2840 const name = self.strtab.get(name_str_index).?;
27992841
2800 const atom_index = try self.createAtom();2842 const atom_index = try self.createAtom();
28012843
...@@ -2900,7 +2942,7 @@ pub fn updateDeclExports(...@@ -2900,7 +2942,7 @@ pub fn updateDeclExports(
2900 if (decl_metadata.getExport(self, exp_name)) |i| {2942 if (decl_metadata.getExport(self, exp_name)) |i| {
2901 const sym = &self.global_symbols.items[i];2943 const sym = &self.global_symbols.items[i];
2902 sym.* = .{2944 sym.* = .{
2903 .st_name = try self.shstrtab.insert(gpa, exp_name),2945 .st_name = try self.strtab.insert(gpa, exp_name),
2904 .st_info = (stb_bits << 4) | stt_bits,2946 .st_info = (stb_bits << 4) | stt_bits,
2905 .st_other = 0,2947 .st_other = 0,
2906 .st_shndx = shdr_index,2948 .st_shndx = shdr_index,
...@@ -2914,7 +2956,7 @@ pub fn updateDeclExports(...@@ -2914,7 +2956,7 @@ pub fn updateDeclExports(
2914 };2956 };
2915 try decl_metadata.exports.append(gpa, @as(u32, @intCast(i)));2957 try decl_metadata.exports.append(gpa, @as(u32, @intCast(i)));
2916 self.global_symbols.items[i] = .{2958 self.global_symbols.items[i] = .{
2917 .st_name = try self.shstrtab.insert(gpa, exp_name),2959 .st_name = try self.strtab.insert(gpa, exp_name),
2918 .st_info = (stb_bits << 4) | stt_bits,2960 .st_info = (stb_bits << 4) | stt_bits,
2919 .st_other = 0,2961 .st_other = 0,
2920 .st_shndx = shdr_index,2962 .st_shndx = shdr_index,
...@@ -3080,7 +3122,7 @@ fn writeSymbol(self: *Elf, index: usize) !void {...@@ -3080,7 +3122,7 @@ fn writeSymbol(self: *Elf, index: usize) !void {
3080 .p64 => syms_sect.sh_offset + @sizeOf(elf.Elf64_Sym) * index,3122 .p64 => syms_sect.sh_offset + @sizeOf(elf.Elf64_Sym) * index,
3081 };3123 };
3082 const local = self.local_symbols.items[index];3124 const local = self.local_symbols.items[index];
3083 log.debug("writing symbol {d}, '{?s}' at 0x{x}", .{ index, self.shstrtab.get(local.st_name), off });3125 log.debug("writing symbol {d}, '{?s}' at 0x{x}", .{ index, self.strtab.get(local.st_name), off });
3084 log.debug(" ({})", .{local});3126 log.debug(" ({})", .{local});
3085 switch (self.ptr_width) {3127 switch (self.ptr_width) {
3086 .p32 => {3128 .p32 => {
...@@ -3460,11 +3502,11 @@ const CsuObjects = struct {...@@ -3460,11 +3502,11 @@ const CsuObjects = struct {
3460fn logSymtab(self: Elf) void {3502fn logSymtab(self: Elf) void {
3461 log.debug("locals:", .{});3503 log.debug("locals:", .{});
3462 for (self.local_symbols.items, 0..) |sym, id| {3504 for (self.local_symbols.items, 0..) |sym, id| {
3463 log.debug(" {d}: {?s}: @{x} in {d}", .{ id, self.shstrtab.get(sym.st_name), sym.st_value, sym.st_shndx });3505 log.debug(" {d}: {?s}: @{x} in {d}", .{ id, self.strtab.get(sym.st_name), sym.st_value, sym.st_shndx });
3464 }3506 }
3465 log.debug("globals:", .{});3507 log.debug("globals:", .{});
3466 for (self.global_symbols.items, 0..) |sym, id| {3508 for (self.global_symbols.items, 0..) |sym, id| {
3467 log.debug(" {d}: {?s}: @{x} in {d}", .{ id, self.shstrtab.get(sym.st_name), sym.st_value, sym.st_shndx });3509 log.debug(" {d}: {?s}: @{x} in {d}", .{ id, self.strtab.get(sym.st_name), sym.st_value, sym.st_shndx });
3468 }3510 }
3469}3511}
34703512
...@@ -3491,13 +3533,13 @@ pub fn getSymbol(self: *const Elf, sym_index: u32) elf.Elf64_Sym {...@@ -3491,13 +3533,13 @@ pub fn getSymbol(self: *const Elf, sym_index: u32) elf.Elf64_Sym {
3491/// Returns name of the symbol at sym_index.3533/// Returns name of the symbol at sym_index.
3492pub fn getSymbolName(self: *const Elf, sym_index: u32) []const u8 {3534pub fn getSymbolName(self: *const Elf, sym_index: u32) []const u8 {
3493 const sym = self.local_symbols.items[sym_index];3535 const sym = self.local_symbols.items[sym_index];
3494 return self.shstrtab.get(sym.st_name).?;3536 return self.strtab.get(sym.st_name).?;
3495}3537}
34963538
3497/// Returns name of the global symbol at index.3539/// Returns name of the global symbol at index.
3498pub fn getGlobalName(self: *const Elf, index: u32) []const u8 {3540pub fn getGlobalName(self: *const Elf, index: u32) []const u8 {
3499 const sym = self.global_symbols.items[index];3541 const sym = self.global_symbols.items[index];
3500 return self.shstrtab.get(sym.st_name).?;3542 return self.strtab.get(sym.st_name).?;
3501}3543}
35023544
3503pub fn getAtom(self: *const Elf, atom_index: Atom.Index) Atom {3545pub fn getAtom(self: *const Elf, atom_index: Atom.Index) Atom {