authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-03 07:52:17+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-09-03 07:52:17+02:00
loge265dc61e651d67bbfb3be675ff132df865902ef
treebedf2868c0ee90f513cc1cb8c130e6e1be113fd8
parent8b74eae9c602433f5f35d30929b455447a3ce78b
parentbaea106b713a49b38f0b568c2cbbf02f3c48537b
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #17057 from ziglang/elf-symtab

elf: write all symbols in bulk in flush

1 files changed, 44 insertions(+), 95 deletions(-)

src/link/Elf.zig+44-95
...@@ -750,7 +750,6 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -750,7 +750,6 @@ pub fn populateMissingMetadata(self: *Elf) !void {
750 .phdr_index = undefined,750 .phdr_index = undefined,
751 });751 });
752 self.shdr_table_dirty = true;752 self.shdr_table_dirty = true;
753 try self.writeSymbol(0);
754 }753 }
755754
756 if (self.dwarf) |*dw| {755 if (self.dwarf) |*dw| {
...@@ -1134,9 +1133,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1134,9 +1133,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1134 }1133 }
1135 }1134 }
11361135
1137 // Unfortunately these have to be buffered and done at the end because ELF does not allow1136 try self.writeSymbols();
1138 // mixing local and global symbols within a symbol table.
1139 try self.writeAllGlobalSymbols();
11401137
1141 if (build_options.enable_logging) {1138 if (build_options.enable_logging) {
1142 self.logSymtab();1139 self.logSymtab();
...@@ -2551,9 +2548,6 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s...@@ -2551,9 +2548,6 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s
2551 self.shrinkAtom(atom_index, code.len);2548 self.shrinkAtom(atom_index, code.len);
2552 }2549 }
2553 local_sym.st_size = code.len;2550 local_sym.st_size = code.len;
2554
2555 // TODO this write could be avoided if no fields of the symbol were changed.
2556 try self.writeSymbol(local_sym_index);
2557 } else {2551 } else {
2558 const local_sym = atom.getSymbolPtr(self);2552 const local_sym = atom.getSymbolPtr(self);
2559 local_sym.* = .{2553 local_sym.* = .{
...@@ -2571,7 +2565,6 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s...@@ -2571,7 +2565,6 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s
2571 local_sym.st_value = vaddr;2565 local_sym.st_value = vaddr;
2572 local_sym.st_size = code.len;2566 local_sym.st_size = code.len;
25732567
2574 try self.writeSymbol(local_sym_index);
2575 const got_entry_index = try atom.getOrCreateOffsetTableEntry(self);2568 const got_entry_index = try atom.getOrCreateOffsetTableEntry(self);
2576 try self.writeOffsetTableEntry(got_entry_index);2569 try self.writeOffsetTableEntry(got_entry_index);
2577 }2570 }
...@@ -2807,7 +2800,6 @@ fn updateLazySymbolAtom(...@@ -2807,7 +2800,6 @@ fn updateLazySymbolAtom(
2807 local_sym.st_value = vaddr;2800 local_sym.st_value = vaddr;
2808 local_sym.st_size = code.len;2801 local_sym.st_size = code.len;
28092802
2810 try self.writeSymbol(local_sym_index);
2811 const got_entry_index = try atom.getOrCreateOffsetTableEntry(self);2803 const got_entry_index = try atom.getOrCreateOffsetTableEntry(self);
2812 try self.writeOffsetTableEntry(got_entry_index);2804 try self.writeOffsetTableEntry(got_entry_index);
28132805
...@@ -2870,7 +2862,6 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module...@@ -2870,7 +2862,6 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
28702862
2871 log.debug("allocated text block for {s} at 0x{x}", .{ name, local_sym.st_value });2863 log.debug("allocated text block for {s} at 0x{x}", .{ name, local_sym.st_value });
28722864
2873 try self.writeSymbol(self.getAtom(atom_index).getSymbolIndex().?);
2874 try unnamed_consts.append(gpa, atom_index);2865 try unnamed_consts.append(gpa, atom_index);
28752866
2876 const section_offset = local_sym.st_value - self.program_headers.items[phdr_index].p_vaddr;2867 const section_offset = local_sym.st_value - self.program_headers.items[phdr_index].p_vaddr;
...@@ -3096,63 +3087,19 @@ fn writeOffsetTableEntry(self: *Elf, index: @TypeOf(self.got_table).Index) !void...@@ -3096,63 +3087,19 @@ fn writeOffsetTableEntry(self: *Elf, index: @TypeOf(self.got_table).Index) !void
3096 }3087 }
3097}3088}
30983089
3099fn writeSymbol(self: *Elf, index: usize) !void {3090fn elf32SymFromSym(sym: elf.Elf64_Sym, out: *elf.Elf32_Sym) void {
3100 const tracy = trace(@src());3091 out.* = .{
3101 defer tracy.end();3092 .st_name = sym.st_name,
31023093 .st_value = @as(u32, @intCast(sym.st_value)),
3103 const syms_sect = &self.sections.items(.shdr)[self.symtab_section_index.?];3094 .st_size = @as(u32, @intCast(sym.st_size)),
3104 // Make sure we are not pointlessly writing symbol data that will have to get relocated3095 .st_info = sym.st_info,
3105 // due to running out of space.3096 .st_other = sym.st_other,
3106 if (self.local_symbols.items.len != syms_sect.sh_info) {3097 .st_shndx = sym.st_shndx,
3107 const sym_size: u64 = switch (self.ptr_width) {
3108 .p32 => @sizeOf(elf.Elf32_Sym),
3109 .p64 => @sizeOf(elf.Elf64_Sym),
3110 };
3111 const sym_align: u16 = switch (self.ptr_width) {
3112 .p32 => @alignOf(elf.Elf32_Sym),
3113 .p64 => @alignOf(elf.Elf64_Sym),
3114 };
3115 const needed_size = (self.local_symbols.items.len + self.global_symbols.items.len) * sym_size;
3116 try self.growNonAllocSection(self.symtab_section_index.?, needed_size, sym_align, true);
3117 syms_sect.sh_info = @as(u32, @intCast(self.local_symbols.items.len));
3118 }
3119 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();
3120 const off = switch (self.ptr_width) {
3121 .p32 => syms_sect.sh_offset + @sizeOf(elf.Elf32_Sym) * index,
3122 .p64 => syms_sect.sh_offset + @sizeOf(elf.Elf64_Sym) * index,
3123 };3098 };
3124 const local = self.local_symbols.items[index];
3125 log.debug("writing symbol {d}, '{?s}' at 0x{x}", .{ index, self.strtab.get(local.st_name), off });
3126 log.debug(" ({})", .{local});
3127 switch (self.ptr_width) {
3128 .p32 => {
3129 var sym = [1]elf.Elf32_Sym{
3130 .{
3131 .st_name = local.st_name,
3132 .st_value = @as(u32, @intCast(local.st_value)),
3133 .st_size = @as(u32, @intCast(local.st_size)),
3134 .st_info = local.st_info,
3135 .st_other = local.st_other,
3136 .st_shndx = local.st_shndx,
3137 },
3138 };
3139 if (foreign_endian) {
3140 mem.byteSwapAllFields(elf.Elf32_Sym, &sym[0]);
3141 }
3142 try self.base.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off);
3143 },
3144 .p64 => {
3145 var sym = [1]elf.Elf64_Sym{local};
3146 if (foreign_endian) {
3147 mem.byteSwapAllFields(elf.Elf64_Sym, &sym[0]);
3148 }
3149 try self.base.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off);
3150 },
3151 }
3152}3099}
31533100
3154fn writeAllGlobalSymbols(self: *Elf) !void {3101fn writeSymbols(self: *Elf) !void {
3155 const syms_sect = &self.sections.items(.shdr)[self.symtab_section_index.?];3102 const gpa = self.base.allocator;
3156 const sym_size: u64 = switch (self.ptr_width) {3103 const sym_size: u64 = switch (self.ptr_width) {
3157 .p32 => @sizeOf(elf.Elf32_Sym),3104 .p32 => @sizeOf(elf.Elf32_Sym),
3158 .p64 => @sizeOf(elf.Elf64_Sym),3105 .p64 => @sizeOf(elf.Elf64_Sym),
...@@ -3161,52 +3108,54 @@ fn writeAllGlobalSymbols(self: *Elf) !void {...@@ -3161,52 +3108,54 @@ fn writeAllGlobalSymbols(self: *Elf) !void {
3161 .p32 => @alignOf(elf.Elf32_Sym),3108 .p32 => @alignOf(elf.Elf32_Sym),
3162 .p64 => @alignOf(elf.Elf64_Sym),3109 .p64 => @alignOf(elf.Elf64_Sym),
3163 };3110 };
3164 const needed_size = (self.local_symbols.items.len + self.global_symbols.items.len) * sym_size;3111
3112 const shdr = &self.sections.items(.shdr)[self.symtab_section_index.?];
3113 shdr.sh_info = @intCast(self.local_symbols.items.len);
3114 self.markDirty(self.symtab_section_index.?, null);
3115
3116 const nsyms = self.local_symbols.items.len + self.global_symbols.items.len;
3117 const needed_size = nsyms * sym_size;
3165 try self.growNonAllocSection(self.symtab_section_index.?, needed_size, sym_align, true);3118 try self.growNonAllocSection(self.symtab_section_index.?, needed_size, sym_align, true);
31663119
3167 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();3120 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();
3168 const global_syms_off = syms_sect.sh_offset + self.local_symbols.items.len * sym_size;3121 log.debug("writing {d} symbols at 0x{x}", .{ nsyms, shdr.sh_offset });
3169 log.debug("writing {d} global symbols at 0x{x}", .{ self.global_symbols.items.len, global_syms_off });
3170 switch (self.ptr_width) {3122 switch (self.ptr_width) {
3171 .p32 => {3123 .p32 => {
3172 const buf = try self.base.allocator.alloc(elf.Elf32_Sym, self.global_symbols.items.len);3124 const buf = try gpa.alloc(elf.Elf32_Sym, nsyms);
3173 defer self.base.allocator.free(buf);3125 defer gpa.free(buf);
31743126
3175 for (buf, 0..) |*sym, i| {3127 for (buf[0..self.local_symbols.items.len], self.local_symbols.items) |*sym, local| {
3176 const global = self.global_symbols.items[i];3128 elf32SymFromSym(local, sym);
3177 sym.* = .{3129 if (foreign_endian) {
3178 .st_name = global.st_name,3130 mem.byteSwapAllFields(elf.Elf32_Sym, sym);
3179 .st_value = @as(u32, @intCast(global.st_value)),3131 }
3180 .st_size = @as(u32, @intCast(global.st_size)),3132 }
3181 .st_info = global.st_info,3133
3182 .st_other = global.st_other,3134 for (buf[self.local_symbols.items.len..], self.global_symbols.items) |*sym, global| {
3183 .st_shndx = global.st_shndx,3135 elf32SymFromSym(global, sym);
3184 };
3185 if (foreign_endian) {3136 if (foreign_endian) {
3186 mem.byteSwapAllFields(elf.Elf32_Sym, sym);3137 mem.byteSwapAllFields(elf.Elf32_Sym, sym);
3187 }3138 }
3188 }3139 }
3189 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off);3140 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), shdr.sh_offset);
3190 },3141 },
3191 .p64 => {3142 .p64 => {
3192 const buf = try self.base.allocator.alloc(elf.Elf64_Sym, self.global_symbols.items.len);3143 const buf = try gpa.alloc(elf.Elf64_Sym, nsyms);
3193 defer self.base.allocator.free(buf);3144 defer gpa.free(buf);
31943145 for (buf[0..self.local_symbols.items.len], self.local_symbols.items) |*sym, local| {
3195 for (buf, 0..) |*sym, i| {3146 sym.* = local;
3196 const global = self.global_symbols.items[i];3147 if (foreign_endian) {
3197 sym.* = .{3148 mem.byteSwapAllFields(elf.Elf64_Sym, sym);
3198 .st_name = global.st_name,3149 }
3199 .st_value = global.st_value,3150 }
3200 .st_size = global.st_size,3151
3201 .st_info = global.st_info,3152 for (buf[self.local_symbols.items.len..], self.global_symbols.items) |*sym, global| {
3202 .st_other = global.st_other,3153 sym.* = global;
3203 .st_shndx = global.st_shndx,
3204 };
3205 if (foreign_endian) {3154 if (foreign_endian) {
3206 mem.byteSwapAllFields(elf.Elf64_Sym, sym);3155 mem.byteSwapAllFields(elf.Elf64_Sym, sym);
3207 }3156 }
3208 }3157 }
3209 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off);3158 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), shdr.sh_offset);
3210 },3159 },
3211 }3160 }
3212}3161}