authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-09-05 09:25:47+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-09-07 22:42:57+02:00
logf1bdf3f62f05388b75d6816b65c9cc5caec71cd9
treea87f6f1c2f3a06eb0a7939f099436e1754dbeb82
parent467d69c68aac0459b6a0c2876083d7295e43134d

coff: fix writing strtab to PE image file


2 files changed, 39 insertions(+), 15 deletions(-)

src/link/Coff.zig+35-15
...@@ -324,6 +324,19 @@ fn populateMissingMetadata(self: *Coff) !void {...@@ -324,6 +324,19 @@ fn populateMissingMetadata(self: *Coff) !void {
324 assert(self.llvm_object == null);324 assert(self.llvm_object == null);
325 const gpa = self.base.allocator;325 const gpa = self.base.allocator;
326326
327 try self.strtab.buffer.ensureUnusedCapacity(gpa, @sizeOf(u32));
328 self.strtab.buffer.appendNTimesAssumeCapacity(0, @sizeOf(u32));
329
330 // Index 0 is always a null symbol.
331 try self.locals.append(gpa, .{
332 .name = [_]u8{0} ** 8,
333 .value = 0,
334 .section_number = .UNDEFINED,
335 .@"type" = .{ .base_type = .NULL, .complex_type = .NULL },
336 .storage_class = .NULL,
337 .number_of_aux_symbols = 0,
338 });
339
327 if (self.text_section_index == null) {340 if (self.text_section_index == null) {
328 self.text_section_index = @intCast(u16, self.sections.slice().len);341 self.text_section_index = @intCast(u16, self.sections.slice().len);
329 const file_size = @intCast(u32, self.base.options.program_code_size_hint);342 const file_size = @intCast(u32, self.base.options.program_code_size_hint);
...@@ -472,21 +485,11 @@ fn populateMissingMetadata(self: *Coff) !void {...@@ -472,21 +485,11 @@ fn populateMissingMetadata(self: *Coff) !void {
472 }485 }
473486
474 if (self.strtab_offset == null) {487 if (self.strtab_offset == null) {
475 try self.strtab.buffer.append(gpa, 0);488 const file_size = @intCast(u32, self.strtab.len());
476 self.strtab_offset = self.findFreeSpace(@intCast(u32, self.strtab.len()), 1);489 self.strtab_offset = self.findFreeSpace(file_size, @alignOf(u32)); // 4bytes aligned seems like a good idea here
477 log.debug("found strtab free space 0x{x} to 0x{x}", .{ self.strtab_offset.?, self.strtab_offset.? + self.strtab.len() });490 log.debug("found strtab free space 0x{x} to 0x{x}", .{ self.strtab_offset.?, self.strtab_offset.? + file_size });
478 }491 }
479492
480 // Index 0 is always a null symbol.
481 try self.locals.append(gpa, .{
482 .name = [_]u8{0} ** 8,
483 .value = 0,
484 .section_number = .UNDEFINED,
485 .@"type" = .{ .base_type = .NULL, .complex_type = .NULL },
486 .storage_class = .NULL,
487 .number_of_aux_symbols = 0,
488 });
489
490 {493 {
491 // We need to find out what the max file offset is according to section headers.494 // We need to find out what the max file offset is according to section headers.
492 // Otherwise, we may end up with an COFF binary with file size not matching the final section's495 // Otherwise, we may end up with an COFF binary with file size not matching the final section's
...@@ -1672,11 +1675,20 @@ fn writeStrtab(self: *Coff) !void {...@@ -1672,11 +1675,20 @@ fn writeStrtab(self: *Coff) !void {
16721675
1673 if (needed_size > allocated_size) {1676 if (needed_size > allocated_size) {
1674 self.strtab_offset = null;1677 self.strtab_offset = null;
1675 self.strtab_offset = @intCast(u32, self.findFreeSpace(needed_size, 1));1678 self.strtab_offset = @intCast(u32, self.findFreeSpace(needed_size, @alignOf(u32)));
1676 }1679 }
16771680
1678 log.debug("writing strtab from 0x{x} to 0x{x}", .{ self.strtab_offset.?, self.strtab_offset.? + needed_size });1681 log.debug("writing strtab from 0x{x} to 0x{x}", .{ self.strtab_offset.?, self.strtab_offset.? + needed_size });
1679 try self.base.file.?.pwriteAll(self.strtab.buffer.items, self.strtab_offset.?);1682
1683 var buffer = std.ArrayList(u8).init(self.base.allocator);
1684 defer buffer.deinit();
1685 try buffer.ensureTotalCapacityPrecise(needed_size);
1686 buffer.appendSliceAssumeCapacity(self.strtab.items());
1687 // Here, we do a trick in that we do not commit the size of the strtab to strtab buffer, instead
1688 // we write the length of the strtab to a temporary buffer that goes to file.
1689 mem.writeIntLittle(u32, buffer.items[0..4], @intCast(u32, self.strtab.len()));
1690
1691 try self.base.file.?.pwriteAll(buffer.items, self.strtab_offset.?);
1680}1692}
16811693
1682fn writeSectionHeaders(self: *Coff) !void {1694fn writeSectionHeaders(self: *Coff) !void {
...@@ -1984,6 +1996,14 @@ fn setSectionName(self: *Coff, header: *coff.SectionHeader, name: []const u8) !v...@@ -1984,6 +1996,14 @@ fn setSectionName(self: *Coff, header: *coff.SectionHeader, name: []const u8) !v
1984 mem.set(u8, header.name[name_offset.len..], 0);1996 mem.set(u8, header.name[name_offset.len..], 0);
1985}1997}
19861998
1999fn getSectionName(self: *const Coff, header: *const coff.SectionHeader) []const u8 {
2000 if (header.getName()) |name| {
2001 return name;
2002 }
2003 const offset = header.getNameOffset().?;
2004 return self.strtab.get(offset).?;
2005}
2006
1987fn setSymbolName(self: *Coff, symbol: *coff.Symbol, name: []const u8) !void {2007fn setSymbolName(self: *Coff, symbol: *coff.Symbol, name: []const u8) !void {
1988 if (name.len <= 8) {2008 if (name.len <= 8) {
1989 mem.copy(u8, &symbol.name, name);2009 mem.copy(u8, &symbol.name, name);
src/link/strtab.zig+4
...@@ -110,6 +110,10 @@ pub fn StringTable(comptime log_scope: @Type(.EnumLiteral)) type {...@@ -110,6 +110,10 @@ pub fn StringTable(comptime log_scope: @Type(.EnumLiteral)) type {
110 return self.get(off) orelse unreachable;110 return self.get(off) orelse unreachable;
111 }111 }
112112
113 pub fn items(self: Self) []const u8 {
114 return self.buffer.items;
115 }
116
113 pub fn len(self: Self) usize {117 pub fn len(self: Self) usize {
114 return self.buffer.items.len;118 return self.buffer.items.len;
115 }119 }