| ... | @@ -32,6 +32,20 @@ const LoadCommand = union(enum) { | ... | @@ -32,6 +32,20 @@ const LoadCommand = union(enum) { |
| 32 | .Dysymtab => |x| x.cmdsize, | 32 | .Dysymtab => |x| x.cmdsize, |
| 33 | }; | 33 | }; |
| 34 | } | 34 | } |
| | 35 | |
| | 36 | pub fn write(self: LoadCommand, file: *fs.File, offset: u64) !void { |
| | 37 | return switch (self) { |
| | 38 | .Segment => |cmd| writeGeneric(cmd, file, offset), |
| | 39 | .LinkeditData => |cmd| writeGeneric(cmd, file, offset), |
| | 40 | .Symtab => |cmd| writeGeneric(cmd, file, offset), |
| | 41 | .Dysymtab => |cmd| writeGeneric(cmd, file, offset), |
| | 42 | }; |
| | 43 | } |
| | 44 | |
| | 45 | fn writeGeneric(cmd: anytype, file: *fs.File, offset: u64) !void { |
| | 46 | const slice = [1]@TypeOf(cmd){cmd}; |
| | 47 | return file.pwriteAll(mem.sliceAsBytes(slice[0..1]), offset); |
| | 48 | } |
| 35 | }; | 49 | }; |
| 36 | | 50 | |
| 37 | base: File, | 51 | base: File, |
| ... | @@ -258,8 +272,7 @@ pub fn flush(self: *MachO, module: *Module) !void { | ... | @@ -258,8 +272,7 @@ pub fn flush(self: *MachO, module: *Module) !void { |
| 258 | | 272 | |
| 259 | var last_cmd_offset: usize = @sizeOf(macho.mach_header_64); | 273 | var last_cmd_offset: usize = @sizeOf(macho.mach_header_64); |
| 260 | for (self.load_commands.items) |cmd| { | 274 | for (self.load_commands.items) |cmd| { |
| 261 | const cmd_to_write = [1]@TypeOf(cmd){cmd}; | 275 | try cmd.write(&self.base.file.?, last_cmd_offset); |
| 262 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(cmd_to_write[0..1]), last_cmd_offset); | | |
| 263 | last_cmd_offset += cmd.cmdsize(); | 276 | last_cmd_offset += cmd.cmdsize(); |
| 264 | } | 277 | } |
| 265 | const off = @sizeOf(macho.mach_header_64) + @sizeOf(macho.segment_command_64); | 278 | const off = @sizeOf(macho.mach_header_64) + @sizeOf(macho.segment_command_64); |
| ... | @@ -346,19 +359,18 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { | ... | @@ -346,19 +359,18 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 346 | .n_desc = 0, | 359 | .n_desc = 0, |
| 347 | .n_value = addr, | 360 | .n_value = addr, |
| 348 | }; | 361 | }; |
| 349 | self.offset_table.items[decl.link.macho.offset_table_index.?] = addr; | | |
| 350 | | 362 | |
| | 363 | // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated. |
| | 364 | const decl_exports = module.decl_exports.get(decl) orelse &[0]*Module.Export{}; |
| | 365 | try self.updateDeclExports(module, decl, decl_exports); |
| 351 | try self.writeSymbol(decl.link.macho.symbol_table_index.?); | 366 | try self.writeSymbol(decl.link.macho.symbol_table_index.?); |
| 352 | | 367 | |
| 353 | const text_section = self.sections.items[self.text_section_index.?]; | 368 | const text_section = self.sections.items[self.text_section_index.?]; |
| 354 | const section_offset = symbol.n_value - text_section.addr; | 369 | const section_offset = symbol.n_value - text_section.addr; |
| 355 | const file_offset = text_section.offset + section_offset; | 370 | const file_offset = text_section.offset + section_offset; |
| 356 | log.debug("file_offset 0x{x}\n", .{file_offset}); | 371 | log.debug("file_offset 0x{x}\n", .{file_offset}); |
| 357 | try self.base.file.?.pwriteAll(code, file_offset); | | |
| 358 | | 372 | |
| 359 | // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated. | 373 | try self.base.file.?.pwriteAll(code, file_offset); |
| 360 | const decl_exports = module.decl_exports.get(decl) orelse &[0]*Module.Export{}; | | |
| 361 | return self.updateDeclExports(module, decl, decl_exports); | | |
| 362 | } | 374 | } |
| 363 | | 375 | |
| 364 | pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.Decl) !void {} | 376 | pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.Decl) !void {} |
| ... | @@ -374,7 +386,7 @@ pub fn updateDeclExports( | ... | @@ -374,7 +386,7 @@ pub fn updateDeclExports( |
| 374 | | 386 | |
| 375 | if (decl.link.macho.symbol_table_index == null) return; | 387 | if (decl.link.macho.symbol_table_index == null) return; |
| 376 | | 388 | |
| 377 | var decl_sym = self.symbol_table.items[decl.link.macho.symbol_table_index.?]; | 389 | const decl_sym = &self.symbol_table.items[decl.link.macho.symbol_table_index.?]; |
| 378 | // TODO implement | 390 | // TODO implement |
| 379 | if (exports.len == 0) return; | 391 | if (exports.len == 0) return; |
| 380 | | 392 | |
| ... | @@ -488,9 +500,8 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, | ... | @@ -488,9 +500,8 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, |
| 488 | const addr = blk: { | 500 | const addr = blk: { |
| 489 | if (self.last_text_block) |last| { | 501 | if (self.last_text_block) |last| { |
| 490 | const last_symbol = self.symbol_table.items[last.symbol_table_index.?]; | 502 | const last_symbol = self.symbol_table.items[last.symbol_table_index.?]; |
| 491 | const ideal_capacity = last.size * alloc_num / alloc_den; | 503 | const end_addr = last_symbol.n_value + last.size; |
| 492 | const ideal_capacity_end_addr = last_symbol.n_value + ideal_capacity; | 504 | const new_start_addr = mem.alignForwardGeneric(u64, end_addr, alignment); |
| 493 | const new_start_addr = mem.alignForwardGeneric(u64, ideal_capacity_end_addr, alignment); | | |
| 494 | block_placement = last; | 505 | block_placement = last; |
| 495 | break :blk new_start_addr; | 506 | break :blk new_start_addr; |
| 496 | } else { | 507 | } else { |
| ... | @@ -504,10 +515,7 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, | ... | @@ -504,10 +515,7 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, |
| 504 | const text_capacity = self.allocatedSize(text_section.offset); | 515 | const text_capacity = self.allocatedSize(text_section.offset); |
| 505 | const needed_size = (addr + new_block_size) - text_section.addr; | 516 | const needed_size = (addr + new_block_size) - text_section.addr; |
| 506 | log.debug("text capacity 0x{x}, needed size 0x{x}\n", .{ text_capacity, needed_size }); | 517 | log.debug("text capacity 0x{x}, needed size 0x{x}\n", .{ text_capacity, needed_size }); |
| 507 | | 518 | assert(needed_size <= text_capacity); // TODO handle growth |
| 508 | if (needed_size > text_capacity) { | | |
| 509 | // TODO handle growth | | |
| 510 | } | | |
| 511 | | 519 | |
| 512 | self.last_text_block = text_block; | 520 | self.last_text_block = text_block; |
| 513 | text_section.size = needed_size; | 521 | text_section.size = needed_size; |
| ... | @@ -659,7 +667,7 @@ fn writeSymbol(self: *MachO, index: usize) !void { | ... | @@ -659,7 +667,7 @@ fn writeSymbol(self: *MachO, index: usize) !void { |
| 659 | defer tracy.end(); | 667 | defer tracy.end(); |
| 660 | | 668 | |
| 661 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; | 669 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; |
| 662 | var sym = [1]macho.nlist_64{self.symbol_table.items[index]}; | 670 | const sym = [1]macho.nlist_64{self.symbol_table.items[index]}; |
| 663 | const off = symtab.symoff + @sizeOf(macho.nlist_64) * index; | 671 | const off = symtab.symoff + @sizeOf(macho.nlist_64) * index; |
| 664 | log.debug("writing symbol {} at 0x{x}\n", .{ sym[0], off }); | 672 | log.debug("writing symbol {} at 0x{x}\n", .{ sym[0], off }); |
| 665 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off); | 673 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off); |