| ... | @@ -43,7 +43,9 @@ sections: std.MultiArrayList(Section) = .{}, | ... | @@ -43,7 +43,9 @@ sections: std.MultiArrayList(Section) = .{}, |
| 43 | data_directories: [16]coff.ImageDataDirectory, | 43 | data_directories: [16]coff.ImageDataDirectory, |
| 44 | | 44 | |
| 45 | text_section_index: ?u16 = null, | 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 | locals: std.ArrayListUnmanaged(coff.Symbol) = .{}, | 50 | locals: std.ArrayListUnmanaged(coff.Symbol) = .{}, |
| 49 | globals: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{}, | 51 | globals: 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 pointers | 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 | 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 | } |
| 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 | 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 | } |
| 222 | | 315 | |
| 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(); |
| 679 | | 772 | |
| | 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 | } |
| 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 | fn writeSectionHeaders(self: *Coff) !void { | 819 | fn 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 bytes | 837 | 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); |
| 733 | | 840 | |
| 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 | } |
| 745 | | 852 | |
| 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 section | 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,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 | } |
| 777 | | 888 | |
| 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 { |
| 971 | fn setSectionName(self: *Coff, header: *coff.SectionHeader, name: []const u8) !void { | 1082 | fn 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 |
| 981 | fn setSymbolName(self: *Coff, symbol: *coff.Symbol, name: []const u8) !void { | 1093 | fn 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); |