authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-26 11:43:11+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-26 11:43:11+02:00
logd19d3342c29cc0f5d78cd91b61e5949a86811680
tree6ec73c2bbd0367ef503c365081173a0f14ff1f48
parentc12183b608c48ec4417c530916fc1a78b7d442f6

macho: save lazy binding info as part of the atom


3 files changed, 130 insertions(+), 96 deletions(-)

src/link/MachO.zig+77-80
...@@ -155,9 +155,7 @@ strtab: std.ArrayListUnmanaged(u8) = .{},...@@ -155,9 +155,7 @@ strtab: std.ArrayListUnmanaged(u8) = .{},
155strtab_dir: std.HashMapUnmanaged(u32, u32, StringIndexContext, std.hash_map.default_max_load_percentage) = .{},155strtab_dir: std.HashMapUnmanaged(u32, u32, StringIndexContext, std.hash_map.default_max_load_percentage) = .{},
156156
157got_entries_map: std.AutoArrayHashMapUnmanaged(GotIndirectionKey, *TextBlock) = .{},157got_entries_map: std.AutoArrayHashMapUnmanaged(GotIndirectionKey, *TextBlock) = .{},
158158stubs_map: std.AutoArrayHashMapUnmanaged(u32, *TextBlock) = .{},
159stubs: std.ArrayListUnmanaged(u32) = .{},
160stubs_map: std.AutoHashMapUnmanaged(u32, u32) = .{},
161159
162error_flags: File.ErrorFlags = File.ErrorFlags{},160error_flags: File.ErrorFlags = File.ErrorFlags{},
163161
...@@ -783,27 +781,6 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {...@@ -783,27 +781,6 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {
783781
784 try self.parseTextBlocks();782 try self.parseTextBlocks();
785 try self.sortSections();783 try self.sortSections();
786
787 for (self.stubs.items) |_| {
788 const stub_helper_atom = try self.createStubHelperAtom();
789 try self.allocateAtomStage1(stub_helper_atom, .{
790 .seg = self.text_segment_cmd_index.?,
791 .sect = self.stub_helper_section_index.?,
792 });
793
794 const laptr_atom = try self.createLazyPointerAtom(stub_helper_atom.local_sym_index);
795 try self.allocateAtomStage1(laptr_atom, .{
796 .seg = self.data_segment_cmd_index.?,
797 .sect = self.la_symbol_ptr_section_index.?,
798 });
799
800 const stub_atom = try self.createStubAtom(laptr_atom.local_sym_index);
801 try self.allocateAtomStage1(stub_atom, .{
802 .seg = self.text_segment_cmd_index.?,
803 .sect = self.stubs_section_index.?,
804 });
805 }
806
807 try self.allocateTextSegment();784 try self.allocateTextSegment();
808 try self.allocateDataConstSegment();785 try self.allocateDataConstSegment();
809 try self.allocateDataSegment();786 try self.allocateDataSegment();
...@@ -2159,7 +2136,7 @@ fn createStubHelperPreambleAtom(self: *MachO) !*TextBlock {...@@ -2159,7 +2136,7 @@ fn createStubHelperPreambleAtom(self: *MachO) !*TextBlock {
2159 return atom;2136 return atom;
2160}2137}
21612138
2162fn createStubHelperAtom(self: *MachO) !*TextBlock {2139pub fn createStubHelperAtom(self: *MachO) !*TextBlock {
2163 const arch = self.base.options.target.cpu.arch;2140 const arch = self.base.options.target.cpu.arch;
2164 const stub_size: u4 = switch (arch) {2141 const stub_size: u4 = switch (arch) {
2165 .x86_64 => 10,2142 .x86_64 => 10,
...@@ -2225,7 +2202,7 @@ fn createStubHelperAtom(self: *MachO) !*TextBlock {...@@ -2225,7 +2202,7 @@ fn createStubHelperAtom(self: *MachO) !*TextBlock {
2225 return atom;2202 return atom;
2226}2203}
22272204
2228fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32) !*TextBlock {2205pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, lazy_binding_sym_index: u32) !*TextBlock {
2229 const local_sym_index = @intCast(u32, self.locals.items.len);2206 const local_sym_index = @intCast(u32, self.locals.items.len);
2230 try self.locals.append(self.base.allocator, .{2207 try self.locals.append(self.base.allocator, .{
2231 .n_strx = try self.makeString("lazy_ptr"),2208 .n_strx = try self.makeString("lazy_ptr"),
...@@ -2248,11 +2225,15 @@ fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32) !*TextBlock {...@@ -2248,11 +2225,15 @@ fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32) !*TextBlock {
2248 },2225 },
2249 });2226 });
2250 try atom.rebases.append(self.base.allocator, 0);2227 try atom.rebases.append(self.base.allocator, 0);
2228 try atom.lazy_bindings.append(self.base.allocator, .{
2229 .local_sym_index = lazy_binding_sym_index,
2230 .offset = 0,
2231 });
2251 self.lazy_binding_info_dirty = true;2232 self.lazy_binding_info_dirty = true;
2252 return atom;2233 return atom;
2253}2234}
22542235
2255fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*TextBlock {2236pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*TextBlock {
2256 const arch = self.base.options.target.cpu.arch;2237 const arch = self.base.options.target.cpu.arch;
2257 const alignment: u2 = switch (arch) {2238 const alignment: u2 = switch (arch) {
2258 .x86_64 => 0,2239 .x86_64 => 0,
...@@ -2661,7 +2642,10 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2661,7 +2642,10 @@ fn resolveSymbols(self: *MachO) !void {
2661 break :blk atom;2642 break :blk atom;
2662 };2643 };
2663 const laptr_atom = blk: {2644 const laptr_atom = blk: {
2664 const atom = try self.createLazyPointerAtom(stub_helper_atom.local_sym_index);2645 const atom = try self.createLazyPointerAtom(
2646 stub_helper_atom.local_sym_index,
2647 resolv.where_index,
2648 );
2665 const match = MatchingSection{2649 const match = MatchingSection{
2666 .seg = self.data_segment_cmd_index.?,2650 .seg = self.data_segment_cmd_index.?,
2667 .sect = self.la_symbol_ptr_section_index.?,2651 .sect = self.la_symbol_ptr_section_index.?,
...@@ -2990,8 +2974,6 @@ fn writeRebaseInfoTableZld(self: *MachO) !void {...@@ -2990,8 +2974,6 @@ fn writeRebaseInfoTableZld(self: *MachO) !void {
2990 }2974 }
2991 }2975 }
29922976
2993 std.sort.sort(bind.Pointer, pointers.items, {}, bind.pointerCmp);
2994
2995 const size = try bind.rebaseInfoSize(pointers.items);2977 const size = try bind.rebaseInfoSize(pointers.items);
2996 var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size));2978 var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size));
2997 defer self.base.allocator.free(buffer);2979 defer self.base.allocator.free(buffer);
...@@ -3067,22 +3049,29 @@ fn writeLazyBindInfoTableZld(self: *MachO) !void {...@@ -3067,22 +3049,29 @@ fn writeLazyBindInfoTableZld(self: *MachO) !void {
3067 var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator);3049 var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator);
3068 defer pointers.deinit();3050 defer pointers.deinit();
30693051
3070 if (self.la_symbol_ptr_section_index) |idx| {3052 if (self.la_symbol_ptr_section_index) |sect| blk: {
3053 var atom = self.blocks.get(.{
3054 .seg = self.data_segment_cmd_index.?,
3055 .sect = sect,
3056 }) orelse break :blk;
3071 const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;3057 const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
3072 const sect = seg.sections.items[idx];3058
3073 const base_offset = sect.addr - seg.inner.vmaddr;3059 while (true) {
3074 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);3060 const sym = self.locals.items[atom.local_sym_index];
30753061 const base_offset = sym.n_value - seg.inner.vmaddr;
3076 try pointers.ensureUnusedCapacity(self.stubs.items.len);3062
30773063 for (atom.lazy_bindings.items) |binding| {
3078 for (self.stubs.items) |import_id, i| {3064 const bind_sym = self.undefs.items[binding.local_sym_index];
3079 const sym = self.undefs.items[import_id];3065 try pointers.append(.{
3080 pointers.appendAssumeCapacity(.{3066 .offset = binding.offset + base_offset,
3081 .offset = base_offset + i * @sizeOf(u64),3067 .segment_id = self.data_segment_cmd_index.?,
3082 .segment_id = segment_id,3068 .dylib_ordinal = @divExact(bind_sym.n_desc, macho.N_SYMBOL_RESOLVER),
3083 .dylib_ordinal = @divExact(sym.n_desc, macho.N_SYMBOL_RESOLVER),3069 .name = self.getString(bind_sym.n_strx),
3084 .name = self.getString(sym.n_strx),3070 });
3085 });3071 }
3072 if (atom.prev) |prev| {
3073 atom = prev;
3074 } else break;
3086 }3075 }
3087 }3076 }
30883077
...@@ -3245,7 +3234,7 @@ fn writeSymbolTable(self: *MachO) !void {...@@ -3245,7 +3234,7 @@ fn writeSymbolTable(self: *MachO) !void {
3245 const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;3234 const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
3246 const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?];3235 const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?];
32473236
3248 const nstubs = @intCast(u32, self.stubs.items.len);3237 const nstubs = @intCast(u32, self.stubs_map.keys().len);
3249 const ngot_entries = @intCast(u32, self.got_entries_map.keys().len);3238 const ngot_entries = @intCast(u32, self.got_entries_map.keys().len);
32503239
3251 dysymtab.indirectsymoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize);3240 dysymtab.indirectsymoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize);
...@@ -3266,8 +3255,8 @@ fn writeSymbolTable(self: *MachO) !void {...@@ -3266,8 +3255,8 @@ fn writeSymbolTable(self: *MachO) !void {
3266 var writer = stream.writer();3255 var writer = stream.writer();
32673256
3268 stubs.reserved1 = 0;3257 stubs.reserved1 = 0;
3269 for (self.stubs.items) |id| {3258 for (self.stubs_map.keys()) |key| {
3270 try writer.writeIntLittle(u32, dysymtab.iundefsym + id);3259 try writer.writeIntLittle(u32, dysymtab.iundefsym + key);
3271 }3260 }
32723261
3273 got.reserved1 = nstubs;3262 got.reserved1 = nstubs;
...@@ -3283,8 +3272,8 @@ fn writeSymbolTable(self: *MachO) !void {...@@ -3283,8 +3272,8 @@ fn writeSymbolTable(self: *MachO) !void {
3283 }3272 }
32843273
3285 la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries;3274 la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries;
3286 for (self.stubs.items) |id| {3275 for (self.stubs_map.keys()) |key| {
3287 try writer.writeIntLittle(u32, dysymtab.iundefsym + id);3276 try writer.writeIntLittle(u32, dysymtab.iundefsym + key);
3288 }3277 }
32893278
3290 try self.base.file.?.pwriteAll(buf, dysymtab.indirectsymoff);3279 try self.base.file.?.pwriteAll(buf, dysymtab.indirectsymoff);
...@@ -3301,7 +3290,6 @@ pub fn deinit(self: *MachO) void {...@@ -3301,7 +3290,6 @@ pub fn deinit(self: *MachO) void {
33013290
3302 self.section_ordinals.deinit(self.base.allocator);3291 self.section_ordinals.deinit(self.base.allocator);
3303 self.got_entries_map.deinit(self.base.allocator);3292 self.got_entries_map.deinit(self.base.allocator);
3304 self.stubs.deinit(self.base.allocator);
3305 self.stubs_map.deinit(self.base.allocator);3293 self.stubs_map.deinit(self.base.allocator);
3306 self.strtab_dir.deinit(self.base.allocator);3294 self.strtab_dir.deinit(self.base.allocator);
3307 self.strtab.deinit(self.base.allocator);3295 self.strtab.deinit(self.base.allocator);
...@@ -4557,10 +4545,6 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {...@@ -4557,10 +4545,6 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {
4557 });4545 });
4558 try self.unresolved.putNoClobber(self.base.allocator, sym_index, .stub);4546 try self.unresolved.putNoClobber(self.base.allocator, sym_index, .stub);
45594547
4560 const stubs_index = @intCast(u32, self.stubs.items.len);
4561 try self.stubs.append(self.base.allocator, sym_index);
4562 try self.stubs_map.putNoClobber(self.base.allocator, sym_index, stubs_index);
4563
4564 return sym_index;4548 return sym_index;
4565}4549}
45664550
...@@ -4803,7 +4787,7 @@ fn writeIndirectSymbolTable(self: *MachO) !void {...@@ -4803,7 +4787,7 @@ fn writeIndirectSymbolTable(self: *MachO) !void {
4803 const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?];4787 const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?];
4804 const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;4788 const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;
48054789
4806 const nstubs = @intCast(u32, self.stubs.items.len);4790 const nstubs = @intCast(u32, self.stubs_map.keys().len);
4807 const ngot_entries = @intCast(u32, self.got_entries_map.keys().len);4791 const ngot_entries = @intCast(u32, self.got_entries_map.keys().len);
4808 const allocated_size = self.allocatedSizeLinkedit(dysymtab.indirectsymoff);4792 const allocated_size = self.allocatedSizeLinkedit(dysymtab.indirectsymoff);
4809 const nindirectsyms = nstubs * 2 + ngot_entries;4793 const nindirectsyms = nstubs * 2 + ngot_entries;
...@@ -4825,8 +4809,8 @@ fn writeIndirectSymbolTable(self: *MachO) !void {...@@ -4825,8 +4809,8 @@ fn writeIndirectSymbolTable(self: *MachO) !void {
4825 var writer = stream.writer();4809 var writer = stream.writer();
48264810
4827 stubs.reserved1 = 0;4811 stubs.reserved1 = 0;
4828 for (self.stubs.items) |id| {4812 for (self.stubs_map.keys()) |key| {
4829 try writer.writeIntLittle(u32, dysymtab.iundefsym + id);4813 try writer.writeIntLittle(u32, dysymtab.iundefsym + key);
4830 }4814 }
48314815
4832 got.reserved1 = nstubs;4816 got.reserved1 = nstubs;
...@@ -4842,8 +4826,8 @@ fn writeIndirectSymbolTable(self: *MachO) !void {...@@ -4842,8 +4826,8 @@ fn writeIndirectSymbolTable(self: *MachO) !void {
4842 }4826 }
48434827
4844 la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries;4828 la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries;
4845 for (self.stubs.items) |id| {4829 for (self.stubs_map.keys()) |key| {
4846 try writer.writeIntLittle(u32, dysymtab.iundefsym + id);4830 try writer.writeIntLittle(u32, dysymtab.iundefsym + key);
4847 }4831 }
48484832
4849 try self.base.file.?.pwriteAll(buf, dysymtab.indirectsymoff);4833 try self.base.file.?.pwriteAll(buf, dysymtab.indirectsymoff);
...@@ -5050,8 +5034,6 @@ fn writeRebaseInfoTable(self: *MachO) !void {...@@ -5050,8 +5034,6 @@ fn writeRebaseInfoTable(self: *MachO) !void {
5050 }5034 }
5051 }5035 }
50525036
5053 std.sort.sort(bind.Pointer, pointers.items, {}, bind.pointerCmp);
5054
5055 const size = try bind.rebaseInfoSize(pointers.items);5037 const size = try bind.rebaseInfoSize(pointers.items);
5056 var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size));5038 var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size));
5057 defer self.base.allocator.free(buffer);5039 defer self.base.allocator.free(buffer);
...@@ -5151,22 +5133,29 @@ fn writeLazyBindInfoTable(self: *MachO) !void {...@@ -5151,22 +5133,29 @@ fn writeLazyBindInfoTable(self: *MachO) !void {
5151 var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator);5133 var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator);
5152 defer pointers.deinit();5134 defer pointers.deinit();
51535135
5154 if (self.la_symbol_ptr_section_index) |idx| {5136 if (self.la_symbol_ptr_section_index) |sect| blk: {
5137 var atom = self.blocks.get(.{
5138 .seg = self.data_segment_cmd_index.?,
5139 .sect = sect,
5140 }) orelse break :blk;
5155 const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;5141 const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
5156 const sect = seg.sections.items[idx];5142
5157 const base_offset = sect.addr - seg.inner.vmaddr;5143 while (true) {
5158 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);5144 const sym = self.locals.items[atom.local_sym_index];
51595145 const base_offset = sym.n_value - seg.inner.vmaddr;
5160 try pointers.ensureUnusedCapacity(self.stubs.items.len);5146
51615147 for (atom.lazy_bindings.items) |binding| {
5162 for (self.stubs.items) |import_id, i| {5148 const bind_sym = self.undefs.items[binding.local_sym_index];
5163 const sym = self.undefs.items[import_id];5149 try pointers.append(.{
5164 pointers.appendAssumeCapacity(.{5150 .offset = binding.offset + base_offset,
5165 .offset = base_offset + i * @sizeOf(u64),5151 .segment_id = self.data_segment_cmd_index.?,
5166 .segment_id = segment_id,5152 .dylib_ordinal = @divExact(bind_sym.n_desc, macho.N_SYMBOL_RESOLVER),
5167 .dylib_ordinal = @divExact(sym.n_desc, macho.N_SYMBOL_RESOLVER),5153 .name = self.getString(bind_sym.n_strx),
5168 .name = self.getString(sym.n_strx),5154 });
5169 });5155 }
5156 if (atom.prev) |prev| {
5157 atom = prev;
5158 } else break;
5170 }5159 }
5171 }5160 }
51725161
...@@ -5203,6 +5192,15 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void {...@@ -5203,6 +5192,15 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void {
5203 }) orelse return;5192 }) orelse return;
5204 if (last_atom.local_sym_index == self.stub_preamble_sym_index.?) return;5193 if (last_atom.local_sym_index == self.stub_preamble_sym_index.?) return;
52055194
5195 // Because we insert lazy binding opcodes in reverse order (from last to the first atom),
5196 // we need reverse the order of atom traversal here as well.
5197 // TODO figure out a less error prone mechanims for this!
5198 var atom = last_atom;
5199 while (atom.prev) |prev| {
5200 atom = prev;
5201 }
5202 atom = atom.next.?;
5203
5206 var stream = std.io.fixedBufferStream(buffer);5204 var stream = std.io.fixedBufferStream(buffer);
5207 var reader = stream.reader();5205 var reader = stream.reader();
5208 var offsets = std.ArrayList(u32).init(self.base.allocator);5206 var offsets = std.ArrayList(u32).init(self.base.allocator);
...@@ -5255,7 +5253,6 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void {...@@ -5255,7 +5253,6 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void {
5255 else => unreachable,5253 else => unreachable,
5256 };5254 };
5257 var buf: [@sizeOf(u32)]u8 = undefined;5255 var buf: [@sizeOf(u32)]u8 = undefined;
5258 var atom = last_atom;
5259 _ = offsets.pop();5256 _ = offsets.pop();
5260 while (offsets.popOrNull()) |bind_offset| {5257 while (offsets.popOrNull()) |bind_offset| {
5261 const sym = self.locals.items[atom.local_sym_index];5258 const sym = self.locals.items[atom.local_sym_index];
...@@ -5268,8 +5265,8 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void {...@@ -5268,8 +5265,8 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void {
5268 });5265 });
5269 try self.base.file.?.pwriteAll(&buf, file_offset);5266 try self.base.file.?.pwriteAll(&buf, file_offset);
52705267
5271 if (atom.prev) |prev| {5268 if (atom.next) |next| {
5272 atom = prev;5269 atom = next;
5273 } else break;5270 } else break;
5274 }5271 }
5275}5272}
src/link/MachO/TextBlock.zig+53-7
...@@ -50,6 +50,9 @@ rebases: std.ArrayListUnmanaged(u64) = .{},...@@ -50,6 +50,9 @@ rebases: std.ArrayListUnmanaged(u64) = .{},
50/// symbols (aka proxies aka imports)50/// symbols (aka proxies aka imports)
51bindings: std.ArrayListUnmanaged(SymbolAtOffset) = .{},51bindings: std.ArrayListUnmanaged(SymbolAtOffset) = .{},
5252
53/// List of lazy bindings
54lazy_bindings: std.ArrayListUnmanaged(SymbolAtOffset) = .{},
55
53/// List of data-in-code entries. This is currently specific to x86_64 only.56/// List of data-in-code entries. This is currently specific to x86_64 only.
54dices: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{},57dices: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{},
5558
...@@ -570,6 +573,7 @@ pub const empty = TextBlock{...@@ -570,6 +573,7 @@ pub const empty = TextBlock{
570573
571pub fn deinit(self: *TextBlock, allocator: *Allocator) void {574pub fn deinit(self: *TextBlock, allocator: *Allocator) void {
572 self.dices.deinit(allocator);575 self.dices.deinit(allocator);
576 self.lazy_bindings.deinit(allocator);
573 self.bindings.deinit(allocator);577 self.bindings.deinit(allocator);
574 self.rebases.deinit(allocator);578 self.rebases.deinit(allocator);
575 self.relocs.deinit(allocator);579 self.relocs.deinit(allocator);
...@@ -898,9 +902,53 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R...@@ -898,9 +902,53 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
898 if (parsed_rel.where != .undef) break :blk;902 if (parsed_rel.where != .undef) break :blk;
899 if (context.macho_file.stubs_map.contains(parsed_rel.where_index)) break :blk;903 if (context.macho_file.stubs_map.contains(parsed_rel.where_index)) break :blk;
900904
901 const stubs_index = @intCast(u32, context.macho_file.stubs.items.len);905 const stub_helper_atom = try context.macho_file.createStubHelperAtom();
902 try context.macho_file.stubs.append(context.allocator, parsed_rel.where_index);906 const laptr_atom = try context.macho_file.createLazyPointerAtom(
903 try context.macho_file.stubs_map.putNoClobber(context.allocator, parsed_rel.where_index, stubs_index);907 stub_helper_atom.local_sym_index,
908 parsed_rel.where_index,
909 );
910 const stub_atom = try context.macho_file.createStubAtom(laptr_atom.local_sym_index);
911 try context.macho_file.stubs_map.putNoClobber(context.allocator, parsed_rel.where_index, stub_atom);
912
913 if (build_options.is_stage1 and context.macho_file.base.options.use_stage1) {
914 try context.macho_file.allocateAtomStage1(stub_helper_atom, .{
915 .seg = context.macho_file.text_segment_cmd_index.?,
916 .sect = context.macho_file.stub_helper_section_index.?,
917 });
918 try context.macho_file.allocateAtomStage1(laptr_atom, .{
919 .seg = context.macho_file.data_segment_cmd_index.?,
920 .sect = context.macho_file.la_symbol_ptr_section_index.?,
921 });
922 try context.macho_file.allocateAtomStage1(stub_atom, .{
923 .seg = context.macho_file.text_segment_cmd_index.?,
924 .sect = context.macho_file.stubs_section_index.?,
925 });
926 } else {
927 {
928 const match = MachO.MatchingSection{
929 .seg = context.macho_file.text_segment_cmd_index.?,
930 .sect = context.macho_file.stub_helper_section_index.?,
931 };
932 _ = try context.macho_file.allocateAtom(stub_helper_atom, match);
933 try context.macho_file.writeAtom(stub_helper_atom, match);
934 }
935 {
936 const match = MachO.MatchingSection{
937 .seg = context.macho_file.data_segment_cmd_index.?,
938 .sect = context.macho_file.la_symbol_ptr_section_index.?,
939 };
940 _ = try context.macho_file.allocateAtom(laptr_atom, match);
941 try context.macho_file.writeAtom(laptr_atom, match);
942 }
943 {
944 const match = MachO.MatchingSection{
945 .seg = context.macho_file.text_segment_cmd_index.?,
946 .sect = context.macho_file.stubs_section_index.?,
947 };
948 _ = try context.macho_file.allocateAtom(stub_atom, match);
949 try context.macho_file.writeAtom(stub_atom, match);
950 }
951 }
904 }952 }
905 }953 }
906}954}
...@@ -1145,13 +1193,11 @@ pub fn resolveRelocs(self: *TextBlock, macho_file: *MachO) !void {...@@ -1145,13 +1193,11 @@ pub fn resolveRelocs(self: *TextBlock, macho_file: *MachO) !void {
1145 break :blk sym.n_value;1193 break :blk sym.n_value;
1146 },1194 },
1147 .undef => {1195 .undef => {
1148 const stubs_index = macho_file.stubs_map.get(rel.where_index) orelse {1196 const atom = macho_file.stubs_map.get(rel.where_index) orelse {
1149 // TODO verify in TextBlock that the symbol is indeed dynamically bound.1197 // TODO verify in TextBlock that the symbol is indeed dynamically bound.
1150 break :blk 0; // Dynamically bound by dyld.1198 break :blk 0; // Dynamically bound by dyld.
1151 };1199 };
1152 const segment = macho_file.load_commands.items[macho_file.text_segment_cmd_index.?].Segment;1200 break :blk macho_file.locals.items[atom.local_sym_index].n_value;
1153 const stubs = segment.sections.items[macho_file.stubs_section_index.?];
1154 break :blk stubs.addr + stubs_index * stubs.reserved2;
1155 },1201 },
1156 }1202 }
1157 };1203 };
src/link/MachO/bind.zig-9
...@@ -9,15 +9,6 @@ pub const Pointer = struct {...@@ -9,15 +9,6 @@ pub const Pointer = struct {
9 name: ?[]const u8 = null,9 name: ?[]const u8 = null,
10};10};
1111
12pub fn pointerCmp(context: void, a: Pointer, b: Pointer) bool {
13 _ = context;
14 if (a.segment_id < b.segment_id) return true;
15 if (a.segment_id == b.segment_id) {
16 return a.offset < b.offset;
17 }
18 return false;
19}
20
21pub fn rebaseInfoSize(pointers: []const Pointer) !u64 {12pub fn rebaseInfoSize(pointers: []const Pointer) !u64 {
22 var stream = std.io.countingWriter(std.io.null_writer);13 var stream = std.io.countingWriter(std.io.null_writer);
23 var writer = stream.writer();14 var writer = stream.writer();