| ... | ... | @@ -807,7 +807,11 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { |
| 807 | 807 | // TODO just a temp |
| 808 | 808 | const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 809 | 809 | const sect = seg.sections.items[self.stub_helper_section_index.?]; |
| 810 | | self.stub_helper_stubs_start_off = sect.offset + 15; |
| 810 | self.stub_helper_stubs_start_off = sect.offset + switch (self.base.options.target.cpu.arch) { |
| 811 | .x86_64 => @intCast(u64, 15), |
| 812 | .aarch64 => @intCast(u64, 6 * @sizeOf(u32)), |
| 813 | else => unreachable, |
| 814 | }; |
| 811 | 815 | } |
| 812 | 816 | try self.flushZld(); |
| 813 | 817 | } else { |
| ... | ... | @@ -2018,11 +2022,12 @@ fn createStubHelperPreambleAtom(self: *MachO) !void { |
| 2018 | 2022 | const atom = try self.createEmptyAtom(match, local_sym_index, size, alignment); |
| 2019 | 2023 | switch (arch) { |
| 2020 | 2024 | .x86_64 => { |
| 2025 | try atom.relocs.ensureUnusedCapacity(self.base.allocator, 2); |
| 2021 | 2026 | // lea %r11, [rip + disp] |
| 2022 | 2027 | atom.code.items[0] = 0x4c; |
| 2023 | 2028 | atom.code.items[1] = 0x8d; |
| 2024 | 2029 | atom.code.items[2] = 0x1d; |
| 2025 | | try atom.relocs.append(self.base.allocator, .{ |
| 2030 | atom.relocs.appendAssumeCapacity(.{ |
| 2026 | 2031 | .offset = 3, |
| 2027 | 2032 | .where = .local, |
| 2028 | 2033 | .where_index = self.dyld_private_sym_index.?, |
| ... | ... | @@ -2039,7 +2044,7 @@ fn createStubHelperPreambleAtom(self: *MachO) !void { |
| 2039 | 2044 | // jmp [rip + disp] |
| 2040 | 2045 | atom.code.items[9] = 0xff; |
| 2041 | 2046 | atom.code.items[10] = 0x25; |
| 2042 | | try atom.relocs.append(self.base.allocator, .{ |
| 2047 | atom.relocs.appendAssumeCapacity(.{ |
| 2043 | 2048 | .offset = 11, |
| 2044 | 2049 | .where = .undef, |
| 2045 | 2050 | .where_index = self.dyld_stub_binder_index.?, |
| ... | ... | @@ -2051,94 +2056,76 @@ fn createStubHelperPreambleAtom(self: *MachO) !void { |
| 2051 | 2056 | }, |
| 2052 | 2057 | }); |
| 2053 | 2058 | }, |
| 2054 | | // .aarch64 => { |
| 2055 | | // var code: [6 * @sizeOf(u32)]u8 = undefined; |
| 2056 | | // data_blk_outer: { |
| 2057 | | // const this_addr = stub_helper.addr; |
| 2058 | | // const target_addr = data.addr + data.size - @sizeOf(u64); |
| 2059 | | // data_blk: { |
| 2060 | | // const displacement = math.cast(i21, target_addr - this_addr) catch break :data_blk; |
| 2061 | | // // adr x17, disp |
| 2062 | | // mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.adr(.x17, displacement).toU32()); |
| 2063 | | // // nop |
| 2064 | | // mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.nop().toU32()); |
| 2065 | | // break :data_blk_outer; |
| 2066 | | // } |
| 2067 | | // data_blk: { |
| 2068 | | // const new_this_addr = this_addr + @sizeOf(u32); |
| 2069 | | // const displacement = math.cast(i21, target_addr - new_this_addr) catch break :data_blk; |
| 2070 | | // // nop |
| 2071 | | // mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.nop().toU32()); |
| 2072 | | // // adr x17, disp |
| 2073 | | // mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.adr(.x17, displacement).toU32()); |
| 2074 | | // break :data_blk_outer; |
| 2075 | | // } |
| 2076 | | // // Jump is too big, replace adr with adrp and add. |
| 2077 | | // const this_page = @intCast(i32, this_addr >> 12); |
| 2078 | | // const target_page = @intCast(i32, target_addr >> 12); |
| 2079 | | // const pages = @intCast(i21, target_page - this_page); |
| 2080 | | // mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.adrp(.x17, pages).toU32()); |
| 2081 | | // const narrowed = @truncate(u12, target_addr); |
| 2082 | | // mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.add(.x17, .x17, narrowed, false).toU32()); |
| 2083 | | // } |
| 2084 | | // // stp x16, x17, [sp, #-16]! |
| 2085 | | // code[8] = 0xf0; |
| 2086 | | // code[9] = 0x47; |
| 2087 | | // code[10] = 0xbf; |
| 2088 | | // code[11] = 0xa9; |
| 2089 | | // binder_blk_outer: { |
| 2090 | | // const got_index = self.got_entries_map.get(.{ |
| 2091 | | // .where = .undef, |
| 2092 | | // .where_index = self.dyld_stub_binder_index.?, |
| 2093 | | // }) orelse unreachable; |
| 2094 | | // const this_addr = stub_helper.addr + 3 * @sizeOf(u32); |
| 2095 | | // const target_addr = got.addr + got_index * @sizeOf(u64); |
| 2096 | | // binder_blk: { |
| 2097 | | // const displacement = math.divExact(u64, target_addr - this_addr, 4) catch break :binder_blk; |
| 2098 | | // const literal = math.cast(u18, displacement) catch break :binder_blk; |
| 2099 | | // // ldr x16, label |
| 2100 | | // mem.writeIntLittle(u32, code[12..16], aarch64.Instruction.ldr(.x16, .{ |
| 2101 | | // .literal = literal, |
| 2102 | | // }).toU32()); |
| 2103 | | // // nop |
| 2104 | | // mem.writeIntLittle(u32, code[16..20], aarch64.Instruction.nop().toU32()); |
| 2105 | | // break :binder_blk_outer; |
| 2106 | | // } |
| 2107 | | // binder_blk: { |
| 2108 | | // const new_this_addr = this_addr + @sizeOf(u32); |
| 2109 | | // const displacement = math.divExact(u64, target_addr - new_this_addr, 4) catch break :binder_blk; |
| 2110 | | // const literal = math.cast(u18, displacement) catch break :binder_blk; |
| 2111 | | // // Pad with nop to please division. |
| 2112 | | // // nop |
| 2113 | | // mem.writeIntLittle(u32, code[12..16], aarch64.Instruction.nop().toU32()); |
| 2114 | | // // ldr x16, label |
| 2115 | | // mem.writeIntLittle(u32, code[16..20], aarch64.Instruction.ldr(.x16, .{ |
| 2116 | | // .literal = literal, |
| 2117 | | // }).toU32()); |
| 2118 | | // break :binder_blk_outer; |
| 2119 | | // } |
| 2120 | | // // Use adrp followed by ldr(immediate). |
| 2121 | | // const this_page = @intCast(i32, this_addr >> 12); |
| 2122 | | // const target_page = @intCast(i32, target_addr >> 12); |
| 2123 | | // const pages = @intCast(i21, target_page - this_page); |
| 2124 | | // mem.writeIntLittle(u32, code[12..16], aarch64.Instruction.adrp(.x16, pages).toU32()); |
| 2125 | | // const narrowed = @truncate(u12, target_addr); |
| 2126 | | // const offset = try math.divExact(u12, narrowed, 8); |
| 2127 | | // mem.writeIntLittle(u32, code[16..20], aarch64.Instruction.ldr(.x16, .{ |
| 2128 | | // .register = .{ |
| 2129 | | // .rn = .x16, |
| 2130 | | // .offset = aarch64.Instruction.LoadStoreOffset.imm(offset), |
| 2131 | | // }, |
| 2132 | | // }).toU32()); |
| 2133 | | // } |
| 2134 | | // // br x16 |
| 2135 | | // code[20] = 0x00; |
| 2136 | | // code[21] = 0x02; |
| 2137 | | // code[22] = 0x1f; |
| 2138 | | // code[23] = 0xd6; |
| 2139 | | // try self.base.file.?.pwriteAll(&code, stub_helper.offset); |
| 2140 | | // break :blk stub_helper.offset + 6 * @sizeOf(u32); |
| 2141 | | // }, |
| 2059 | .aarch64 => { |
| 2060 | try atom.relocs.ensureUnusedCapacity(self.base.allocator, 4); |
| 2061 | // adrp x17, 0 |
| 2062 | mem.writeIntLittle(u32, atom.code.items[0..][0..4], aarch64.Instruction.adrp(.x17, 0).toU32()); |
| 2063 | atom.relocs.appendAssumeCapacity(.{ |
| 2064 | .offset = 0, |
| 2065 | .where = .local, |
| 2066 | .where_index = self.dyld_private_sym_index.?, |
| 2067 | .payload = .{ |
| 2068 | .page = .{ |
| 2069 | .kind = .page, |
| 2070 | .addend = 0, |
| 2071 | }, |
| 2072 | }, |
| 2073 | }); |
| 2074 | // add x17, x17, 0 |
| 2075 | mem.writeIntLittle(u32, atom.code.items[4..][0..4], aarch64.Instruction.add(.x17, .x17, 0, false).toU32()); |
| 2076 | atom.relocs.appendAssumeCapacity(.{ |
| 2077 | .offset = 4, |
| 2078 | .where = .local, |
| 2079 | .where_index = self.dyld_private_sym_index.?, |
| 2080 | .payload = .{ |
| 2081 | .page_off = .{ |
| 2082 | .kind = .page, |
| 2083 | .addend = 0, |
| 2084 | .op_kind = .arithmetic, |
| 2085 | }, |
| 2086 | }, |
| 2087 | }); |
| 2088 | // stp x16, x17, [sp, #-16]! |
| 2089 | mem.writeIntLittle(u32, atom.code.items[8..][0..4], aarch64.Instruction.stp( |
| 2090 | .x16, |
| 2091 | .x17, |
| 2092 | aarch64.Register.sp, |
| 2093 | aarch64.Instruction.LoadStorePairOffset.pre_index(-16), |
| 2094 | ).toU32()); |
| 2095 | // adrp x16, 0 |
| 2096 | mem.writeIntLittle(u32, atom.code.items[12..][0..4], aarch64.Instruction.adrp(.x16, 0).toU32()); |
| 2097 | atom.relocs.appendAssumeCapacity(.{ |
| 2098 | .offset = 12, |
| 2099 | .where = .undef, |
| 2100 | .where_index = self.dyld_stub_binder_index.?, |
| 2101 | .payload = .{ |
| 2102 | .page = .{ |
| 2103 | .kind = .got, |
| 2104 | .addend = 0, |
| 2105 | }, |
| 2106 | }, |
| 2107 | }); |
| 2108 | // ldr x16, [x16, 0] |
| 2109 | mem.writeIntLittle(u32, atom.code.items[16..][0..4], aarch64.Instruction.ldr(.x16, .{ |
| 2110 | .register = .{ |
| 2111 | .rn = .x16, |
| 2112 | .offset = aarch64.Instruction.LoadStoreOffset.imm(0), |
| 2113 | }, |
| 2114 | }).toU32()); |
| 2115 | atom.relocs.appendAssumeCapacity(.{ |
| 2116 | .offset = 16, |
| 2117 | .where = .undef, |
| 2118 | .where_index = self.dyld_stub_binder_index.?, |
| 2119 | .payload = .{ |
| 2120 | .page_off = .{ |
| 2121 | .kind = .got, |
| 2122 | .addend = 0, |
| 2123 | }, |
| 2124 | }, |
| 2125 | }); |
| 2126 | // br x16 |
| 2127 | mem.writeIntLittle(u32, atom.code.items[20..][0..4], aarch64.Instruction.br(.x16).toU32()); |
| 2128 | }, |
| 2142 | 2129 | else => unreachable, |
| 2143 | 2130 | } |
| 2144 | 2131 | self.stub_preamble_sym_index = local_sym_index; |