| ... | @@ -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 | } |
| 755 | | 754 | |
| 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 | } |
| 1136 | | 1135 | |
| 1137 | // Unfortunately these have to be buffered and done at the end because ELF does not allow | 1136 | try self.writeSymbols(); |
| 1138 | // mixing local and global symbols within a symbol table. | | |
| 1139 | try self.writeAllGlobalSymbols(); | | |
| 1140 | | 1137 | |
| 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; |
| 2573 | | 2567 | |
| 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; |
| 2809 | | 2802 | |
| 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); |
| 2813 | | 2805 | |
| ... | @@ -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 |
| 2870 | | 2862 | |
| 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 }); |
| 2872 | | 2864 | |
| 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); |
| 2875 | | 2866 | |
| 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 | } |
| 3098 | | 3089 | |
| 3099 | fn writeSymbol(self: *Elf, index: usize) !void { | 3090 | fn 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, |
| 3102 | | 3093 | .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 relocated | 3095 | .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 | } |
| 3153 | | 3100 | |
| 3154 | fn writeAllGlobalSymbols(self: *Elf) !void { | 3101 | fn 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); |
| 3166 | | 3119 | |
| 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); |
| 3174 | | 3126 | |
| 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); |
| 3194 | | 3145 | 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 | } |