| ... | @@ -263,6 +263,7 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8, args: L | ... | @@ -263,6 +263,7 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8, args: L |
| 263 | self.allocateLinkeditSegment(); | 263 | self.allocateLinkeditSegment(); |
| 264 | try self.allocateSymbols(); | 264 | try self.allocateSymbols(); |
| 265 | try self.allocateTentativeSymbols(); | 265 | try self.allocateTentativeSymbols(); |
| | 266 | try self.allocateProxiesBindAddresses(); |
| 266 | try self.flush(); | 267 | try self.flush(); |
| 267 | } | 268 | } |
| 268 | | 269 | |
| ... | @@ -1346,6 +1347,30 @@ fn allocateTentativeSymbols(self: *Zld) !void { | ... | @@ -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 | fn writeStubHelperCommon(self: *Zld) !void { | 1374 | fn writeStubHelperCommon(self: *Zld) !void { |
| 1350 | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; | 1375 | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 1351 | const stub_helper = &text_segment.sections.items[self.stub_helper_section_index.?]; | 1376 | const stub_helper = &text_segment.sections.items[self.stub_helper_section_index.?]; |
| ... | @@ -1863,6 +1888,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void { | ... | @@ -1863,6 +1888,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void { |
| 1863 | const relocs = sect.relocs orelse continue; | 1888 | const relocs = sect.relocs orelse continue; |
| 1864 | for (relocs) |rel| { | 1889 | for (relocs) |rel| { |
| 1865 | switch (rel.@"type") { | 1890 | switch (rel.@"type") { |
| | 1891 | .unsigned => continue, |
| 1866 | .got_page, .got_page_off, .got_load, .got, .pointer_to_got => { | 1892 | .got_page, .got_page_off, .got_load, .got, .pointer_to_got => { |
| 1867 | const sym = rel.target.symbol.getTopmostAlias(); | 1893 | const sym = rel.target.symbol.getTopmostAlias(); |
| 1868 | if (sym.got_index != null) continue; | 1894 | if (sym.got_index != null) continue; |
| ... | @@ -2090,7 +2116,10 @@ fn relocTargetAddr(self: *Zld, object: *const Object, target: reloc.Relocation.T | ... | @@ -2090,7 +2116,10 @@ fn relocTargetAddr(self: *Zld, object: *const Object, target: reloc.Relocation.T |
| 2090 | const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment; | 2116 | const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 2091 | const stubs = segment.sections.items[self.stubs_section_index.?]; | 2117 | const stubs = segment.sections.items[self.stubs_section_index.?]; |
| 2092 | const stubs_index = proxy.base.stubs_index orelse { | 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 | log.err("this is an internal linker error", .{}); | 2123 | log.err("this is an internal linker error", .{}); |
| 2095 | return error.FailedToResolveRelocationTarget; | 2124 | return error.FailedToResolveRelocationTarget; |
| 2096 | }; | 2125 | }; |
| ... | @@ -2640,6 +2669,20 @@ fn writeBindInfoTable(self: *Zld) !void { | ... | @@ -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 | if (self.tlv_section_index) |idx| { | 2686 | if (self.tlv_section_index) |idx| { |
| 2644 | const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; | 2687 | const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 2645 | const sect = seg.sections.items[idx]; | 2688 | const sect = seg.sections.items[idx]; |