authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-08-28 14:25:58+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-08-30 10:42:21+02:00
log2a994ba4a713f0bd469265ea3c55e335048d4c91
treeda980743b810aa9c2367c62d613802e2ce275b14
parentf36029a3851756d6e98eb486c89dc741db79752e

coff: populate missing section metadata


1 files changed, 126 insertions(+), 13 deletions(-)

src/link/Coff.zig+126-13
...@@ -43,7 +43,9 @@ sections: std.MultiArrayList(Section) = .{},...@@ -43,7 +43,9 @@ sections: std.MultiArrayList(Section) = .{},
43data_directories: [16]coff.ImageDataDirectory,43data_directories: [16]coff.ImageDataDirectory,
4444
45text_section_index: ?u16 = null,45text_section_index: ?u16 = null,
46got_section_index: ?u16 = null,46rdata_section_index: ?u16 = null,
47pdata_section_index: ?u16 = null,
48data_section_index: ?u16 = null,
4749
48locals: std.ArrayListUnmanaged(coff.Symbol) = .{},50locals: std.ArrayListUnmanaged(coff.Symbol) = .{},
49globals: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{},51globals: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{},
...@@ -212,12 +214,103 @@ fn populateMissingMetadata(self: *Coff) !void {...@@ -212,12 +214,103 @@ fn populateMissingMetadata(self: *Coff) !void {
212 const file_size = self.base.options.program_code_size_hint;214 const file_size = self.base.options.program_code_size_hint;
213 const off = self.findFreeSpace(file_size, self.page_size); // TODO we are over-aligning in file; we should track both in file and in memory pointers215 const off = self.findFreeSpace(file_size, self.page_size); // TODO we are over-aligning in file; we should track both in file and in memory pointers
214 log.debug("found .text free space 0x{x} to 0x{x}", .{ off, off + file_size });216 log.debug("found .text free space 0x{x} to 0x{x}", .{ off, off + file_size });
217 var header = coff.SectionHeader{
218 .name = undefined,
219 .virtual_size = @intCast(u32, file_size),
220 .virtual_address = @intCast(u32, off),
221 .size_of_raw_data = @intCast(u32, file_size),
222 .pointer_to_raw_data = @intCast(u32, off),
223 .pointer_to_relocations = 0,
224 .pointer_to_linenumbers = 0,
225 .number_of_relocations = 0,
226 .number_of_linenumbers = 0,
227 .flags = .{
228 .CNT_CODE = 1,
229 .MEM_EXECUTE = 1,
230 .MEM_READ = 1,
231 },
232 };
233 try self.setSectionName(&header, ".text");
234 try self.sections.append(gpa, .{ .header = header });
215 }235 }
216236
217 if (self.got_section_index == null) {}237 if (self.pdata_section_index == null) {
238 self.pdata_section_index = @intCast(u16, self.sections.slice().len);
239 const file_size = self.base.options.symbol_count_hint;
240 const off = self.findFreeSpace(file_size, self.page_size);
241 log.debug("found .pdata free space 0x{x} to 0x{x}", .{ off, off + file_size });
242 var header = coff.SectionHeader{
243 .name = undefined,
244 .virtual_size = @intCast(u32, file_size),
245 .virtual_address = @intCast(u32, off),
246 .size_of_raw_data = @intCast(u32, file_size),
247 .pointer_to_raw_data = @intCast(u32, off),
248 .pointer_to_relocations = 0,
249 .pointer_to_linenumbers = 0,
250 .number_of_relocations = 0,
251 .number_of_linenumbers = 0,
252 .flags = .{
253 .CNT_INITIALIZED_DATA = 1,
254 .MEM_READ = 1,
255 },
256 };
257 try self.setSectionName(&header, ".pdata");
258 try self.sections.append(gpa, .{ .header = header });
259 }
260
261 if (self.rdata_section_index == null) {
262 self.rdata_section_index = @intCast(u16, self.sections.slice().len);
263 const file_size = 1024;
264 const off = self.findFreeSpace(file_size, self.page_size);
265 log.debug("found .rdata free space 0x{x} to 0x{x}", .{ off, off + file_size });
266 var header = coff.SectionHeader{
267 .name = undefined,
268 .virtual_size = @intCast(u32, file_size),
269 .virtual_address = @intCast(u32, off),
270 .size_of_raw_data = @intCast(u32, file_size),
271 .pointer_to_raw_data = @intCast(u32, off),
272 .pointer_to_relocations = 0,
273 .pointer_to_linenumbers = 0,
274 .number_of_relocations = 0,
275 .number_of_linenumbers = 0,
276 .flags = .{
277 .CNT_INITIALIZED_DATA = 1,
278 .MEM_READ = 1,
279 },
280 };
281 try self.setSectionName(&header, ".rdata");
282 try self.sections.append(gpa, .{ .header = header });
283 }
284
285 if (self.data_section_index == null) {
286 self.data_section_index = @intCast(u16, self.sections.slice().len);
287 const file_size = 1024;
288 const off = self.findFreeSpace(file_size, self.page_size);
289 log.debug("found .data free space 0x{x} to 0x{x}", .{ off, off + file_size });
290 var header = coff.SectionHeader{
291 .name = undefined,
292 .virtual_size = @intCast(u32, file_size),
293 .virtual_address = @intCast(u32, off),
294 .size_of_raw_data = @intCast(u32, file_size),
295 .pointer_to_raw_data = @intCast(u32, off),
296 .pointer_to_relocations = 0,
297 .pointer_to_linenumbers = 0,
298 .number_of_relocations = 0,
299 .number_of_linenumbers = 0,
300 .flags = .{
301 .CNT_INITIALIZED_DATA = 1,
302 .MEM_READ = 1,
303 .MEM_WRITE = 1,
304 },
305 };
306 try self.setSectionName(&header, ".data");
307 try self.sections.append(gpa, .{ .header = header });
308 }
218309
219 if (self.strtab_offset == null) {310 if (self.strtab_offset == null) {
220 try self.strtab.buffer.append(gpa, 0);311 try self.strtab.buffer.append(gpa, 0);
312 self.strtab_offset = @intCast(u32, self.findFreeSpace(self.strtab.len(), 1));
313 log.debug("found strtab free space 0x{x} to 0x{x}", .{ self.strtab_offset.?, self.strtab_offset.? + self.strtab.len() });
221 }314 }
222315
223 // Index 0 is always a null symbol.316 // Index 0 is always a null symbol.
...@@ -677,6 +770,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -677,6 +770,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
677 sub_prog_node.activate();770 sub_prog_node.activate();
678 defer sub_prog_node.end();771 defer sub_prog_node.end();
679772
773 try self.writeStrtab();
680 try self.writeDataDirectoriesHeaders();774 try self.writeDataDirectoriesHeaders();
681 try self.writeSectionHeaders();775 try self.writeSectionHeaders();
682 try self.writeHeader();776 try self.writeHeader();
...@@ -709,6 +803,19 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !v...@@ -709,6 +803,19 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !v
709 log.debug("TODO implement updateDeclLineNumber", .{});803 log.debug("TODO implement updateDeclLineNumber", .{});
710}804}
711805
806fn writeStrtab(self: *Coff) !void {
807 const allocated_size = self.allocatedSize(self.strtab_offset.?);
808 const needed_size = self.strtab.len();
809
810 if (needed_size > allocated_size) {
811 self.strtab_offset = null;
812 self.strtab_offset = @intCast(u32, self.findFreeSpace(needed_size, 1));
813 }
814
815 log.debug("writing strtab from 0x{x} to 0x{x}", .{ self.strtab_offset.?, self.strtab_offset.? + needed_size });
816 try self.base.file.?.pwriteAll(self.strtab.buffer.items, self.strtab_offset.?);
817}
818
712fn writeSectionHeaders(self: *Coff) !void {819fn writeSectionHeaders(self: *Coff) !void {
713 const offset = self.getSectionHeadersOffset();820 const offset = self.getSectionHeadersOffset();
714 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.sections.items(.header)), offset);821 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.sections.items(.header)), offset);
...@@ -729,7 +836,7 @@ fn writeHeader(self: *Coff) !void {...@@ -729,7 +836,7 @@ fn writeHeader(self: *Coff) !void {
729 writer.writeAll(msdos_stub) catch unreachable;836 writer.writeAll(msdos_stub) catch unreachable;
730 writer.writeByteNTimes(0, 4) catch unreachable; // align to 8 bytes837 writer.writeByteNTimes(0, 4) catch unreachable; // align to 8 bytes
731 writer.writeAll("PE\x00\x00") catch unreachable;838 writer.writeAll("PE\x00\x00") catch unreachable;
732 buffer.items[0x3c] = @intCast(u8, msdos_stub.len + 4);839 mem.writeIntLittle(u32, buffer.items[0x3c..][0..4], msdos_stub.len + 4);
733840
734 var flags = coff.CoffHeaderFlags{841 var flags = coff.CoffHeaderFlags{
735 .EXECUTABLE_IMAGE = 1,842 .EXECUTABLE_IMAGE = 1,
...@@ -743,10 +850,7 @@ fn writeHeader(self: *Coff) !void {...@@ -743,10 +850,7 @@ fn writeHeader(self: *Coff) !void {
743 flags.DLL = 1;850 flags.DLL = 1;
744 }851 }
745852
746 const size_of_optional_header = @intCast(853 const size_of_optional_header = @intCast(u16, self.getOptionalHeaderSize() + self.getDataDirectoryHeadersSize());
747 u16,
748 self.getOptionalHeaderSize() + self.getDataDirectoryHeadersSize() + self.getSectionHeadersSize(),
749 );
750 var coff_header = coff.CoffHeader{854 var coff_header = coff.CoffHeader{
751 .machine = coff.MachineType.fromTargetCpuArch(self.base.options.target.cpu.arch),855 .machine = coff.MachineType.fromTargetCpuArch(self.base.options.target.cpu.arch),
752 .number_of_sections = @intCast(u16, self.sections.slice().len), // TODO what if we prune a section856 .number_of_sections = @intCast(u16, self.sections.slice().len), // TODO what if we prune a section
...@@ -774,6 +878,13 @@ fn writeHeader(self: *Coff) !void {...@@ -774,6 +878,13 @@ fn writeHeader(self: *Coff) !void {
774 .Lib => default_image_base_dll,878 .Lib => default_image_base_dll,
775 else => unreachable,879 else => unreachable,
776 };880 };
881 const text_section = self.sections.get(self.text_section_index.?).header;
882
883 var size_of_initialized_data: u32 = 0;
884 for (self.sections.items(.header)) |header| {
885 if (header.flags.CNT_INITIALIZED_DATA == 0) continue;
886 size_of_initialized_data += header.virtual_size;
887 }
777888
778 switch (self.ptr_width) {889 switch (self.ptr_width) {
779 .p32 => {890 .p32 => {
...@@ -781,11 +892,11 @@ fn writeHeader(self: *Coff) !void {...@@ -781,11 +892,11 @@ fn writeHeader(self: *Coff) !void {
781 .magic = coff.IMAGE_NT_OPTIONAL_HDR32_MAGIC,892 .magic = coff.IMAGE_NT_OPTIONAL_HDR32_MAGIC,
782 .major_linker_version = 0,893 .major_linker_version = 0,
783 .minor_linker_version = 0,894 .minor_linker_version = 0,
784 .size_of_code = 0,895 .size_of_code = text_section.virtual_size,
785 .size_of_initialized_data = 0,896 .size_of_initialized_data = size_of_initialized_data,
786 .size_of_uninitialized_data = 0,897 .size_of_uninitialized_data = 0,
787 .address_of_entry_point = self.entry_addr orelse 0,898 .address_of_entry_point = self.entry_addr orelse 0,
788 .base_of_code = 0,899 .base_of_code = text_section.virtual_address,
789 .base_of_data = 0,900 .base_of_data = 0,
790 .image_base = @intCast(u32, image_base),901 .image_base = @intCast(u32, image_base),
791 .section_alignment = self.page_size,902 .section_alignment = self.page_size,
...@@ -816,11 +927,11 @@ fn writeHeader(self: *Coff) !void {...@@ -816,11 +927,11 @@ fn writeHeader(self: *Coff) !void {
816 .magic = coff.IMAGE_NT_OPTIONAL_HDR64_MAGIC,927 .magic = coff.IMAGE_NT_OPTIONAL_HDR64_MAGIC,
817 .major_linker_version = 0,928 .major_linker_version = 0,
818 .minor_linker_version = 0,929 .minor_linker_version = 0,
819 .size_of_code = 0,930 .size_of_code = text_section.virtual_size,
820 .size_of_initialized_data = 0,931 .size_of_initialized_data = size_of_initialized_data,
821 .size_of_uninitialized_data = 0,932 .size_of_uninitialized_data = 0,
822 .address_of_entry_point = self.entry_addr orelse 0,933 .address_of_entry_point = self.entry_addr orelse 0,
823 .base_of_code = 0,934 .base_of_code = text_section.virtual_address,
824 .image_base = image_base,935 .image_base = image_base,
825 .section_alignment = self.page_size,936 .section_alignment = self.page_size,
826 .file_alignment = default_file_alignment,937 .file_alignment = default_file_alignment,
...@@ -971,6 +1082,7 @@ pub fn getGotAtomForSymbol(self: *Coff, sym_loc: SymbolWithLoc) ?*Atom {...@@ -971,6 +1082,7 @@ pub fn getGotAtomForSymbol(self: *Coff, sym_loc: SymbolWithLoc) ?*Atom {
971fn setSectionName(self: *Coff, header: *coff.SectionHeader, name: []const u8) !void {1082fn setSectionName(self: *Coff, header: *coff.SectionHeader, name: []const u8) !void {
972 if (name.len <= 8) {1083 if (name.len <= 8) {
973 mem.copy(u8, &header.name, name);1084 mem.copy(u8, &header.name, name);
1085 mem.set(u8, header.name[name.len..], 0);
974 return;1086 return;
975 }1087 }
976 const offset = try self.strtab.insert(self.base.allocator, name);1088 const offset = try self.strtab.insert(self.base.allocator, name);
...@@ -981,6 +1093,7 @@ fn setSectionName(self: *Coff, header: *coff.SectionHeader, name: []const u8) !v...@@ -981,6 +1093,7 @@ fn setSectionName(self: *Coff, header: *coff.SectionHeader, name: []const u8) !v
981fn setSymbolName(self: *Coff, symbol: *coff.Symbol, name: []const u8) !void {1093fn setSymbolName(self: *Coff, symbol: *coff.Symbol, name: []const u8) !void {
982 if (name.len <= 8) {1094 if (name.len <= 8) {
983 mem.copy(u8, &symbol.name, name);1095 mem.copy(u8, &symbol.name, name);
1096 mem.set(u8, symbol.name[name.len..], 0);
984 return;1097 return;
985 }1098 }
986 const offset = try self.strtab.insert(self.base.allocator, name);1099 const offset = try self.strtab.insert(self.base.allocator, name);