| ... | ... | @@ -263,6 +263,7 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8, args: L |
| 263 | 263 | self.allocateLinkeditSegment(); |
| 264 | 264 | try self.allocateSymbols(); |
| 265 | 265 | try self.allocateTentativeSymbols(); |
| 266 | try self.allocateProxiesBindAddresses(); |
| 266 | 267 | try self.flush(); |
| 267 | 268 | } |
| 268 | 269 | |
| ... | ... | @@ -1346,6 +1347,30 @@ fn allocateTentativeSymbols(self: *Zld) !void { |
| 1346 | 1347 | } |
| 1347 | 1348 | } |
| 1348 | 1349 | |
| 1350 | fn allocateProxiesBindAddresses(self: *Zld) !void { |
| 1351 | for (self.objects.items) |object| { |
| 1352 | for (object.sections.items) |sect| { |
| 1353 | const relocs = sect.relocs orelse continue; |
| 1354 | |
| 1355 | for (relocs) |rel| { |
| 1356 | if (rel.@"type" != .unsigned) continue; // GOT is currently special-cased |
| 1357 | if (rel.target != .symbol) continue; |
| 1358 | |
| 1359 | const sym = rel.target.symbol.getTopmostAlias(); |
| 1360 | if (sym.cast(Symbol.Proxy)) |proxy| { |
| 1361 | const target_map = sect.target_map orelse continue; |
| 1362 | const target_seg = self.load_commands.items[target_map.segment_id].Segment; |
| 1363 | const target_sect = target_seg.sections.items[target_map.section_id]; |
| 1364 | try proxy.bind_info.append(self.allocator, .{ |
| 1365 | .segment_id = target_map.segment_id, |
| 1366 | .address = target_sect.addr + target_map.offset + rel.offset, |
| 1367 | }); |
| 1368 | } |
| 1369 | } |
| 1370 | } |
| 1371 | } |
| 1372 | } |
| 1373 | |
| 1349 | 1374 | fn writeStubHelperCommon(self: *Zld) !void { |
| 1350 | 1375 | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 1351 | 1376 | const stub_helper = &text_segment.sections.items[self.stub_helper_section_index.?]; |
| ... | ... | @@ -1863,6 +1888,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void { |
| 1863 | 1888 | const relocs = sect.relocs orelse continue; |
| 1864 | 1889 | for (relocs) |rel| { |
| 1865 | 1890 | switch (rel.@"type") { |
| 1891 | .unsigned => continue, |
| 1866 | 1892 | .got_page, .got_page_off, .got_load, .got, .pointer_to_got => { |
| 1867 | 1893 | const sym = rel.target.symbol.getTopmostAlias(); |
| 1868 | 1894 | if (sym.got_index != null) continue; |
| ... | ... | @@ -2090,7 +2116,10 @@ fn relocTargetAddr(self: *Zld, object: *const Object, target: reloc.Relocation.T |
| 2090 | 2116 | const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 2091 | 2117 | const stubs = segment.sections.items[self.stubs_section_index.?]; |
| 2092 | 2118 | const stubs_index = proxy.base.stubs_index orelse { |
| 2093 | | log.err("expected stubs index when relocating symbol '{s}'", .{final.name}); |
| 2119 | if (proxy.bind_info.items.len > 0) { |
| 2120 | break :blk 0; // Dynamically bound by dyld. |
| 2121 | } |
| 2122 | log.err("expected stubs index or dynamic bind address when relocating symbol '{s}'", .{final.name}); |
| 2094 | 2123 | log.err("this is an internal linker error", .{}); |
| 2095 | 2124 | return error.FailedToResolveRelocationTarget; |
| 2096 | 2125 | }; |
| ... | ... | @@ -2640,6 +2669,20 @@ fn writeBindInfoTable(self: *Zld) !void { |
| 2640 | 2669 | } |
| 2641 | 2670 | } |
| 2642 | 2671 | |
| 2672 | for (self.imports.values()) |sym| { |
| 2673 | if (sym.cast(Symbol.Proxy)) |proxy| { |
| 2674 | for (proxy.bind_info.items) |info| { |
| 2675 | const seg = self.load_commands.items[info.segment_id].Segment; |
| 2676 | try pointers.append(.{ |
| 2677 | .offset = info.address - seg.inner.vmaddr, |
| 2678 | .segment_id = info.segment_id, |
| 2679 | .dylib_ordinal = proxy.dylibOrdinal(), |
| 2680 | .name = proxy.base.name, |
| 2681 | }); |
| 2682 | } |
| 2683 | } |
| 2684 | } |
| 2685 | |
| 2643 | 2686 | if (self.tlv_section_index) |idx| { |
| 2644 | 2687 | const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 2645 | 2688 | const sect = seg.sections.items[idx]; |