authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-01-08 22:26:18+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-01-13 23:54:46+01:00
log44a052a65f5c59b02383178f36fcc231df28b49f
tree55bb58983ccd0908b4b8f1337af6ff0321b204ae
parent2f7cd7119387b517b07e5feb02a13e69651fe9eb

macho: write out stubs for new externs only


2 files changed, 68 insertions(+), 55 deletions(-)

src/codegen.zig+20-10
...@@ -1862,18 +1862,28 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1862,18 +1862,28 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1862 } else if (func_value.castTag(.extern_fn)) |func_payload| {1862 } else if (func_value.castTag(.extern_fn)) |func_payload| {
1863 const decl = func_payload.data;1863 const decl = func_payload.data;
1864 const decl_name = try std.fmt.allocPrint(self.bin_file.allocator, "_{s}", .{decl.name});1864 const decl_name = try std.fmt.allocPrint(self.bin_file.allocator, "_{s}", .{decl.name});
1865 defer self.bin_file.allocator.free(decl_name);1865 const exists: bool = macho_file.externs.contains(decl_name);
1866 const name = try macho_file.makeString(decl_name);1866 const symbol: u32 = blk: {
1867 const symbol = macho_file.undef_symbols.items.len;1867 if (macho_file.externs.get(decl_name)) |index| {
1868 try macho_file.undef_symbols.append(self.bin_file.allocator, .{1868 self.bin_file.allocator.free(decl_name);
1869 .n_strx = name,1869 break :blk index;
1870 .n_type = std.macho.N_UNDF | std.macho.N_EXT,1870 } else {
1871 .n_sect = 0,1871 const extern_index = @intCast(u32, macho_file.undef_symbols.items.len - 1); // TODO
1872 .n_desc = std.macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY | std.macho.N_SYMBOL_RESOLVER,1872 try macho_file.externs.putNoClobber(self.bin_file.allocator, decl_name, extern_index);
1873 .n_value = 0,1873 const name = try macho_file.makeString(decl_name);
1874 });1874 try macho_file.undef_symbols.append(self.bin_file.allocator, .{
1875 .n_strx = name,
1876 .n_type = std.macho.N_UNDF | std.macho.N_EXT,
1877 .n_sect = 0,
1878 .n_desc = std.macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY | std.macho.N_SYMBOL_RESOLVER,
1879 .n_value = 0,
1880 });
1881 break :blk extern_index;
1882 }
1883 };
1875 try macho_file.stub_fixups.append(self.bin_file.allocator, .{1884 try macho_file.stub_fixups.append(self.bin_file.allocator, .{
1876 .symbol = symbol,1885 .symbol = symbol,
1886 .exists = exists,
1877 .start = self.code.items.len,1887 .start = self.code.items.len,
1878 .len = 4,1888 .len = 4,
1879 });1889 });
src/link/MachO.zig+48-45
...@@ -167,9 +167,11 @@ last_text_block: ?*TextBlock = null,...@@ -167,9 +167,11 @@ last_text_block: ?*TextBlock = null,
167pie_fixups: std.ArrayListUnmanaged(PieFixup) = .{},167pie_fixups: std.ArrayListUnmanaged(PieFixup) = .{},
168168
169stub_fixups: std.ArrayListUnmanaged(StubFixup) = .{},169stub_fixups: std.ArrayListUnmanaged(StubFixup) = .{},
170externs: std.StringHashMapUnmanaged(u32) = .{},
170171
171pub const StubFixup = struct {172pub const StubFixup = struct {
172 symbol: usize,173 symbol: u32,
174 exists: bool,
173 start: usize,175 start: usize,
174 len: usize,176 len: usize,
175};177};
...@@ -1263,56 +1265,57 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -1263,56 +1265,57 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1263 const stub_h = &text_segment.sections.items[self.stub_helper_section_index.?];1265 const stub_h = &text_segment.sections.items[self.stub_helper_section_index.?];
1264 const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;1266 const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1265 const la_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?];1267 const la_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?];
1266 for (self.stub_fixups.items) |fixup, idx| {1268 for (self.stub_fixups.items) |fixup| {
1267 const i = @intCast(u32, idx);
1268 // TODO increment offset for stub writing1269 // TODO increment offset for stub writing
1269 const stub_addr = stubs.addr + i * stubs.reserved2;1270 const stub_addr = stubs.addr + fixup.symbol * stubs.reserved2;
1270 const text_addr = symbol.n_value + fixup.start;1271 const text_addr = symbol.n_value + fixup.start;
1271 const displacement = @intCast(u32, stub_addr - text_addr);1272 const displacement = @intCast(u32, stub_addr - text_addr);
1272 var placeholder = code_buffer.items[fixup.start..][0..fixup.len];1273 var placeholder = code_buffer.items[fixup.start..][0..fixup.len];
1273 mem.writeIntSliceLittle(u32, placeholder, aarch64.Instruction.bl(@intCast(i28, displacement)).toU32());1274 mem.writeIntSliceLittle(u32, placeholder, aarch64.Instruction.bl(@intCast(i28, displacement)).toU32());
12741275
1275 const end = stub_h.addr + self.next_stub_helper_off.? - stub_h.offset;1276 if (!fixup.exists) {
1276 var buf: [@sizeOf(u64)]u8 = undefined;1277 const end = stub_h.addr + self.next_stub_helper_off.? - stub_h.offset;
1277 mem.writeIntLittle(u64, &buf, end);1278 var buf: [@sizeOf(u64)]u8 = undefined;
1278 try self.base.file.?.pwriteAll(&buf, la_ptr.offset + i * @sizeOf(u64));1279 mem.writeIntLittle(u64, &buf, end);
12791280 try self.base.file.?.pwriteAll(&buf, la_ptr.offset + fixup.symbol * @sizeOf(u64));
1280 const la_ptr_addr = la_ptr.addr + i * @sizeOf(u64);1281
1281 const displacement2 = la_ptr_addr - stub_addr;1282 const la_ptr_addr = la_ptr.addr + fixup.symbol * @sizeOf(u64);
1282 var ccode: [2 * @sizeOf(u32)]u8 = undefined;1283 const displacement2 = la_ptr_addr - stub_addr;
1283 mem.writeIntLittle(u32, ccode[0..4], aarch64.Instruction.ldr(.x16, .{1284 var ccode: [2 * @sizeOf(u32)]u8 = undefined;
1284 .literal = @intCast(u19, displacement2 / 4),1285 mem.writeIntLittle(u32, ccode[0..4], aarch64.Instruction.ldr(.x16, .{
1285 }).toU32());1286 .literal = @intCast(u19, displacement2 / 4),
1286 mem.writeIntLittle(u32, ccode[4..8], aarch64.Instruction.br(.x16).toU32());1287 }).toU32());
1287 try self.base.file.?.pwriteAll(&ccode, stubs.offset + i * stubs.reserved2);1288 mem.writeIntLittle(u32, ccode[4..8], aarch64.Instruction.br(.x16).toU32());
12881289 try self.base.file.?.pwriteAll(&ccode, stubs.offset + fixup.symbol * stubs.reserved2);
1289 const displacement3 = @intCast(i64, stub_h.addr) - @intCast(i64, end + 4);1290
1290 var cccode: [3 * @sizeOf(u32)]u8 = undefined;1291 const displacement3 = @intCast(i64, stub_h.addr) - @intCast(i64, end + 4);
1291 mem.writeIntLittle(u32, cccode[0..4], aarch64.Instruction.ldr(.w16, .{1292 var cccode: [3 * @sizeOf(u32)]u8 = undefined;
1292 .literal = 0x2,1293 mem.writeIntLittle(u32, cccode[0..4], aarch64.Instruction.ldr(.w16, .{
1293 }).toU32());1294 .literal = 0x2,
1294 mem.writeIntLittle(u32, cccode[4..8], aarch64.Instruction.b(@intCast(i28, displacement3)).toU32());1295 }).toU32());
1295 mem.writeIntLittle(u32, cccode[8..12], i * 0xd);1296 mem.writeIntLittle(u32, cccode[4..8], aarch64.Instruction.b(@intCast(i28, displacement3)).toU32());
1296 try self.base.file.?.pwriteAll(&cccode, self.next_stub_helper_off.?);1297 mem.writeIntLittle(u32, cccode[8..12], fixup.symbol * 0xd);
1297 self.next_stub_helper_off = self.next_stub_helper_off.? + 3 * @sizeOf(u32);1298 try self.base.file.?.pwriteAll(&cccode, self.next_stub_helper_off.?);
12981299 self.next_stub_helper_off = self.next_stub_helper_off.? + 3 * @sizeOf(u32);
1299 try self.rebase_info_table.symbols.append(self.base.allocator, .{1300
1300 .segment = 3,1301 try self.rebase_info_table.symbols.append(self.base.allocator, .{
1301 .offset = i * stubs.reserved2,1302 .segment = 3,
1302 });1303 .offset = fixup.symbol * stubs.reserved2,
1303 self.rebase_info_dirty = true;1304 });
13041305 self.rebase_info_dirty = true;
1305 const sym = self.undef_symbols.items[fixup.symbol];1306
1306 const name_str = self.getString(sym.n_strx);1307 const sym = self.undef_symbols.items[fixup.symbol + 1];
1307 var name = try self.base.allocator.alloc(u8, name_str.len);1308 const name_str = self.getString(sym.n_strx);
1308 mem.copy(u8, name, name_str);1309 var name = try self.base.allocator.alloc(u8, name_str.len);
1309 try self.lazy_binding_info_table.symbols.append(self.base.allocator, .{1310 mem.copy(u8, name, name_str);
1310 .segment = 3,1311 try self.lazy_binding_info_table.symbols.append(self.base.allocator, .{
1311 .offset = i * @sizeOf(u64),1312 .segment = 3,
1312 .dylib_ordinal = 1,1313 .offset = fixup.symbol * @sizeOf(u64),
1313 .name = name,1314 .dylib_ordinal = 1,
1314 });1315 .name = name,
1315 self.lazy_binding_info_dirty = true;1316 });
1317 self.lazy_binding_info_dirty = true;
1318 }
1316 }1319 }
1317 self.stub_fixups.shrinkRetainingCapacity(0);1320 self.stub_fixups.shrinkRetainingCapacity(0);
13181321