| ... | ... | @@ -84,6 +84,11 @@ common_section_index: ?u16 = null, |
| 84 | 84 | globals: std.StringArrayHashMapUnmanaged(*Symbol) = .{}, |
| 85 | 85 | imports: std.StringArrayHashMapUnmanaged(*Symbol) = .{}, |
| 86 | 86 | unresolved: std.StringArrayHashMapUnmanaged(*Symbol) = .{}, |
| 87 | tentatives: std.StringArrayHashMapUnmanaged(*Symbol) = .{}, |
| 88 | |
| 89 | /// Offset into __DATA,__common section. |
| 90 | /// Set if the linker found tentative definitions in any of the objects. |
| 91 | tentative_defs_offset: u64 = 0, |
| 87 | 92 | |
| 88 | 93 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 89 | 94 | strtab_dir: std.StringHashMapUnmanaged(u32) = .{}, |
| ... | ... | @@ -95,9 +100,6 @@ got_entries: std.ArrayListUnmanaged(*Symbol) = .{}, |
| 95 | 100 | |
| 96 | 101 | stub_helper_stubs_start_off: ?u64 = null, |
| 97 | 102 | |
| 98 | | mappings: std.AutoHashMapUnmanaged(MappingKey, SectionMapping) = .{}, |
| 99 | | unhandled_sections: std.AutoHashMapUnmanaged(MappingKey, u0) = .{}, |
| 100 | | |
| 101 | 103 | const TlvOffset = struct { |
| 102 | 104 | source_addr: u64, |
| 103 | 105 | offset: u64, |
| ... | ... | @@ -107,18 +109,6 @@ const TlvOffset = struct { |
| 107 | 109 | } |
| 108 | 110 | }; |
| 109 | 111 | |
| 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 | 112 | /// Default path to dyld |
| 123 | 113 | const DEFAULT_DYLD_PATH: [*:0]const u8 = "/usr/lib/dyld"; |
| 124 | 114 | |
| ... | ... | @@ -159,9 +149,7 @@ pub fn deinit(self: *Zld) void { |
| 159 | 149 | } |
| 160 | 150 | self.dylibs.deinit(self.allocator); |
| 161 | 151 | |
| 162 | | self.mappings.deinit(self.allocator); |
| 163 | | self.unhandled_sections.deinit(self.allocator); |
| 164 | | |
| 152 | self.tentatives.deinit(self.allocator); |
| 165 | 153 | self.globals.deinit(self.allocator); |
| 166 | 154 | self.imports.deinit(self.allocator); |
| 167 | 155 | self.unresolved.deinit(self.allocator); |
| ... | ... | @@ -239,6 +227,7 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8, args: L |
| 239 | 227 | try self.allocateDataSegment(); |
| 240 | 228 | self.allocateLinkeditSegment(); |
| 241 | 229 | try self.allocateSymbols(); |
| 230 | try self.allocateTentativeSymbols(); |
| 242 | 231 | try self.flush(); |
| 243 | 232 | } |
| 244 | 233 | |
| ... | ... | @@ -407,46 +396,39 @@ fn parseLibs(self: *Zld, libs: []const []const u8) !void { |
| 407 | 396 | |
| 408 | 397 | fn mapAndUpdateSections( |
| 409 | 398 | self: *Zld, |
| 410 | | object_id: u16, |
| 399 | object: *Object, |
| 411 | 400 | source_sect_id: u16, |
| 412 | 401 | target_seg_id: u16, |
| 413 | 402 | target_sect_id: u16, |
| 414 | 403 | ) !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]; |
| 404 | const source_sect = &object.sections.items[source_sect_id]; |
| 418 | 405 | const target_seg = &self.load_commands.items[target_seg_id].Segment; |
| 419 | 406 | const target_sect = &target_seg.sections.items[target_sect_id]; |
| 420 | 407 | |
| 421 | 408 | const alignment = try math.powi(u32, 2, target_sect.@"align"); |
| 422 | 409 | 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), |
| 410 | const size = mem.alignForwardGeneric(u64, source_sect.inner.size, alignment); |
| 411 | |
| 412 | log.debug("{s}: '{s},{s}' mapped to '{s},{s}' from 0x{x} to 0x{x}", .{ |
| 413 | object.name.?, |
| 414 | parseName(&source_sect.inner.segname), |
| 415 | parseName(&source_sect.inner.sectname), |
| 438 | 416 | parseName(&target_sect.segname), |
| 439 | 417 | parseName(&target_sect.sectname), |
| 440 | 418 | offset, |
| 441 | 419 | offset + size, |
| 442 | 420 | }); |
| 443 | 421 | |
| 422 | source_sect.target_map = .{ |
| 423 | .segment_id = target_seg_id, |
| 424 | .section_id = target_sect_id, |
| 425 | .offset = @intCast(u32, offset), |
| 426 | }; |
| 444 | 427 | target_sect.size = offset + size; |
| 445 | 428 | } |
| 446 | 429 | |
| 447 | 430 | fn updateMetadata(self: *Zld) !void { |
| 448 | | for (self.objects.items) |object, id| { |
| 449 | | const object_id = @intCast(u16, id); |
| 431 | for (self.objects.items) |object| { |
| 450 | 432 | const object_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; |
| 451 | 433 | const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 452 | 434 | const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| ... | ... | @@ -699,20 +681,57 @@ fn updateMetadata(self: *Zld) !void { |
| 699 | 681 | for (object_seg.sections.items) |source_sect, sect_id| { |
| 700 | 682 | const source_sect_id = @intCast(u16, sect_id); |
| 701 | 683 | if (self.getMatchingSection(source_sect)) |res| { |
| 702 | | try self.mapAndUpdateSections(object_id, source_sect_id, res.seg, res.sect); |
| 684 | try self.mapAndUpdateSections(object, source_sect_id, res.seg, res.sect); |
| 703 | 685 | continue; |
| 704 | 686 | } |
| 705 | 687 | |
| 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 }); |
| 688 | log.debug("section '{s},{s}' will be unmapped", .{ |
| 689 | parseName(&source_sect.segname), |
| 690 | parseName(&source_sect.sectname), |
| 691 | }); |
| 692 | } |
| 693 | } |
| 710 | 694 | |
| 711 | | try self.unhandled_sections.putNoClobber(self.allocator, .{ |
| 712 | | .object_id = object_id, |
| 713 | | .source_sect_id = source_sect_id, |
| 714 | | }, 0); |
| 695 | // Ensure we have __DATA,__common section if we have tentative definitions. |
| 696 | // Update size and alignment of __DATA,__common section. |
| 697 | if (self.tentatives.values().len > 0) { |
| 698 | const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 699 | const common_section_index = self.common_section_index orelse ind: { |
| 700 | self.common_section_index = @intCast(u16, data_seg.sections.items.len); |
| 701 | try data_seg.addSection(self.allocator, .{ |
| 702 | .sectname = makeStaticString("__common"), |
| 703 | .segname = makeStaticString("__DATA"), |
| 704 | .addr = 0, |
| 705 | .size = 0, |
| 706 | .offset = 0, |
| 707 | .@"align" = 0, |
| 708 | .reloff = 0, |
| 709 | .nreloc = 0, |
| 710 | .flags = macho.S_ZEROFILL, |
| 711 | .reserved1 = 0, |
| 712 | .reserved2 = 0, |
| 713 | .reserved3 = 0, |
| 714 | }); |
| 715 | break :ind self.common_section_index.?; |
| 716 | }; |
| 717 | const common_sect = &data_seg.sections.items[common_section_index]; |
| 718 | |
| 719 | var max_align: u16 = 0; |
| 720 | var added_size: u64 = 0; |
| 721 | for (self.tentatives.values()) |sym| { |
| 722 | const tent = sym.cast(Symbol.Tentative) orelse unreachable; |
| 723 | max_align = math.max(max_align, tent.alignment); |
| 724 | added_size += tent.size; |
| 715 | 725 | } |
| 726 | |
| 727 | common_sect.@"align" = math.max(common_sect.@"align", max_align); |
| 728 | |
| 729 | const alignment = try math.powi(u32, 2, common_sect.@"align"); |
| 730 | const offset = mem.alignForwardGeneric(u64, common_sect.size, alignment); |
| 731 | const size = mem.alignForwardGeneric(u64, added_size, alignment); |
| 732 | |
| 733 | common_sect.size = offset + size; |
| 734 | self.tentative_defs_offset = offset; |
| 716 | 735 | } |
| 717 | 736 | |
| 718 | 737 | tlv_align: { |
| ... | ... | @@ -954,18 +973,34 @@ fn sortSections(self: *Zld) !void { |
| 954 | 973 | } |
| 955 | 974 | } |
| 956 | 975 | |
| 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; |
| 976 | for (self.objects.items) |object| { |
| 977 | for (object.sections.items) |*sect| { |
| 978 | const target_map = sect.target_map orelse continue; |
| 979 | |
| 980 | const new_index = blk: { |
| 981 | if (self.text_segment_cmd_index.? == target_map.segment_id) { |
| 982 | break :blk text_index_mapping.get(target_map.section_id) orelse unreachable; |
| 983 | } else if (self.data_const_segment_cmd_index.? == target_map.segment_id) { |
| 984 | break :blk data_const_index_mapping.get(target_map.section_id) orelse unreachable; |
| 985 | } else if (self.data_segment_cmd_index.? == target_map.segment_id) { |
| 986 | break :blk data_index_mapping.get(target_map.section_id) orelse unreachable; |
| 987 | } else unreachable; |
| 988 | }; |
| 989 | |
| 990 | log.debug("remapping in {s}: '{s},{s}': {} => {}", .{ |
| 991 | object.name.?, |
| 992 | parseName(&sect.inner.segname), |
| 993 | parseName(&sect.inner.sectname), |
| 994 | target_map.section_id, |
| 995 | new_index, |
| 996 | }); |
| 997 | |
| 998 | sect.target_map = .{ |
| 999 | .segment_id = target_map.segment_id, |
| 1000 | .section_id = new_index, |
| 1001 | .offset = target_map.offset, |
| 1002 | }; |
| 1003 | } |
| 969 | 1004 | } |
| 970 | 1005 | } |
| 971 | 1006 | |
| ... | ... | @@ -1080,30 +1115,24 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void { |
| 1080 | 1115 | } |
| 1081 | 1116 | |
| 1082 | 1117 | fn allocateSymbols(self: *Zld) !void { |
| 1083 | | for (self.objects.items) |object, object_id| { |
| 1118 | for (self.objects.items) |object| { |
| 1084 | 1119 | for (object.symbols.items) |sym| { |
| 1085 | 1120 | const reg = sym.cast(Symbol.Regular) orelse continue; |
| 1086 | 1121 | |
| 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; |
| 1122 | const source_sect = &object.sections.items[reg.section]; |
| 1123 | const target_map = source_sect.target_map orelse { |
| 1124 | log.debug("section '{s},{s}' not mapped for symbol '{s}'", .{ |
| 1125 | parseName(&source_sect.inner.segname), |
| 1126 | parseName(&source_sect.inner.sectname), |
| 1127 | sym.name, |
| 1128 | }); |
| 1129 | continue; |
| 1099 | 1130 | }; |
| 1100 | 1131 | |
| 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; |
| 1132 | const target_seg = self.load_commands.items[target_map.segment_id].Segment; |
| 1133 | const target_sect = target_seg.sections.items[target_map.section_id]; |
| 1134 | const target_addr = target_sect.addr + target_map.offset; |
| 1135 | const address = reg.address - source_sect.inner.addr + target_addr; |
| 1107 | 1136 | |
| 1108 | 1137 | log.debug("resolving symbol '{s}' at 0x{x}", .{ sym.name, address }); |
| 1109 | 1138 | |
| ... | ... | @@ -1111,8 +1140,8 @@ fn allocateSymbols(self: *Zld) !void { |
| 1111 | 1140 | var section: u8 = 0; |
| 1112 | 1141 | for (self.load_commands.items) |cmd, cmd_id| { |
| 1113 | 1142 | if (cmd != .Segment) break; |
| 1114 | | if (cmd_id == target_mapping.target_seg_id) { |
| 1115 | | section += @intCast(u8, target_mapping.target_sect_id) + 1; |
| 1143 | if (cmd_id == target_map.segment_id) { |
| 1144 | section += @intCast(u8, target_map.section_id) + 1; |
| 1116 | 1145 | break; |
| 1117 | 1146 | } |
| 1118 | 1147 | section += @intCast(u8, cmd.Segment.sections.items.len); |
| ... | ... | @@ -1124,6 +1153,74 @@ fn allocateSymbols(self: *Zld) !void { |
| 1124 | 1153 | } |
| 1125 | 1154 | } |
| 1126 | 1155 | |
| 1156 | fn allocateTentativeSymbols(self: *Zld) !void { |
| 1157 | if (self.tentatives.values().len == 0) return; |
| 1158 | |
| 1159 | const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 1160 | const common_sect = &data_seg.sections.items[self.common_section_index.?]; |
| 1161 | |
| 1162 | const alignment = try math.powi(u32, 2, common_sect.@"align"); |
| 1163 | var base_address: u64 = common_sect.addr + self.tentative_defs_offset; |
| 1164 | |
| 1165 | log.debug("base address for tentative definitions 0x{x}", .{base_address}); |
| 1166 | |
| 1167 | // TODO there might be a more generic way of doing this. |
| 1168 | var section: u8 = 0; |
| 1169 | for (self.load_commands.items) |cmd, cmd_id| { |
| 1170 | if (cmd != .Segment) break; |
| 1171 | if (cmd_id == self.data_segment_cmd_index.?) { |
| 1172 | section += @intCast(u8, self.common_section_index.?) + 1; |
| 1173 | break; |
| 1174 | } |
| 1175 | section += @intCast(u8, cmd.Segment.sections.items.len); |
| 1176 | } |
| 1177 | |
| 1178 | // Convert tentative definitions into regular symbols. |
| 1179 | for (self.tentatives.values()) |sym, i| { |
| 1180 | const tent = sym.cast(Symbol.Tentative) orelse unreachable; |
| 1181 | const reg = try self.allocator.create(Symbol.Regular); |
| 1182 | errdefer self.allocator.destroy(reg); |
| 1183 | |
| 1184 | reg.* = .{ |
| 1185 | .base = .{ |
| 1186 | .@"type" = .regular, |
| 1187 | .name = try self.allocator.dupe(u8, tent.base.name), |
| 1188 | .got_index = tent.base.got_index, |
| 1189 | .stubs_index = tent.base.stubs_index, |
| 1190 | }, |
| 1191 | .linkage = .global, |
| 1192 | .address = base_address, |
| 1193 | .section = section, |
| 1194 | .weak_ref = false, |
| 1195 | .file = tent.file, |
| 1196 | .stab = .{ |
| 1197 | .kind = .global, |
| 1198 | .size = 0, |
| 1199 | }, |
| 1200 | }; |
| 1201 | |
| 1202 | try self.globals.putNoClobber(self.allocator, reg.base.name, &reg.base); |
| 1203 | tent.base.alias = &reg.base; |
| 1204 | |
| 1205 | if (tent.base.got_index) |idx| { |
| 1206 | self.got_entries.items[idx] = &reg.base; |
| 1207 | } |
| 1208 | if (tent.base.stubs_index) |idx| { |
| 1209 | self.stubs.items[idx] = &reg.base; |
| 1210 | } |
| 1211 | |
| 1212 | const address = mem.alignForwardGeneric(u64, base_address + tent.size, alignment); |
| 1213 | |
| 1214 | log.debug("tentative definition '{s}' allocated from 0x{x} to 0x{x}", .{ |
| 1215 | tent.base.name, |
| 1216 | base_address, |
| 1217 | address, |
| 1218 | }); |
| 1219 | |
| 1220 | base_address = address; |
| 1221 | } |
| 1222 | } |
| 1223 | |
| 1127 | 1224 | fn writeStubHelperCommon(self: *Zld) !void { |
| 1128 | 1225 | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 1129 | 1226 | const stub_helper = &text_segment.sections.items[self.stub_helper_section_index.?]; |
| ... | ... | @@ -1399,6 +1496,10 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void { |
| 1399 | 1496 | if (sym.cast(Symbol.Regular)) |reg| { |
| 1400 | 1497 | if (reg.linkage == .translation_unit) continue; // Symbol local to TU. |
| 1401 | 1498 | |
| 1499 | if (self.tentatives.fetchSwapRemove(sym.name)) |kv| { |
| 1500 | // Create link to the global. |
| 1501 | kv.value.alias = sym; |
| 1502 | } |
| 1402 | 1503 | if (self.unresolved.fetchSwapRemove(sym.name)) |kv| { |
| 1403 | 1504 | // Create link to the global. |
| 1404 | 1505 | kv.value.alias = sym; |
| ... | ... | @@ -1432,15 +1533,49 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void { |
| 1432 | 1533 | |
| 1433 | 1534 | g_sym.alias = sym; |
| 1434 | 1535 | sym_ptr.* = sym; |
| 1536 | } else if (sym.cast(Symbol.Tentative)) |tent| { |
| 1537 | if (self.globals.get(sym.name)) |g_sym| { |
| 1538 | sym.alias = g_sym; |
| 1539 | continue; |
| 1540 | } |
| 1541 | |
| 1542 | if (self.unresolved.fetchSwapRemove(sym.name)) |kv| { |
| 1543 | kv.value.alias = sym; |
| 1544 | } |
| 1545 | |
| 1546 | const sym_ptr = self.tentatives.getPtr(sym.name) orelse { |
| 1547 | // Put new tentative definition symbol into symbol table. |
| 1548 | try self.tentatives.putNoClobber(self.allocator, sym.name, sym); |
| 1549 | continue; |
| 1550 | }; |
| 1551 | |
| 1552 | // Compare by size and pick the largest tentative definition. |
| 1553 | // We model this like a heap where the tentative definition with the |
| 1554 | // largest size always washes up on top. |
| 1555 | const t_sym = sym_ptr.*; |
| 1556 | const t_tent = t_sym.cast(Symbol.Tentative) orelse unreachable; |
| 1557 | |
| 1558 | if (tent.size < t_tent.size) { |
| 1559 | sym.alias = t_sym; |
| 1560 | continue; |
| 1561 | } |
| 1562 | |
| 1563 | t_sym.alias = sym; |
| 1564 | sym_ptr.* = sym; |
| 1435 | 1565 | } else if (sym.cast(Symbol.Unresolved)) |und| { |
| 1436 | 1566 | if (self.globals.get(sym.name)) |g_sym| { |
| 1437 | 1567 | sym.alias = g_sym; |
| 1438 | 1568 | continue; |
| 1439 | 1569 | } |
| 1570 | if (self.tentatives.get(sym.name)) |t_sym| { |
| 1571 | sym.alias = t_sym; |
| 1572 | continue; |
| 1573 | } |
| 1440 | 1574 | if (self.unresolved.get(sym.name)) |u_sym| { |
| 1441 | 1575 | sym.alias = u_sym; |
| 1442 | 1576 | continue; |
| 1443 | 1577 | } |
| 1578 | |
| 1444 | 1579 | try self.unresolved.putNoClobber(self.allocator, sym.name, sym); |
| 1445 | 1580 | } else unreachable; |
| 1446 | 1581 | } |
| ... | ... | @@ -1482,7 +1617,6 @@ fn resolveSymbols(self: *Zld) !void { |
| 1482 | 1617 | next_sym += 1; |
| 1483 | 1618 | } |
| 1484 | 1619 | } |
| 1485 | | |
| 1486 | 1620 | // Third pass, resolve symbols in dynamic libraries. |
| 1487 | 1621 | // TODO Implement libSystem as a hard-coded library, or ship with |
| 1488 | 1622 | // a libSystem.B.tbd definition file? |
| ... | ... | @@ -1602,10 +1736,10 @@ fn resolveStubsAndGotEntries(self: *Zld) !void { |
| 1602 | 1736 | } |
| 1603 | 1737 | |
| 1604 | 1738 | fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1605 | | for (self.objects.items) |object, object_id| { |
| 1739 | for (self.objects.items) |object| { |
| 1606 | 1740 | log.debug("relocating object {s}", .{object.name}); |
| 1607 | 1741 | |
| 1608 | | for (object.sections.items) |sect, source_sect_id| { |
| 1742 | for (object.sections.items) |sect| { |
| 1609 | 1743 | if (sect.inner.flags == macho.S_MOD_INIT_FUNC_POINTERS or |
| 1610 | 1744 | sect.inner.flags == macho.S_MOD_TERM_FUNC_POINTERS) continue; |
| 1611 | 1745 | |
| ... | ... | @@ -1614,18 +1748,15 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1614 | 1748 | |
| 1615 | 1749 | log.debug("relocating section '{s},{s}'", .{ segname, sectname }); |
| 1616 | 1750 | |
| 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 }); |
| 1751 | // Get target mapping |
| 1752 | const target_map = sect.target_map orelse { |
| 1753 | log.debug("no mapping for '{s},{s}'; skipping", .{ segname, sectname }); |
| 1623 | 1754 | continue; |
| 1624 | 1755 | }; |
| 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; |
| 1756 | const target_seg = self.load_commands.items[target_map.segment_id].Segment; |
| 1757 | const target_sect = target_seg.sections.items[target_map.section_id]; |
| 1758 | const target_sect_addr = target_sect.addr + target_map.offset; |
| 1759 | const target_sect_off = target_sect.offset + target_map.offset; |
| 1629 | 1760 | |
| 1630 | 1761 | if (sect.relocs) |relocs| { |
| 1631 | 1762 | for (relocs) |rel| { |
| ... | ... | @@ -1638,11 +1769,11 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1638 | 1769 | |
| 1639 | 1770 | switch (rel.@"type") { |
| 1640 | 1771 | .unsigned => { |
| 1641 | | args.target_addr = try self.relocTargetAddr(@intCast(u16, object_id), rel.target); |
| 1772 | args.target_addr = try self.relocTargetAddr(object, rel.target); |
| 1642 | 1773 | |
| 1643 | 1774 | const unsigned = rel.cast(reloc.Unsigned) orelse unreachable; |
| 1644 | 1775 | if (unsigned.subtractor) |subtractor| { |
| 1645 | | args.subtractor = try self.relocTargetAddr(@intCast(u16, object_id), subtractor); |
| 1776 | args.subtractor = try self.relocTargetAddr(object, subtractor); |
| 1646 | 1777 | } |
| 1647 | 1778 | if (rel.target == .section) { |
| 1648 | 1779 | const source_sect = object.sections.items[rel.target.section]; |
| ... | ... | @@ -1652,14 +1783,14 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1652 | 1783 | |
| 1653 | 1784 | rebases: { |
| 1654 | 1785 | var hit: bool = false; |
| 1655 | | if (target_mapping.target_seg_id == self.data_segment_cmd_index.?) { |
| 1786 | if (target_map.segment_id == self.data_segment_cmd_index.?) { |
| 1656 | 1787 | if (self.data_section_index) |index| { |
| 1657 | | if (index == target_mapping.target_sect_id) hit = true; |
| 1788 | if (index == target_map.section_id) hit = true; |
| 1658 | 1789 | } |
| 1659 | 1790 | } |
| 1660 | | if (target_mapping.target_seg_id == self.data_const_segment_cmd_index.?) { |
| 1791 | if (target_map.segment_id == self.data_const_segment_cmd_index.?) { |
| 1661 | 1792 | if (self.data_const_section_index) |index| { |
| 1662 | | if (index == target_mapping.target_sect_id) hit = true; |
| 1793 | if (index == target_map.section_id) hit = true; |
| 1663 | 1794 | } |
| 1664 | 1795 | } |
| 1665 | 1796 | |
| ... | ... | @@ -1667,7 +1798,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1667 | 1798 | |
| 1668 | 1799 | try self.local_rebases.append(self.allocator, .{ |
| 1669 | 1800 | .offset = source_addr - target_seg.inner.vmaddr, |
| 1670 | | .segment_id = target_mapping.target_seg_id, |
| 1801 | .segment_id = target_map.segment_id, |
| 1671 | 1802 | }); |
| 1672 | 1803 | } |
| 1673 | 1804 | // TLV is handled via a separate offset mechanism. |
| ... | ... | @@ -1705,7 +1836,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1705 | 1836 | args.source_source_sect_addr = sect.inner.addr; |
| 1706 | 1837 | args.source_target_sect_addr = source_sect.inner.addr; |
| 1707 | 1838 | } |
| 1708 | | args.target_addr = try self.relocTargetAddr(@intCast(u16, object_id), rel.target); |
| 1839 | args.target_addr = try self.relocTargetAddr(object, rel.target); |
| 1709 | 1840 | }, |
| 1710 | 1841 | } |
| 1711 | 1842 | |
| ... | ... | @@ -1744,7 +1875,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1744 | 1875 | } |
| 1745 | 1876 | } |
| 1746 | 1877 | |
| 1747 | | fn relocTargetAddr(self: *Zld, object_id: u16, target: reloc.Relocation.Target) !u64 { |
| 1878 | fn relocTargetAddr(self: *Zld, object: *const Object, target: reloc.Relocation.Target) !u64 { |
| 1748 | 1879 | const target_addr = blk: { |
| 1749 | 1880 | switch (target) { |
| 1750 | 1881 | .symbol => |sym| { |
| ... | ... | @@ -1770,13 +1901,11 @@ fn relocTargetAddr(self: *Zld, object_id: u16, target: reloc.Relocation.Target) |
| 1770 | 1901 | } |
| 1771 | 1902 | }, |
| 1772 | 1903 | .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; |
| 1904 | const source_sect = object.sections.items[sect_id]; |
| 1905 | const target_map = source_sect.target_map orelse unreachable; |
| 1906 | const target_seg = self.load_commands.items[target_map.segment_id].Segment; |
| 1907 | const target_sect = target_seg.sections.items[target_map.section_id]; |
| 1908 | break :blk target_sect.addr + target_map.offset; |
| 1780 | 1909 | }, |
| 1781 | 1910 | } |
| 1782 | 1911 | }; |
| ... | ... | @@ -2646,8 +2775,17 @@ fn writeDebugInfo(self: *Zld) !void { |
| 2646 | 2775 | }); |
| 2647 | 2776 | |
| 2648 | 2777 | for (object.symbols.items) |sym| { |
| 2649 | | if (sym.@"type" != .regular) continue; |
| 2650 | | const reg = sym.cast(Symbol.Regular) orelse unreachable; |
| 2778 | const reg = reg: { |
| 2779 | switch (sym.@"type") { |
| 2780 | .regular => break :reg sym.cast(Symbol.Regular) orelse unreachable, |
| 2781 | .tentative => { |
| 2782 | const final = sym.getTopmostAlias().cast(Symbol.Regular) orelse unreachable; |
| 2783 | if (object != final.file) continue; |
| 2784 | break :reg final; |
| 2785 | }, |
| 2786 | else => continue, |
| 2787 | } |
| 2788 | }; |
| 2651 | 2789 | |
| 2652 | 2790 | if (reg.isTemp() or reg.stab == null) continue; |
| 2653 | 2791 | const stab = reg.stab orelse unreachable; |
| ... | ... | @@ -2751,6 +2889,7 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2751 | 2889 | |
| 2752 | 2890 | const reg = final.cast(Symbol.Regular) orelse unreachable; |
| 2753 | 2891 | if (reg.isTemp()) continue; |
| 2892 | if (reg.visited) continue; |
| 2754 | 2893 | |
| 2755 | 2894 | switch (reg.linkage) { |
| 2756 | 2895 | .translation_unit => { |
| ... | ... | @@ -2772,6 +2911,8 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2772 | 2911 | }); |
| 2773 | 2912 | }, |
| 2774 | 2913 | } |
| 2914 | |
| 2915 | reg.visited = true; |
| 2775 | 2916 | } |
| 2776 | 2917 | } |
| 2777 | 2918 | |
| ... | ... | @@ -2901,20 +3042,16 @@ fn writeDataInCode(self: *Zld) !void { |
| 2901 | 3042 | |
| 2902 | 3043 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 2903 | 3044 | 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; |
| 3045 | for (self.objects.items) |object| { |
| 3046 | const source_sect = object.sections.items[object.text_section_index.?]; |
| 3047 | const target_map = source_sect.target_map orelse continue; |
| 2911 | 3048 | |
| 2912 | 3049 | try buf.ensureCapacity( |
| 2913 | 3050 | buf.items.len + object.data_in_code_entries.items.len * @sizeOf(macho.data_in_code_entry), |
| 2914 | 3051 | ); |
| 2915 | 3052 | for (object.data_in_code_entries.items) |dice| { |
| 2916 | 3053 | const new_dice: macho.data_in_code_entry = .{ |
| 2917 | | .offset = text_sect.offset + target_mapping.offset + dice.offset, |
| 3054 | .offset = text_sect.offset + target_map.offset + dice.offset, |
| 2918 | 3055 | .length = dice.length, |
| 2919 | 3056 | .kind = dice.kind, |
| 2920 | 3057 | }; |