| ... | @@ -138,7 +138,11 @@ locals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | ... | @@ -138,7 +138,11 @@ locals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 138 | globals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | 138 | globals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 139 | undefs: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | 139 | undefs: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 140 | symbol_resolver: std.AutoHashMapUnmanaged(u32, SymbolWithLoc) = .{}, | 140 | symbol_resolver: std.AutoHashMapUnmanaged(u32, SymbolWithLoc) = .{}, |
| 141 | unresolved: std.AutoArrayHashMapUnmanaged(u32, void) = .{}, | 141 | unresolved: std.AutoArrayHashMapUnmanaged(u32, enum { |
| | 142 | none, |
| | 143 | stub, |
| | 144 | got, |
| | 145 | }) = .{}, |
| 142 | | 146 | |
| 143 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, | 147 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 144 | globals_free_list: std.ArrayListUnmanaged(u32) = .{}, | 148 | globals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| ... | @@ -147,8 +151,6 @@ dyld_private_sym_index: ?u32 = null, | ... | @@ -147,8 +151,6 @@ dyld_private_sym_index: ?u32 = null, |
| 147 | dyld_stub_binder_index: ?u32 = null, | 151 | dyld_stub_binder_index: ?u32 = null, |
| 148 | stub_preamble_sym_index: ?u32 = null, | 152 | stub_preamble_sym_index: ?u32 = null, |
| 149 | | 153 | |
| 150 | stub_helper_stubs_start_off: ?u64 = null, | | |
| 151 | | | |
| 152 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 154 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 153 | strtab_dir: std.HashMapUnmanaged(u32, u32, StringIndexContext, std.hash_map.default_max_load_percentage) = .{}, | 155 | strtab_dir: std.HashMapUnmanaged(u32, u32, StringIndexContext, std.hash_map.default_max_load_percentage) = .{}, |
| 154 | | 156 | |
| ... | @@ -382,26 +384,6 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -382,26 +384,6 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 382 | try ds.writeLocalSymbol(0); | 384 | try ds.writeLocalSymbol(0); |
| 383 | } | 385 | } |
| 384 | | 386 | |
| 385 | { | | |
| 386 | const atom = try self.createDyldPrivateAtom(); | | |
| 387 | const match = MatchingSection{ | | |
| 388 | .seg = self.data_segment_cmd_index.?, | | |
| 389 | .sect = self.data_section_index.?, | | |
| 390 | }; | | |
| 391 | const vaddr = try self.allocateAtom(atom, match); | | |
| 392 | try self.writeAtom(atom, match); | | |
| 393 | } | | |
| 394 | | | |
| 395 | { | | |
| 396 | const atom = try self.createStubHelperPreambleAtom(); | | |
| 397 | const match = MatchingSection{ | | |
| 398 | .seg = self.text_segment_cmd_index.?, | | |
| 399 | .sect = self.stub_helper_section_index.?, | | |
| 400 | }; | | |
| 401 | const vaddr = try self.allocateAtom(atom, match); | | |
| 402 | try self.writeAtom(atom, match); | | |
| 403 | } | | |
| 404 | | | |
| 405 | return self; | 387 | return self; |
| 406 | } | 388 | } |
| 407 | | 389 | |
| ... | @@ -776,8 +758,8 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { | ... | @@ -776,8 +758,8 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { |
| 776 | | 758 | |
| 777 | try self.parseInputFiles(positionals.items, self.base.options.sysroot); | 759 | try self.parseInputFiles(positionals.items, self.base.options.sysroot); |
| 778 | try self.parseLibs(libs.items, self.base.options.sysroot); | 760 | try self.parseLibs(libs.items, self.base.options.sysroot); |
| | 761 | |
| 779 | try self.resolveSymbols(); | 762 | try self.resolveSymbols(); |
| 780 | try self.resolveDyldStubBinder(); | | |
| 781 | try self.addRpathLCs(rpath_table.keys()); | 763 | try self.addRpathLCs(rpath_table.keys()); |
| 782 | try self.addLoadDylibLCs(); | 764 | try self.addLoadDylibLCs(); |
| 783 | try self.addDataInCodeLC(); | 765 | try self.addDataInCodeLC(); |
| ... | @@ -799,7 +781,6 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { | ... | @@ -799,7 +781,6 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { |
| 799 | .seg = self.text_segment_cmd_index.?, | 781 | .seg = self.text_segment_cmd_index.?, |
| 800 | .sect = self.stub_helper_section_index.?, | 782 | .sect = self.stub_helper_section_index.?, |
| 801 | }); | 783 | }); |
| 802 | | | |
| 803 | // TODO this is just a temp | 784 | // TODO this is just a temp |
| 804 | // We already prealloc stub helper size in populateMissingMetadata(), but | 785 | // We already prealloc stub helper size in populateMissingMetadata(), but |
| 805 | // perhaps it's not needed after all? | 786 | // perhaps it's not needed after all? |
| ... | @@ -807,6 +788,7 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { | ... | @@ -807,6 +788,7 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { |
| 807 | const sect = &seg.sections.items[self.stub_helper_section_index.?]; | 788 | const sect = &seg.sections.items[self.stub_helper_section_index.?]; |
| 808 | sect.size -= atom.size; | 789 | sect.size -= atom.size; |
| 809 | } | 790 | } |
| | 791 | |
| 810 | for (self.stubs.items) |_| { | 792 | for (self.stubs.items) |_| { |
| 811 | const stub_helper_atom = try self.createStubHelperAtom(); | 793 | const stub_helper_atom = try self.createStubHelperAtom(); |
| 812 | try self.allocateAtomStage1(stub_helper_atom, .{ | 794 | try self.allocateAtomStage1(stub_helper_atom, .{ |
| ... | @@ -826,21 +808,12 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { | ... | @@ -826,21 +808,12 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { |
| 826 | .sect = self.stubs_section_index.?, | 808 | .sect = self.stubs_section_index.?, |
| 827 | }); | 809 | }); |
| 828 | } | 810 | } |
| | 811 | |
| 829 | try self.allocateTextSegment(); | 812 | try self.allocateTextSegment(); |
| 830 | try self.allocateDataConstSegment(); | 813 | try self.allocateDataConstSegment(); |
| 831 | try self.allocateDataSegment(); | 814 | try self.allocateDataSegment(); |
| 832 | self.allocateLinkeditSegment(); | 815 | self.allocateLinkeditSegment(); |
| 833 | try self.allocateTextBlocks(); | 816 | try self.allocateTextBlocks(); |
| 834 | { | | |
| 835 | // TODO just a temp | | |
| 836 | const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; | | |
| 837 | const sect = seg.sections.items[self.stub_helper_section_index.?]; | | |
| 838 | self.stub_helper_stubs_start_off = sect.offset + switch (self.base.options.target.cpu.arch) { | | |
| 839 | .x86_64 => @intCast(u64, 15), | | |
| 840 | .aarch64 => @intCast(u64, 6 * @sizeOf(u32)), | | |
| 841 | else => unreachable, | | |
| 842 | }; | | |
| 843 | } | | |
| 844 | try self.flushZld(); | 817 | try self.flushZld(); |
| 845 | } else { | 818 | } else { |
| 846 | try self.flushModule(comp); | 819 | try self.flushModule(comp); |
| ... | @@ -1937,13 +1910,7 @@ fn writeTextBlocks(self: *MachO) !void { | ... | @@ -1937,13 +1910,7 @@ fn writeTextBlocks(self: *MachO) !void { |
| 1937 | } | 1910 | } |
| 1938 | } | 1911 | } |
| 1939 | | 1912 | |
| 1940 | fn createEmptyAtom( | 1913 | fn createEmptyAtom(self: *MachO, local_sym_index: u32, size: u64, alignment: u32) !*TextBlock { |
| 1941 | self: *MachO, | | |
| 1942 | match: MatchingSection, | | |
| 1943 | local_sym_index: u32, | | |
| 1944 | size: u64, | | |
| 1945 | alignment: u32, | | |
| 1946 | ) !*TextBlock { | | |
| 1947 | const code = try self.base.allocator.alloc(u8, size); | 1914 | const code = try self.base.allocator.alloc(u8, size); |
| 1948 | defer self.base.allocator.free(code); | 1915 | defer self.base.allocator.free(code); |
| 1949 | mem.set(u8, code, 0); | 1916 | mem.set(u8, code, 0); |
| ... | @@ -1964,15 +1931,20 @@ fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 { | ... | @@ -1964,15 +1931,20 @@ fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 { |
| 1964 | // TODO converge with `allocateTextBlock` | 1931 | // TODO converge with `allocateTextBlock` |
| 1965 | const seg = self.load_commands.items[match.seg].Segment; | 1932 | const seg = self.load_commands.items[match.seg].Segment; |
| 1966 | const sect = seg.sections.items[match.sect]; | 1933 | const sect = seg.sections.items[match.sect]; |
| 1967 | const base_addr = if (atom.prev) |prev| blk: { | 1934 | const sym = &self.locals.items[atom.local_sym_index]; |
| 1968 | const prev_atom_sym = self.locals.items[prev.local_sym_index]; | 1935 | const base_addr = if (self.blocks.get(match)) |last| blk: { |
| 1969 | break :blk prev_atom_sym.n_value; | 1936 | const last_atom_sym = self.locals.items[last.local_sym_index]; |
| | 1937 | break :blk last_atom_sym.n_value + last.size; |
| 1970 | } else sect.addr; | 1938 | } else sect.addr; |
| 1971 | const atom_alignment = try math.powi(u32, 2, atom.alignment); | 1939 | const atom_alignment = try math.powi(u32, 2, atom.alignment); |
| 1972 | const vaddr = mem.alignForwardGeneric(u64, base_addr, atom_alignment); | 1940 | const vaddr = mem.alignForwardGeneric(u64, base_addr, atom_alignment); |
| | 1941 | log.debug("allocating atom for symbol {s} at address 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| 1973 | | 1942 | |
| 1974 | // TODO we should check if we need to expand the section or not like we | 1943 | // TODO we should check if we need to expand the section or not like we |
| 1975 | // do in `allocateTextBlock`. | 1944 | // do in `allocateTextBlock`. |
| | 1945 | sym.n_value = vaddr; |
| | 1946 | sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); |
| | 1947 | |
| 1976 | if (self.blocks.getPtr(match)) |last| { | 1948 | if (self.blocks.getPtr(match)) |last| { |
| 1977 | last.*.next = atom; | 1949 | last.*.next = atom; |
| 1978 | atom.prev = last.*; | 1950 | atom.prev = last.*; |
| ... | @@ -1987,15 +1959,9 @@ fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 { | ... | @@ -1987,15 +1959,9 @@ fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 { |
| 1987 | fn writeAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !void { | 1959 | fn writeAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !void { |
| 1988 | const seg = self.load_commands.items[match.seg].Segment; | 1960 | const seg = self.load_commands.items[match.seg].Segment; |
| 1989 | const sect = seg.sections.items[match.sect]; | 1961 | const sect = seg.sections.items[match.sect]; |
| 1990 | | 1962 | const sym = self.locals.items[atom.local_sym_index]; |
| 1991 | const vaddr = try self.allocateAtom(atom, match); | 1963 | const file_offset = sect.offset + sym.n_value - sect.addr; |
| 1992 | const sym = &self.locals.items[atom.local_sym_index]; | | |
| 1993 | sym.n_value = vaddr; | | |
| 1994 | sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); | | |
| 1995 | | | |
| 1996 | try atom.resolveRelocs(self); | 1964 | try atom.resolveRelocs(self); |
| 1997 | | | |
| 1998 | const file_offset = sect.offset + vaddr - sect.addr; | | |
| 1999 | log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ self.getString(sym.n_strx), file_offset }); | 1965 | log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ self.getString(sym.n_strx), file_offset }); |
| 2000 | try self.base.file.?.pwriteAll(atom.code.items, file_offset); | 1966 | try self.base.file.?.pwriteAll(atom.code.items, file_offset); |
| 2001 | try self.writeLocalSymbol(atom.local_sym_index); | 1967 | try self.writeLocalSymbol(atom.local_sym_index); |
| ... | @@ -2023,10 +1989,6 @@ fn allocateAtomStage1(self: *MachO, atom: *TextBlock, match: MatchingSection) !v | ... | @@ -2023,10 +1989,6 @@ fn allocateAtomStage1(self: *MachO, atom: *TextBlock, match: MatchingSection) !v |
| 2023 | } | 1989 | } |
| 2024 | | 1990 | |
| 2025 | fn createDyldPrivateAtom(self: *MachO) !*TextBlock { | 1991 | fn createDyldPrivateAtom(self: *MachO) !*TextBlock { |
| 2026 | const match = MatchingSection{ | | |
| 2027 | .seg = self.data_segment_cmd_index.?, | | |
| 2028 | .sect = self.data_section_index.?, | | |
| 2029 | }; | | |
| 2030 | const local_sym_index = @intCast(u32, self.locals.items.len); | 1992 | const local_sym_index = @intCast(u32, self.locals.items.len); |
| 2031 | try self.locals.append(self.base.allocator, .{ | 1993 | try self.locals.append(self.base.allocator, .{ |
| 2032 | .n_strx = try self.makeString("dyld_private"), | 1994 | .n_strx = try self.makeString("dyld_private"), |
| ... | @@ -2036,15 +1998,11 @@ fn createDyldPrivateAtom(self: *MachO) !*TextBlock { | ... | @@ -2036,15 +1998,11 @@ fn createDyldPrivateAtom(self: *MachO) !*TextBlock { |
| 2036 | .n_value = 0, | 1998 | .n_value = 0, |
| 2037 | }); | 1999 | }); |
| 2038 | self.dyld_private_sym_index = local_sym_index; | 2000 | self.dyld_private_sym_index = local_sym_index; |
| 2039 | return self.createEmptyAtom(match, local_sym_index, @sizeOf(u64), 3); | 2001 | return self.createEmptyAtom(local_sym_index, @sizeOf(u64), 3); |
| 2040 | } | 2002 | } |
| 2041 | | 2003 | |
| 2042 | fn createStubHelperPreambleAtom(self: *MachO) !*TextBlock { | 2004 | fn createStubHelperPreambleAtom(self: *MachO) !*TextBlock { |
| 2043 | const arch = self.base.options.target.cpu.arch; | 2005 | const arch = self.base.options.target.cpu.arch; |
| 2044 | const match = MatchingSection{ | | |
| 2045 | .seg = self.text_segment_cmd_index.?, | | |
| 2046 | .sect = self.stub_helper_section_index.?, | | |
| 2047 | }; | | |
| 2048 | const size: u64 = switch (arch) { | 2006 | const size: u64 = switch (arch) { |
| 2049 | .x86_64 => 15, | 2007 | .x86_64 => 15, |
| 2050 | .aarch64 => 6 * @sizeOf(u32), | 2008 | .aarch64 => 6 * @sizeOf(u32), |
| ... | @@ -2063,7 +2021,7 @@ fn createStubHelperPreambleAtom(self: *MachO) !*TextBlock { | ... | @@ -2063,7 +2021,7 @@ fn createStubHelperPreambleAtom(self: *MachO) !*TextBlock { |
| 2063 | .n_desc = 0, | 2021 | .n_desc = 0, |
| 2064 | .n_value = 0, | 2022 | .n_value = 0, |
| 2065 | }); | 2023 | }); |
| 2066 | const atom = try self.createEmptyAtom(match, local_sym_index, size, alignment); | 2024 | const atom = try self.createEmptyAtom(local_sym_index, size, alignment); |
| 2067 | switch (arch) { | 2025 | switch (arch) { |
| 2068 | .x86_64 => { | 2026 | .x86_64 => { |
| 2069 | try atom.relocs.ensureUnusedCapacity(self.base.allocator, 2); | 2027 | try atom.relocs.ensureUnusedCapacity(self.base.allocator, 2); |
| ... | @@ -2196,10 +2154,7 @@ fn createStubHelperAtom(self: *MachO) !*TextBlock { | ... | @@ -2196,10 +2154,7 @@ fn createStubHelperAtom(self: *MachO) !*TextBlock { |
| 2196 | .n_desc = 0, | 2154 | .n_desc = 0, |
| 2197 | .n_value = 0, | 2155 | .n_value = 0, |
| 2198 | }); | 2156 | }); |
| 2199 | const atom = try self.createEmptyAtom(.{ | 2157 | const atom = try self.createEmptyAtom(local_sym_index, stub_size, alignment); |
| 2200 | .seg = self.text_segment_cmd_index.?, | | |
| 2201 | .sect = self.stub_helper_section_index.?, | | |
| 2202 | }, local_sym_index, stub_size, alignment); | | |
| 2203 | try atom.relocs.ensureTotalCapacity(self.base.allocator, 1); | 2158 | try atom.relocs.ensureTotalCapacity(self.base.allocator, 1); |
| 2204 | | 2159 | |
| 2205 | switch (arch) { | 2160 | switch (arch) { |
| ... | @@ -2254,10 +2209,7 @@ fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32) !*TextBlock { | ... | @@ -2254,10 +2209,7 @@ fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32) !*TextBlock { |
| 2254 | .n_desc = 0, | 2209 | .n_desc = 0, |
| 2255 | .n_value = 0, | 2210 | .n_value = 0, |
| 2256 | }); | 2211 | }); |
| 2257 | const atom = try self.createEmptyAtom(.{ | 2212 | const atom = try self.createEmptyAtom(local_sym_index, @sizeOf(u64), 3); |
| 2258 | .seg = self.data_segment_cmd_index.?, | | |
| 2259 | .sect = self.la_symbol_ptr_section_index.?, | | |
| 2260 | }, local_sym_index, @sizeOf(u64), 3); | | |
| 2261 | try atom.relocs.append(self.base.allocator, .{ | 2213 | try atom.relocs.append(self.base.allocator, .{ |
| 2262 | .offset = 0, | 2214 | .offset = 0, |
| 2263 | .where = .local, | 2215 | .where = .local, |
| ... | @@ -2294,10 +2246,7 @@ fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*TextBlock { | ... | @@ -2294,10 +2246,7 @@ fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*TextBlock { |
| 2294 | .n_desc = 0, | 2246 | .n_desc = 0, |
| 2295 | .n_value = 0, | 2247 | .n_value = 0, |
| 2296 | }); | 2248 | }); |
| 2297 | const atom = try self.createEmptyAtom(.{ | 2249 | const atom = try self.createEmptyAtom(local_sym_index, stub_size, alignment); |
| 2298 | .seg = self.text_segment_cmd_index.?, | | |
| 2299 | .sect = self.stubs_section_index.?, | | |
| 2300 | }, local_sym_index, stub_size, alignment); | | |
| 2301 | switch (arch) { | 2250 | switch (arch) { |
| 2302 | .x86_64 => { | 2251 | .x86_64 => { |
| 2303 | // jmp | 2252 | // jmp |
| ... | @@ -2547,12 +2496,14 @@ fn resolveSymbolsInObject( | ... | @@ -2547,12 +2496,14 @@ fn resolveSymbolsInObject( |
| 2547 | .where_index = undef_sym_index, | 2496 | .where_index = undef_sym_index, |
| 2548 | .file = object_id, | 2497 | .file = object_id, |
| 2549 | }); | 2498 | }); |
| 2550 | _ = try self.unresolved.getOrPut(self.base.allocator, undef_sym_index); | 2499 | try self.unresolved.putNoClobber(self.base.allocator, undef_sym_index, .none); |
| 2551 | } | 2500 | } |
| 2552 | } | 2501 | } |
| 2553 | } | 2502 | } |
| 2554 | | 2503 | |
| 2555 | fn resolveSymbols(self: *MachO) !void { | 2504 | fn resolveSymbols(self: *MachO) !void { |
| | 2505 | const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1; |
| | 2506 | |
| 2556 | var tentatives = std.AutoArrayHashMap(u32, void).init(self.base.allocator); | 2507 | var tentatives = std.AutoArrayHashMap(u32, void).init(self.base.allocator); |
| 2557 | defer tentatives.deinit(); | 2508 | defer tentatives.deinit(); |
| 2558 | | 2509 | |
| ... | @@ -2620,7 +2571,32 @@ fn resolveSymbols(self: *MachO) !void { | ... | @@ -2620,7 +2571,32 @@ fn resolveSymbols(self: *MachO) !void { |
| 2620 | const resolv = self.symbol_resolver.getPtr(sym.n_strx) orelse unreachable; | 2571 | const resolv = self.symbol_resolver.getPtr(sym.n_strx) orelse unreachable; |
| 2621 | resolv.local_sym_index = local_sym_index; | 2572 | resolv.local_sym_index = local_sym_index; |
| 2622 | | 2573 | |
| 2623 | _ = try self.createEmptyAtom(match, local_sym_index, size, alignment); | 2574 | const atom = try self.createEmptyAtom(local_sym_index, size, alignment); |
| | 2575 | if (use_stage1) { |
| | 2576 | try self.allocateAtomStage1(atom, match); |
| | 2577 | } |
| | 2578 | } |
| | 2579 | |
| | 2580 | try self.resolveDyldStubBinder(); |
| | 2581 | if (!use_stage1) { |
| | 2582 | { |
| | 2583 | const atom = try self.createDyldPrivateAtom(); |
| | 2584 | const match = MatchingSection{ |
| | 2585 | .seg = self.data_segment_cmd_index.?, |
| | 2586 | .sect = self.data_section_index.?, |
| | 2587 | }; |
| | 2588 | _ = try self.allocateAtom(atom, match); |
| | 2589 | try self.writeAtom(atom, match); |
| | 2590 | } |
| | 2591 | { |
| | 2592 | const atom = try self.createStubHelperPreambleAtom(); |
| | 2593 | const match = MatchingSection{ |
| | 2594 | .seg = self.text_segment_cmd_index.?, |
| | 2595 | .sect = self.stub_helper_section_index.?, |
| | 2596 | }; |
| | 2597 | _ = try self.allocateAtom(atom, match); |
| | 2598 | try self.writeAtom(atom, match); |
| | 2599 | } |
| 2624 | } | 2600 | } |
| 2625 | | 2601 | |
| 2626 | // Third pass, resolve symbols in dynamic libraries. | 2602 | // Third pass, resolve symbols in dynamic libraries. |
| ... | @@ -2643,7 +2619,43 @@ fn resolveSymbols(self: *MachO) !void { | ... | @@ -2643,7 +2619,43 @@ fn resolveSymbols(self: *MachO) !void { |
| 2643 | undef.n_type |= macho.N_EXT; | 2619 | undef.n_type |= macho.N_EXT; |
| 2644 | undef.n_desc = @intCast(u16, ordinal + 1) * macho.N_SYMBOL_RESOLVER; | 2620 | undef.n_desc = @intCast(u16, ordinal + 1) * macho.N_SYMBOL_RESOLVER; |
| 2645 | | 2621 | |
| 2646 | _ = self.unresolved.fetchSwapRemove(resolv.where_index); | 2622 | if (self.unresolved.fetchSwapRemove(resolv.where_index)) |entry| { |
| | 2623 | switch (entry.value) { |
| | 2624 | .none => {}, |
| | 2625 | .got => return error.TODOGotHint, |
| | 2626 | .stub => { |
| | 2627 | const stub_helper_atom = blk: { |
| | 2628 | const atom = try self.createStubHelperAtom(); |
| | 2629 | const match = MatchingSection{ |
| | 2630 | .seg = self.text_segment_cmd_index.?, |
| | 2631 | .sect = self.stub_helper_section_index.?, |
| | 2632 | }; |
| | 2633 | _ = try self.allocateAtom(atom, match); |
| | 2634 | try self.writeAtom(atom, match); |
| | 2635 | break :blk atom; |
| | 2636 | }; |
| | 2637 | const laptr_atom = blk: { |
| | 2638 | const atom = try self.createLazyPointerAtom(stub_helper_atom.local_sym_index); |
| | 2639 | const match = MatchingSection{ |
| | 2640 | .seg = self.data_segment_cmd_index.?, |
| | 2641 | .sect = self.la_symbol_ptr_section_index.?, |
| | 2642 | }; |
| | 2643 | _ = try self.allocateAtom(atom, match); |
| | 2644 | try self.writeAtom(atom, match); |
| | 2645 | break :blk atom; |
| | 2646 | }; |
| | 2647 | { |
| | 2648 | const atom = try self.createStubAtom(laptr_atom.local_sym_index); |
| | 2649 | const match = MatchingSection{ |
| | 2650 | .seg = self.text_segment_cmd_index.?, |
| | 2651 | .sect = self.stubs_section_index.?, |
| | 2652 | }; |
| | 2653 | _ = try self.allocateAtom(atom, match); |
| | 2654 | try self.writeAtom(atom, match); |
| | 2655 | } |
| | 2656 | }, |
| | 2657 | } |
| | 2658 | } |
| 2647 | | 2659 | |
| 2648 | continue :loop; | 2660 | continue :loop; |
| 2649 | } | 2661 | } |
| ... | @@ -2695,7 +2707,10 @@ fn resolveSymbols(self: *MachO) !void { | ... | @@ -2695,7 +2707,10 @@ fn resolveSymbols(self: *MachO) !void { |
| 2695 | // We create an empty atom for this symbol. | 2707 | // We create an empty atom for this symbol. |
| 2696 | // TODO perhaps we should special-case special symbols? Create a separate | 2708 | // TODO perhaps we should special-case special symbols? Create a separate |
| 2697 | // linked list of atoms? | 2709 | // linked list of atoms? |
| 2698 | _ = try self.createEmptyAtom(match, local_sym_index, 0, 0); | 2710 | const atom = try self.createEmptyAtom(local_sym_index, 0, 0); |
| | 2711 | if (use_stage1) { |
| | 2712 | try self.allocateAtomStage1(atom, match); |
| | 2713 | } |
| 2699 | } | 2714 | } |
| 2700 | | 2715 | |
| 2701 | for (self.unresolved.keys()) |index| { | 2716 | for (self.unresolved.keys()) |index| { |
| ... | @@ -4554,14 +4569,12 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 { | ... | @@ -4554,14 +4569,12 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 { |
| 4554 | .where = .undef, | 4569 | .where = .undef, |
| 4555 | .where_index = sym_index, | 4570 | .where_index = sym_index, |
| 4556 | }); | 4571 | }); |
| 4557 | _ = try self.unresolved.getOrPut(self.base.allocator, sym_index); | 4572 | try self.unresolved.putNoClobber(self.base.allocator, sym_index, .stub); |
| 4558 | | 4573 | |
| 4559 | const stubs_index = @intCast(u32, self.stubs.items.len); | 4574 | const stubs_index = @intCast(u32, self.stubs.items.len); |
| 4560 | try self.stubs.append(self.base.allocator, sym_index); | 4575 | try self.stubs.append(self.base.allocator, sym_index); |
| 4561 | try self.stubs_map.putNoClobber(self.base.allocator, sym_index, stubs_index); | 4576 | try self.stubs_map.putNoClobber(self.base.allocator, sym_index, stubs_index); |
| 4562 | | 4577 | |
| 4563 | // TODO create and write stub, stub_helper and lazy_ptr atoms | | |
| 4564 | | | |
| 4565 | return sym_index; | 4578 | return sym_index; |
| 4566 | } | 4579 | } |
| 4567 | | 4580 | |
| ... | @@ -5271,7 +5284,11 @@ fn writeLazyBindInfoTable(self: *MachO) !void { | ... | @@ -5271,7 +5284,11 @@ fn writeLazyBindInfoTable(self: *MachO) !void { |
| 5271 | } | 5284 | } |
| 5272 | | 5285 | |
| 5273 | fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { | 5286 | fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { |
| 5274 | if (self.stubs.items.len == 0) return; | 5287 | const last_atom = self.blocks.get(.{ |
| | 5288 | .seg = self.text_segment_cmd_index.?, |
| | 5289 | .sect = self.stub_helper_section_index.?, |
| | 5290 | }) orelse return; |
| | 5291 | if (last_atom.local_sym_index == self.stub_preamble_sym_index.?) return; |
| 5275 | | 5292 | |
| 5276 | var stream = std.io.fixedBufferStream(buffer); | 5293 | var stream = std.io.fixedBufferStream(buffer); |
| 5277 | var reader = stream.reader(); | 5294 | var reader = stream.reader(); |
| ... | @@ -5316,7 +5333,6 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { | ... | @@ -5316,7 +5333,6 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { |
| 5316 | else => {}, | 5333 | else => {}, |
| 5317 | } | 5334 | } |
| 5318 | } | 5335 | } |
| 5319 | assert(self.stubs.items.len <= offsets.items.len); | | |
| 5320 | | 5336 | |
| 5321 | const stub_size: u4 = switch (self.base.options.target.cpu.arch) { | 5337 | const stub_size: u4 = switch (self.base.options.target.cpu.arch) { |
| 5322 | .x86_64 => 10, | 5338 | .x86_64 => 10, |
| ... | @@ -5329,8 +5345,22 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { | ... | @@ -5329,8 +5345,22 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { |
| 5329 | else => unreachable, | 5345 | else => unreachable, |
| 5330 | }; | 5346 | }; |
| 5331 | var buf: [@sizeOf(u32)]u8 = undefined; | 5347 | var buf: [@sizeOf(u32)]u8 = undefined; |
| | 5348 | |
| | 5349 | var first_atom = last_atom; |
| | 5350 | while (first_atom.prev) |prev| { |
| | 5351 | first_atom = prev; |
| | 5352 | } |
| | 5353 | |
| | 5354 | const start_off = blk: { |
| | 5355 | const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| | 5356 | const sect = seg.sections.items[self.stub_helper_section_index.?]; |
| | 5357 | const sym = self.locals.items[first_atom.next.?.local_sym_index]; |
| | 5358 | break :blk sym.n_value - sect.addr + sect.offset; |
| | 5359 | }; |
| | 5360 | log.warn("start_off = 0x{x}", .{start_off}); |
| | 5361 | |
| 5332 | for (self.stubs.items) |_, index| { | 5362 | for (self.stubs.items) |_, index| { |
| 5333 | const placeholder_off = self.stub_helper_stubs_start_off.? + index * stub_size + off; | 5363 | const placeholder_off = start_off + index * stub_size + off; |
| 5334 | mem.writeIntLittle(u32, &buf, offsets.items[index]); | 5364 | mem.writeIntLittle(u32, &buf, offsets.items[index]); |
| 5335 | try self.base.file.?.pwriteAll(&buf, placeholder_off); | 5365 | try self.base.file.?.pwriteAll(&buf, placeholder_off); |
| 5336 | } | 5366 | } |