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) = .{},
4343data_directories: [16]coff.ImageDataDirectory,
4444
4545text_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
4850locals: std.ArrayListUnmanaged(coff.Symbol) = .{},
4951globals: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{},
......@@ -212,12 +214,103 @@ fn populateMissingMetadata(self: *Coff) !void {
212214 const file_size = self.base.options.program_code_size_hint;
213215 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
214216 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 });
215235 }
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
219310 if (self.strtab_offset == null) {
220311 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() });
221314 }
222315
223316 // Index 0 is always a null symbol.
......@@ -677,6 +770,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
677770 sub_prog_node.activate();
678771 defer sub_prog_node.end();
679772
773 try self.writeStrtab();
680774 try self.writeDataDirectoriesHeaders();
681775 try self.writeSectionHeaders();
682776 try self.writeHeader();
......@@ -709,6 +803,19 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !v
709803 log.debug("TODO implement updateDeclLineNumber", .{});
710804}
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
712819fn writeSectionHeaders(self: *Coff) !void {
713820 const offset = self.getSectionHeadersOffset();
714821 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.sections.items(.header)), offset);
......@@ -729,7 +836,7 @@ fn writeHeader(self: *Coff) !void {
729836 writer.writeAll(msdos_stub) catch unreachable;
730837 writer.writeByteNTimes(0, 4) catch unreachable; // align to 8 bytes
731838 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
734841 var flags = coff.CoffHeaderFlags{
735842 .EXECUTABLE_IMAGE = 1,
......@@ -743,10 +850,7 @@ fn writeHeader(self: *Coff) !void {
743850 flags.DLL = 1;
744851 }
745852
746 const size_of_optional_header = @intCast(
747 u16,
748 self.getOptionalHeaderSize() + self.getDataDirectoryHeadersSize() + self.getSectionHeadersSize(),
749 );
853 const size_of_optional_header = @intCast(u16, self.getOptionalHeaderSize() + self.getDataDirectoryHeadersSize());
750854 var coff_header = coff.CoffHeader{
751855 .machine = coff.MachineType.fromTargetCpuArch(self.base.options.target.cpu.arch),
752856 .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 {
774878 .Lib => default_image_base_dll,
775879 else => unreachable,
776880 };
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
778889 switch (self.ptr_width) {
779890 .p32 => {
......@@ -781,11 +892,11 @@ fn writeHeader(self: *Coff) !void {
781892 .magic = coff.IMAGE_NT_OPTIONAL_HDR32_MAGIC,
782893 .major_linker_version = 0,
783894 .minor_linker_version = 0,
784 .size_of_code = 0,
785 .size_of_initialized_data = 0,
895 .size_of_code = text_section.virtual_size,
896 .size_of_initialized_data = size_of_initialized_data,
786897 .size_of_uninitialized_data = 0,
787898 .address_of_entry_point = self.entry_addr orelse 0,
788 .base_of_code = 0,
899 .base_of_code = text_section.virtual_address,
789900 .base_of_data = 0,
790901 .image_base = @intCast(u32, image_base),
791902 .section_alignment = self.page_size,
......@@ -816,11 +927,11 @@ fn writeHeader(self: *Coff) !void {
816927 .magic = coff.IMAGE_NT_OPTIONAL_HDR64_MAGIC,
817928 .major_linker_version = 0,
818929 .minor_linker_version = 0,
819 .size_of_code = 0,
820 .size_of_initialized_data = 0,
930 .size_of_code = text_section.virtual_size,
931 .size_of_initialized_data = size_of_initialized_data,
821932 .size_of_uninitialized_data = 0,
822933 .address_of_entry_point = self.entry_addr orelse 0,
823 .base_of_code = 0,
934 .base_of_code = text_section.virtual_address,
824935 .image_base = image_base,
825936 .section_alignment = self.page_size,
826937 .file_alignment = default_file_alignment,
......@@ -971,6 +1082,7 @@ pub fn getGotAtomForSymbol(self: *Coff, sym_loc: SymbolWithLoc) ?*Atom {
9711082fn setSectionName(self: *Coff, header: *coff.SectionHeader, name: []const u8) !void {
9721083 if (name.len <= 8) {
9731084 mem.copy(u8, &header.name, name);
1085 mem.set(u8, header.name[name.len..], 0);
9741086 return;
9751087 }
9761088 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
9811093fn setSymbolName(self: *Coff, symbol: *coff.Symbol, name: []const u8) !void {
9821094 if (name.len <= 8) {
9831095 mem.copy(u8, &symbol.name, name);
1096 mem.set(u8, symbol.name[name.len..], 0);
9841097 return;
9851098 }
9861099 const offset = try self.strtab.insert(self.base.allocator, name);