| author | |
| committer | |
| log | 96441bd829b731cba080753c4833aff3f672a24a |
| tree | fc4d4d5eb4654d81dd09e91052be11b55fcb09f8 |
| parent | bb70501060a8bfff25818cf1d80491d724f8a634 |
11 files changed, 147 insertions(+), 272 deletions(-)
src/arch/x86_64/CodeGen.zig+25-23| ... | @@ -12364,13 +12364,10 @@ fn genCall(self: *Self, info: union(enum) { | ... | @@ -12364,13 +12364,10 @@ fn genCall(self: *Self, info: union(enum) { |
| 12364 | const zo = macho_file.getZigObject().?; | 12364 | const zo = macho_file.getZigObject().?; |
| 12365 | const sym_index = try zo.getOrCreateMetadataForNav(macho_file, func.owner_nav); | 12365 | const sym_index = try zo.getOrCreateMetadataForNav(macho_file, func.owner_nav); |
| 12366 | const sym = zo.symbols.items[sym_index]; | 12366 | const sym = zo.symbols.items[sym_index]; |
| 12367 | try self.genSetReg( | 12367 | try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ |
| 12368 | .rax, | 12368 | .atom_index = try self.owner.getSymbolIndex(self), |
| 12369 | Type.usize, | 12369 | .sym_index = sym.nlist_idx, |
| 12370 | .{ .load_symbol = .{ .sym = sym.nlist_idx } }, | 12370 | })); |
| 12371 | .{}, | ||
| 12372 | ); | ||
| 12373 | try self.asmRegister(.{ ._, .call }, .rax); | ||
| 12374 | } else if (self.bin_file.cast(.plan9)) |p9| { | 12371 | } else if (self.bin_file.cast(.plan9)) |p9| { |
| 12375 | const atom_index = try p9.seeNav(pt, func.owner_nav); | 12372 | const atom_index = try p9.seeNav(pt, func.owner_nav); |
| 12376 | const atom = p9.getAtom(atom_index); | 12373 | const atom = p9.getAtom(atom_index); |
| ... | @@ -12392,6 +12389,15 @@ fn genCall(self: *Self, info: union(enum) { | ... | @@ -12392,6 +12389,15 @@ fn genCall(self: *Self, info: union(enum) { |
| 12392 | .atom_index = try self.owner.getSymbolIndex(self), | 12389 | .atom_index = try self.owner.getSymbolIndex(self), |
| 12393 | .sym_index = target_sym_index, | 12390 | .sym_index = target_sym_index, |
| 12394 | })); | 12391 | })); |
| 12392 | } else if (self.bin_file.cast(.macho)) |macho_file| { | ||
| 12393 | const target_sym_index = try macho_file.getGlobalSymbol( | ||
| 12394 | @"extern".name.toSlice(ip), | ||
| 12395 | @"extern".lib_name.toSlice(ip), | ||
| 12396 | ); | ||
| 12397 | try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ | ||
| 12398 | .atom_index = try self.owner.getSymbolIndex(self), | ||
| 12399 | .sym_index = target_sym_index, | ||
| 12400 | })); | ||
| 12395 | } else try self.genExternSymbolRef( | 12401 | } else try self.genExternSymbolRef( |
| 12396 | .call, | 12402 | .call, |
| 12397 | @"extern".lib_name.toSlice(ip), | 12403 | @"extern".lib_name.toSlice(ip), |
| ... | @@ -12410,6 +12416,12 @@ fn genCall(self: *Self, info: union(enum) { | ... | @@ -12410,6 +12416,12 @@ fn genCall(self: *Self, info: union(enum) { |
| 12410 | .atom_index = try self.owner.getSymbolIndex(self), | 12416 | .atom_index = try self.owner.getSymbolIndex(self), |
| 12411 | .sym_index = target_sym_index, | 12417 | .sym_index = target_sym_index, |
| 12412 | })); | 12418 | })); |
| 12419 | } else if (self.bin_file.cast(.macho)) |macho_file| { | ||
| 12420 | const target_sym_index = try macho_file.getGlobalSymbol(lib.callee, lib.lib); | ||
| 12421 | try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ | ||
| 12422 | .atom_index = try self.owner.getSymbolIndex(self), | ||
| 12423 | .sym_index = target_sym_index, | ||
| 12424 | })); | ||
| 12413 | } else try self.genExternSymbolRef(.call, lib.lib, lib.callee), | 12425 | } else try self.genExternSymbolRef(.call, lib.lib, lib.callee), |
| 12414 | } | 12426 | } |
| 12415 | return call_info.return_value.short; | 12427 | return call_info.return_value.short; |
| ... | @@ -15335,15 +15347,6 @@ fn genExternSymbolRef( | ... | @@ -15335,15 +15347,6 @@ fn genExternSymbolRef( |
| 15335 | .call => try self.asmRegister(.{ ._, .call }, .rax), | 15347 | .call => try self.asmRegister(.{ ._, .call }, .rax), |
| 15336 | else => unreachable, | 15348 | else => unreachable, |
| 15337 | } | 15349 | } |
| 15338 | } else if (self.bin_file.cast(.macho)) |macho_file| { | ||
| 15339 | _ = try self.addInst(.{ | ||
| 15340 | .tag = .call, | ||
| 15341 | .ops = .extern_fn_reloc, | ||
| 15342 | .data = .{ .reloc = .{ | ||
| 15343 | .atom_index = atom_index, | ||
| 15344 | .sym_index = try macho_file.getGlobalSymbol(callee, lib), | ||
| 15345 | } }, | ||
| 15346 | }); | ||
| 15347 | } else return self.fail("TODO implement calling extern functions", .{}); | 15350 | } else return self.fail("TODO implement calling extern functions", .{}); |
| 15348 | } | 15351 | } |
| 15349 | 15352 | ||
| ... | @@ -15434,13 +15437,12 @@ fn genLazySymbolRef( | ... | @@ -15434,13 +15437,12 @@ fn genLazySymbolRef( |
| 15434 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); | 15437 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| 15435 | const sym = zo.symbols.items[sym_index]; | 15438 | const sym = zo.symbols.items[sym_index]; |
| 15436 | switch (tag) { | 15439 | switch (tag) { |
| 15437 | .lea, .call => try self.genSetReg( | 15440 | .lea, .call => try self.genSetReg(reg, Type.usize, .{ |
| 15438 | reg, | 15441 | .lea_symbol = .{ .sym = sym.nlist_idx }, |
| 15439 | Type.usize, | 15442 | }, .{}), |
| 15440 | .{ .load_symbol = .{ .sym = sym.nlist_idx } }, | 15443 | .mov => try self.genSetReg(reg, Type.usize, .{ |
| 15441 | .{}, | 15444 | .load_symbol = .{ .sym = sym.nlist_idx }, |
| 15442 | ), | 15445 | }, .{}), |
| 15443 | .mov => try self.genSetReg(reg, Type.usize, .{ .load_symbol = .{ .sym = sym.nlist_idx } }, .{}), | ||
| 15444 | else => unreachable, | 15446 | else => unreachable, |
| 15445 | } | 15447 | } |
| 15446 | switch (tag) { | 15448 | switch (tag) { |
src/arch/x86_64/Emit.zig+2-14| ... | @@ -135,23 +135,11 @@ pub fn emitMir(emit: *Emit) Error!void { | ... | @@ -135,23 +135,11 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 135 | }); | 135 | }); |
| 136 | } | 136 | } |
| 137 | } else if (emit.lower.bin_file.cast(.macho)) |macho_file| { | 137 | } else if (emit.lower.bin_file.cast(.macho)) |macho_file| { |
| 138 | const is_obj_or_static_lib = switch (emit.lower.output_mode) { | ||
| 139 | .Exe => false, | ||
| 140 | .Obj => true, | ||
| 141 | .Lib => emit.lower.link_mode == .static, | ||
| 142 | }; | ||
| 143 | const zo = macho_file.getZigObject().?; | 138 | const zo = macho_file.getZigObject().?; |
| 144 | const atom = zo.symbols.items[data.atom_index].getAtom(macho_file).?; | 139 | const atom = zo.symbols.items[data.atom_index].getAtom(macho_file).?; |
| 145 | const sym = &zo.symbols.items[data.sym_index]; | 140 | const sym = &zo.symbols.items[data.sym_index]; |
| 146 | if (sym.getSectionFlags().needs_zig_got and !is_obj_or_static_lib) { | 141 | const @"type": link.File.MachO.Relocation.Type = if (sym.flags.is_extern_ptr) |
| 147 | _ = try sym.getOrCreateZigGotEntry(data.sym_index, macho_file); | 142 | .got_load |
| 148 | } | ||
| 149 | const @"type": link.File.MachO.Relocation.Type = if (sym.getSectionFlags().needs_zig_got and !is_obj_or_static_lib) | ||
| 150 | .zig_got_load | ||
| 151 | else if (sym.getSectionFlags().needs_got) | ||
| 152 | // TODO: it is possible to emit .got_load here that can potentially be relaxed | ||
| 153 | // however this requires always to use a MOVQ mnemonic | ||
| 154 | .got | ||
| 155 | else if (sym.flags.tlv) | 143 | else if (sym.flags.tlv) |
| 156 | .tlv | 144 | .tlv |
| 157 | else | 145 | else |
src/arch/x86_64/Lower.zig+13-7| ... | @@ -328,12 +328,6 @@ fn reloc(lower: *Lower, target: Reloc.Target) Immediate { | ... | @@ -328,12 +328,6 @@ fn reloc(lower: *Lower, target: Reloc.Target) Immediate { |
| 328 | } | 328 | } |
| 329 | 329 | ||
| 330 | fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void { | 330 | fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void { |
| 331 | const is_obj_or_static_lib = switch (lower.output_mode) { | ||
| 332 | .Exe => false, | ||
| 333 | .Obj => true, | ||
| 334 | .Lib => lower.link_mode == .static, | ||
| 335 | }; | ||
| 336 | |||
| 337 | const emit_prefix = prefix; | 331 | const emit_prefix = prefix; |
| 338 | var emit_mnemonic = mnemonic; | 332 | var emit_mnemonic = mnemonic; |
| 339 | var emit_ops_storage: [4]Operand = undefined; | 333 | var emit_ops_storage: [4]Operand = undefined; |
| ... | @@ -455,10 +449,22 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) | ... | @@ -455,10 +449,22 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) |
| 455 | _ = lower.reloc(.{ .linker_reloc = sym }); | 449 | _ = lower.reloc(.{ .linker_reloc = sym }); |
| 456 | break :op switch (mnemonic) { | 450 | break :op switch (mnemonic) { |
| 457 | .lea => { | 451 | .lea => { |
| 452 | if (macho_sym.flags.is_extern_ptr) emit_mnemonic = .mov; | ||
| 458 | break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }; | 453 | break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }; |
| 459 | }, | 454 | }, |
| 460 | .mov => { | 455 | .mov => { |
| 461 | if (is_obj_or_static_lib and macho_sym.getSectionFlags().needs_zig_got) emit_mnemonic = .lea; | 456 | if (macho_sym.flags.is_extern_ptr) { |
| 457 | const reg = ops[0].reg; | ||
| 458 | lower.result_insts[lower.result_insts_len] = | ||
| 459 | try Instruction.new(.none, .mov, &[_]Operand{ | ||
| 460 | .{ .reg = reg.to64() }, | ||
| 461 | .{ .mem = Memory.rip(.qword, 0) }, | ||
| 462 | }); | ||
| 463 | lower.result_insts_len += 1; | ||
| 464 | break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ .base = .{ | ||
| 465 | .reg = reg.to64(), | ||
| 466 | } }) }; | ||
| 467 | } | ||
| 462 | break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }; | 468 | break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }; |
| 463 | }, | 469 | }, |
| 464 | else => unreachable, | 470 | else => unreachable, |
src/codegen.zig+3-3| ... | @@ -910,15 +910,15 @@ fn genNavRef( | ... | @@ -910,15 +910,15 @@ fn genNavRef( |
| 910 | const zo = macho_file.getZigObject().?; | 910 | const zo = macho_file.getZigObject().?; |
| 911 | if (is_extern) { | 911 | if (is_extern) { |
| 912 | const sym_index = try macho_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip)); | 912 | const sym_index = try macho_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip)); |
| 913 | zo.symbols.items[sym_index].setSectionFlags(.{ .needs_got = true }); | 913 | zo.symbols.items[sym_index].flags.is_extern_ptr = true; |
| 914 | return .{ .mcv = .{ .load_symbol = sym_index } }; | 914 | return GenResult.mcv(.{ .lea_symbol = sym_index }); |
| 915 | } | 915 | } |
| 916 | const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_index); | 916 | const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_index); |
| 917 | const sym = zo.symbols.items[sym_index]; | 917 | const sym = zo.symbols.items[sym_index]; |
| 918 | if (!single_threaded and is_threadlocal) { | 918 | if (!single_threaded and is_threadlocal) { |
| 919 | return .{ .mcv = .{ .load_tlv = sym.nlist_idx } }; | 919 | return .{ .mcv = .{ .load_tlv = sym.nlist_idx } }; |
| 920 | } | 920 | } |
| 921 | return .{ .mcv = .{ .load_symbol = sym.nlist_idx } }; | 921 | return GenResult.mcv(.{ .lea_symbol = sym.nlist_idx }); |
| 922 | } else if (lf.cast(.coff)) |coff_file| { | 922 | } else if (lf.cast(.coff)) |coff_file| { |
| 923 | if (is_extern) { | 923 | if (is_extern) { |
| 924 | // TODO audit this | 924 | // TODO audit this |
src/link/MachO.zig-29| ... | @@ -59,7 +59,6 @@ symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | ... | @@ -59,7 +59,6 @@ symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 59 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 59 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 60 | indsymtab: Indsymtab = .{}, | 60 | indsymtab: Indsymtab = .{}, |
| 61 | got: GotSection = .{}, | 61 | got: GotSection = .{}, |
| 62 | zig_got: ZigGotSection = .{}, | ||
| 63 | stubs: StubsSection = .{}, | 62 | stubs: StubsSection = .{}, |
| 64 | stubs_helper: StubsHelperSection = .{}, | 63 | stubs_helper: StubsHelperSection = .{}, |
| 65 | objc_stubs: ObjcStubsSection = .{}, | 64 | objc_stubs: ObjcStubsSection = .{}, |
| ... | @@ -75,14 +74,12 @@ data_in_code: DataInCode = .{}, | ... | @@ -75,14 +74,12 @@ data_in_code: DataInCode = .{}, |
| 75 | 74 | ||
| 76 | /// Tracked loadable segments during incremental linking. | 75 | /// Tracked loadable segments during incremental linking. |
| 77 | zig_text_seg_index: ?u8 = null, | 76 | zig_text_seg_index: ?u8 = null, |
| 78 | zig_got_seg_index: ?u8 = null, | ||
| 79 | zig_const_seg_index: ?u8 = null, | 77 | zig_const_seg_index: ?u8 = null, |
| 80 | zig_data_seg_index: ?u8 = null, | 78 | zig_data_seg_index: ?u8 = null, |
| 81 | zig_bss_seg_index: ?u8 = null, | 79 | zig_bss_seg_index: ?u8 = null, |
| 82 | 80 | ||
| 83 | /// Tracked section headers with incremental updates to Zig object. | 81 | /// Tracked section headers with incremental updates to Zig object. |
| 84 | zig_text_sect_index: ?u8 = null, | 82 | zig_text_sect_index: ?u8 = null, |
| 85 | zig_got_sect_index: ?u8 = null, | ||
| 86 | zig_const_sect_index: ?u8 = null, | 83 | zig_const_sect_index: ?u8 = null, |
| 87 | zig_data_sect_index: ?u8 = null, | 84 | zig_data_sect_index: ?u8 = null, |
| 88 | zig_bss_sect_index: ?u8 = null, | 85 | zig_bss_sect_index: ?u8 = null, |
| ... | @@ -324,7 +321,6 @@ pub fn deinit(self: *MachO) void { | ... | @@ -324,7 +321,6 @@ pub fn deinit(self: *MachO) void { |
| 324 | self.symtab.deinit(gpa); | 321 | self.symtab.deinit(gpa); |
| 325 | self.strtab.deinit(gpa); | 322 | self.strtab.deinit(gpa); |
| 326 | self.got.deinit(gpa); | 323 | self.got.deinit(gpa); |
| 327 | self.zig_got.deinit(gpa); | ||
| 328 | self.stubs.deinit(gpa); | 324 | self.stubs.deinit(gpa); |
| 329 | self.objc_stubs.deinit(gpa); | 325 | self.objc_stubs.deinit(gpa); |
| 330 | self.tlv_ptr.deinit(gpa); | 326 | self.tlv_ptr.deinit(gpa); |
| ... | @@ -1796,7 +1792,6 @@ pub fn sortSections(self: *MachO) !void { | ... | @@ -1796,7 +1792,6 @@ pub fn sortSections(self: *MachO) !void { |
| 1796 | &self.data_sect_index, | 1792 | &self.data_sect_index, |
| 1797 | &self.got_sect_index, | 1793 | &self.got_sect_index, |
| 1798 | &self.zig_text_sect_index, | 1794 | &self.zig_text_sect_index, |
| 1799 | &self.zig_got_sect_index, | ||
| 1800 | &self.zig_const_sect_index, | 1795 | &self.zig_const_sect_index, |
| 1801 | &self.zig_data_sect_index, | 1796 | &self.zig_data_sect_index, |
| 1802 | &self.zig_bss_sect_index, | 1797 | &self.zig_bss_sect_index, |
| ... | @@ -2114,7 +2109,6 @@ fn initSegments(self: *MachO) !void { | ... | @@ -2114,7 +2109,6 @@ fn initSegments(self: *MachO) !void { |
| 2114 | &self.text_seg_index, | 2109 | &self.text_seg_index, |
| 2115 | &self.linkedit_seg_index, | 2110 | &self.linkedit_seg_index, |
| 2116 | &self.zig_text_seg_index, | 2111 | &self.zig_text_seg_index, |
| 2117 | &self.zig_got_seg_index, | ||
| 2118 | &self.zig_const_seg_index, | 2112 | &self.zig_const_seg_index, |
| 2119 | &self.zig_data_seg_index, | 2113 | &self.zig_data_seg_index, |
| 2120 | &self.zig_bss_seg_index, | 2114 | &self.zig_bss_seg_index, |
| ... | @@ -3231,18 +3225,6 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { | ... | @@ -3231,18 +3225,6 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { |
| 3231 | }); | 3225 | }); |
| 3232 | } | 3226 | } |
| 3233 | 3227 | ||
| 3234 | { | ||
| 3235 | const filesize = options.symbol_count_hint * @sizeOf(u64); | ||
| 3236 | const off = try self.findFreeSpace(filesize, self.getPageSize()); | ||
| 3237 | self.zig_got_seg_index = try self.addSegment("__GOT_ZIG", .{ | ||
| 3238 | .fileoff = off, | ||
| 3239 | .filesize = filesize, | ||
| 3240 | .vmaddr = base_vmaddr + 0x4000000, | ||
| 3241 | .vmsize = filesize, | ||
| 3242 | .prot = macho.PROT.READ | macho.PROT.WRITE, | ||
| 3243 | }); | ||
| 3244 | } | ||
| 3245 | |||
| 3246 | { | 3228 | { |
| 3247 | const filesize: u64 = 1024; | 3229 | const filesize: u64 = 1024; |
| 3248 | const off = try self.findFreeSpace(filesize, self.getPageSize()); | 3230 | const off = try self.findFreeSpace(filesize, self.getPageSize()); |
| ... | @@ -3343,13 +3325,6 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { | ... | @@ -3343,13 +3325,6 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { |
| 3343 | } | 3325 | } |
| 3344 | } | 3326 | } |
| 3345 | 3327 | ||
| 3346 | if (!self.base.isRelocatable()) { | ||
| 3347 | self.zig_got_sect_index = try self.addSection("__GOT_ZIG", "__got_zig", .{ | ||
| 3348 | .alignment = 3, | ||
| 3349 | }); | ||
| 3350 | appendSect(self, self.zig_got_sect_index.?, self.zig_got_seg_index.?); | ||
| 3351 | } | ||
| 3352 | |||
| 3353 | { | 3328 | { |
| 3354 | self.zig_const_sect_index = try self.addSection("__CONST_ZIG", "__const_zig", .{}); | 3329 | self.zig_const_sect_index = try self.addSection("__CONST_ZIG", "__const_zig", .{}); |
| 3355 | if (self.base.isRelocatable()) { | 3330 | if (self.base.isRelocatable()) { |
| ... | @@ -3572,7 +3547,6 @@ inline fn requiresThunks(self: MachO) bool { | ... | @@ -3572,7 +3547,6 @@ inline fn requiresThunks(self: MachO) bool { |
| 3572 | pub fn isZigSegment(self: MachO, seg_id: u8) bool { | 3547 | pub fn isZigSegment(self: MachO, seg_id: u8) bool { |
| 3573 | inline for (&[_]?u8{ | 3548 | inline for (&[_]?u8{ |
| 3574 | self.zig_text_seg_index, | 3549 | self.zig_text_seg_index, |
| 3575 | self.zig_got_seg_index, | ||
| 3576 | self.zig_const_seg_index, | 3550 | self.zig_const_seg_index, |
| 3577 | self.zig_data_seg_index, | 3551 | self.zig_data_seg_index, |
| 3578 | self.zig_bss_seg_index, | 3552 | self.zig_bss_seg_index, |
| ... | @@ -3587,7 +3561,6 @@ pub fn isZigSegment(self: MachO, seg_id: u8) bool { | ... | @@ -3587,7 +3561,6 @@ pub fn isZigSegment(self: MachO, seg_id: u8) bool { |
| 3587 | pub fn isZigSection(self: MachO, sect_id: u8) bool { | 3561 | pub fn isZigSection(self: MachO, sect_id: u8) bool { |
| 3588 | inline for (&[_]?u8{ | 3562 | inline for (&[_]?u8{ |
| 3589 | self.zig_text_sect_index, | 3563 | self.zig_text_sect_index, |
| 3590 | self.zig_got_sect_index, | ||
| 3591 | self.zig_const_sect_index, | 3564 | self.zig_const_sect_index, |
| 3592 | self.zig_data_sect_index, | 3565 | self.zig_data_sect_index, |
| 3593 | self.zig_bss_sect_index, | 3566 | self.zig_bss_sect_index, |
| ... | @@ -3957,7 +3930,6 @@ fn fmtDumpState( | ... | @@ -3957,7 +3930,6 @@ fn fmtDumpState( |
| 3957 | try writer.print("stubs\n{}\n", .{self.stubs.fmt(self)}); | 3930 | try writer.print("stubs\n{}\n", .{self.stubs.fmt(self)}); |
| 3958 | try writer.print("objc_stubs\n{}\n", .{self.objc_stubs.fmt(self)}); | 3931 | try writer.print("objc_stubs\n{}\n", .{self.objc_stubs.fmt(self)}); |
| 3959 | try writer.print("got\n{}\n", .{self.got.fmt(self)}); | 3932 | try writer.print("got\n{}\n", .{self.got.fmt(self)}); |
| 3960 | try writer.print("zig_got\n{}\n", .{self.zig_got.fmt(self)}); | ||
| 3961 | try writer.print("tlv_ptr\n{}\n", .{self.tlv_ptr.fmt(self)}); | 3933 | try writer.print("tlv_ptr\n{}\n", .{self.tlv_ptr.fmt(self)}); |
| 3962 | try writer.writeByte('\n'); | 3934 | try writer.writeByte('\n'); |
| 3963 | try writer.print("sections\n{}\n", .{self.fmtSections()}); | 3935 | try writer.print("sections\n{}\n", .{self.fmtSections()}); |
| ... | @@ -4665,7 +4637,6 @@ const Value = @import("../Value.zig"); | ... | @@ -4665,7 +4637,6 @@ const Value = @import("../Value.zig"); |
| 4665 | const UnwindInfo = @import("MachO/UnwindInfo.zig"); | 4637 | const UnwindInfo = @import("MachO/UnwindInfo.zig"); |
| 4666 | const WaitGroup = std.Thread.WaitGroup; | 4638 | const WaitGroup = std.Thread.WaitGroup; |
| 4667 | const WeakBind = bind.WeakBind; | 4639 | const WeakBind = bind.WeakBind; |
| 4668 | const ZigGotSection = synthetic.ZigGotSection; | ||
| 4669 | const ZigObject = @import("MachO/ZigObject.zig"); | 4640 | const ZigObject = @import("MachO/ZigObject.zig"); |
| 4670 | const dev = @import("../dev.zig"); | 4641 | const dev = @import("../dev.zig"); |
| 4671 | 4642 |
src/link/MachO/Atom.zig+1-21| ... | @@ -492,10 +492,6 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void { | ... | @@ -492,10 +492,6 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void { |
| 492 | } | 492 | } |
| 493 | }, | 493 | }, |
| 494 | 494 | ||
| 495 | .zig_got_load => { | ||
| 496 | assert(rel.getTargetSymbol(self, macho_file).getSectionFlags().has_zig_got); | ||
| 497 | }, | ||
| 498 | |||
| 499 | .got => { | 495 | .got => { |
| 500 | rel.getTargetSymbol(self, macho_file).setSectionFlags(.{ .needs_got = true }); | 496 | rel.getTargetSymbol(self, macho_file).setSectionFlags(.{ .needs_got = true }); |
| 501 | }, | 497 | }, |
| ... | @@ -652,8 +648,6 @@ fn resolveRelocInner( | ... | @@ -652,8 +648,6 @@ fn resolveRelocInner( |
| 652 | const G: i64 = @intCast(rel.getGotTargetAddress(self, macho_file)); | 648 | const G: i64 = @intCast(rel.getGotTargetAddress(self, macho_file)); |
| 653 | const TLS = @as(i64, @intCast(macho_file.getTlsAddress())); | 649 | const TLS = @as(i64, @intCast(macho_file.getTlsAddress())); |
| 654 | const SUB = if (subtractor) |sub| @as(i64, @intCast(sub.getTargetAddress(self, macho_file))) else 0; | 650 | const SUB = if (subtractor) |sub| @as(i64, @intCast(sub.getTargetAddress(self, macho_file))) else 0; |
| 655 | // Address of the __got_zig table entry if any. | ||
| 656 | const ZIG_GOT = @as(i64, @intCast(rel.getZigGotTargetAddress(macho_file))); | ||
| 657 | 651 | ||
| 658 | const divExact = struct { | 652 | const divExact = struct { |
| 659 | fn divExact(atom: Atom, r: Relocation, num: u12, den: u12, ctx: *MachO) !u12 { | 653 | fn divExact(atom: Atom, r: Relocation, num: u12, den: u12, ctx: *MachO) !u12 { |
| ... | @@ -676,13 +670,12 @@ fn resolveRelocInner( | ... | @@ -676,13 +670,12 @@ fn resolveRelocInner( |
| 676 | S + A - SUB, | 670 | S + A - SUB, |
| 677 | rel.getTargetAtom(self, macho_file).atom_index, | 671 | rel.getTargetAtom(self, macho_file).atom_index, |
| 678 | }), | 672 | }), |
| 679 | .@"extern" => relocs_log.debug(" {x}<+{d}>: {}: [=> {x}] G({x}) ZG({x}) ({s})", .{ | 673 | .@"extern" => relocs_log.debug(" {x}<+{d}>: {}: [=> {x}] G({x}) ({s})", .{ |
| 680 | P, | 674 | P, |
| 681 | rel_offset, | 675 | rel_offset, |
| 682 | rel.fmtPretty(cpu_arch), | 676 | rel.fmtPretty(cpu_arch), |
| 683 | S + A - SUB, | 677 | S + A - SUB, |
| 684 | G + A, | 678 | G + A, |
| 685 | ZIG_GOT + A, | ||
| 686 | rel.getTargetSymbol(self, macho_file).getName(macho_file), | 679 | rel.getTargetSymbol(self, macho_file).getName(macho_file), |
| 687 | }), | 680 | }), |
| 688 | } | 681 | } |
| ... | @@ -745,17 +738,6 @@ fn resolveRelocInner( | ... | @@ -745,17 +738,6 @@ fn resolveRelocInner( |
| 745 | } | 738 | } |
| 746 | }, | 739 | }, |
| 747 | 740 | ||
| 748 | .zig_got_load => { | ||
| 749 | assert(rel.tag == .@"extern"); | ||
| 750 | assert(rel.meta.length == 2); | ||
| 751 | assert(rel.meta.pcrel); | ||
| 752 | switch (cpu_arch) { | ||
| 753 | .x86_64 => try writer.writeInt(i32, @intCast(ZIG_GOT + A - P), .little), | ||
| 754 | .aarch64 => @panic("TODO resolve __got_zig indirection reloc"), | ||
| 755 | else => unreachable, | ||
| 756 | } | ||
| 757 | }, | ||
| 758 | |||
| 759 | .tlv => { | 741 | .tlv => { |
| 760 | assert(rel.tag == .@"extern"); | 742 | assert(rel.tag == .@"extern"); |
| 761 | assert(rel.meta.length == 2); | 743 | assert(rel.meta.length == 2); |
| ... | @@ -1065,7 +1047,6 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r | ... | @@ -1065,7 +1047,6 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r |
| 1065 | .subtractor => .ARM64_RELOC_SUBTRACTOR, | 1047 | .subtractor => .ARM64_RELOC_SUBTRACTOR, |
| 1066 | .unsigned => .ARM64_RELOC_UNSIGNED, | 1048 | .unsigned => .ARM64_RELOC_UNSIGNED, |
| 1067 | 1049 | ||
| 1068 | .zig_got_load, | ||
| 1069 | .signed, | 1050 | .signed, |
| 1070 | .signed1, | 1051 | .signed1, |
| 1071 | .signed2, | 1052 | .signed2, |
| ... | @@ -1109,7 +1090,6 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r | ... | @@ -1109,7 +1090,6 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r |
| 1109 | .subtractor => .X86_64_RELOC_SUBTRACTOR, | 1090 | .subtractor => .X86_64_RELOC_SUBTRACTOR, |
| 1110 | .unsigned => .X86_64_RELOC_UNSIGNED, | 1091 | .unsigned => .X86_64_RELOC_UNSIGNED, |
| 1111 | 1092 | ||
| 1112 | .zig_got_load, | ||
| 1113 | .page, | 1093 | .page, |
| 1114 | .pageoff, | 1094 | .pageoff, |
| 1115 | .got_load_page, | 1095 | .got_load_page, |
src/link/MachO/Relocation.zig-3| ... | @@ -92,7 +92,6 @@ fn formatPretty( | ... | @@ -92,7 +92,6 @@ fn formatPretty( |
| 92 | .signed4 => "X86_64_RELOC_SIGNED_4", | 92 | .signed4 => "X86_64_RELOC_SIGNED_4", |
| 93 | .got_load => "X86_64_RELOC_GOT_LOAD", | 93 | .got_load => "X86_64_RELOC_GOT_LOAD", |
| 94 | .tlv => "X86_64_RELOC_TLV", | 94 | .tlv => "X86_64_RELOC_TLV", |
| 95 | .zig_got_load => "ZIG_GOT_LOAD", | ||
| 96 | .page => "ARM64_RELOC_PAGE21", | 95 | .page => "ARM64_RELOC_PAGE21", |
| 97 | .pageoff => "ARM64_RELOC_PAGEOFF12", | 96 | .pageoff => "ARM64_RELOC_PAGEOFF12", |
| 98 | .got_load_page => "ARM64_RELOC_GOT_LOAD_PAGE21", | 97 | .got_load_page => "ARM64_RELOC_GOT_LOAD_PAGE21", |
| ... | @@ -137,8 +136,6 @@ pub const Type = enum { | ... | @@ -137,8 +136,6 @@ pub const Type = enum { |
| 137 | got_load, | 136 | got_load, |
| 138 | /// RIP-relative TLV load (X86_64_RELOC_TLV) | 137 | /// RIP-relative TLV load (X86_64_RELOC_TLV) |
| 139 | tlv, | 138 | tlv, |
| 140 | /// Zig-specific __got_zig indirection | ||
| 141 | zig_got_load, | ||
| 142 | 139 | ||
| 143 | // arm64 | 140 | // arm64 |
| 144 | /// PC-relative load (distance to page, ARM64_RELOC_PAGE21) | 141 | /// PC-relative load (distance to page, ARM64_RELOC_PAGE21) |
src/link/MachO/Symbol.zig+19-24| ... | @@ -123,6 +123,7 @@ pub fn getSymbolRank(symbol: Symbol, macho_file: *MachO) u32 { | ... | @@ -123,6 +123,7 @@ pub fn getSymbolRank(symbol: Symbol, macho_file: *MachO) u32 { |
| 123 | 123 | ||
| 124 | pub fn getAddress(symbol: Symbol, opts: struct { | 124 | pub fn getAddress(symbol: Symbol, opts: struct { |
| 125 | stubs: bool = true, | 125 | stubs: bool = true, |
| 126 | trampoline: bool = true, | ||
| 126 | }, macho_file: *MachO) u64 { | 127 | }, macho_file: *MachO) u64 { |
| 127 | if (opts.stubs) { | 128 | if (opts.stubs) { |
| 128 | if (symbol.getSectionFlags().stubs) { | 129 | if (symbol.getSectionFlags().stubs) { |
| ... | @@ -131,6 +132,9 @@ pub fn getAddress(symbol: Symbol, opts: struct { | ... | @@ -131,6 +132,9 @@ pub fn getAddress(symbol: Symbol, opts: struct { |
| 131 | return symbol.getObjcStubsAddress(macho_file); | 132 | return symbol.getObjcStubsAddress(macho_file); |
| 132 | } | 133 | } |
| 133 | } | 134 | } |
| 135 | if (symbol.flags.trampoline and opts.trampoline) { | ||
| 136 | return symbol.getTrampolineAddress(macho_file); | ||
| 137 | } | ||
| 134 | if (symbol.getAtom(macho_file)) |atom| return atom.getAddress(macho_file) + symbol.value; | 138 | if (symbol.getAtom(macho_file)) |atom| return atom.getAddress(macho_file) + symbol.value; |
| 135 | return symbol.value; | 139 | return symbol.value; |
| 136 | } | 140 | } |
| ... | @@ -169,23 +173,11 @@ pub fn getTlvPtrAddress(symbol: Symbol, macho_file: *MachO) u64 { | ... | @@ -169,23 +173,11 @@ pub fn getTlvPtrAddress(symbol: Symbol, macho_file: *MachO) u64 { |
| 169 | return macho_file.tlv_ptr.getAddress(extra.tlv_ptr, macho_file); | 173 | return macho_file.tlv_ptr.getAddress(extra.tlv_ptr, macho_file); |
| 170 | } | 174 | } |
| 171 | 175 | ||
| 172 | const GetOrCreateZigGotEntryResult = struct { | 176 | pub fn getTrampolineAddress(symbol: Symbol, macho_file: *MachO) u64 { |
| 173 | found_existing: bool, | 177 | if (!symbol.flags.trampoline) return 0; |
| 174 | index: ZigGotSection.Index, | 178 | const zo = macho_file.getZigObject().?; |
| 175 | }; | 179 | const index = symbol.getExtra(macho_file).trampoline; |
| 176 | 180 | return zo.symbols.items[index].getAddress(.{}, macho_file); | |
| 177 | pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, macho_file: *MachO) !GetOrCreateZigGotEntryResult { | ||
| 178 | assert(!macho_file.base.isRelocatable()); | ||
| 179 | assert(symbol.getSectionFlags().needs_zig_got); | ||
| 180 | if (symbol.getSectionFlags().has_zig_got) return .{ .found_existing = true, .index = symbol.getExtra(macho_file).zig_got }; | ||
| 181 | const index = try macho_file.zig_got.addSymbol(symbol_index, macho_file); | ||
| 182 | return .{ .found_existing = false, .index = index }; | ||
| 183 | } | ||
| 184 | |||
| 185 | pub fn getZigGotAddress(symbol: Symbol, macho_file: *MachO) u64 { | ||
| 186 | if (!symbol.getSectionFlags().has_zig_got) return 0; | ||
| 187 | const extras = symbol.getExtra(macho_file); | ||
| 188 | return macho_file.zig_got.entryAddress(extras.zig_got, macho_file); | ||
| 189 | } | 181 | } |
| 190 | 182 | ||
| 191 | pub fn getOutputSymtabIndex(symbol: Symbol, macho_file: *MachO) ?u32 { | 183 | pub fn getOutputSymtabIndex(symbol: Symbol, macho_file: *MachO) ?u32 { |
| ... | @@ -209,12 +201,12 @@ pub fn getOutputSymtabIndex(symbol: Symbol, macho_file: *MachO) ?u32 { | ... | @@ -209,12 +201,12 @@ pub fn getOutputSymtabIndex(symbol: Symbol, macho_file: *MachO) ?u32 { |
| 209 | 201 | ||
| 210 | const AddExtraOpts = struct { | 202 | const AddExtraOpts = struct { |
| 211 | got: ?u32 = null, | 203 | got: ?u32 = null, |
| 212 | zig_got: ?u32 = null, | ||
| 213 | stubs: ?u32 = null, | 204 | stubs: ?u32 = null, |
| 214 | objc_stubs: ?u32 = null, | 205 | objc_stubs: ?u32 = null, |
| 215 | objc_selrefs: ?u32 = null, | 206 | objc_selrefs: ?u32 = null, |
| 216 | tlv_ptr: ?u32 = null, | 207 | tlv_ptr: ?u32 = null, |
| 217 | symtab: ?u32 = null, | 208 | symtab: ?u32 = null, |
| 209 | trampoline: ?u32 = null, | ||
| 218 | }; | 210 | }; |
| 219 | 211 | ||
| 220 | pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, macho_file: *MachO) void { | 212 | pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, macho_file: *MachO) void { |
| ... | @@ -393,6 +385,13 @@ pub const Flags = packed struct { | ... | @@ -393,6 +385,13 @@ pub const Flags = packed struct { |
| 393 | 385 | ||
| 394 | /// Whether the symbol makes into the output symtab or not. | 386 | /// Whether the symbol makes into the output symtab or not. |
| 395 | output_symtab: bool = false, | 387 | output_symtab: bool = false, |
| 388 | |||
| 389 | /// ZigObject specific flags | ||
| 390 | /// Whether the symbol has a trampoline | ||
| 391 | trampoline: bool = false, | ||
| 392 | |||
| 393 | /// Whether the symbol is an extern pointer (as opposed to function). | ||
| 394 | is_extern_ptr: bool = false, | ||
| 396 | }; | 395 | }; |
| 397 | 396 | ||
| 398 | pub const SectionFlags = packed struct(u8) { | 397 | pub const SectionFlags = packed struct(u8) { |
| ... | @@ -400,10 +399,6 @@ pub const SectionFlags = packed struct(u8) { | ... | @@ -400,10 +399,6 @@ pub const SectionFlags = packed struct(u8) { |
| 400 | needs_got: bool = false, | 399 | needs_got: bool = false, |
| 401 | has_got: bool = false, | 400 | has_got: bool = false, |
| 402 | 401 | ||
| 403 | /// Whether the symbol contains __got_zig indirection. | ||
| 404 | needs_zig_got: bool = false, | ||
| 405 | has_zig_got: bool = false, | ||
| 406 | |||
| 407 | /// Whether the symbols contains __stubs indirection. | 402 | /// Whether the symbols contains __stubs indirection. |
| 408 | stubs: bool = false, | 403 | stubs: bool = false, |
| 409 | 404 | ||
| ... | @@ -413,7 +408,7 @@ pub const SectionFlags = packed struct(u8) { | ... | @@ -413,7 +408,7 @@ pub const SectionFlags = packed struct(u8) { |
| 413 | /// Whether the symbol contains __objc_stubs indirection. | 408 | /// Whether the symbol contains __objc_stubs indirection. |
| 414 | objc_stubs: bool = false, | 409 | objc_stubs: bool = false, |
| 415 | 410 | ||
| 416 | _: u1 = 0, | 411 | _: u3 = 0, |
| 417 | }; | 412 | }; |
| 418 | 413 | ||
| 419 | pub const Visibility = enum { | 414 | pub const Visibility = enum { |
| ... | @@ -432,12 +427,12 @@ pub const Visibility = enum { | ... | @@ -432,12 +427,12 @@ pub const Visibility = enum { |
| 432 | 427 | ||
| 433 | pub const Extra = struct { | 428 | pub const Extra = struct { |
| 434 | got: u32 = 0, | 429 | got: u32 = 0, |
| 435 | zig_got: u32 = 0, | ||
| 436 | stubs: u32 = 0, | 430 | stubs: u32 = 0, |
| 437 | objc_stubs: u32 = 0, | 431 | objc_stubs: u32 = 0, |
| 438 | objc_selrefs: u32 = 0, | 432 | objc_selrefs: u32 = 0, |
| 439 | tlv_ptr: u32 = 0, | 433 | tlv_ptr: u32 = 0, |
| 440 | symtab: u32 = 0, | 434 | symtab: u32 = 0, |
| 435 | trampoline: u32 = 0, | ||
| 441 | }; | 436 | }; |
| 442 | 437 | ||
| 443 | pub const Index = u32; | 438 | pub const Index = u32; |
src/link/MachO/ZigObject.zig+84-28| ... | @@ -795,7 +795,15 @@ pub fn updateFunc( | ... | @@ -795,7 +795,15 @@ pub fn updateFunc( |
| 795 | }; | 795 | }; |
| 796 | 796 | ||
| 797 | const sect_index = try self.getNavOutputSection(macho_file, zcu, func.owner_nav, code); | 797 | const sect_index = try self.getNavOutputSection(macho_file, zcu, func.owner_nav, code); |
| 798 | const old_rva, const old_alignment = blk: { | ||
| 799 | const atom = self.symbols.items[sym_index].getAtom(macho_file).?; | ||
| 800 | break :blk .{ atom.value, atom.alignment }; | ||
| 801 | }; | ||
| 798 | try self.updateNavCode(macho_file, pt, func.owner_nav, sym_index, sect_index, code); | 802 | try self.updateNavCode(macho_file, pt, func.owner_nav, sym_index, sect_index, code); |
| 803 | const new_rva, const new_alignment = blk: { | ||
| 804 | const atom = self.symbols.items[sym_index].getAtom(macho_file).?; | ||
| 805 | break :blk .{ atom.value, atom.alignment }; | ||
| 806 | }; | ||
| 799 | 807 | ||
| 800 | if (dwarf_wip_nav) |*wip_nav| { | 808 | if (dwarf_wip_nav) |*wip_nav| { |
| 801 | const sym = self.symbols.items[sym_index]; | 809 | const sym = self.symbols.items[sym_index]; |
| ... | @@ -812,6 +820,42 @@ pub fn updateFunc( | ... | @@ -812,6 +820,42 @@ pub fn updateFunc( |
| 812 | } | 820 | } |
| 813 | 821 | ||
| 814 | // Exports will be updated by `Zcu.processExports` after the update. | 822 | // Exports will be updated by `Zcu.processExports` after the update. |
| 823 | if (old_rva != new_rva and old_rva > 0) { | ||
| 824 | // If we had to reallocate the function, we re-use the existing slot for a trampoline. | ||
| 825 | // In the rare case that the function has been further overaligned we skip creating a | ||
| 826 | // trampoline and update all symbols referring this function. | ||
| 827 | if (old_alignment.order(new_alignment) == .lt) { | ||
| 828 | @panic("TODO update all symbols referring this function"); | ||
| 829 | } | ||
| 830 | |||
| 831 | // Create a trampoline to the new location at `old_rva`. | ||
| 832 | if (!self.symbols.items[sym_index].flags.trampoline) { | ||
| 833 | const name = try std.fmt.allocPrint(gpa, "{s}$trampoline", .{ | ||
| 834 | self.symbols.items[sym_index].getName(macho_file), | ||
| 835 | }); | ||
| 836 | defer gpa.free(name); | ||
| 837 | const name_off = try self.addString(gpa, name); | ||
| 838 | const tr_size = trampolineSize(macho_file.getTarget().cpu.arch); | ||
| 839 | const tr_sym_index = try self.newSymbolWithAtom(gpa, name_off, macho_file); | ||
| 840 | const tr_sym = &self.symbols.items[tr_sym_index]; | ||
| 841 | tr_sym.out_n_sect = macho_file.zig_text_sect_index.?; | ||
| 842 | const tr_nlist = &self.symtab.items(.nlist)[tr_sym.nlist_idx]; | ||
| 843 | tr_nlist.n_sect = macho_file.zig_text_sect_index.? + 1; | ||
| 844 | const tr_atom = tr_sym.getAtom(macho_file).?; | ||
| 845 | tr_atom.value = old_rva; | ||
| 846 | tr_atom.setAlive(true); | ||
| 847 | tr_atom.alignment = old_alignment; | ||
| 848 | tr_atom.out_n_sect = macho_file.zig_text_sect_index.?; | ||
| 849 | tr_atom.size = tr_size; | ||
| 850 | self.symtab.items(.size)[tr_sym.nlist_idx] = tr_size; | ||
| 851 | const target_sym = &self.symbols.items[sym_index]; | ||
| 852 | target_sym.addExtra(.{ .trampoline = tr_sym_index }, macho_file); | ||
| 853 | target_sym.flags.trampoline = true; | ||
| 854 | } | ||
| 855 | const target_sym = self.symbols.items[sym_index]; | ||
| 856 | const source_sym = self.symbols.items[target_sym.getExtra(macho_file).trampoline]; | ||
| 857 | try writeTrampoline(source_sym, target_sym, macho_file); | ||
| 858 | } | ||
| 815 | } | 859 | } |
| 816 | 860 | ||
| 817 | pub fn updateNav( | 861 | pub fn updateNav( |
| ... | @@ -836,7 +880,7 @@ pub fn updateNav( | ... | @@ -836,7 +880,7 @@ pub fn updateNav( |
| 836 | const lib_name = @"extern".lib_name.toSlice(ip); | 880 | const lib_name = @"extern".lib_name.toSlice(ip); |
| 837 | const index = try self.getGlobalSymbol(macho_file, name, lib_name); | 881 | const index = try self.getGlobalSymbol(macho_file, name, lib_name); |
| 838 | const sym = &self.symbols.items[index]; | 882 | const sym = &self.symbols.items[index]; |
| 839 | sym.setSectionFlags(.{ .needs_got = true }); | 883 | sym.flags.is_extern_ptr = true; |
| 840 | return; | 884 | return; |
| 841 | }, | 885 | }, |
| 842 | else => nav_val, | 886 | else => nav_val, |
| ... | @@ -946,13 +990,6 @@ fn updateNavCode( | ... | @@ -946,13 +990,6 @@ fn updateNavCode( |
| 946 | if (old_vaddr != atom.value) { | 990 | if (old_vaddr != atom.value) { |
| 947 | sym.value = 0; | 991 | sym.value = 0; |
| 948 | nlist.n_value = 0; | 992 | nlist.n_value = 0; |
| 949 | |||
| 950 | if (!macho_file.base.isRelocatable()) { | ||
| 951 | log.debug(" (updating offset table entry)", .{}); | ||
| 952 | assert(sym.getSectionFlags().has_zig_got); | ||
| 953 | const extra = sym.getExtra(macho_file); | ||
| 954 | try macho_file.zig_got.writeOne(macho_file, extra.zig_got); | ||
| 955 | } | ||
| 956 | } | 993 | } |
| 957 | } else if (code.len < old_size) { | 994 | } else if (code.len < old_size) { |
| 958 | atom.shrink(macho_file); | 995 | atom.shrink(macho_file); |
| ... | @@ -965,13 +1002,7 @@ fn updateNavCode( | ... | @@ -965,13 +1002,7 @@ fn updateNavCode( |
| 965 | errdefer self.freeNavMetadata(macho_file, sym_index); | 1002 | errdefer self.freeNavMetadata(macho_file, sym_index); |
| 966 | 1003 | ||
| 967 | sym.value = 0; | 1004 | sym.value = 0; |
| 968 | sym.setSectionFlags(.{ .needs_zig_got = true }); | ||
| 969 | nlist.n_value = 0; | 1005 | nlist.n_value = 0; |
| 970 | |||
| 971 | if (!macho_file.base.isRelocatable()) { | ||
| 972 | const gop = try sym.getOrCreateZigGotEntry(sym_index, macho_file); | ||
| 973 | try macho_file.zig_got.writeOne(macho_file, gop.index); | ||
| 974 | } | ||
| 975 | } | 1006 | } |
| 976 | 1007 | ||
| 977 | if (!sect.isZerofill()) { | 1008 | if (!sect.isZerofill()) { |
| ... | @@ -1381,14 +1412,8 @@ fn updateLazySymbol( | ... | @@ -1381,14 +1412,8 @@ fn updateLazySymbol( |
| 1381 | errdefer self.freeNavMetadata(macho_file, symbol_index); | 1412 | errdefer self.freeNavMetadata(macho_file, symbol_index); |
| 1382 | 1413 | ||
| 1383 | sym.value = 0; | 1414 | sym.value = 0; |
| 1384 | sym.setSectionFlags(.{ .needs_zig_got = true }); | ||
| 1385 | nlist.n_value = 0; | 1415 | nlist.n_value = 0; |
| 1386 | 1416 | ||
| 1387 | if (!macho_file.base.isRelocatable()) { | ||
| 1388 | const gop = try sym.getOrCreateZigGotEntry(symbol_index, macho_file); | ||
| 1389 | try macho_file.zig_got.writeOne(macho_file, gop.index); | ||
| 1390 | } | ||
| 1391 | |||
| 1392 | const sect = macho_file.sections.items(.header)[output_section_index]; | 1417 | const sect = macho_file.sections.items(.header)[output_section_index]; |
| 1393 | const file_offset = sect.offset + atom.value; | 1418 | const file_offset = sect.offset + atom.value; |
| 1394 | try macho_file.base.file.?.pwriteAll(code, file_offset); | 1419 | try macho_file.base.file.?.pwriteAll(code, file_offset); |
| ... | @@ -1448,6 +1473,31 @@ pub fn getGlobalSymbol(self: *ZigObject, macho_file: *MachO, name: []const u8, l | ... | @@ -1448,6 +1473,31 @@ pub fn getGlobalSymbol(self: *ZigObject, macho_file: *MachO, name: []const u8, l |
| 1448 | return lookup_gop.value_ptr.*; | 1473 | return lookup_gop.value_ptr.*; |
| 1449 | } | 1474 | } |
| 1450 | 1475 | ||
| 1476 | const max_trampoline_len = 12; | ||
| 1477 | |||
| 1478 | fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) u64 { | ||
| 1479 | const len = switch (cpu_arch) { | ||
| 1480 | .x86_64 => 5, // jmp rel32 | ||
| 1481 | else => @panic("TODO implement trampoline size for this CPU arch"), | ||
| 1482 | }; | ||
| 1483 | comptime assert(len <= max_trampoline_len); | ||
| 1484 | return len; | ||
| 1485 | } | ||
| 1486 | |||
| 1487 | fn writeTrampoline(tr_sym: Symbol, target: Symbol, macho_file: *MachO) !void { | ||
| 1488 | const atom = tr_sym.getAtom(macho_file).?; | ||
| 1489 | const header = macho_file.sections.items(.header)[atom.out_n_sect]; | ||
| 1490 | const fileoff = header.offset + atom.value; | ||
| 1491 | const source_addr = tr_sym.getAddress(.{}, macho_file); | ||
| 1492 | const target_addr = target.getAddress(.{ .trampoline = false }, macho_file); | ||
| 1493 | var buf: [max_trampoline_len]u8 = undefined; | ||
| 1494 | const out = switch (macho_file.getTarget().cpu.arch) { | ||
| 1495 | .x86_64 => try x86_64.writeTrampolineCode(source_addr, target_addr, &buf), | ||
| 1496 | else => @panic("TODO implement write trampoline for this CPU arch"), | ||
| 1497 | }; | ||
| 1498 | try macho_file.base.file.?.pwriteAll(out, fileoff); | ||
| 1499 | } | ||
| 1500 | |||
| 1451 | pub fn getOrCreateMetadataForNav( | 1501 | pub fn getOrCreateMetadataForNav( |
| 1452 | self: *ZigObject, | 1502 | self: *ZigObject, |
| 1453 | macho_file: *MachO, | 1503 | macho_file: *MachO, |
| ... | @@ -1460,8 +1510,6 @@ pub fn getOrCreateMetadataForNav( | ... | @@ -1460,8 +1510,6 @@ pub fn getOrCreateMetadataForNav( |
| 1460 | const sym = &self.symbols.items[sym_index]; | 1510 | const sym = &self.symbols.items[sym_index]; |
| 1461 | if (isThreadlocal(macho_file, nav_index)) { | 1511 | if (isThreadlocal(macho_file, nav_index)) { |
| 1462 | sym.flags.tlv = true; | 1512 | sym.flags.tlv = true; |
| 1463 | } else { | ||
| 1464 | sym.setSectionFlags(.{ .needs_zig_got = true }); | ||
| 1465 | } | 1513 | } |
| 1466 | gop.value_ptr.* = .{ .symbol_index = sym_index }; | 1514 | gop.value_ptr.* = .{ .symbol_index = sym_index }; |
| 1467 | } | 1515 | } |
| ... | @@ -1482,12 +1530,7 @@ pub fn getOrCreateMetadataForLazySymbol( | ... | @@ -1482,12 +1530,7 @@ pub fn getOrCreateMetadataForLazySymbol( |
| 1482 | .const_data => .{ &gop.value_ptr.const_symbol_index, &gop.value_ptr.const_state }, | 1530 | .const_data => .{ &gop.value_ptr.const_symbol_index, &gop.value_ptr.const_state }, |
| 1483 | }; | 1531 | }; |
| 1484 | switch (state_ptr.*) { | 1532 | switch (state_ptr.*) { |
| 1485 | .unused => { | 1533 | .unused => symbol_index_ptr.* = try self.newSymbolWithAtom(pt.zcu.gpa, .{}, macho_file), |
| 1486 | const symbol_index = try self.newSymbolWithAtom(pt.zcu.gpa, .{}, macho_file); | ||
| 1487 | const sym = &self.symbols.items[symbol_index]; | ||
| 1488 | sym.setSectionFlags(.{ .needs_zig_got = true }); | ||
| 1489 | symbol_index_ptr.* = symbol_index; | ||
| 1490 | }, | ||
| 1491 | .pending_flush => return symbol_index_ptr.*, | 1534 | .pending_flush => return symbol_index_ptr.*, |
| 1492 | .flushed => {}, | 1535 | .flushed => {}, |
| 1493 | } | 1536 | } |
| ... | @@ -1749,6 +1792,19 @@ const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, LazySymb | ... | @@ -1749,6 +1792,19 @@ const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, LazySymb |
| 1749 | const RelocationTable = std.ArrayListUnmanaged(std.ArrayListUnmanaged(Relocation)); | 1792 | const RelocationTable = std.ArrayListUnmanaged(std.ArrayListUnmanaged(Relocation)); |
| 1750 | const TlvInitializerTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlvInitializer); | 1793 | const TlvInitializerTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlvInitializer); |
| 1751 | 1794 | ||
| 1795 | const x86_64 = struct { | ||
| 1796 | fn writeTrampolineCode(source_addr: u64, target_addr: u64, buf: *[max_trampoline_len]u8) ![]u8 { | ||
| 1797 | const disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr)) - 5; | ||
| 1798 | var bytes = [_]u8{ | ||
| 1799 | 0xe9, 0x00, 0x00, 0x00, 0x00, // jmp rel32 | ||
| 1800 | }; | ||
| 1801 | assert(bytes.len == trampolineSize(.x86_64)); | ||
| 1802 | mem.writeInt(i32, bytes[1..][0..4], @intCast(disp), .little); | ||
| 1803 | @memcpy(buf[0..bytes.len], &bytes); | ||
| 1804 | return buf[0..bytes.len]; | ||
| 1805 | } | ||
| 1806 | }; | ||
| 1807 | |||
| 1752 | const assert = std.debug.assert; | 1808 | const assert = std.debug.assert; |
| 1753 | const builtin = @import("builtin"); | 1809 | const builtin = @import("builtin"); |
| 1754 | const codegen = @import("../../codegen.zig"); | 1810 | const codegen = @import("../../codegen.zig"); |
src/link/MachO/dyld_info/Rebase.zig-12| ... | @@ -56,18 +56,6 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void { | ... | @@ -56,18 +56,6 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void { |
| 56 | } | 56 | } |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | if (macho_file.zig_got_sect_index) |sid| { | ||
| 60 | const seg_id = macho_file.sections.items(.segment_id)[sid]; | ||
| 61 | const seg = macho_file.segments.items[seg_id]; | ||
| 62 | for (0..macho_file.zig_got.entries.items.len) |idx| { | ||
| 63 | const addr = macho_file.zig_got.entryAddress(@intCast(idx), macho_file); | ||
| 64 | try rebase.entries.append(gpa, .{ | ||
| 65 | .offset = addr - seg.vmaddr, | ||
| 66 | .segment_id = seg_id, | ||
| 67 | }); | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | if (macho_file.got_sect_index) |sid| { | 59 | if (macho_file.got_sect_index) |sid| { |
| 72 | const seg_id = macho_file.sections.items(.segment_id)[sid]; | 60 | const seg_id = macho_file.sections.items(.segment_id)[sid]; |
| 73 | const seg = macho_file.segments.items[seg_id]; | 61 | const seg = macho_file.segments.items[seg_id]; |
src/link/MachO/synthetic.zig-108| ... | @@ -1,111 +1,3 @@ | ... | @@ -1,111 +1,3 @@ |
| 1 | pub const ZigGotSection = struct { | ||
| 2 | entries: std.ArrayListUnmanaged(Symbol.Index) = .{}, | ||
| 3 | dirty: bool = false, | ||
| 4 | |||
| 5 | pub const Index = u32; | ||
| 6 | |||
| 7 | pub fn deinit(zig_got: *ZigGotSection, allocator: Allocator) void { | ||
| 8 | zig_got.entries.deinit(allocator); | ||
| 9 | } | ||
| 10 | |||
| 11 | fn allocateEntry(zig_got: *ZigGotSection, allocator: Allocator) !Index { | ||
| 12 | try zig_got.entries.ensureUnusedCapacity(allocator, 1); | ||
| 13 | // TODO add free list | ||
| 14 | const index = @as(Index, @intCast(zig_got.entries.items.len)); | ||
| 15 | _ = zig_got.entries.addOneAssumeCapacity(); | ||
| 16 | zig_got.dirty = true; | ||
| 17 | return index; | ||
| 18 | } | ||
| 19 | |||
| 20 | pub fn addSymbol(zig_got: *ZigGotSection, sym_index: Symbol.Index, macho_file: *MachO) !Index { | ||
| 21 | const gpa = macho_file.base.comp.gpa; | ||
| 22 | const zo = macho_file.getZigObject().?; | ||
| 23 | const index = try zig_got.allocateEntry(gpa); | ||
| 24 | const entry = &zig_got.entries.items[index]; | ||
| 25 | entry.* = sym_index; | ||
| 26 | const symbol = &zo.symbols.items[sym_index]; | ||
| 27 | assert(symbol.getSectionFlags().needs_zig_got); | ||
| 28 | symbol.setSectionFlags(.{ .has_zig_got = true }); | ||
| 29 | symbol.addExtra(.{ .zig_got = index }, macho_file); | ||
| 30 | return index; | ||
| 31 | } | ||
| 32 | |||
| 33 | pub fn entryOffset(zig_got: ZigGotSection, index: Index, macho_file: *MachO) u64 { | ||
| 34 | _ = zig_got; | ||
| 35 | const sect = macho_file.sections.items(.header)[macho_file.zig_got_sect_index.?]; | ||
| 36 | return sect.offset + @sizeOf(u64) * index; | ||
| 37 | } | ||
| 38 | |||
| 39 | pub fn entryAddress(zig_got: ZigGotSection, index: Index, macho_file: *MachO) u64 { | ||
| 40 | _ = zig_got; | ||
| 41 | const sect = macho_file.sections.items(.header)[macho_file.zig_got_sect_index.?]; | ||
| 42 | return sect.addr + @sizeOf(u64) * index; | ||
| 43 | } | ||
| 44 | |||
| 45 | pub fn size(zig_got: ZigGotSection, macho_file: *MachO) usize { | ||
| 46 | _ = macho_file; | ||
| 47 | return @sizeOf(u64) * zig_got.entries.items.len; | ||
| 48 | } | ||
| 49 | |||
| 50 | pub fn writeOne(zig_got: *ZigGotSection, macho_file: *MachO, index: Index) !void { | ||
| 51 | if (zig_got.dirty) { | ||
| 52 | const needed_size = zig_got.size(macho_file); | ||
| 53 | try macho_file.growSection(macho_file.zig_got_sect_index.?, needed_size); | ||
| 54 | zig_got.dirty = false; | ||
| 55 | } | ||
| 56 | const zo = macho_file.getZigObject().?; | ||
| 57 | const off = zig_got.entryOffset(index, macho_file); | ||
| 58 | const entry = zig_got.entries.items[index]; | ||
| 59 | const value = zo.symbols.items[entry].getAddress(.{ .stubs = false }, macho_file); | ||
| 60 | |||
| 61 | var buf: [8]u8 = undefined; | ||
| 62 | std.mem.writeInt(u64, &buf, value, .little); | ||
| 63 | try macho_file.base.file.?.pwriteAll(&buf, off); | ||
| 64 | } | ||
| 65 | |||
| 66 | pub fn writeAll(zig_got: ZigGotSection, macho_file: *MachO, writer: anytype) !void { | ||
| 67 | const zo = macho_file.getZigObject().?; | ||
| 68 | for (zig_got.entries.items) |entry| { | ||
| 69 | const symbol = zo.symbols.items[entry]; | ||
| 70 | const value = symbol.address(.{ .stubs = false }, macho_file); | ||
| 71 | try writer.writeInt(u64, value, .little); | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | const FormatCtx = struct { | ||
| 76 | zig_got: ZigGotSection, | ||
| 77 | macho_file: *MachO, | ||
| 78 | }; | ||
| 79 | |||
| 80 | pub fn fmt(zig_got: ZigGotSection, macho_file: *MachO) std.fmt.Formatter(format2) { | ||
| 81 | return .{ .data = .{ .zig_got = zig_got, .macho_file = macho_file } }; | ||
| 82 | } | ||
| 83 | |||
| 84 | pub fn format2( | ||
| 85 | ctx: FormatCtx, | ||
| 86 | comptime unused_fmt_string: []const u8, | ||
| 87 | options: std.fmt.FormatOptions, | ||
| 88 | writer: anytype, | ||
| 89 | ) !void { | ||
| 90 | _ = options; | ||
| 91 | _ = unused_fmt_string; | ||
| 92 | const zig_got = ctx.zig_got; | ||
| 93 | const macho_file = ctx.macho_file; | ||
| 94 | try writer.writeAll("__zig_got\n"); | ||
| 95 | for (zig_got.entries.items, 0..) |entry, index| { | ||
| 96 | const zo = macho_file.getZigObject().?; | ||
| 97 | const symbol = zo.symbols.items[entry]; | ||
| 98 | try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{ | ||
| 99 | index, | ||
| 100 | zig_got.entryAddress(@intCast(index), macho_file), | ||
| 101 | entry, | ||
| 102 | symbol.getAddress(.{}, macho_file), | ||
| 103 | symbol.getName(macho_file), | ||
| 104 | }); | ||
| 105 | } | ||
| 106 | } | ||
| 107 | }; | ||
| 108 | |||
| 109 | pub const GotSection = struct { | 1 | pub const GotSection = struct { |
| 110 | symbols: std.ArrayListUnmanaged(MachO.Ref) = .{}, | 2 | symbols: std.ArrayListUnmanaged(MachO.Ref) = .{}, |
| 111 | 3 |