authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-06-10 08:30:25+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-06-10 09:13:35+02:00
log96bb81b6ef0896d0b63c54bfd5d1ac0fa267d68a
tree8d751f4925f3c05ff04dca9db3560af21593ef5f
parent88aec4a1ee49088685b16d744f35c902c4900a09

zld: moving target seg,sect mapping into Object.Section


2 files changed, 94 insertions(+), 118 deletions(-)

src/link/MachO/Object.zig+5
...@@ -54,6 +54,11 @@ pub const Section = struct {...@@ -54,6 +54,11 @@ pub const Section = struct {
54 inner: macho.section_64,54 inner: macho.section_64,
55 code: []u8,55 code: []u8,
56 relocs: ?[]*Relocation,56 relocs: ?[]*Relocation,
57 target_map: ?struct {
58 segment_id: u16,
59 section_id: u16,
60 offset: u32,
61 } = null,
5762
58 pub fn deinit(self: *Section, allocator: *Allocator) void {63 pub fn deinit(self: *Section, allocator: *Allocator) void {
59 allocator.free(self.code);64 allocator.free(self.code);
src/link/MachO/Zld.zig+89-118
...@@ -95,9 +95,6 @@ got_entries: std.ArrayListUnmanaged(*Symbol) = .{},...@@ -95,9 +95,6 @@ got_entries: std.ArrayListUnmanaged(*Symbol) = .{},
9595
96stub_helper_stubs_start_off: ?u64 = null,96stub_helper_stubs_start_off: ?u64 = null,
9797
98mappings: std.AutoHashMapUnmanaged(MappingKey, SectionMapping) = .{},
99unhandled_sections: std.AutoHashMapUnmanaged(MappingKey, u0) = .{},
100
101const TlvOffset = struct {98const TlvOffset = struct {
102 source_addr: u64,99 source_addr: u64,
103 offset: u64,100 offset: u64,
...@@ -107,18 +104,6 @@ const TlvOffset = struct {...@@ -107,18 +104,6 @@ const TlvOffset = struct {
107 }104 }
108};105};
109106
110const MappingKey = struct {
111 object_id: u16,
112 source_sect_id: u16,
113};
114
115pub const SectionMapping = struct {
116 source_sect_id: u16,
117 target_seg_id: u16,
118 target_sect_id: u16,
119 offset: u32,
120};
121
122/// Default path to dyld107/// Default path to dyld
123const DEFAULT_DYLD_PATH: [*:0]const u8 = "/usr/lib/dyld";108const DEFAULT_DYLD_PATH: [*:0]const u8 = "/usr/lib/dyld";
124109
...@@ -159,9 +144,6 @@ pub fn deinit(self: *Zld) void {...@@ -159,9 +144,6 @@ pub fn deinit(self: *Zld) void {
159 }144 }
160 self.dylibs.deinit(self.allocator);145 self.dylibs.deinit(self.allocator);
161146
162 self.mappings.deinit(self.allocator);
163 self.unhandled_sections.deinit(self.allocator);
164
165 self.globals.deinit(self.allocator);147 self.globals.deinit(self.allocator);
166 self.imports.deinit(self.allocator);148 self.imports.deinit(self.allocator);
167 self.unresolved.deinit(self.allocator);149 self.unresolved.deinit(self.allocator);
...@@ -407,46 +389,39 @@ fn parseLibs(self: *Zld, libs: []const []const u8) !void {...@@ -407,46 +389,39 @@ fn parseLibs(self: *Zld, libs: []const []const u8) !void {
407389
408fn mapAndUpdateSections(390fn mapAndUpdateSections(
409 self: *Zld,391 self: *Zld,
410 object_id: u16,392 object: *Object,
411 source_sect_id: u16,393 source_sect_id: u16,
412 target_seg_id: u16,394 target_seg_id: u16,
413 target_sect_id: u16,395 target_sect_id: u16,
414) !void {396) !void {
415 const object = self.objects.items[object_id];397 const source_sect = &object.sections.items[source_sect_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];
418 const target_seg = &self.load_commands.items[target_seg_id].Segment;398 const target_seg = &self.load_commands.items[target_seg_id].Segment;
419 const target_sect = &target_seg.sections.items[target_sect_id];399 const target_sect = &target_seg.sections.items[target_sect_id];
420400
421 const alignment = try math.powi(u32, 2, target_sect.@"align");401 const alignment = try math.powi(u32, 2, target_sect.@"align");
422 const offset = mem.alignForwardGeneric(u64, target_sect.size, alignment);402 const offset = mem.alignForwardGeneric(u64, target_sect.size, alignment);
423 const size = mem.alignForwardGeneric(u64, source_sect.size, alignment);403 const size = mem.alignForwardGeneric(u64, source_sect.inner.size, alignment);
424 const key = MappingKey{404
425 .object_id = object_id,405 log.debug("{s}: '{s},{s}' mapped to '{s},{s}' from 0x{x} to 0x{x}", .{
426 .source_sect_id = source_sect_id,406 object.name.?,
427 };407 parseName(&source_sect.inner.segname),
428 try self.mappings.putNoClobber(self.allocator, key, .{408 parseName(&source_sect.inner.sectname),
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),
438 parseName(&target_sect.segname),409 parseName(&target_sect.segname),
439 parseName(&target_sect.sectname),410 parseName(&target_sect.sectname),
440 offset,411 offset,
441 offset + size,412 offset + size,
442 });413 });
443414
415 source_sect.target_map = .{
416 .segment_id = target_seg_id,
417 .section_id = target_sect_id,
418 .offset = @intCast(u32, offset),
419 };
444 target_sect.size = offset + size;420 target_sect.size = offset + size;
445}421}
446422
447fn updateMetadata(self: *Zld) !void {423fn updateMetadata(self: *Zld) !void {
448 for (self.objects.items) |object, id| {424 for (self.objects.items) |object| {
449 const object_id = @intCast(u16, id);
450 const object_seg = object.load_commands.items[object.segment_cmd_index.?].Segment;425 const object_seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
451 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;426 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
452 const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;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,19 +674,14 @@ fn updateMetadata(self: *Zld) !void {
699 for (object_seg.sections.items) |source_sect, sect_id| {674 for (object_seg.sections.items) |source_sect, sect_id| {
700 const source_sect_id = @intCast(u16, sect_id);675 const source_sect_id = @intCast(u16, sect_id);
701 if (self.getMatchingSection(source_sect)) |res| {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 continue;678 continue;
704 }679 }
705680
706 const segname = parseName(&source_sect.segname);681 log.debug("section '{s},{s}' will be unmapped", .{
707 const sectname = parseName(&source_sect.sectname);682 parseName(&source_sect.segname),
708683 parseName(&source_sect.sectname),
709 log.debug("section '{s}/{s}' will be unmapped", .{ segname, sectname });684 });
710
711 try self.unhandled_sections.putNoClobber(self.allocator, .{
712 .object_id = object_id,
713 .source_sect_id = source_sect_id,
714 }, 0);
715 }685 }
716 }686 }
717687
...@@ -954,18 +924,34 @@ fn sortSections(self: *Zld) !void {...@@ -954,18 +924,34 @@ fn sortSections(self: *Zld) !void {
954 }924 }
955 }925 }
956926
957 var it = self.mappings.valueIterator();927 for (self.objects.items) |object| {
958 while (it.next()) |mapping| {928 for (object.sections.items) |*sect| {
959 if (self.text_segment_cmd_index.? == mapping.target_seg_id) {929 const target_map = sect.target_map orelse continue;
960 const new_index = text_index_mapping.get(mapping.target_sect_id) orelse unreachable;930
961 mapping.target_sect_id = new_index;931 const new_index = blk: {
962 } else if (self.data_const_segment_cmd_index.? == mapping.target_seg_id) {932 if (self.text_segment_cmd_index.? == target_map.segment_id) {
963 const new_index = data_const_index_mapping.get(mapping.target_sect_id) orelse unreachable;933 break :blk text_index_mapping.get(target_map.section_id) orelse unreachable;
964 mapping.target_sect_id = new_index;934 } else if (self.data_const_segment_cmd_index.? == target_map.segment_id) {
965 } else if (self.data_segment_cmd_index.? == mapping.target_seg_id) {935 break :blk data_const_index_mapping.get(target_map.section_id) orelse unreachable;
966 const new_index = data_index_mapping.get(mapping.target_sect_id) orelse unreachable;936 } else if (self.data_segment_cmd_index.? == target_map.segment_id) {
967 mapping.target_sect_id = new_index;937 break :blk data_index_mapping.get(target_map.section_id) orelse unreachable;
968 } else 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}
971957
...@@ -1080,30 +1066,24 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void {...@@ -1080,30 +1066,24 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void {
1080}1066}
10811067
1082fn allocateSymbols(self: *Zld) !void {1068fn allocateSymbols(self: *Zld) !void {
1083 for (self.objects.items) |object, object_id| {1069 for (self.objects.items) |object| {
1084 for (object.symbols.items) |sym| {1070 for (object.symbols.items) |sym| {
1085 const reg = sym.cast(Symbol.Regular) orelse continue;1071 const reg = sym.cast(Symbol.Regular) orelse continue;
10861072
1087 // TODO I am more and more convinced we should store the mapping as part of the Object struct.1073 const source_sect = &object.sections.items[reg.section];
1088 const target_mapping = self.mappings.get(.{1074 const target_map = source_sect.target_map orelse {
1089 .object_id = @intCast(u16, object_id),1075 log.debug("section '{s},{s}' not mapped for symbol '{s}'", .{
1090 .source_sect_id = reg.section,1076 parseName(&source_sect.inner.segname),
1091 }) orelse {1077 parseName(&source_sect.inner.sectname),
1092 if (self.unhandled_sections.get(.{1078 sym.name,
1093 .object_id = @intCast(u16, object_id),1079 });
1094 .source_sect_id = reg.section,1080 continue;
1095 }) != null) continue;
1096
1097 log.err("section not mapped for symbol '{s}'", .{sym.name});
1098 return error.SectionNotMappedForSymbol;
1099 };1081 };
11001082
1101 const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment;1083 const target_seg = self.load_commands.items[target_map.segment_id].Segment;
1102 const source_sect = source_seg.sections.items[reg.section];1084 const target_sect = target_seg.sections.items[target_map.section_id];
1103 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;1085 const target_addr = target_sect.addr + target_map.offset;
1104 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];1086 const address = reg.address - source_sect.inner.addr + target_addr;
1105 const target_addr = target_sect.addr + target_mapping.offset;
1106 const address = reg.address - source_sect.addr + target_addr;
11071087
1108 log.debug("resolving symbol '{s}' at 0x{x}", .{ sym.name, address });1088 log.debug("resolving symbol '{s}' at 0x{x}", .{ sym.name, address });
11091089
...@@ -1111,8 +1091,8 @@ fn allocateSymbols(self: *Zld) !void {...@@ -1111,8 +1091,8 @@ fn allocateSymbols(self: *Zld) !void {
1111 var section: u8 = 0;1091 var section: u8 = 0;
1112 for (self.load_commands.items) |cmd, cmd_id| {1092 for (self.load_commands.items) |cmd, cmd_id| {
1113 if (cmd != .Segment) break;1093 if (cmd != .Segment) break;
1114 if (cmd_id == target_mapping.target_seg_id) {1094 if (cmd_id == target_map.segment_id) {
1115 section += @intCast(u8, target_mapping.target_sect_id) + 1;1095 section += @intCast(u8, target_map.section_id) + 1;
1116 break;1096 break;
1117 }1097 }
1118 section += @intCast(u8, cmd.Segment.sections.items.len);1098 section += @intCast(u8, cmd.Segment.sections.items.len);
...@@ -1602,10 +1582,10 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {...@@ -1602,10 +1582,10 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
1602}1582}
16031583
1604fn resolveRelocsAndWriteSections(self: *Zld) !void {1584fn resolveRelocsAndWriteSections(self: *Zld) !void {
1605 for (self.objects.items) |object, object_id| {1585 for (self.objects.items) |object| {
1606 log.debug("relocating object {s}", .{object.name});1586 log.debug("relocating object {s}", .{object.name});
16071587
1608 for (object.sections.items) |sect, source_sect_id| {1588 for (object.sections.items) |sect| {
1609 if (sect.inner.flags == macho.S_MOD_INIT_FUNC_POINTERS or1589 if (sect.inner.flags == macho.S_MOD_INIT_FUNC_POINTERS or
1610 sect.inner.flags == macho.S_MOD_TERM_FUNC_POINTERS) continue;1590 sect.inner.flags == macho.S_MOD_TERM_FUNC_POINTERS) continue;
16111591
...@@ -1614,18 +1594,15 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1614,18 +1594,15 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
16141594
1615 log.debug("relocating section '{s},{s}'", .{ segname, sectname });1595 log.debug("relocating section '{s},{s}'", .{ segname, sectname });
16161596
1617 // Get mapping1597 // Get target mapping
1618 const target_mapping = self.mappings.get(.{1598 const target_map = sect.target_map orelse {
1619 .object_id = @intCast(u16, object_id),1599 log.debug("no mapping for '{s},{s}'; skipping", .{ segname, sectname });
1620 .source_sect_id = @intCast(u16, source_sect_id),
1621 }) orelse {
1622 log.debug("no mapping for {s},{s}; skipping", .{ segname, sectname });
1623 continue;1600 continue;
1624 };1601 };
1625 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;1602 const target_seg = self.load_commands.items[target_map.segment_id].Segment;
1626 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];1603 const target_sect = target_seg.sections.items[target_map.section_id];
1627 const target_sect_addr = target_sect.addr + target_mapping.offset;1604 const target_sect_addr = target_sect.addr + target_map.offset;
1628 const target_sect_off = target_sect.offset + target_mapping.offset;1605 const target_sect_off = target_sect.offset + target_map.offset;
16291606
1630 if (sect.relocs) |relocs| {1607 if (sect.relocs) |relocs| {
1631 for (relocs) |rel| {1608 for (relocs) |rel| {
...@@ -1638,11 +1615,11 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1638,11 +1615,11 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
16381615
1639 switch (rel.@"type") {1616 switch (rel.@"type") {
1640 .unsigned => {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);
16421619
1643 const unsigned = rel.cast(reloc.Unsigned) orelse unreachable;1620 const unsigned = rel.cast(reloc.Unsigned) orelse unreachable;
1644 if (unsigned.subtractor) |subtractor| {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 if (rel.target == .section) {1624 if (rel.target == .section) {
1648 const source_sect = object.sections.items[rel.target.section];1625 const source_sect = object.sections.items[rel.target.section];
...@@ -1652,14 +1629,14 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1652,14 +1629,14 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
16521629
1653 rebases: {1630 rebases: {
1654 var hit: bool = false;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 if (self.data_section_index) |index| {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 if (self.data_const_section_index) |index| {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 }
16651642
...@@ -1667,7 +1644,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1667,7 +1644,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
16671644
1668 try self.local_rebases.append(self.allocator, .{1645 try self.local_rebases.append(self.allocator, .{
1669 .offset = source_addr - target_seg.inner.vmaddr,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 // TLV is handled via a separate offset mechanism.1650 // TLV is handled via a separate offset mechanism.
...@@ -1705,7 +1682,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1705,7 +1682,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1705 args.source_source_sect_addr = sect.inner.addr;1682 args.source_source_sect_addr = sect.inner.addr;
1706 args.source_target_sect_addr = source_sect.inner.addr;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 }
17111688
...@@ -1744,7 +1721,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1744,7 +1721,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1744 }1721 }
1745}1722}
17461723
1747fn relocTargetAddr(self: *Zld, object_id: u16, target: reloc.Relocation.Target) !u64 {1724fn relocTargetAddr(self: *Zld, object: *const Object, target: reloc.Relocation.Target) !u64 {
1748 const target_addr = blk: {1725 const target_addr = blk: {
1749 switch (target) {1726 switch (target) {
1750 .symbol => |sym| {1727 .symbol => |sym| {
...@@ -1770,13 +1747,11 @@ fn relocTargetAddr(self: *Zld, object_id: u16, target: reloc.Relocation.Target)...@@ -1770,13 +1747,11 @@ fn relocTargetAddr(self: *Zld, object_id: u16, target: reloc.Relocation.Target)
1770 }1747 }
1771 },1748 },
1772 .section => |sect_id| {1749 .section => |sect_id| {
1773 const target_mapping = self.mappings.get(.{1750 const source_sect = object.sections.items[sect_id];
1774 .object_id = object_id,1751 const target_map = source_sect.target_map orelse unreachable;
1775 .source_sect_id = sect_id,1752 const target_seg = self.load_commands.items[target_map.segment_id].Segment;
1776 }) orelse unreachable;1753 const target_sect = target_seg.sections.items[target_map.section_id];
1777 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;1754 break :blk target_sect.addr + target_map.offset;
1778 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];
1779 break :blk target_sect.addr + target_mapping.offset;
1780 },1755 },
1781 }1756 }
1782 };1757 };
...@@ -2901,20 +2876,16 @@ fn writeDataInCode(self: *Zld) !void {...@@ -2901,20 +2876,16 @@ fn writeDataInCode(self: *Zld) !void {
29012876
2902 const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;2877 const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2903 const text_sect = text_seg.sections.items[self.text_section_index.?];2878 const text_sect = text_seg.sections.items[self.text_section_index.?];
2904 for (self.objects.items) |object, object_id| {2879 for (self.objects.items) |object| {
2905 const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment;2880 const source_sect = object.sections.items[object.text_section_index.?];
2906 const source_sect = source_seg.sections.items[object.text_section_index.?];2881 const target_map = source_sect.target_map orelse continue;
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;
29112882
2912 try buf.ensureCapacity(2883 try buf.ensureCapacity(
2913 buf.items.len + object.data_in_code_entries.items.len * @sizeOf(macho.data_in_code_entry),2884 buf.items.len + object.data_in_code_entries.items.len * @sizeOf(macho.data_in_code_entry),
2914 );2885 );
2915 for (object.data_in_code_entries.items) |dice| {2886 for (object.data_in_code_entries.items) |dice| {
2916 const new_dice: macho.data_in_code_entry = .{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 .length = dice.length,2889 .length = dice.length,
2919 .kind = dice.kind,2890 .kind = dice.kind,
2920 };2891 };