| ... | @@ -332,7 +332,7 @@ fn mapAndUpdateSections( | ... | @@ -332,7 +332,7 @@ fn mapAndUpdateSections( |
| 332 | const target_seg = &self.load_commands.items[target_seg_id].Segment; | 332 | const target_seg = &self.load_commands.items[target_seg_id].Segment; |
| 333 | const target_sect = &target_seg.sections.items[target_sect_id]; | 333 | const target_sect = &target_seg.sections.items[target_sect_id]; |
| 334 | | 334 | |
| 335 | const alignment = try math.powi(u32, 2, source_sect.@"align"); | 335 | const alignment = try math.powi(u32, 2, target_sect.@"align"); |
| 336 | const offset = mem.alignForwardGeneric(u64, target_sect.size, alignment); | 336 | const offset = mem.alignForwardGeneric(u64, target_sect.size, alignment); |
| 337 | const size = mem.alignForwardGeneric(u64, source_sect.size, alignment); | 337 | const size = mem.alignForwardGeneric(u64, source_sect.size, alignment); |
| 338 | const key = MappingKey{ | 338 | const key = MappingKey{ |
| ... | @@ -345,7 +345,7 @@ fn mapAndUpdateSections( | ... | @@ -345,7 +345,7 @@ fn mapAndUpdateSections( |
| 345 | .target_sect_id = target_sect_id, | 345 | .target_sect_id = target_sect_id, |
| 346 | .offset = @intCast(u32, offset), | 346 | .offset = @intCast(u32, offset), |
| 347 | }); | 347 | }); |
| 348 | log.debug("{s}: {s},{s} mapped to {s},{s} from 0x{x} to 0x{x}", .{ | 348 | log.warn("{s}: {s},{s} mapped to {s},{s} from 0x{x} to 0x{x}", .{ |
| 349 | object.name, | 349 | object.name, |
| 350 | parseName(&source_sect.segname), | 350 | parseName(&source_sect.segname), |
| 351 | parseName(&source_sect.sectname), | 351 | parseName(&source_sect.sectname), |
| ... | @@ -355,7 +355,6 @@ fn mapAndUpdateSections( | ... | @@ -355,7 +355,6 @@ fn mapAndUpdateSections( |
| 355 | offset + size, | 355 | offset + size, |
| 356 | }); | 356 | }); |
| 357 | | 357 | |
| 358 | target_sect.@"align" = math.max(target_sect.@"align", source_sect.@"align"); | | |
| 359 | target_sect.size = offset + size; | 358 | target_sect.size = offset + size; |
| 360 | } | 359 | } |
| 361 | | 360 | |
| ... | @@ -514,120 +513,117 @@ fn updateMetadata(self: *Zld, object_id: u16) !void { | ... | @@ -514,120 +513,117 @@ fn updateMetadata(self: *Zld, object_id: u16) !void { |
| 514 | }); | 513 | }); |
| 515 | }, | 514 | }, |
| 516 | else => { | 515 | else => { |
| 517 | log.debug("unhandled section type 0x{x} for '{s}/{s}'", .{ flags, segname, sectname }); | 516 | log.warn("unhandled section type 0x{x} for '{s}/{s}'", .{ flags, segname, sectname }); |
| 518 | }, | 517 | }, |
| 519 | } | 518 | } |
| 520 | } | 519 | } |
| 521 | | 520 | |
| 522 | // Update section mappings | 521 | // Find ideal section alignment. |
| 523 | // __TEXT,__text has to be always defined! | 522 | for (object_seg.sections.items) |source_sect, id| { |
| 524 | try self.mapAndUpdateSections( | 523 | if (self.getMatchingSection(source_sect)) |res| { |
| 525 | object_id, | 524 | const target_seg = &self.load_commands.items[res.seg].Segment; |
| 526 | object.text_section_index.?, | 525 | const target_sect = &target_seg.sections.items[res.sect]; |
| 527 | self.text_segment_cmd_index.?, | 526 | target_sect.@"align" = math.max(target_sect.@"align", source_sect.@"align"); |
| 528 | self.text_section_index.?, | 527 | } |
| 529 | ); | 528 | } |
| 530 | | 529 | |
| | 530 | // Update section mappings |
| 531 | for (object_seg.sections.items) |source_sect, id| { | 531 | for (object_seg.sections.items) |source_sect, id| { |
| 532 | const source_sect_id = @intCast(u16, id); | 532 | const source_sect_id = @intCast(u16, id); |
| 533 | if (id == object.text_section_index.?) continue; | 533 | if (self.getMatchingSection(source_sect)) |res| { |
| | 534 | try self.mapAndUpdateSections(object_id, source_sect_id, res.seg, res.sect); |
| | 535 | continue; |
| | 536 | } |
| 534 | | 537 | |
| 535 | const segname = parseName(&source_sect.segname); | 538 | const segname = parseName(&source_sect.segname); |
| 536 | const sectname = parseName(&source_sect.sectname); | 539 | const sectname = parseName(&source_sect.sectname); |
| 537 | const flags = source_sect.flags; | 540 | log.warn("section '{s}/{s}' will be unmapped", .{ segname, sectname }); |
| | 541 | try self.unhandled_sections.putNoClobber(self.allocator, .{ |
| | 542 | .object_id = object_id, |
| | 543 | .source_sect_id = source_sect_id, |
| | 544 | }, 0); |
| | 545 | } |
| | 546 | } |
| 538 | | 547 | |
| 539 | switch (flags) { | 548 | const MatchingSection = struct { |
| | 549 | seg: u16, |
| | 550 | sect: u16, |
| | 551 | }; |
| | 552 | |
| | 553 | fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection { |
| | 554 | const segname = parseName(&section.segname); |
| | 555 | const sectname = parseName(&section.sectname); |
| | 556 | const res: ?MatchingSection = blk: { |
| | 557 | switch (section.flags) { |
| 540 | macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => { | 558 | macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => { |
| 541 | try self.mapAndUpdateSections( | 559 | break :blk .{ |
| 542 | object_id, | 560 | .seg = self.text_segment_cmd_index.?, |
| 543 | source_sect_id, | 561 | .sect = self.text_const_section_index.?, |
| 544 | self.text_segment_cmd_index.?, | 562 | }; |
| 545 | self.text_const_section_index.?, | | |
| 546 | ); | | |
| 547 | }, | 563 | }, |
| 548 | macho.S_CSTRING_LITERALS => { | 564 | macho.S_CSTRING_LITERALS => { |
| 549 | try self.mapAndUpdateSections( | 565 | break :blk .{ |
| 550 | object_id, | 566 | .seg = self.text_segment_cmd_index.?, |
| 551 | source_sect_id, | 567 | .sect = self.cstring_section_index.?, |
| 552 | self.text_segment_cmd_index.?, | 568 | }; |
| 553 | self.cstring_section_index.?, | | |
| 554 | ); | | |
| 555 | }, | 569 | }, |
| 556 | macho.S_ZEROFILL => { | 570 | macho.S_ZEROFILL => { |
| 557 | try self.mapAndUpdateSections( | 571 | break :blk .{ |
| 558 | object_id, | 572 | .seg = self.data_segment_cmd_index.?, |
| 559 | source_sect_id, | 573 | .sect = self.bss_section_index.?, |
| 560 | self.data_segment_cmd_index.?, | 574 | }; |
| 561 | self.bss_section_index.?, | | |
| 562 | ); | | |
| 563 | }, | 575 | }, |
| 564 | macho.S_THREAD_LOCAL_VARIABLES => { | 576 | macho.S_THREAD_LOCAL_VARIABLES => { |
| 565 | try self.mapAndUpdateSections( | 577 | break :blk .{ |
| 566 | object_id, | 578 | .seg = self.data_segment_cmd_index.?, |
| 567 | source_sect_id, | 579 | .sect = self.tlv_section_index.?, |
| 568 | self.data_segment_cmd_index.?, | 580 | }; |
| 569 | self.tlv_section_index.?, | | |
| 570 | ); | | |
| 571 | }, | 581 | }, |
| 572 | macho.S_THREAD_LOCAL_REGULAR => { | 582 | macho.S_THREAD_LOCAL_REGULAR => { |
| 573 | try self.mapAndUpdateSections( | 583 | break :blk .{ |
| 574 | object_id, | 584 | .seg = self.data_segment_cmd_index.?, |
| 575 | source_sect_id, | 585 | .sect = self.tlv_data_section_index.?, |
| 576 | self.data_segment_cmd_index.?, | 586 | }; |
| 577 | self.tlv_data_section_index.?, | | |
| 578 | ); | | |
| 579 | }, | 587 | }, |
| 580 | macho.S_THREAD_LOCAL_ZEROFILL => { | 588 | macho.S_THREAD_LOCAL_ZEROFILL => { |
| 581 | try self.mapAndUpdateSections( | 589 | break :blk .{ |
| 582 | object_id, | 590 | .seg = self.data_segment_cmd_index.?, |
| 583 | source_sect_id, | 591 | .sect = self.tlv_bss_section_index.?, |
| 584 | self.data_segment_cmd_index.?, | 592 | }; |
| 585 | self.tlv_bss_section_index.?, | 593 | }, |
| 586 | ); | 594 | macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS => { |
| | 595 | break :blk .{ |
| | 596 | .seg = self.text_segment_cmd_index.?, |
| | 597 | .sect = self.text_section_index.?, |
| | 598 | }; |
| 587 | }, | 599 | }, |
| 588 | macho.S_REGULAR => { | 600 | macho.S_REGULAR => { |
| 589 | if (mem.eql(u8, segname, "__TEXT")) { | 601 | if (mem.eql(u8, segname, "__TEXT")) { |
| 590 | try self.mapAndUpdateSections( | 602 | break :blk .{ |
| 591 | object_id, | 603 | .seg = self.text_segment_cmd_index.?, |
| 592 | source_sect_id, | 604 | .sect = self.text_const_section_index.?, |
| 593 | self.text_segment_cmd_index.?, | 605 | }; |
| 594 | self.text_const_section_index.?, | | |
| 595 | ); | | |
| 596 | continue; | | |
| 597 | } else if (mem.eql(u8, segname, "__DATA")) { | 606 | } else if (mem.eql(u8, segname, "__DATA")) { |
| 598 | if (mem.eql(u8, sectname, "__data")) { | 607 | if (mem.eql(u8, sectname, "__data")) { |
| 599 | try self.mapAndUpdateSections( | 608 | break :blk .{ |
| 600 | object_id, | 609 | .seg = self.data_segment_cmd_index.?, |
| 601 | source_sect_id, | 610 | .sect = self.data_section_index.?, |
| 602 | self.data_segment_cmd_index.?, | 611 | }; |
| 603 | self.data_section_index.?, | | |
| 604 | ); | | |
| 605 | continue; | | |
| 606 | } else if (mem.eql(u8, sectname, "__const")) { | 612 | } else if (mem.eql(u8, sectname, "__const")) { |
| 607 | try self.mapAndUpdateSections( | 613 | break :blk .{ |
| 608 | object_id, | 614 | .seg = self.data_segment_cmd_index.?, |
| 609 | source_sect_id, | 615 | .sect = self.data_const_section_index.?, |
| 610 | self.data_segment_cmd_index.?, | 616 | }; |
| 611 | self.data_const_section_index.?, | | |
| 612 | ); | | |
| 613 | continue; | | |
| 614 | } | 617 | } |
| 615 | } | 618 | } |
| 616 | log.debug("section '{s}/{s}' will be unmapped", .{ segname, sectname }); | 619 | break :blk null; |
| 617 | try self.unhandled_sections.putNoClobber(self.allocator, .{ | | |
| 618 | .object_id = object_id, | | |
| 619 | .source_sect_id = source_sect_id, | | |
| 620 | }, 0); | | |
| 621 | }, | 620 | }, |
| 622 | else => { | 621 | else => { |
| 623 | log.debug("section '{s}/{s}' will be unmapped", .{ segname, sectname }); | 622 | break :blk null; |
| 624 | try self.unhandled_sections.putNoClobber(self.allocator, .{ | | |
| 625 | .object_id = object_id, | | |
| 626 | .source_sect_id = source_sect_id, | | |
| 627 | }, 0); | | |
| 628 | }, | 623 | }, |
| 629 | } | 624 | } |
| 630 | } | 625 | }; |
| | 626 | return res; |
| 631 | } | 627 | } |
| 632 | | 628 | |
| 633 | fn sortSections(self: *Zld) !void { | 629 | fn sortSections(self: *Zld) !void { |
| ... | @@ -784,7 +780,7 @@ fn resolveImports(self: *Zld) !void { | ... | @@ -784,7 +780,7 @@ fn resolveImports(self: *Zld) !void { |
| 784 | mem.eql(u8, sym_name, "___stack_chk_guard") or | 780 | mem.eql(u8, sym_name, "___stack_chk_guard") or |
| 785 | mem.eql(u8, sym_name, "_environ")) | 781 | mem.eql(u8, sym_name, "_environ")) |
| 786 | { | 782 | { |
| 787 | log.debug("writing nonlazy symbol '{s}'", .{sym_name}); | 783 | log.warn("writing nonlazy symbol '{s}'", .{sym_name}); |
| 788 | const index = @intCast(u32, self.nonlazy_imports.items().len); | 784 | const index = @intCast(u32, self.nonlazy_imports.items().len); |
| 789 | try self.nonlazy_imports.putNoClobber(self.allocator, key, .{ | 785 | try self.nonlazy_imports.putNoClobber(self.allocator, key, .{ |
| 790 | .symbol = new_sym, | 786 | .symbol = new_sym, |
| ... | @@ -792,7 +788,7 @@ fn resolveImports(self: *Zld) !void { | ... | @@ -792,7 +788,7 @@ fn resolveImports(self: *Zld) !void { |
| 792 | .index = index, | 788 | .index = index, |
| 793 | }); | 789 | }); |
| 794 | } else if (mem.eql(u8, sym_name, "__tlv_bootstrap")) { | 790 | } else if (mem.eql(u8, sym_name, "__tlv_bootstrap")) { |
| 795 | log.debug("writing threadlocal symbol '{s}'", .{sym_name}); | 791 | log.warn("writing threadlocal symbol '{s}'", .{sym_name}); |
| 796 | const index = @intCast(u32, self.threadlocal_imports.items().len); | 792 | const index = @intCast(u32, self.threadlocal_imports.items().len); |
| 797 | try self.threadlocal_imports.putNoClobber(self.allocator, key, .{ | 793 | try self.threadlocal_imports.putNoClobber(self.allocator, key, .{ |
| 798 | .symbol = new_sym, | 794 | .symbol = new_sym, |
| ... | @@ -800,7 +796,7 @@ fn resolveImports(self: *Zld) !void { | ... | @@ -800,7 +796,7 @@ fn resolveImports(self: *Zld) !void { |
| 800 | .index = index, | 796 | .index = index, |
| 801 | }); | 797 | }); |
| 802 | } else { | 798 | } else { |
| 803 | log.debug("writing lazy symbol '{s}'", .{sym_name}); | 799 | log.warn("writing lazy symbol '{s}'", .{sym_name}); |
| 804 | const index = @intCast(u32, self.lazy_imports.items().len); | 800 | const index = @intCast(u32, self.lazy_imports.items().len); |
| 805 | try self.lazy_imports.putNoClobber(self.allocator, key, .{ | 801 | try self.lazy_imports.putNoClobber(self.allocator, key, .{ |
| 806 | .symbol = new_sym, | 802 | .symbol = new_sym, |
| ... | @@ -812,7 +808,7 @@ fn resolveImports(self: *Zld) !void { | ... | @@ -812,7 +808,7 @@ fn resolveImports(self: *Zld) !void { |
| 812 | | 808 | |
| 813 | const n_strx = try self.makeString("dyld_stub_binder"); | 809 | const n_strx = try self.makeString("dyld_stub_binder"); |
| 814 | const name = try self.allocator.dupe(u8, "dyld_stub_binder"); | 810 | const name = try self.allocator.dupe(u8, "dyld_stub_binder"); |
| 815 | log.debug("writing nonlazy symbol 'dyld_stub_binder'", .{}); | 811 | log.warn("writing nonlazy symbol 'dyld_stub_binder'", .{}); |
| 816 | const index = @intCast(u32, self.nonlazy_imports.items().len); | 812 | const index = @intCast(u32, self.nonlazy_imports.items().len); |
| 817 | try self.nonlazy_imports.putNoClobber(self.allocator, name, .{ | 813 | try self.nonlazy_imports.putNoClobber(self.allocator, name, .{ |
| 818 | .symbol = .{ | 814 | .symbol = .{ |
| ... | @@ -1016,7 +1012,7 @@ fn writeStubHelperCommon(self: *Zld) !void { | ... | @@ -1016,7 +1012,7 @@ fn writeStubHelperCommon(self: *Zld) !void { |
| 1016 | const new_this_addr = this_addr + @sizeOf(u32); | 1012 | const new_this_addr = this_addr + @sizeOf(u32); |
| 1017 | const displacement = math.divExact(u64, target_addr - new_this_addr, 4) catch |_| break :binder_blk; | 1013 | const displacement = math.divExact(u64, target_addr - new_this_addr, 4) catch |_| break :binder_blk; |
| 1018 | const literal = math.cast(u18, displacement) catch |_| break :binder_blk; | 1014 | const literal = math.cast(u18, displacement) catch |_| break :binder_blk; |
| 1019 | log.debug("2: disp=0x{x}, literal=0x{x}", .{ displacement, literal }); | 1015 | log.warn("2: disp=0x{x}, literal=0x{x}", .{ displacement, literal }); |
| 1020 | // Pad with nop to please division. | 1016 | // Pad with nop to please division. |
| 1021 | // nop | 1017 | // nop |
| 1022 | mem.writeIntLittle(u32, code[12..16], Arm64.nop().toU32()); | 1018 | mem.writeIntLittle(u32, code[12..16], Arm64.nop().toU32()); |
| ... | @@ -1069,7 +1065,7 @@ fn writeLazySymbolPointer(self: *Zld, index: u32) !void { | ... | @@ -1069,7 +1065,7 @@ fn writeLazySymbolPointer(self: *Zld, index: u32) !void { |
| 1069 | var buf: [@sizeOf(u64)]u8 = undefined; | 1065 | var buf: [@sizeOf(u64)]u8 = undefined; |
| 1070 | mem.writeIntLittle(u64, &buf, end); | 1066 | mem.writeIntLittle(u64, &buf, end); |
| 1071 | const off = la_symbol_ptr.offset + index * @sizeOf(u64); | 1067 | const off = la_symbol_ptr.offset + index * @sizeOf(u64); |
| 1072 | log.debug("writing lazy symbol pointer entry 0x{x} at 0x{x}", .{ end, off }); | 1068 | log.warn("writing lazy symbol pointer entry 0x{x} at 0x{x}", .{ end, off }); |
| 1073 | try self.file.?.pwriteAll(&buf, off); | 1069 | try self.file.?.pwriteAll(&buf, off); |
| 1074 | } | 1070 | } |
| 1075 | | 1071 | |
| ... | @@ -1082,7 +1078,7 @@ fn writeStub(self: *Zld, index: u32) !void { | ... | @@ -1082,7 +1078,7 @@ fn writeStub(self: *Zld, index: u32) !void { |
| 1082 | const stub_off = stubs.offset + index * stubs.reserved2; | 1078 | const stub_off = stubs.offset + index * stubs.reserved2; |
| 1083 | const stub_addr = stubs.addr + index * stubs.reserved2; | 1079 | const stub_addr = stubs.addr + index * stubs.reserved2; |
| 1084 | const la_ptr_addr = la_symbol_ptr.addr + index * @sizeOf(u64); | 1080 | const la_ptr_addr = la_symbol_ptr.addr + index * @sizeOf(u64); |
| 1085 | log.debug("writing stub at 0x{x}", .{stub_off}); | 1081 | log.warn("writing stub at 0x{x}", .{stub_off}); |
| 1086 | var code = try self.allocator.alloc(u8, stubs.reserved2); | 1082 | var code = try self.allocator.alloc(u8, stubs.reserved2); |
| 1087 | defer self.allocator.free(code); | 1083 | defer self.allocator.free(code); |
| 1088 | switch (self.arch.?) { | 1084 | switch (self.arch.?) { |
| ... | @@ -1229,7 +1225,7 @@ fn resolveSymbols(self: *Zld) !void { | ... | @@ -1229,7 +1225,7 @@ fn resolveSymbols(self: *Zld) !void { |
| 1229 | const target_addr = target_sect.addr + target_mapping.offset; | 1225 | const target_addr = target_sect.addr + target_mapping.offset; |
| 1230 | const n_value = sym.n_value - source_sect.addr + target_addr; | 1226 | const n_value = sym.n_value - source_sect.addr + target_addr; |
| 1231 | | 1227 | |
| 1232 | log.debug("resolving '{s}':{} as {s} symbol at 0x{x}", .{ sym_name, sym, tt, n_value }); | 1228 | log.warn("resolving '{s}':{} as {s} symbol at 0x{x}", .{ sym_name, sym, tt, n_value }); |
| 1233 | | 1229 | |
| 1234 | // TODO this assumes only two symbol-filled segments. Also, there might be a more | 1230 | // TODO this assumes only two symbol-filled segments. Also, there might be a more |
| 1235 | // generic way of doing this. | 1231 | // generic way of doing this. |
| ... | @@ -1259,8 +1255,8 @@ fn resolveSymbols(self: *Zld) !void { | ... | @@ -1259,8 +1255,8 @@ fn resolveSymbols(self: *Zld) !void { |
| 1259 | | 1255 | |
| 1260 | fn doRelocs(self: *Zld) !void { | 1256 | fn doRelocs(self: *Zld) !void { |
| 1261 | for (self.objects.items) |object, object_id| { | 1257 | for (self.objects.items) |object, object_id| { |
| 1262 | log.debug("\n\n", .{}); | 1258 | log.warn("\n\n", .{}); |
| 1263 | log.debug("relocating object {s}", .{object.name}); | 1259 | log.warn("relocating object {s}", .{object.name}); |
| 1264 | | 1260 | |
| 1265 | const seg = object.load_commands.items[object.segment_cmd_index.?].Segment; | 1261 | const seg = object.load_commands.items[object.segment_cmd_index.?].Segment; |
| 1266 | | 1262 | |
| ... | @@ -1283,7 +1279,7 @@ fn doRelocs(self: *Zld) !void { | ... | @@ -1283,7 +1279,7 @@ fn doRelocs(self: *Zld) !void { |
| 1283 | .object_id = @intCast(u16, object_id), | 1279 | .object_id = @intCast(u16, object_id), |
| 1284 | .source_sect_id = @intCast(u16, source_sect_id), | 1280 | .source_sect_id = @intCast(u16, source_sect_id), |
| 1285 | }) orelse { | 1281 | }) orelse { |
| 1286 | log.debug("no mapping for {s},{s}; skipping", .{ segname, sectname }); | 1282 | log.warn("no mapping for {s},{s}; skipping", .{ segname, sectname }); |
| 1287 | continue; | 1283 | continue; |
| 1288 | }; | 1284 | }; |
| 1289 | const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment; | 1285 | const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment; |
| ... | @@ -1301,34 +1297,34 @@ fn doRelocs(self: *Zld) !void { | ... | @@ -1301,34 +1297,34 @@ fn doRelocs(self: *Zld) !void { |
| 1301 | switch (self.arch.?) { | 1297 | switch (self.arch.?) { |
| 1302 | .aarch64 => { | 1298 | .aarch64 => { |
| 1303 | const rel_type = @intToEnum(macho.reloc_type_arm64, rel.r_type); | 1299 | const rel_type = @intToEnum(macho.reloc_type_arm64, rel.r_type); |
| 1304 | log.debug("{s}", .{rel_type}); | 1300 | log.warn("{s}", .{rel_type}); |
| 1305 | log.debug(" | source address 0x{x}", .{this_addr}); | 1301 | log.warn(" | source address 0x{x}", .{this_addr}); |
| 1306 | log.debug(" | offset 0x{x}", .{off}); | 1302 | log.warn(" | offset 0x{x}", .{off}); |
| 1307 | | 1303 | |
| 1308 | if (rel_type == .ARM64_RELOC_ADDEND) { | 1304 | if (rel_type == .ARM64_RELOC_ADDEND) { |
| 1309 | addend = rel.r_symbolnum; | 1305 | addend = rel.r_symbolnum; |
| 1310 | log.debug(" | calculated addend = 0x{x}", .{addend}); | 1306 | log.warn(" | calculated addend = 0x{x}", .{addend}); |
| 1311 | // TODO followed by either PAGE21 or PAGEOFF12 only. | 1307 | // TODO followed by either PAGE21 or PAGEOFF12 only. |
| 1312 | continue; | 1308 | continue; |
| 1313 | } | 1309 | } |
| 1314 | }, | 1310 | }, |
| 1315 | .x86_64 => { | 1311 | .x86_64 => { |
| 1316 | const rel_type = @intToEnum(macho.reloc_type_x86_64, rel.r_type); | 1312 | const rel_type = @intToEnum(macho.reloc_type_x86_64, rel.r_type); |
| 1317 | log.debug("{s}", .{rel_type}); | 1313 | log.warn("{s}", .{rel_type}); |
| 1318 | log.debug(" | source address 0x{x}", .{this_addr}); | 1314 | log.warn(" | source address 0x{x}", .{this_addr}); |
| 1319 | log.debug(" | offset 0x{x}", .{off}); | 1315 | log.warn(" | offset 0x{x}", .{off}); |
| 1320 | }, | 1316 | }, |
| 1321 | else => {}, | 1317 | else => {}, |
| 1322 | } | 1318 | } |
| 1323 | | 1319 | |
| 1324 | const target_addr = try self.relocTargetAddr(@intCast(u16, object_id), rel); | 1320 | const target_addr = try self.relocTargetAddr(@intCast(u16, object_id), rel); |
| 1325 | log.debug(" | target address 0x{x}", .{target_addr}); | 1321 | log.warn(" | target address 0x{x}", .{target_addr}); |
| 1326 | if (rel.r_extern == 1) { | 1322 | if (rel.r_extern == 1) { |
| 1327 | const target_symname = object.getString(object.symtab.items[rel.r_symbolnum].n_strx); | 1323 | const target_symname = object.getString(object.symtab.items[rel.r_symbolnum].n_strx); |
| 1328 | log.debug(" | target symbol '{s}'", .{target_symname}); | 1324 | log.warn(" | target symbol '{s}'", .{target_symname}); |
| 1329 | } else { | 1325 | } else { |
| 1330 | const target_sectname = seg.sections.items[rel.r_symbolnum - 1].sectname; | 1326 | const target_sectname = seg.sections.items[rel.r_symbolnum - 1].sectname; |
| 1331 | log.debug(" | target section '{s}'", .{parseName(&target_sectname)}); | 1327 | log.warn(" | target section '{s}'", .{parseName(&target_sectname)}); |
| 1332 | } | 1328 | } |
| 1333 | | 1329 | |
| 1334 | switch (self.arch.?) { | 1330 | switch (self.arch.?) { |
| ... | @@ -1361,13 +1357,12 @@ fn doRelocs(self: *Zld) !void { | ... | @@ -1361,13 +1357,12 @@ fn doRelocs(self: *Zld) !void { |
| 1361 | => { | 1357 | => { |
| 1362 | assert(rel.r_length == 2); | 1358 | assert(rel.r_length == 2); |
| 1363 | const inst = code[off..][0..4]; | 1359 | const inst = code[off..][0..4]; |
| 1364 | const offset: i32 = blk: { | 1360 | const offset = @intCast(i64, mem.readIntLittle(i32, inst)); |
| | 1361 | log.warn(" | calculated addend 0x{x}", .{offset}); |
| | 1362 | const actual_target_addr = blk: { |
| 1365 | if (rel.r_extern == 1) { | 1363 | if (rel.r_extern == 1) { |
| 1366 | break :blk mem.readIntLittle(i32, inst); | 1364 | break :blk @intCast(i64, target_addr) + offset; |
| 1367 | } else { | 1365 | } else { |
| 1368 | // TODO it might be required here to parse the offset from the instruction placeholder, | | |
| 1369 | // compare the displacement with the original displacement in the .o file, and adjust | | |
| 1370 | // the displacement in the resultant binary file. | | |
| 1371 | const correction: i4 = switch (rel_type) { | 1366 | const correction: i4 = switch (rel_type) { |
| 1372 | .X86_64_RELOC_SIGNED => 0, | 1367 | .X86_64_RELOC_SIGNED => 0, |
| 1373 | .X86_64_RELOC_SIGNED_1 => 1, | 1368 | .X86_64_RELOC_SIGNED_1 => 1, |
| ... | @@ -1375,11 +1370,28 @@ fn doRelocs(self: *Zld) !void { | ... | @@ -1375,11 +1370,28 @@ fn doRelocs(self: *Zld) !void { |
| 1375 | .X86_64_RELOC_SIGNED_4 => 4, | 1370 | .X86_64_RELOC_SIGNED_4 => 4, |
| 1376 | else => unreachable, | 1371 | else => unreachable, |
| 1377 | }; | 1372 | }; |
| 1378 | break :blk correction; | 1373 | log.warn(" | calculated correction 0x{x}", .{correction}); |
| | 1374 | |
| | 1375 | // The value encoded in the instruction is a displacement - 4 - correction. |
| | 1376 | // To obtain the adjusted target address in the final binary, we need |
| | 1377 | // calculate the original target address within the object file, establish |
| | 1378 | // what the offset from the original target section was, and apply this |
| | 1379 | // offset to the resultant target section with this relocated binary. |
| | 1380 | const orig_sect_id = @intCast(u16, rel.r_symbolnum - 1); |
| | 1381 | const target_map = self.mappings.get(.{ |
| | 1382 | .object_id = @intCast(u16, object_id), |
| | 1383 | .source_sect_id = orig_sect_id, |
| | 1384 | }) orelse unreachable; |
| | 1385 | const orig_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; |
| | 1386 | const orig_sect = orig_seg.sections.items[orig_sect_id]; |
| | 1387 | const orig_offset = off + offset + 4 + correction - @intCast(i64, orig_sect.addr); |
| | 1388 | log.warn(" | original offset 0x{x}", .{orig_offset}); |
| | 1389 | const adjusted = @intCast(i64, target_addr) + orig_offset; |
| | 1390 | log.warn(" | adjusted target address 0x{x}", .{adjusted}); |
| | 1391 | break :blk adjusted - correction; |
| 1379 | } | 1392 | } |
| 1380 | }; | 1393 | }; |
| 1381 | log.debug(" | calculated addend 0x{x}", .{offset}); | 1394 | const result = actual_target_addr - @intCast(i64, this_addr) - 4; |
| 1382 | const result = @intCast(i64, target_addr) - @intCast(i64, this_addr) - 4 + offset; | | |
| 1383 | const displacement = @bitCast(u32, @intCast(i32, result)); | 1395 | const displacement = @bitCast(u32, @intCast(i32, result)); |
| 1384 | mem.writeIntLittle(u32, inst, displacement); | 1396 | mem.writeIntLittle(u32, inst, displacement); |
| 1385 | }, | 1397 | }, |
| ... | @@ -1391,11 +1403,40 @@ fn doRelocs(self: *Zld) !void { | ... | @@ -1391,11 +1403,40 @@ fn doRelocs(self: *Zld) !void { |
| 1391 | 3 => { | 1403 | 3 => { |
| 1392 | const inst = code[off..][0..8]; | 1404 | const inst = code[off..][0..8]; |
| 1393 | const offset = mem.readIntLittle(i64, inst); | 1405 | const offset = mem.readIntLittle(i64, inst); |
| 1394 | log.debug(" | calculated addend 0x{x}", .{offset}); | 1406 | |
| 1395 | const result = if (sub) |s| | 1407 | const result = outer: { |
| 1396 | @intCast(i64, target_addr) - s + offset | 1408 | if (rel.r_extern == 1) { |
| 1397 | else | 1409 | log.warn(" | calculated addend 0x{x}", .{offset}); |
| 1398 | @intCast(i64, target_addr) + offset; | 1410 | if (sub) |s| { |
| | 1411 | break :outer @intCast(i64, target_addr) - s + offset; |
| | 1412 | } else { |
| | 1413 | break :outer @intCast(i64, target_addr) + offset; |
| | 1414 | } |
| | 1415 | } else { |
| | 1416 | // The value encoded in the instruction is an absolute offset |
| | 1417 | // from the start of MachO header to the target address in the |
| | 1418 | // object file. To extract the address, we calculate the offset from |
| | 1419 | // the beginning of the source section to the address, and apply it to |
| | 1420 | // the target address value. |
| | 1421 | const orig_sect_id = @intCast(u16, rel.r_symbolnum - 1); |
| | 1422 | const target_map = self.mappings.get(.{ |
| | 1423 | .object_id = @intCast(u16, object_id), |
| | 1424 | .source_sect_id = orig_sect_id, |
| | 1425 | }) orelse unreachable; |
| | 1426 | const orig_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; |
| | 1427 | const orig_sect = orig_seg.sections.items[orig_sect_id]; |
| | 1428 | const orig_offset = offset - @intCast(i64, orig_sect.addr); |
| | 1429 | const actual_target_addr = inner: { |
| | 1430 | if (sub) |s| { |
| | 1431 | break :inner @intCast(i64, target_addr) - s + orig_offset; |
| | 1432 | } else { |
| | 1433 | break :inner @intCast(i64, target_addr) + orig_offset; |
| | 1434 | } |
| | 1435 | }; |
| | 1436 | log.warn(" | adjusted target address 0x{x}", .{actual_target_addr}); |
| | 1437 | break :outer actual_target_addr; |
| | 1438 | } |
| | 1439 | }; |
| 1399 | mem.writeIntLittle(u64, inst, @bitCast(u64, result)); | 1440 | mem.writeIntLittle(u64, inst, @bitCast(u64, result)); |
| 1400 | sub = null; | 1441 | sub = null; |
| 1401 | | 1442 | |
| ... | @@ -1422,7 +1463,7 @@ fn doRelocs(self: *Zld) !void { | ... | @@ -1422,7 +1463,7 @@ fn doRelocs(self: *Zld) !void { |
| 1422 | 2 => { | 1463 | 2 => { |
| 1423 | const inst = code[off..][0..4]; | 1464 | const inst = code[off..][0..4]; |
| 1424 | const offset = mem.readIntLittle(i32, inst); | 1465 | const offset = mem.readIntLittle(i32, inst); |
| 1425 | log.debug(" | calculated addend 0x{x}", .{offset}); | 1466 | log.warn(" | calculated addend 0x{x}", .{offset}); |
| 1426 | const result = if (sub) |s| | 1467 | const result = if (sub) |s| |
| 1427 | @intCast(i64, target_addr) - s + offset | 1468 | @intCast(i64, target_addr) - s + offset |
| 1428 | else | 1469 | else |
| ... | @@ -1459,7 +1500,7 @@ fn doRelocs(self: *Zld) !void { | ... | @@ -1459,7 +1500,7 @@ fn doRelocs(self: *Zld) !void { |
| 1459 | const this_page = @intCast(i32, this_addr >> 12); | 1500 | const this_page = @intCast(i32, this_addr >> 12); |
| 1460 | const target_page = @intCast(i32, ta >> 12); | 1501 | const target_page = @intCast(i32, ta >> 12); |
| 1461 | const pages = @bitCast(u21, @intCast(i21, target_page - this_page)); | 1502 | const pages = @bitCast(u21, @intCast(i21, target_page - this_page)); |
| 1462 | log.debug(" | moving by {} pages", .{pages}); | 1503 | log.warn(" | moving by {} pages", .{pages}); |
| 1463 | var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Address), inst); | 1504 | var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Address), inst); |
| 1464 | parsed.immhi = @truncate(u19, pages >> 2); | 1505 | parsed.immhi = @truncate(u19, pages >> 2); |
| 1465 | parsed.immlo = @truncate(u2, pages); | 1506 | parsed.immlo = @truncate(u2, pages); |
| ... | @@ -1470,14 +1511,14 @@ fn doRelocs(self: *Zld) !void { | ... | @@ -1470,14 +1511,14 @@ fn doRelocs(self: *Zld) !void { |
| 1470 | => { | 1511 | => { |
| 1471 | const inst = code[off..][0..4]; | 1512 | const inst = code[off..][0..4]; |
| 1472 | if (Arm64.isArithmetic(inst)) { | 1513 | if (Arm64.isArithmetic(inst)) { |
| 1473 | log.debug(" | detected ADD opcode", .{}); | 1514 | log.warn(" | detected ADD opcode", .{}); |
| 1474 | // add | 1515 | // add |
| 1475 | var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Add), inst); | 1516 | var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Add), inst); |
| 1476 | const ta = if (addend) |a| target_addr + a else target_addr; | 1517 | const ta = if (addend) |a| target_addr + a else target_addr; |
| 1477 | const narrowed = @truncate(u12, ta); | 1518 | const narrowed = @truncate(u12, ta); |
| 1478 | parsed.offset = narrowed; | 1519 | parsed.offset = narrowed; |
| 1479 | } else { | 1520 | } else { |
| 1480 | log.debug(" | detected LDR/STR opcode", .{}); | 1521 | log.warn(" | detected LDR/STR opcode", .{}); |
| 1481 | // ldr/str | 1522 | // ldr/str |
| 1482 | var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.LoadRegister), inst); | 1523 | var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.LoadRegister), inst); |
| 1483 | const ta = if (addend) |a| target_addr + a else target_addr; | 1524 | const ta = if (addend) |a| target_addr + a else target_addr; |
| ... | @@ -1518,7 +1559,7 @@ fn doRelocs(self: *Zld) !void { | ... | @@ -1518,7 +1559,7 @@ fn doRelocs(self: *Zld) !void { |
| 1518 | }; | 1559 | }; |
| 1519 | const ta = if (addend) |a| target_addr + a else target_addr; | 1560 | const ta = if (addend) |a| target_addr + a else target_addr; |
| 1520 | const narrowed = @truncate(u12, ta); | 1561 | const narrowed = @truncate(u12, ta); |
| 1521 | log.debug(" | rewriting TLV access to ADD opcode", .{}); | 1562 | log.warn(" | rewriting TLV access to ADD opcode", .{}); |
| 1522 | // For TLV, we always generate an add instruction. | 1563 | // For TLV, we always generate an add instruction. |
| 1523 | mem.writeIntLittle(u32, inst, Arm64.add(parsed.rt, parsed.rn, narrowed, parsed.size).toU32()); | 1564 | mem.writeIntLittle(u32, inst, Arm64.add(parsed.rt, parsed.rn, narrowed, parsed.size).toU32()); |
| 1524 | }, | 1565 | }, |
| ... | @@ -1530,7 +1571,7 @@ fn doRelocs(self: *Zld) !void { | ... | @@ -1530,7 +1571,7 @@ fn doRelocs(self: *Zld) !void { |
| 1530 | 3 => { | 1571 | 3 => { |
| 1531 | const inst = code[off..][0..8]; | 1572 | const inst = code[off..][0..8]; |
| 1532 | const offset = mem.readIntLittle(i64, inst); | 1573 | const offset = mem.readIntLittle(i64, inst); |
| 1533 | log.debug(" | calculated addend 0x{x}", .{offset}); | 1574 | log.warn(" | calculated addend 0x{x}", .{offset}); |
| 1534 | const result = if (sub) |s| | 1575 | const result = if (sub) |s| |
| 1535 | @intCast(i64, target_addr) - s + offset | 1576 | @intCast(i64, target_addr) - s + offset |
| 1536 | else | 1577 | else |
| ... | @@ -1561,7 +1602,7 @@ fn doRelocs(self: *Zld) !void { | ... | @@ -1561,7 +1602,7 @@ fn doRelocs(self: *Zld) !void { |
| 1561 | 2 => { | 1602 | 2 => { |
| 1562 | const inst = code[off..][0..4]; | 1603 | const inst = code[off..][0..4]; |
| 1563 | const offset = mem.readIntLittle(i32, inst); | 1604 | const offset = mem.readIntLittle(i32, inst); |
| 1564 | log.debug(" | calculated addend 0x{x}", .{offset}); | 1605 | log.warn(" | calculated addend 0x{x}", .{offset}); |
| 1565 | const result = if (sub) |s| | 1606 | const result = if (sub) |s| |
| 1566 | @intCast(i64, target_addr) - s + offset | 1607 | @intCast(i64, target_addr) - s + offset |
| 1567 | else | 1608 | else |
| ... | @@ -1583,7 +1624,7 @@ fn doRelocs(self: *Zld) !void { | ... | @@ -1583,7 +1624,7 @@ fn doRelocs(self: *Zld) !void { |
| 1583 | } | 1624 | } |
| 1584 | } | 1625 | } |
| 1585 | | 1626 | |
| 1586 | log.debug("writing contents of '{s},{s}' section from '{s}' from 0x{x} to 0x{x}", .{ | 1627 | log.warn("writing contents of '{s},{s}' section from '{s}' from 0x{x} to 0x{x}", .{ |
| 1587 | segname, | 1628 | segname, |
| 1588 | sectname, | 1629 | sectname, |
| 1589 | object.name, | 1630 | object.name, |
| ... | @@ -1595,7 +1636,7 @@ fn doRelocs(self: *Zld) !void { | ... | @@ -1595,7 +1636,7 @@ fn doRelocs(self: *Zld) !void { |
| 1595 | target_sect.flags == macho.S_THREAD_LOCAL_ZEROFILL or | 1636 | target_sect.flags == macho.S_THREAD_LOCAL_ZEROFILL or |
| 1596 | target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES) | 1637 | target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES) |
| 1597 | { | 1638 | { |
| 1598 | log.debug("zeroing out '{s},{s}' from 0x{x} to 0x{x}", .{ | 1639 | log.warn("zeroing out '{s},{s}' from 0x{x} to 0x{x}", .{ |
| 1599 | parseName(&target_sect.segname), | 1640 | parseName(&target_sect.segname), |
| 1600 | parseName(&target_sect.sectname), | 1641 | parseName(&target_sect.sectname), |
| 1601 | target_sect_off, | 1642 | target_sect_off, |
| ... | @@ -1629,7 +1670,7 @@ fn relocTargetAddr(self: *Zld, object_id: u16, rel: macho.relocation_info) !u64 | ... | @@ -1629,7 +1670,7 @@ fn relocTargetAddr(self: *Zld, object_id: u16, rel: macho.relocation_info) !u64 |
| 1629 | const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment; | 1670 | const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment; |
| 1630 | const target_sect = target_seg.sections.items[target_mapping.target_sect_id]; | 1671 | const target_sect = target_seg.sections.items[target_mapping.target_sect_id]; |
| 1631 | const target_sect_addr = target_sect.addr + target_mapping.offset; | 1672 | const target_sect_addr = target_sect.addr + target_mapping.offset; |
| 1632 | log.debug(" | symbol local to object", .{}); | 1673 | log.warn(" | symbol local to object", .{}); |
| 1633 | break :blk target_sect_addr + sym.n_value - source_sect.addr; | 1674 | break :blk target_sect_addr + sym.n_value - source_sect.addr; |
| 1634 | } else if (isImport(&sym)) { | 1675 | } else if (isImport(&sym)) { |
| 1635 | // Relocate to either the artifact's local symbol, or an import from | 1676 | // Relocate to either the artifact's local symbol, or an import from |
| ... | @@ -2059,6 +2100,18 @@ fn populateMetadata(self: *Zld) !void { | ... | @@ -2059,6 +2100,18 @@ fn populateMetadata(self: *Zld) !void { |
| 2059 | }, | 2100 | }, |
| 2060 | }); | 2101 | }); |
| 2061 | } | 2102 | } |
| | 2103 | |
| | 2104 | if (self.data_in_code_cmd_index == null and self.arch.? == .x86_64) { |
| | 2105 | self.data_in_code_cmd_index = @intCast(u16, self.load_commands.items.len); |
| | 2106 | try self.load_commands.append(self.allocator, .{ |
| | 2107 | .LinkeditData = .{ |
| | 2108 | .cmd = macho.LC_DATA_IN_CODE, |
| | 2109 | .cmdsize = @sizeOf(macho.linkedit_data_command), |
| | 2110 | .dataoff = 0, |
| | 2111 | .datasize = 0, |
| | 2112 | }, |
| | 2113 | }); |
| | 2114 | } |
| 2062 | } | 2115 | } |
| 2063 | | 2116 | |
| 2064 | fn flush(self: *Zld) !void { | 2117 | fn flush(self: *Zld) !void { |
| ... | @@ -2077,6 +2130,9 @@ fn flush(self: *Zld) !void { | ... | @@ -2077,6 +2130,9 @@ fn flush(self: *Zld) !void { |
| 2077 | try self.writeBindInfoTable(); | 2130 | try self.writeBindInfoTable(); |
| 2078 | try self.writeLazyBindInfoTable(); | 2131 | try self.writeLazyBindInfoTable(); |
| 2079 | try self.writeExportInfo(); | 2132 | try self.writeExportInfo(); |
| | 2133 | if (self.arch.? == .x86_64) { |
| | 2134 | try self.writeDataInCode(); |
| | 2135 | } |
| 2080 | | 2136 | |
| 2081 | { | 2137 | { |
| 2082 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | 2138 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| ... | @@ -2169,12 +2225,42 @@ fn writeRebaseInfoTable(self: *Zld) !void { | ... | @@ -2169,12 +2225,42 @@ fn writeRebaseInfoTable(self: *Zld) !void { |
| 2169 | } | 2225 | } |
| 2170 | | 2226 | |
| 2171 | try pointers.ensureCapacity(pointers.items.len + self.local_rebases.items.len); | 2227 | try pointers.ensureCapacity(pointers.items.len + self.local_rebases.items.len); |
| 2172 | | 2228 | pointers.appendSliceAssumeCapacity(self.local_rebases.items); |
| 2173 | const nlocals = self.local_rebases.items.len; | 2229 | |
| 2174 | var i = nlocals; | 2230 | // const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 2175 | while (i > 0) : (i -= 1) { | 2231 | // const base_id = text_seg.sections.items.len; |
| 2176 | pointers.appendAssumeCapacity(self.local_rebases.items[i - 1]); | 2232 | // for (self.locals.items()) |entry| { |
| 2177 | } | 2233 | // for (entry.value.items) |symbol| { |
| | 2234 | // const local = symbol.inner; |
| | 2235 | |
| | 2236 | // if (self.data_const_section_index) |index| { |
| | 2237 | // if (local.n_sect == base_id + index) { |
| | 2238 | // const offset = local.n_value - data_seg.inner.vmaddr; |
| | 2239 | // try pointers.append(.{ |
| | 2240 | // .offset = offset, |
| | 2241 | // .segment_id = @intCast(u16, self.data_segment_cmd_index.?), |
| | 2242 | // }); |
| | 2243 | // } |
| | 2244 | // } |
| | 2245 | // if (self.data_section_index) |index| { |
| | 2246 | // if (local.n_sect == base_id + index) { |
| | 2247 | // const offset = local.n_value - data_seg.inner.vmaddr; |
| | 2248 | // try pointers.append(.{ |
| | 2249 | // .offset = offset, |
| | 2250 | // .segment_id = @intCast(u16, self.data_segment_cmd_index.?), |
| | 2251 | // }); |
| | 2252 | // } |
| | 2253 | // } |
| | 2254 | // } |
| | 2255 | // } |
| | 2256 | |
| | 2257 | std.sort.sort(Pointer, pointers.items, {}, pointerCmp); |
| | 2258 | |
| | 2259 | // const nlocals = self.local_rebases.items.len; |
| | 2260 | // var i = nlocals; |
| | 2261 | // while (i > 0) : (i -= 1) { |
| | 2262 | // pointers.appendAssumeCapacity(self.local_rebases.items[i - 1]); |
| | 2263 | // } |
| 2178 | | 2264 | |
| 2179 | const size = try rebaseInfoSize(pointers.items); | 2265 | const size = try rebaseInfoSize(pointers.items); |
| 2180 | var buffer = try self.allocator.alloc(u8, @intCast(usize, size)); | 2266 | var buffer = try self.allocator.alloc(u8, @intCast(usize, size)); |
| ... | @@ -2189,11 +2275,19 @@ fn writeRebaseInfoTable(self: *Zld) !void { | ... | @@ -2189,11 +2275,19 @@ fn writeRebaseInfoTable(self: *Zld) !void { |
| 2189 | dyld_info.rebase_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @sizeOf(u64))); | 2275 | dyld_info.rebase_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @sizeOf(u64))); |
| 2190 | seg.inner.filesize += dyld_info.rebase_size; | 2276 | seg.inner.filesize += dyld_info.rebase_size; |
| 2191 | | 2277 | |
| 2192 | log.debug("writing rebase info from 0x{x} to 0x{x}", .{ dyld_info.rebase_off, dyld_info.rebase_off + dyld_info.rebase_size }); | 2278 | log.warn("writing rebase info from 0x{x} to 0x{x}", .{ dyld_info.rebase_off, dyld_info.rebase_off + dyld_info.rebase_size }); |
| 2193 | | 2279 | |
| 2194 | try self.file.?.pwriteAll(buffer, dyld_info.rebase_off); | 2280 | try self.file.?.pwriteAll(buffer, dyld_info.rebase_off); |
| 2195 | } | 2281 | } |
| 2196 | | 2282 | |
| | 2283 | fn pointerCmp(context: void, a: Pointer, b: Pointer) bool { |
| | 2284 | if (a.segment_id < b.segment_id) return true; |
| | 2285 | if (a.segment_id == b.segment_id) { |
| | 2286 | return a.offset < b.offset; |
| | 2287 | } |
| | 2288 | return false; |
| | 2289 | } |
| | 2290 | |
| 2197 | fn writeBindInfoTable(self: *Zld) !void { | 2291 | fn writeBindInfoTable(self: *Zld) !void { |
| 2198 | const data_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; | 2292 | const data_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 2199 | | 2293 | |
| ... | @@ -2242,7 +2336,7 @@ fn writeBindInfoTable(self: *Zld) !void { | ... | @@ -2242,7 +2336,7 @@ fn writeBindInfoTable(self: *Zld) !void { |
| 2242 | dyld_info.bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64))); | 2336 | dyld_info.bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64))); |
| 2243 | seg.inner.filesize += dyld_info.bind_size; | 2337 | seg.inner.filesize += dyld_info.bind_size; |
| 2244 | | 2338 | |
| 2245 | log.debug("writing binding info from 0x{x} to 0x{x}", .{ dyld_info.bind_off, dyld_info.bind_off + dyld_info.bind_size }); | 2339 | log.warn("writing binding info from 0x{x} to 0x{x}", .{ dyld_info.bind_off, dyld_info.bind_off + dyld_info.bind_size }); |
| 2246 | | 2340 | |
| 2247 | try self.file.?.pwriteAll(buffer, dyld_info.bind_off); | 2341 | try self.file.?.pwriteAll(buffer, dyld_info.bind_off); |
| 2248 | } | 2342 | } |
| ... | @@ -2281,7 +2375,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void { | ... | @@ -2281,7 +2375,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void { |
| 2281 | dyld_info.lazy_bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64))); | 2375 | dyld_info.lazy_bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64))); |
| 2282 | seg.inner.filesize += dyld_info.lazy_bind_size; | 2376 | seg.inner.filesize += dyld_info.lazy_bind_size; |
| 2283 | | 2377 | |
| 2284 | log.debug("writing lazy binding info from 0x{x} to 0x{x}", .{ dyld_info.lazy_bind_off, dyld_info.lazy_bind_off + dyld_info.lazy_bind_size }); | 2378 | log.warn("writing lazy binding info from 0x{x} to 0x{x}", .{ dyld_info.lazy_bind_off, dyld_info.lazy_bind_off + dyld_info.lazy_bind_size }); |
| 2285 | | 2379 | |
| 2286 | try self.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off); | 2380 | try self.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off); |
| 2287 | try self.populateLazyBindOffsetsInStubHelper(buffer); | 2381 | try self.populateLazyBindOffsetsInStubHelper(buffer); |
| ... | @@ -2383,7 +2477,7 @@ fn writeExportInfo(self: *Zld) !void { | ... | @@ -2383,7 +2477,7 @@ fn writeExportInfo(self: *Zld) !void { |
| 2383 | dyld_info.export_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64))); | 2477 | dyld_info.export_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64))); |
| 2384 | seg.inner.filesize += dyld_info.export_size; | 2478 | seg.inner.filesize += dyld_info.export_size; |
| 2385 | | 2479 | |
| 2386 | log.debug("writing export info from 0x{x} to 0x{x}", .{ dyld_info.export_off, dyld_info.export_off + dyld_info.export_size }); | 2480 | log.warn("writing export info from 0x{x} to 0x{x}", .{ dyld_info.export_off, dyld_info.export_off + dyld_info.export_size }); |
| 2387 | | 2481 | |
| 2388 | try self.file.?.pwriteAll(buffer, dyld_info.export_off); | 2482 | try self.file.?.pwriteAll(buffer, dyld_info.export_off); |
| 2389 | } | 2483 | } |
| ... | @@ -2517,7 +2611,7 @@ fn writeDebugInfo(self: *Zld) !void { | ... | @@ -2517,7 +2611,7 @@ fn writeDebugInfo(self: *Zld) !void { |
| 2517 | | 2611 | |
| 2518 | const stabs_off = symtab.symoff; | 2612 | const stabs_off = symtab.symoff; |
| 2519 | const stabs_size = symtab.nsyms * @sizeOf(macho.nlist_64); | 2613 | const stabs_size = symtab.nsyms * @sizeOf(macho.nlist_64); |
| 2520 | log.debug("writing symbol stabs from 0x{x} to 0x{x}", .{ stabs_off, stabs_size + stabs_off }); | 2614 | log.warn("writing symbol stabs from 0x{x} to 0x{x}", .{ stabs_off, stabs_size + stabs_off }); |
| 2521 | try self.file.?.pwriteAll(mem.sliceAsBytes(stabs.items), stabs_off); | 2615 | try self.file.?.pwriteAll(mem.sliceAsBytes(stabs.items), stabs_off); |
| 2522 | | 2616 | |
| 2523 | linkedit.inner.filesize += stabs_size; | 2617 | linkedit.inner.filesize += stabs_size; |
| ... | @@ -2535,12 +2629,12 @@ fn writeSymbolTable(self: *Zld) !void { | ... | @@ -2535,12 +2629,12 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2535 | defer locals.deinit(); | 2629 | defer locals.deinit(); |
| 2536 | | 2630 | |
| 2537 | for (self.locals.items()) |entries| { | 2631 | for (self.locals.items()) |entries| { |
| 2538 | log.debug("'{s}': {} entries", .{ entries.key, entries.value.items.len }); | 2632 | log.warn("'{s}': {} entries", .{ entries.key, entries.value.items.len }); |
| 2539 | // var symbol: ?macho.nlist_64 = null; | 2633 | // var symbol: ?macho.nlist_64 = null; |
| 2540 | for (entries.value.items) |entry| { | 2634 | for (entries.value.items) |entry| { |
| 2541 | log.debug(" | {}", .{entry.inner}); | 2635 | log.warn(" | {}", .{entry.inner}); |
| 2542 | log.debug(" | {}", .{entry.tt}); | 2636 | log.warn(" | {}", .{entry.tt}); |
| 2543 | log.debug(" | {s}", .{self.objects.items[entry.object_id].name}); | 2637 | log.warn(" | {s}", .{self.objects.items[entry.object_id].name}); |
| 2544 | // switch (entry.tt) { | 2638 | // switch (entry.tt) { |
| 2545 | // .Global => { | 2639 | // .Global => { |
| 2546 | // symbol = entry.inner; | 2640 | // symbol = entry.inner; |
| ... | @@ -2585,17 +2679,17 @@ fn writeSymbolTable(self: *Zld) !void { | ... | @@ -2585,17 +2679,17 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2585 | | 2679 | |
| 2586 | const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64); | 2680 | const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64); |
| 2587 | const locals_size = nlocals * @sizeOf(macho.nlist_64); | 2681 | const locals_size = nlocals * @sizeOf(macho.nlist_64); |
| 2588 | log.debug("writing local symbols from 0x{x} to 0x{x}", .{ locals_off, locals_size + locals_off }); | 2682 | log.warn("writing local symbols from 0x{x} to 0x{x}", .{ locals_off, locals_size + locals_off }); |
| 2589 | try self.file.?.pwriteAll(mem.sliceAsBytes(locals.items), locals_off); | 2683 | try self.file.?.pwriteAll(mem.sliceAsBytes(locals.items), locals_off); |
| 2590 | | 2684 | |
| 2591 | const exports_off = locals_off + locals_size; | 2685 | const exports_off = locals_off + locals_size; |
| 2592 | const exports_size = nexports * @sizeOf(macho.nlist_64); | 2686 | const exports_size = nexports * @sizeOf(macho.nlist_64); |
| 2593 | log.debug("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off }); | 2687 | log.warn("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off }); |
| 2594 | try self.file.?.pwriteAll(mem.sliceAsBytes(exports.items), exports_off); | 2688 | try self.file.?.pwriteAll(mem.sliceAsBytes(exports.items), exports_off); |
| 2595 | | 2689 | |
| 2596 | const undefs_off = exports_off + exports_size; | 2690 | const undefs_off = exports_off + exports_size; |
| 2597 | const undefs_size = nundefs * @sizeOf(macho.nlist_64); | 2691 | const undefs_size = nundefs * @sizeOf(macho.nlist_64); |
| 2598 | log.debug("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off }); | 2692 | log.warn("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off }); |
| 2599 | try self.file.?.pwriteAll(mem.sliceAsBytes(undefs.items), undefs_off); | 2693 | try self.file.?.pwriteAll(mem.sliceAsBytes(undefs.items), undefs_off); |
| 2600 | | 2694 | |
| 2601 | symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs); | 2695 | symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs); |
| ... | @@ -2626,7 +2720,7 @@ fn writeDynamicSymbolTable(self: *Zld) !void { | ... | @@ -2626,7 +2720,7 @@ fn writeDynamicSymbolTable(self: *Zld) !void { |
| 2626 | const needed_size = dysymtab.nindirectsyms * @sizeOf(u32); | 2720 | const needed_size = dysymtab.nindirectsyms * @sizeOf(u32); |
| 2627 | seg.inner.filesize += needed_size; | 2721 | seg.inner.filesize += needed_size; |
| 2628 | | 2722 | |
| 2629 | log.debug("writing indirect symbol table from 0x{x} to 0x{x}", .{ | 2723 | log.warn("writing indirect symbol table from 0x{x} to 0x{x}", .{ |
| 2630 | dysymtab.indirectsymoff, | 2724 | dysymtab.indirectsymoff, |
| 2631 | dysymtab.indirectsymoff + needed_size, | 2725 | dysymtab.indirectsymoff + needed_size, |
| 2632 | }); | 2726 | }); |
| ... | @@ -2665,7 +2759,7 @@ fn writeStringTable(self: *Zld) !void { | ... | @@ -2665,7 +2759,7 @@ fn writeStringTable(self: *Zld) !void { |
| 2665 | symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64))); | 2759 | symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64))); |
| 2666 | seg.inner.filesize += symtab.strsize; | 2760 | seg.inner.filesize += symtab.strsize; |
| 2667 | | 2761 | |
| 2668 | log.debug("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize }); | 2762 | log.warn("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize }); |
| 2669 | | 2763 | |
| 2670 | try self.file.?.pwriteAll(self.strtab.items, symtab.stroff); | 2764 | try self.file.?.pwriteAll(self.strtab.items, symtab.stroff); |
| 2671 | | 2765 | |
| ... | @@ -2675,6 +2769,48 @@ fn writeStringTable(self: *Zld) !void { | ... | @@ -2675,6 +2769,48 @@ fn writeStringTable(self: *Zld) !void { |
| 2675 | } | 2769 | } |
| 2676 | } | 2770 | } |
| 2677 | | 2771 | |
| | 2772 | fn writeDataInCode(self: *Zld) !void { |
| | 2773 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| | 2774 | const dice_cmd = &self.load_commands.items[self.data_in_code_cmd_index.?].LinkeditData; |
| | 2775 | const fileoff = seg.inner.fileoff + seg.inner.filesize; |
| | 2776 | |
| | 2777 | var buf = std.ArrayList(u8).init(self.allocator); |
| | 2778 | defer buf.deinit(); |
| | 2779 | |
| | 2780 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| | 2781 | const text_sect = text_seg.sections.items[self.text_section_index.?]; |
| | 2782 | for (self.objects.items) |object, object_id| { |
| | 2783 | const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; |
| | 2784 | const source_sect = source_seg.sections.items[object.text_section_index.?]; |
| | 2785 | const target_mapping = self.mappings.get(.{ |
| | 2786 | .object_id = @intCast(u16, object_id), |
| | 2787 | .source_sect_id = object.text_section_index.?, |
| | 2788 | }) orelse continue; |
| | 2789 | |
| | 2790 | // TODO Currently assume that Dice will always be within the __TEXT,__text section. |
| | 2791 | try buf.ensureCapacity( |
| | 2792 | buf.items.len + object.data_in_code_entries.items.len * @sizeOf(macho.data_in_code_entry), |
| | 2793 | ); |
| | 2794 | for (object.data_in_code_entries.items) |dice| { |
| | 2795 | const new_dice: macho.data_in_code_entry = .{ |
| | 2796 | .offset = text_sect.offset + target_mapping.offset + dice.offset - source_sect.offset, |
| | 2797 | .length = dice.length, |
| | 2798 | .kind = dice.kind, |
| | 2799 | }; |
| | 2800 | buf.appendSliceAssumeCapacity(mem.asBytes(&new_dice)); |
| | 2801 | } |
| | 2802 | } |
| | 2803 | const datasize = @intCast(u32, buf.items.len); |
| | 2804 | |
| | 2805 | dice_cmd.dataoff = @intCast(u32, fileoff); |
| | 2806 | dice_cmd.datasize = datasize; |
| | 2807 | seg.inner.filesize += datasize; |
| | 2808 | |
| | 2809 | log.warn("writing data-in-code from 0x{x} to 0x{x}", .{ fileoff, fileoff + datasize }); |
| | 2810 | |
| | 2811 | try self.file.?.pwriteAll(buf.items, fileoff); |
| | 2812 | } |
| | 2813 | |
| 2678 | fn writeCodeSignaturePadding(self: *Zld) !void { | 2814 | fn writeCodeSignaturePadding(self: *Zld) !void { |
| 2679 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | 2815 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| 2680 | const code_sig_cmd = &self.load_commands.items[self.code_signature_cmd_index.?].LinkeditData; | 2816 | const code_sig_cmd = &self.load_commands.items[self.code_signature_cmd_index.?].LinkeditData; |
| ... | @@ -2691,7 +2827,7 @@ fn writeCodeSignaturePadding(self: *Zld) !void { | ... | @@ -2691,7 +2827,7 @@ fn writeCodeSignaturePadding(self: *Zld) !void { |
| 2691 | seg.inner.filesize += needed_size; | 2827 | seg.inner.filesize += needed_size; |
| 2692 | seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?); | 2828 | seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?); |
| 2693 | | 2829 | |
| 2694 | log.debug("writing code signature padding from 0x{x} to 0x{x}", .{ fileoff, fileoff + needed_size }); | 2830 | log.warn("writing code signature padding from 0x{x} to 0x{x}", .{ fileoff, fileoff + needed_size }); |
| 2695 | | 2831 | |
| 2696 | // Pad out the space. We need to do this to calculate valid hashes for everything in the file | 2832 | // Pad out the space. We need to do this to calculate valid hashes for everything in the file |
| 2697 | // except for code signature data. | 2833 | // except for code signature data. |
| ... | @@ -2717,7 +2853,7 @@ fn writeCodeSignature(self: *Zld) !void { | ... | @@ -2717,7 +2853,7 @@ fn writeCodeSignature(self: *Zld) !void { |
| 2717 | var stream = std.io.fixedBufferStream(buffer); | 2853 | var stream = std.io.fixedBufferStream(buffer); |
| 2718 | try code_sig.write(stream.writer()); | 2854 | try code_sig.write(stream.writer()); |
| 2719 | | 2855 | |
| 2720 | log.debug("writing code signature from 0x{x} to 0x{x}", .{ code_sig_cmd.dataoff, code_sig_cmd.dataoff + buffer.len }); | 2856 | log.warn("writing code signature from 0x{x} to 0x{x}", .{ code_sig_cmd.dataoff, code_sig_cmd.dataoff + buffer.len }); |
| 2721 | | 2857 | |
| 2722 | try self.file.?.pwriteAll(buffer, code_sig_cmd.dataoff); | 2858 | try self.file.?.pwriteAll(buffer, code_sig_cmd.dataoff); |
| 2723 | } | 2859 | } |
| ... | @@ -2736,7 +2872,7 @@ fn writeLoadCommands(self: *Zld) !void { | ... | @@ -2736,7 +2872,7 @@ fn writeLoadCommands(self: *Zld) !void { |
| 2736 | } | 2872 | } |
| 2737 | | 2873 | |
| 2738 | const off = @sizeOf(macho.mach_header_64); | 2874 | const off = @sizeOf(macho.mach_header_64); |
| 2739 | log.debug("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds }); | 2875 | log.warn("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds }); |
| 2740 | try self.file.?.pwriteAll(buffer, off); | 2876 | try self.file.?.pwriteAll(buffer, off); |
| 2741 | } | 2877 | } |
| 2742 | | 2878 | |
| ... | @@ -2774,7 +2910,7 @@ fn writeHeader(self: *Zld) !void { | ... | @@ -2774,7 +2910,7 @@ fn writeHeader(self: *Zld) !void { |
| 2774 | for (self.load_commands.items) |cmd| { | 2910 | for (self.load_commands.items) |cmd| { |
| 2775 | header.sizeofcmds += cmd.cmdsize(); | 2911 | header.sizeofcmds += cmd.cmdsize(); |
| 2776 | } | 2912 | } |
| 2777 | log.debug("writing Mach-O header {}", .{header}); | 2913 | log.warn("writing Mach-O header {}", .{header}); |
| 2778 | try self.file.?.pwriteAll(mem.asBytes(&header), 0); | 2914 | try self.file.?.pwriteAll(mem.asBytes(&header), 0); |
| 2779 | } | 2915 | } |
| 2780 | | 2916 | |
| ... | @@ -2788,7 +2924,7 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 { | ... | @@ -2788,7 +2924,7 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 { |
| 2788 | fn makeString(self: *Zld, bytes: []const u8) !u32 { | 2924 | fn makeString(self: *Zld, bytes: []const u8) !u32 { |
| 2789 | try self.strtab.ensureCapacity(self.allocator, self.strtab.items.len + bytes.len + 1); | 2925 | try self.strtab.ensureCapacity(self.allocator, self.strtab.items.len + bytes.len + 1); |
| 2790 | const offset = @intCast(u32, self.strtab.items.len); | 2926 | const offset = @intCast(u32, self.strtab.items.len); |
| 2791 | log.debug("writing new string '{s}' into string table at offset 0x{x}", .{ bytes, offset }); | 2927 | log.warn("writing new string '{s}' into string table at offset 0x{x}", .{ bytes, offset }); |
| 2792 | self.strtab.appendSliceAssumeCapacity(bytes); | 2928 | self.strtab.appendSliceAssumeCapacity(bytes); |
| 2793 | self.strtab.appendAssumeCapacity(0); | 2929 | self.strtab.appendAssumeCapacity(0); |
| 2794 | return offset; | 2930 | return offset; |