diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 969ba53d87..adeeb0bbbb 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1539,14 +1539,14 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void try self.initShStrtab(); try self.sortShdrs(); zig_object.updateRelaSectionSizes(self); - try self.updateSymtabSize(); + self.updateSymtabSizeObject(zig_object); self.updateShStrtabSize(); try self.allocateNonAllocSections(); try self.writeShdrTable(); try zig_object.writeRelaSections(self); - try self.writeSymtab(); + try self.writeSymtabObject(zig_object); try self.writeShStrtab(); try self.writeElfHeader(); } @@ -4060,7 +4060,7 @@ fn updateSectionSizes(self: *Elf) !void { self.shdrs.items[index].sh_size = self.verneed.size(); } - try self.updateSymtabSize(); + self.updateSymtabSize(); self.updateShStrtabSize(); } @@ -4483,7 +4483,7 @@ fn writeAtoms(self: *Elf) !void { try self.reportUndefined(&undefs); } -fn updateSymtabSize(self: *Elf) !void { +fn updateSymtabSize(self: *Elf) void { var sizes = SymtabSize{}; if (self.zigObjectPtr()) |zig_object| { @@ -4544,6 +4544,25 @@ fn updateSymtabSize(self: *Elf) !void { strtab.sh_size = sizes.strsize + 1; } +fn updateSymtabSizeObject(self: *Elf, zig_object: *ZigObject) void { + zig_object.asFile().updateSymtabSize(self); + const sizes = zig_object.output_symtab_size; + + const symtab_shdr = &self.shdrs.items[self.symtab_section_index.?]; + symtab_shdr.sh_info = sizes.nlocals + 1; + symtab_shdr.sh_link = self.strtab_section_index.?; + + const sym_size: u64 = switch (self.ptr_width) { + .p32 => @sizeOf(elf.Elf32_Sym), + .p64 => @sizeOf(elf.Elf64_Sym), + }; + const needed_size = (sizes.nlocals + sizes.nglobals + 1) * sym_size; + symtab_shdr.sh_size = needed_size; + + const strtab = &self.shdrs.items[self.strtab_section_index.?]; + strtab.sh_size = sizes.strsize + 1; +} + fn writeSyntheticSections(self: *Elf) !void { const gpa = self.base.allocator; @@ -4788,6 +4807,54 @@ fn writeSymtab(self: *Elf) !void { try self.base.file.?.pwriteAll(self.strtab.items, strtab_shdr.sh_offset); } +fn writeSymtabObject(self: *Elf, zig_object: *ZigObject) !void { + const gpa = self.base.allocator; + const symtab_shdr = self.shdrs.items[self.symtab_section_index.?]; + const strtab_shdr = self.shdrs.items[self.strtab_section_index.?]; + const sym_size: u64 = switch (self.ptr_width) { + .p32 => @sizeOf(elf.Elf32_Sym), + .p64 => @sizeOf(elf.Elf64_Sym), + }; + const nsyms = math.cast(usize, @divExact(symtab_shdr.sh_size, sym_size)) orelse return error.Overflow; + + log.debug("writing {d} symbols at 0x{x}", .{ nsyms, symtab_shdr.sh_offset }); + + try self.symtab.resize(gpa, nsyms); + const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow; + try self.strtab.ensureUnusedCapacity(gpa, needed_strtab_size); + + zig_object.asFile().writeSymtab(self, .{ .ilocal = 1, .iglobal = symtab_shdr.sh_info }); + + const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian(); + switch (self.ptr_width) { + .p32 => { + const buf = try gpa.alloc(elf.Elf32_Sym, self.symtab.items.len); + defer gpa.free(buf); + + for (buf, self.symtab.items) |*out, sym| { + out.* = .{ + .st_name = sym.st_name, + .st_info = sym.st_info, + .st_other = sym.st_other, + .st_shndx = sym.st_shndx, + .st_value = @as(u32, @intCast(sym.st_value)), + .st_size = @as(u32, @intCast(sym.st_size)), + }; + if (foreign_endian) mem.byteSwapAllFields(elf.Elf32_Sym, out); + } + try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), symtab_shdr.sh_offset); + }, + .p64 => { + if (foreign_endian) { + for (self.symtab.items) |*sym| mem.byteSwapAllFields(elf.Elf64_Sym, sym); + } + try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.symtab.items), symtab_shdr.sh_offset); + }, + } + + try self.base.file.?.pwriteAll(self.strtab.items, strtab_shdr.sh_offset); +} + /// Always 4 or 8 depending on whether this is 32-bit ELF or 64-bit ELF. fn ptrWidthBytes(self: Elf) u8 { return switch (self.ptr_width) { diff --git a/src/link/Elf/file.zig b/src/link/Elf/file.zig index b5c8b2bd19..cc0b486692 100644 --- a/src/link/Elf/file.zig +++ b/src/link/Elf/file.zig @@ -161,7 +161,7 @@ pub const File = union(enum) { } pub fn writeSymtab(file: File, elf_file: *Elf, ctx: anytype) void { - var ilocal = ctx.ilocal; + var ilocal: usize = ctx.ilocal; for (file.locals()) |local_index| { const local = elf_file.symbol(local_index); if (!local.flags.output_symtab) continue; @@ -173,7 +173,7 @@ pub const File = union(enum) { ilocal += 1; } - var iglobal = ctx.iglobal; + var iglobal: usize = ctx.iglobal; for (file.globals()) |global_index| { const global = elf_file.symbol(global_index); const file_ptr = global.file(elf_file) orelse continue;