| ... | ... | @@ -43,7 +43,9 @@ sections: std.MultiArrayList(Section) = .{}, |
| 43 | 43 | data_directories: [16]coff.ImageDataDirectory, |
| 44 | 44 | |
| 45 | 45 | text_section_index: ?u16 = null, |
| 46 | | got_section_index: ?u16 = null, |
| 46 | rdata_section_index: ?u16 = null, |
| 47 | pdata_section_index: ?u16 = null, |
| 48 | data_section_index: ?u16 = null, |
| 47 | 49 | |
| 48 | 50 | locals: std.ArrayListUnmanaged(coff.Symbol) = .{}, |
| 49 | 51 | globals: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{}, |
| ... | ... | @@ -212,12 +214,103 @@ fn populateMissingMetadata(self: *Coff) !void { |
| 212 | 214 | const file_size = self.base.options.program_code_size_hint; |
| 213 | 215 | 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 | 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 | } |
| 216 | 236 | |
| 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 | } |
| 218 | 309 | |
| 219 | 310 | if (self.strtab_offset == null) { |
| 220 | 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 | } |
| 222 | 315 | |
| 223 | 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 | 770 | sub_prog_node.activate(); |
| 678 | 771 | defer sub_prog_node.end(); |
| 679 | 772 | |
| 773 | try self.writeStrtab(); |
| 680 | 774 | try self.writeDataDirectoriesHeaders(); |
| 681 | 775 | try self.writeSectionHeaders(); |
| 682 | 776 | try self.writeHeader(); |
| ... | ... | @@ -709,6 +803,19 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !v |
| 709 | 803 | log.debug("TODO implement updateDeclLineNumber", .{}); |
| 710 | 804 | } |
| 711 | 805 | |
| 806 | fn 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 | |
| 712 | 819 | fn writeSectionHeaders(self: *Coff) !void { |
| 713 | 820 | const offset = self.getSectionHeadersOffset(); |
| 714 | 821 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.sections.items(.header)), offset); |
| ... | ... | @@ -729,7 +836,7 @@ fn writeHeader(self: *Coff) !void { |
| 729 | 836 | writer.writeAll(msdos_stub) catch unreachable; |
| 730 | 837 | writer.writeByteNTimes(0, 4) catch unreachable; // align to 8 bytes |
| 731 | 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); |
| 733 | 840 | |
| 734 | 841 | var flags = coff.CoffHeaderFlags{ |
| 735 | 842 | .EXECUTABLE_IMAGE = 1, |
| ... | ... | @@ -743,10 +850,7 @@ fn writeHeader(self: *Coff) !void { |
| 743 | 850 | flags.DLL = 1; |
| 744 | 851 | } |
| 745 | 852 | |
| 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()); |
| 750 | 854 | var coff_header = coff.CoffHeader{ |
| 751 | 855 | .machine = coff.MachineType.fromTargetCpuArch(self.base.options.target.cpu.arch), |
| 752 | 856 | .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 | 878 | .Lib => default_image_base_dll, |
| 775 | 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 | } |
| 777 | 888 | |
| 778 | 889 | switch (self.ptr_width) { |
| 779 | 890 | .p32 => { |
| ... | ... | @@ -781,11 +892,11 @@ fn writeHeader(self: *Coff) !void { |
| 781 | 892 | .magic = coff.IMAGE_NT_OPTIONAL_HDR32_MAGIC, |
| 782 | 893 | .major_linker_version = 0, |
| 783 | 894 | .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, |
| 786 | 897 | .size_of_uninitialized_data = 0, |
| 787 | 898 | .address_of_entry_point = self.entry_addr orelse 0, |
| 788 | | .base_of_code = 0, |
| 899 | .base_of_code = text_section.virtual_address, |
| 789 | 900 | .base_of_data = 0, |
| 790 | 901 | .image_base = @intCast(u32, image_base), |
| 791 | 902 | .section_alignment = self.page_size, |
| ... | ... | @@ -816,11 +927,11 @@ fn writeHeader(self: *Coff) !void { |
| 816 | 927 | .magic = coff.IMAGE_NT_OPTIONAL_HDR64_MAGIC, |
| 817 | 928 | .major_linker_version = 0, |
| 818 | 929 | .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, |
| 821 | 932 | .size_of_uninitialized_data = 0, |
| 822 | 933 | .address_of_entry_point = self.entry_addr orelse 0, |
| 823 | | .base_of_code = 0, |
| 934 | .base_of_code = text_section.virtual_address, |
| 824 | 935 | .image_base = image_base, |
| 825 | 936 | .section_alignment = self.page_size, |
| 826 | 937 | .file_alignment = default_file_alignment, |
| ... | ... | @@ -971,6 +1082,7 @@ pub fn getGotAtomForSymbol(self: *Coff, sym_loc: SymbolWithLoc) ?*Atom { |
| 971 | 1082 | fn setSectionName(self: *Coff, header: *coff.SectionHeader, name: []const u8) !void { |
| 972 | 1083 | if (name.len <= 8) { |
| 973 | 1084 | mem.copy(u8, &header.name, name); |
| 1085 | mem.set(u8, header.name[name.len..], 0); |
| 974 | 1086 | return; |
| 975 | 1087 | } |
| 976 | 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 | 1093 | fn setSymbolName(self: *Coff, symbol: *coff.Symbol, name: []const u8) !void { |
| 982 | 1094 | if (name.len <= 8) { |
| 983 | 1095 | mem.copy(u8, &symbol.name, name); |
| 1096 | mem.set(u8, symbol.name[name.len..], 0); |
| 984 | 1097 | return; |
| 985 | 1098 | } |
| 986 | 1099 | const offset = try self.strtab.insert(self.base.allocator, name); |