diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-09-02 10:32:21 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-09-02 15:17:44 +0200 |
| commit | da56727e6a50286992b025ce8ef39bd3dc88c630 (patch) | |
| tree | 1b8e982744e65dbc01e6ed3508debcc459b3c0b8 /src | |
| parent | cf3a6fe0f539fd07d99701a06d0c3672ef0992c2 (diff) | |
| download | zig-da56727e6a50286992b025ce8ef39bd3dc88c630.tar.gz zig-da56727e6a50286992b025ce8ef39bd3dc88c630.zip | |
elf: write symbol names into .strtab rather than .shstrtab
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Elf.zig | 86 |
1 files changed, 64 insertions, 22 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index c1cc4355c6..73513af9d7 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -129,8 +129,10 @@ phdr_load_rw_index: ?u16 = null, entry_addr: ?u64 = null, page_size: u32, +/// .shstrtab buffer shstrtab: StringTable(.strtab) = .{}, -shstrtab_index: ?u16 = null, +/// .strtab buffer +strtab: StringTable(.strtab) = .{}, symtab_section_index: ?u16 = null, text_section_index: ?u16 = null, @@ -142,6 +144,8 @@ debug_abbrev_section_index: ?u16 = null, debug_str_section_index: ?u16 = null, debug_aranges_section_index: ?u16 = null, debug_line_section_index: ?u16 = null, +shstrtab_section_index: ?u16 = null, +strtab_section_index: ?u16 = null, /// The same order as in the file. ELF requires global symbols to all be after the /// local symbols, they cannot be mixed. So we must buffer all the global symbols and @@ -158,6 +162,7 @@ got_table: TableSection(u32) = .{}, phdr_table_dirty: bool = false, shdr_table_dirty: bool = false, shstrtab_dirty: bool = false, +strtab_dirty: bool = false, got_table_count_dirty: bool = false, debug_strtab_dirty: bool = false, @@ -323,6 +328,7 @@ pub fn deinit(self: *Elf) void { self.program_headers.deinit(gpa); self.shstrtab.deinit(gpa); + self.strtab.deinit(gpa); self.local_symbols.deinit(gpa); self.global_symbols.deinit(gpa); self.global_symbol_free_list.deinit(gpa); @@ -581,12 +587,12 @@ pub fn populateMissingMetadata(self: *Elf) !void { self.phdr_table_dirty = true; } - if (self.shstrtab_index == null) { - self.shstrtab_index = @as(u16, @intCast(self.sections.slice().len)); + if (self.shstrtab_section_index == null) { + self.shstrtab_section_index = @as(u16, @intCast(self.sections.slice().len)); assert(self.shstrtab.buffer.items.len == 0); try self.shstrtab.buffer.append(gpa, 0); // need a 0 at position 0 const off = self.findFreeSpace(self.shstrtab.buffer.items.len, 1); - log.debug("found shstrtab free space 0x{x} to 0x{x}", .{ off, off + self.shstrtab.buffer.items.len }); + log.debug("found .shstrtab free space 0x{x} to 0x{x}", .{ off, off + self.shstrtab.buffer.items.len }); try self.sections.append(gpa, .{ .shdr = .{ .sh_name = try self.shstrtab.insert(gpa, ".shstrtab"), @@ -606,6 +612,31 @@ pub fn populateMissingMetadata(self: *Elf) !void { self.shdr_table_dirty = true; } + if (self.strtab_section_index == null) { + self.strtab_section_index = @as(u16, @intCast(self.sections.slice().len)); + assert(self.strtab.buffer.items.len == 0); + try self.strtab.buffer.append(gpa, 0); // need a 0 at position 0 + const off = self.findFreeSpace(self.strtab.buffer.items.len, 1); + log.debug("found .strtab free space 0x{x} to 0x{x}", .{ off, off + self.strtab.buffer.items.len }); + try self.sections.append(gpa, .{ + .shdr = .{ + .sh_name = try self.shstrtab.insert(gpa, ".strtab"), + .sh_type = elf.SHT_STRTAB, + .sh_flags = 0, + .sh_addr = 0, + .sh_offset = off, + .sh_size = self.strtab.buffer.items.len, + .sh_link = 0, + .sh_info = 0, + .sh_addralign = 1, + .sh_entsize = 0, + }, + .phdr_index = undefined, + }); + self.strtab_dirty = true; + self.shdr_table_dirty = true; + } + if (self.text_section_index == null) { self.text_section_index = @as(u16, @intCast(self.sections.slice().len)); const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; @@ -711,7 +742,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { .sh_offset = off, .sh_size = file_size, // The section header index of the associated string table. - .sh_link = self.shstrtab_index.?, + .sh_link = self.strtab_section_index.?, .sh_info = @as(u32, @intCast(self.local_symbols.items.len)), .sh_addralign = min_align, .sh_entsize = each_size, @@ -1076,7 +1107,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node const source_sym = atom.getSymbol(self); const source_shdr = self.sections.items(.shdr)[source_sym.st_shndx]; - log.debug("relocating '{?s}'", .{self.shstrtab.get(source_sym.st_name)}); + log.debug("relocating '{?s}'", .{self.strtab.get(source_sym.st_name)}); for (relocs.items) |*reloc| { 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 log.debug(" ({x}: [() => 0x{x}] ({?s}))", .{ reloc.offset, target_vaddr, - self.shstrtab.get(target_sym.st_name), + self.strtab.get(target_sym.st_name), }); switch (self.ptr_width) { @@ -1212,7 +1243,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node } { - const shdr_index = self.shstrtab_index.?; + const shdr_index = self.shstrtab_section_index.?; if (self.shstrtab_dirty or self.shstrtab.buffer.items.len != self.sections.items(.shdr)[shdr_index].sh_size) { try self.growNonAllocSection(shdr_index, self.shstrtab.buffer.items.len, 1, false); 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 } } + { + const shdr_index = self.strtab_section_index.?; + if (self.strtab_dirty or self.strtab.buffer.items.len != self.sections.items(.shdr)[shdr_index].sh_size) { + try self.growNonAllocSection(shdr_index, self.strtab.buffer.items.len, 1, false); + const strtab_sect = self.sections.items(.shdr)[shdr_index]; + try self.base.file.?.pwriteAll(self.strtab.buffer.items, strtab_sect.sh_offset); + self.strtab_dirty = false; + } + } + if (self.dwarf) |dwarf| { const shdr_index = self.debug_str_section_index.?; 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 assert(!self.phdr_table_dirty); assert(!self.shdr_table_dirty); assert(!self.shstrtab_dirty); + assert(!self.strtab_dirty); assert(!self.debug_strtab_dirty); assert(!self.got_table_count_dirty); } @@ -2115,7 +2157,7 @@ fn writeElfHeader(self: *Elf) !void { mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian); index += 2; - mem.writeInt(u16, hdr_buf[index..][0..2], self.shstrtab_index.?, endian); + mem.writeInt(u16, hdr_buf[index..][0..2], self.shstrtab_section_index.?, endian); index += 2; assert(index == e_ehsize); @@ -2485,7 +2527,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s const shdr_index = decl_metadata.shdr; if (atom.getSymbol(self).st_size != 0 and self.base.child_pid == null) { const local_sym = atom.getSymbolPtr(self); - local_sym.st_name = try self.shstrtab.insert(gpa, decl_name); + local_sym.st_name = try self.strtab.insert(gpa, decl_name); local_sym.st_info = (elf.STB_LOCAL << 4) | stt_bits; local_sym.st_other = 0; local_sym.st_shndx = shdr_index; @@ -2515,7 +2557,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s } else { const local_sym = atom.getSymbolPtr(self); local_sym.* = .{ - .st_name = try self.shstrtab.insert(gpa, decl_name), + .st_name = try self.strtab.insert(gpa, decl_name), .st_info = (elf.STB_LOCAL << 4) | stt_bits, .st_other = 0, .st_shndx = shdr_index, @@ -2716,9 +2758,9 @@ fn updateLazySymbolAtom( sym.ty.fmt(mod), }); defer gpa.free(name); - break :blk try self.shstrtab.insert(gpa, name); + break :blk try self.strtab.insert(gpa, name); }; - const name = self.shstrtab.get(name_str_index).?; + const name = self.strtab.get(name_str_index).?; const atom = self.getAtom(atom_index); const local_sym_index = atom.getSymbolIndex().?; @@ -2793,9 +2835,9 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module const index = unnamed_consts.items.len; const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); defer gpa.free(name); - break :blk try self.shstrtab.insert(gpa, name); + break :blk try self.strtab.insert(gpa, name); }; - const name = self.shstrtab.get(name_str_index).?; + const name = self.strtab.get(name_str_index).?; const atom_index = try self.createAtom(); @@ -2900,7 +2942,7 @@ pub fn updateDeclExports( if (decl_metadata.getExport(self, exp_name)) |i| { const sym = &self.global_symbols.items[i]; sym.* = .{ - .st_name = try self.shstrtab.insert(gpa, exp_name), + .st_name = try self.strtab.insert(gpa, exp_name), .st_info = (stb_bits << 4) | stt_bits, .st_other = 0, .st_shndx = shdr_index, @@ -2914,7 +2956,7 @@ pub fn updateDeclExports( }; try decl_metadata.exports.append(gpa, @as(u32, @intCast(i))); self.global_symbols.items[i] = .{ - .st_name = try self.shstrtab.insert(gpa, exp_name), + .st_name = try self.strtab.insert(gpa, exp_name), .st_info = (stb_bits << 4) | stt_bits, .st_other = 0, .st_shndx = shdr_index, @@ -3080,7 +3122,7 @@ fn writeSymbol(self: *Elf, index: usize) !void { .p64 => syms_sect.sh_offset + @sizeOf(elf.Elf64_Sym) * index, }; const local = self.local_symbols.items[index]; - log.debug("writing symbol {d}, '{?s}' at 0x{x}", .{ index, self.shstrtab.get(local.st_name), off }); + log.debug("writing symbol {d}, '{?s}' at 0x{x}", .{ index, self.strtab.get(local.st_name), off }); log.debug(" ({})", .{local}); switch (self.ptr_width) { .p32 => { @@ -3460,11 +3502,11 @@ const CsuObjects = struct { fn logSymtab(self: Elf) void { log.debug("locals:", .{}); for (self.local_symbols.items, 0..) |sym, id| { - log.debug(" {d}: {?s}: @{x} in {d}", .{ id, self.shstrtab.get(sym.st_name), sym.st_value, sym.st_shndx }); + log.debug(" {d}: {?s}: @{x} in {d}", .{ id, self.strtab.get(sym.st_name), sym.st_value, sym.st_shndx }); } log.debug("globals:", .{}); for (self.global_symbols.items, 0..) |sym, id| { - log.debug(" {d}: {?s}: @{x} in {d}", .{ id, self.shstrtab.get(sym.st_name), sym.st_value, sym.st_shndx }); + log.debug(" {d}: {?s}: @{x} in {d}", .{ id, self.strtab.get(sym.st_name), sym.st_value, sym.st_shndx }); } } @@ -3491,13 +3533,13 @@ pub fn getSymbol(self: *const Elf, sym_index: u32) elf.Elf64_Sym { /// Returns name of the symbol at sym_index. pub fn getSymbolName(self: *const Elf, sym_index: u32) []const u8 { const sym = self.local_symbols.items[sym_index]; - return self.shstrtab.get(sym.st_name).?; + return self.strtab.get(sym.st_name).?; } /// Returns name of the global symbol at index. pub fn getGlobalName(self: *const Elf, index: u32) []const u8 { const sym = self.global_symbols.items[index]; - return self.shstrtab.get(sym.st_name).?; + return self.strtab.get(sym.st_name).?; } pub fn getAtom(self: *const Elf, atom_index: Atom.Index) Atom { |
