| ... | ... | @@ -95,9 +95,6 @@ got_entries: std.ArrayListUnmanaged(*Symbol) = .{}, |
| 95 | 95 | |
| 96 | 96 | stub_helper_stubs_start_off: ?u64 = null, |
| 97 | 97 | |
| 98 | | mappings: std.AutoHashMapUnmanaged(MappingKey, SectionMapping) = .{}, |
| 99 | | unhandled_sections: std.AutoHashMapUnmanaged(MappingKey, u0) = .{}, |
| 100 | | |
| 101 | 98 | const TlvOffset = struct { |
| 102 | 99 | source_addr: u64, |
| 103 | 100 | offset: u64, |
| ... | ... | @@ -107,18 +104,6 @@ const TlvOffset = struct { |
| 107 | 104 | } |
| 108 | 105 | }; |
| 109 | 106 | |
| 110 | | const MappingKey = struct { |
| 111 | | object_id: u16, |
| 112 | | source_sect_id: u16, |
| 113 | | }; |
| 114 | | |
| 115 | | pub const SectionMapping = struct { |
| 116 | | source_sect_id: u16, |
| 117 | | target_seg_id: u16, |
| 118 | | target_sect_id: u16, |
| 119 | | offset: u32, |
| 120 | | }; |
| 121 | | |
| 122 | 107 | /// Default path to dyld |
| 123 | 108 | const DEFAULT_DYLD_PATH: [*:0]const u8 = "/usr/lib/dyld"; |
| 124 | 109 | |
| ... | ... | @@ -159,9 +144,6 @@ pub fn deinit(self: *Zld) void { |
| 159 | 144 | } |
| 160 | 145 | self.dylibs.deinit(self.allocator); |
| 161 | 146 | |
| 162 | | self.mappings.deinit(self.allocator); |
| 163 | | self.unhandled_sections.deinit(self.allocator); |
| 164 | | |
| 165 | 147 | self.globals.deinit(self.allocator); |
| 166 | 148 | self.imports.deinit(self.allocator); |
| 167 | 149 | self.unresolved.deinit(self.allocator); |
| ... | ... | @@ -407,46 +389,39 @@ fn parseLibs(self: *Zld, libs: []const []const u8) !void { |
| 407 | 389 | |
| 408 | 390 | fn mapAndUpdateSections( |
| 409 | 391 | self: *Zld, |
| 410 | | object_id: u16, |
| 392 | object: *Object, |
| 411 | 393 | source_sect_id: u16, |
| 412 | 394 | target_seg_id: u16, |
| 413 | 395 | target_sect_id: u16, |
| 414 | 396 | ) !void { |
| 415 | | const object = self.objects.items[object_id]; |
| 416 | | const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; |
| 417 | | const source_sect = source_seg.sections.items[source_sect_id]; |
| 397 | const source_sect = &object.sections.items[source_sect_id]; |
| 418 | 398 | const target_seg = &self.load_commands.items[target_seg_id].Segment; |
| 419 | 399 | const target_sect = &target_seg.sections.items[target_sect_id]; |
| 420 | 400 | |
| 421 | 401 | const alignment = try math.powi(u32, 2, target_sect.@"align"); |
| 422 | 402 | const offset = mem.alignForwardGeneric(u64, target_sect.size, alignment); |
| 423 | | const size = mem.alignForwardGeneric(u64, source_sect.size, alignment); |
| 424 | | const key = MappingKey{ |
| 425 | | .object_id = object_id, |
| 426 | | .source_sect_id = source_sect_id, |
| 427 | | }; |
| 428 | | try self.mappings.putNoClobber(self.allocator, key, .{ |
| 429 | | .source_sect_id = source_sect_id, |
| 430 | | .target_seg_id = target_seg_id, |
| 431 | | .target_sect_id = target_sect_id, |
| 432 | | .offset = @intCast(u32, offset), |
| 433 | | }); |
| 434 | | log.debug("{s}: {s},{s} mapped to {s},{s} from 0x{x} to 0x{x}", .{ |
| 435 | | object.name, |
| 436 | | parseName(&source_sect.segname), |
| 437 | | parseName(&source_sect.sectname), |
| 403 | const size = mem.alignForwardGeneric(u64, source_sect.inner.size, alignment); |
| 404 | |
| 405 | log.debug("{s}: '{s},{s}' mapped to '{s},{s}' from 0x{x} to 0x{x}", .{ |
| 406 | object.name.?, |
| 407 | parseName(&source_sect.inner.segname), |
| 408 | parseName(&source_sect.inner.sectname), |
| 438 | 409 | parseName(&target_sect.segname), |
| 439 | 410 | parseName(&target_sect.sectname), |
| 440 | 411 | offset, |
| 441 | 412 | offset + size, |
| 442 | 413 | }); |
| 443 | 414 | |
| 415 | source_sect.target_map = .{ |
| 416 | .segment_id = target_seg_id, |
| 417 | .section_id = target_sect_id, |
| 418 | .offset = @intCast(u32, offset), |
| 419 | }; |
| 444 | 420 | target_sect.size = offset + size; |
| 445 | 421 | } |
| 446 | 422 | |
| 447 | 423 | fn updateMetadata(self: *Zld) !void { |
| 448 | | for (self.objects.items) |object, id| { |
| 449 | | const object_id = @intCast(u16, id); |
| 424 | for (self.objects.items) |object| { |
| 450 | 425 | const object_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; |
| 451 | 426 | const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 452 | 427 | const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| ... | ... | @@ -699,19 +674,14 @@ fn updateMetadata(self: *Zld) !void { |
| 699 | 674 | for (object_seg.sections.items) |source_sect, sect_id| { |
| 700 | 675 | const source_sect_id = @intCast(u16, sect_id); |
| 701 | 676 | if (self.getMatchingSection(source_sect)) |res| { |
| 702 | | try self.mapAndUpdateSections(object_id, source_sect_id, res.seg, res.sect); |
| 677 | try self.mapAndUpdateSections(object, source_sect_id, res.seg, res.sect); |
| 703 | 678 | continue; |
| 704 | 679 | } |
| 705 | 680 | |
| 706 | | const segname = parseName(&source_sect.segname); |
| 707 | | const sectname = parseName(&source_sect.sectname); |
| 708 | | |
| 709 | | log.debug("section '{s}/{s}' will be unmapped", .{ segname, sectname }); |
| 710 | | |
| 711 | | try self.unhandled_sections.putNoClobber(self.allocator, .{ |
| 712 | | .object_id = object_id, |
| 713 | | .source_sect_id = source_sect_id, |
| 714 | | }, 0); |
| 681 | log.debug("section '{s},{s}' will be unmapped", .{ |
| 682 | parseName(&source_sect.segname), |
| 683 | parseName(&source_sect.sectname), |
| 684 | }); |
| 715 | 685 | } |
| 716 | 686 | } |
| 717 | 687 | |
| ... | ... | @@ -954,18 +924,34 @@ fn sortSections(self: *Zld) !void { |
| 954 | 924 | } |
| 955 | 925 | } |
| 956 | 926 | |
| 957 | | var it = self.mappings.valueIterator(); |
| 958 | | while (it.next()) |mapping| { |
| 959 | | if (self.text_segment_cmd_index.? == mapping.target_seg_id) { |
| 960 | | const new_index = text_index_mapping.get(mapping.target_sect_id) orelse unreachable; |
| 961 | | mapping.target_sect_id = new_index; |
| 962 | | } else if (self.data_const_segment_cmd_index.? == mapping.target_seg_id) { |
| 963 | | const new_index = data_const_index_mapping.get(mapping.target_sect_id) orelse unreachable; |
| 964 | | mapping.target_sect_id = new_index; |
| 965 | | } else if (self.data_segment_cmd_index.? == mapping.target_seg_id) { |
| 966 | | const new_index = data_index_mapping.get(mapping.target_sect_id) orelse unreachable; |
| 967 | | mapping.target_sect_id = new_index; |
| 968 | | } else unreachable; |
| 927 | for (self.objects.items) |object| { |
| 928 | for (object.sections.items) |*sect| { |
| 929 | const target_map = sect.target_map orelse continue; |
| 930 | |
| 931 | const new_index = blk: { |
| 932 | if (self.text_segment_cmd_index.? == target_map.segment_id) { |
| 933 | break :blk text_index_mapping.get(target_map.section_id) orelse unreachable; |
| 934 | } else if (self.data_const_segment_cmd_index.? == target_map.segment_id) { |
| 935 | break :blk data_const_index_mapping.get(target_map.section_id) orelse unreachable; |
| 936 | } else if (self.data_segment_cmd_index.? == target_map.segment_id) { |
| 937 | break :blk data_index_mapping.get(target_map.section_id) orelse unreachable; |
| 938 | } else unreachable; |
| 939 | }; |
| 940 | |
| 941 | log.debug("remapping in {s}: '{s},{s}': {} => {}", .{ |
| 942 | object.name.?, |
| 943 | parseName(&sect.inner.segname), |
| 944 | parseName(&sect.inner.sectname), |
| 945 | target_map.section_id, |
| 946 | new_index, |
| 947 | }); |
| 948 | |
| 949 | sect.target_map = .{ |
| 950 | .segment_id = target_map.segment_id, |
| 951 | .section_id = new_index, |
| 952 | .offset = target_map.offset, |
| 953 | }; |
| 954 | } |
| 969 | 955 | } |
| 970 | 956 | } |
| 971 | 957 | |
| ... | ... | @@ -1080,30 +1066,24 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void { |
| 1080 | 1066 | } |
| 1081 | 1067 | |
| 1082 | 1068 | fn allocateSymbols(self: *Zld) !void { |
| 1083 | | for (self.objects.items) |object, object_id| { |
| 1069 | for (self.objects.items) |object| { |
| 1084 | 1070 | for (object.symbols.items) |sym| { |
| 1085 | 1071 | const reg = sym.cast(Symbol.Regular) orelse continue; |
| 1086 | 1072 | |
| 1087 | | // TODO I am more and more convinced we should store the mapping as part of the Object struct. |
| 1088 | | const target_mapping = self.mappings.get(.{ |
| 1089 | | .object_id = @intCast(u16, object_id), |
| 1090 | | .source_sect_id = reg.section, |
| 1091 | | }) orelse { |
| 1092 | | if (self.unhandled_sections.get(.{ |
| 1093 | | .object_id = @intCast(u16, object_id), |
| 1094 | | .source_sect_id = reg.section, |
| 1095 | | }) != null) continue; |
| 1096 | | |
| 1097 | | log.err("section not mapped for symbol '{s}'", .{sym.name}); |
| 1098 | | return error.SectionNotMappedForSymbol; |
| 1073 | const source_sect = &object.sections.items[reg.section]; |
| 1074 | const target_map = source_sect.target_map orelse { |
| 1075 | log.debug("section '{s},{s}' not mapped for symbol '{s}'", .{ |
| 1076 | parseName(&source_sect.inner.segname), |
| 1077 | parseName(&source_sect.inner.sectname), |
| 1078 | sym.name, |
| 1079 | }); |
| 1080 | continue; |
| 1099 | 1081 | }; |
| 1100 | 1082 | |
| 1101 | | const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; |
| 1102 | | const source_sect = source_seg.sections.items[reg.section]; |
| 1103 | | const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment; |
| 1104 | | const target_sect = target_seg.sections.items[target_mapping.target_sect_id]; |
| 1105 | | const target_addr = target_sect.addr + target_mapping.offset; |
| 1106 | | const address = reg.address - source_sect.addr + target_addr; |
| 1083 | const target_seg = self.load_commands.items[target_map.segment_id].Segment; |
| 1084 | const target_sect = target_seg.sections.items[target_map.section_id]; |
| 1085 | const target_addr = target_sect.addr + target_map.offset; |
| 1086 | const address = reg.address - source_sect.inner.addr + target_addr; |
| 1107 | 1087 | |
| 1108 | 1088 | log.debug("resolving symbol '{s}' at 0x{x}", .{ sym.name, address }); |
| 1109 | 1089 | |
| ... | ... | @@ -1111,8 +1091,8 @@ fn allocateSymbols(self: *Zld) !void { |
| 1111 | 1091 | var section: u8 = 0; |
| 1112 | 1092 | for (self.load_commands.items) |cmd, cmd_id| { |
| 1113 | 1093 | if (cmd != .Segment) break; |
| 1114 | | if (cmd_id == target_mapping.target_seg_id) { |
| 1115 | | section += @intCast(u8, target_mapping.target_sect_id) + 1; |
| 1094 | if (cmd_id == target_map.segment_id) { |
| 1095 | section += @intCast(u8, target_map.section_id) + 1; |
| 1116 | 1096 | break; |
| 1117 | 1097 | } |
| 1118 | 1098 | section += @intCast(u8, cmd.Segment.sections.items.len); |
| ... | ... | @@ -1602,10 +1582,10 @@ fn resolveStubsAndGotEntries(self: *Zld) !void { |
| 1602 | 1582 | } |
| 1603 | 1583 | |
| 1604 | 1584 | fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1605 | | for (self.objects.items) |object, object_id| { |
| 1585 | for (self.objects.items) |object| { |
| 1606 | 1586 | log.debug("relocating object {s}", .{object.name}); |
| 1607 | 1587 | |
| 1608 | | for (object.sections.items) |sect, source_sect_id| { |
| 1588 | for (object.sections.items) |sect| { |
| 1609 | 1589 | if (sect.inner.flags == macho.S_MOD_INIT_FUNC_POINTERS or |
| 1610 | 1590 | sect.inner.flags == macho.S_MOD_TERM_FUNC_POINTERS) continue; |
| 1611 | 1591 | |
| ... | ... | @@ -1614,18 +1594,15 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1614 | 1594 | |
| 1615 | 1595 | log.debug("relocating section '{s},{s}'", .{ segname, sectname }); |
| 1616 | 1596 | |
| 1617 | | // Get mapping |
| 1618 | | const target_mapping = self.mappings.get(.{ |
| 1619 | | .object_id = @intCast(u16, object_id), |
| 1620 | | .source_sect_id = @intCast(u16, source_sect_id), |
| 1621 | | }) orelse { |
| 1622 | | log.debug("no mapping for {s},{s}; skipping", .{ segname, sectname }); |
| 1597 | // Get target mapping |
| 1598 | const target_map = sect.target_map orelse { |
| 1599 | log.debug("no mapping for '{s},{s}'; skipping", .{ segname, sectname }); |
| 1623 | 1600 | continue; |
| 1624 | 1601 | }; |
| 1625 | | const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment; |
| 1626 | | const target_sect = target_seg.sections.items[target_mapping.target_sect_id]; |
| 1627 | | const target_sect_addr = target_sect.addr + target_mapping.offset; |
| 1628 | | const target_sect_off = target_sect.offset + target_mapping.offset; |
| 1602 | const target_seg = self.load_commands.items[target_map.segment_id].Segment; |
| 1603 | const target_sect = target_seg.sections.items[target_map.section_id]; |
| 1604 | const target_sect_addr = target_sect.addr + target_map.offset; |
| 1605 | const target_sect_off = target_sect.offset + target_map.offset; |
| 1629 | 1606 | |
| 1630 | 1607 | if (sect.relocs) |relocs| { |
| 1631 | 1608 | for (relocs) |rel| { |
| ... | ... | @@ -1638,11 +1615,11 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1638 | 1615 | |
| 1639 | 1616 | switch (rel.@"type") { |
| 1640 | 1617 | .unsigned => { |
| 1641 | | args.target_addr = try self.relocTargetAddr(@intCast(u16, object_id), rel.target); |
| 1618 | args.target_addr = try self.relocTargetAddr(object, rel.target); |
| 1642 | 1619 | |
| 1643 | 1620 | const unsigned = rel.cast(reloc.Unsigned) orelse unreachable; |
| 1644 | 1621 | if (unsigned.subtractor) |subtractor| { |
| 1645 | | args.subtractor = try self.relocTargetAddr(@intCast(u16, object_id), subtractor); |
| 1622 | args.subtractor = try self.relocTargetAddr(object, subtractor); |
| 1646 | 1623 | } |
| 1647 | 1624 | if (rel.target == .section) { |
| 1648 | 1625 | const source_sect = object.sections.items[rel.target.section]; |
| ... | ... | @@ -1652,14 +1629,14 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1652 | 1629 | |
| 1653 | 1630 | rebases: { |
| 1654 | 1631 | var hit: bool = false; |
| 1655 | | if (target_mapping.target_seg_id == self.data_segment_cmd_index.?) { |
| 1632 | if (target_map.segment_id == self.data_segment_cmd_index.?) { |
| 1656 | 1633 | if (self.data_section_index) |index| { |
| 1657 | | if (index == target_mapping.target_sect_id) hit = true; |
| 1634 | if (index == target_map.section_id) hit = true; |
| 1658 | 1635 | } |
| 1659 | 1636 | } |
| 1660 | | if (target_mapping.target_seg_id == self.data_const_segment_cmd_index.?) { |
| 1637 | if (target_map.segment_id == self.data_const_segment_cmd_index.?) { |
| 1661 | 1638 | if (self.data_const_section_index) |index| { |
| 1662 | | if (index == target_mapping.target_sect_id) hit = true; |
| 1639 | if (index == target_map.section_id) hit = true; |
| 1663 | 1640 | } |
| 1664 | 1641 | } |
| 1665 | 1642 | |
| ... | ... | @@ -1667,7 +1644,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1667 | 1644 | |
| 1668 | 1645 | try self.local_rebases.append(self.allocator, .{ |
| 1669 | 1646 | .offset = source_addr - target_seg.inner.vmaddr, |
| 1670 | | .segment_id = target_mapping.target_seg_id, |
| 1647 | .segment_id = target_map.segment_id, |
| 1671 | 1648 | }); |
| 1672 | 1649 | } |
| 1673 | 1650 | // TLV is handled via a separate offset mechanism. |
| ... | ... | @@ -1705,7 +1682,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1705 | 1682 | args.source_source_sect_addr = sect.inner.addr; |
| 1706 | 1683 | args.source_target_sect_addr = source_sect.inner.addr; |
| 1707 | 1684 | } |
| 1708 | | args.target_addr = try self.relocTargetAddr(@intCast(u16, object_id), rel.target); |
| 1685 | args.target_addr = try self.relocTargetAddr(object, rel.target); |
| 1709 | 1686 | }, |
| 1710 | 1687 | } |
| 1711 | 1688 | |
| ... | ... | @@ -1744,7 +1721,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1744 | 1721 | } |
| 1745 | 1722 | } |
| 1746 | 1723 | |
| 1747 | | fn relocTargetAddr(self: *Zld, object_id: u16, target: reloc.Relocation.Target) !u64 { |
| 1724 | fn relocTargetAddr(self: *Zld, object: *const Object, target: reloc.Relocation.Target) !u64 { |
| 1748 | 1725 | const target_addr = blk: { |
| 1749 | 1726 | switch (target) { |
| 1750 | 1727 | .symbol => |sym| { |
| ... | ... | @@ -1770,13 +1747,11 @@ fn relocTargetAddr(self: *Zld, object_id: u16, target: reloc.Relocation.Target) |
| 1770 | 1747 | } |
| 1771 | 1748 | }, |
| 1772 | 1749 | .section => |sect_id| { |
| 1773 | | const target_mapping = self.mappings.get(.{ |
| 1774 | | .object_id = object_id, |
| 1775 | | .source_sect_id = sect_id, |
| 1776 | | }) orelse unreachable; |
| 1777 | | const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment; |
| 1778 | | const target_sect = target_seg.sections.items[target_mapping.target_sect_id]; |
| 1779 | | break :blk target_sect.addr + target_mapping.offset; |
| 1750 | const source_sect = object.sections.items[sect_id]; |
| 1751 | const target_map = source_sect.target_map orelse unreachable; |
| 1752 | const target_seg = self.load_commands.items[target_map.segment_id].Segment; |
| 1753 | const target_sect = target_seg.sections.items[target_map.section_id]; |
| 1754 | break :blk target_sect.addr + target_map.offset; |
| 1780 | 1755 | }, |
| 1781 | 1756 | } |
| 1782 | 1757 | }; |
| ... | ... | @@ -2901,20 +2876,16 @@ fn writeDataInCode(self: *Zld) !void { |
| 2901 | 2876 | |
| 2902 | 2877 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 2903 | 2878 | const text_sect = text_seg.sections.items[self.text_section_index.?]; |
| 2904 | | for (self.objects.items) |object, object_id| { |
| 2905 | | const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; |
| 2906 | | const source_sect = source_seg.sections.items[object.text_section_index.?]; |
| 2907 | | const target_mapping = self.mappings.get(.{ |
| 2908 | | .object_id = @intCast(u16, object_id), |
| 2909 | | .source_sect_id = object.text_section_index.?, |
| 2910 | | }) orelse continue; |
| 2879 | for (self.objects.items) |object| { |
| 2880 | const source_sect = object.sections.items[object.text_section_index.?]; |
| 2881 | const target_map = source_sect.target_map orelse continue; |
| 2911 | 2882 | |
| 2912 | 2883 | try buf.ensureCapacity( |
| 2913 | 2884 | buf.items.len + object.data_in_code_entries.items.len * @sizeOf(macho.data_in_code_entry), |
| 2914 | 2885 | ); |
| 2915 | 2886 | for (object.data_in_code_entries.items) |dice| { |
| 2916 | 2887 | const new_dice: macho.data_in_code_entry = .{ |
| 2917 | | .offset = text_sect.offset + target_mapping.offset + dice.offset, |
| 2888 | .offset = text_sect.offset + target_map.offset + dice.offset, |
| 2918 | 2889 | .length = dice.length, |
| 2919 | 2890 | .kind = dice.kind, |
| 2920 | 2891 | }; |