| author | |
| committer | |
| log | 69da56b36c1bd23214b9c72587cdd424637d2ced |
| tree | 7a89fa64057fae83b41de04f4b16f16505655957 |
| parent | 5b9c5191ab919f4166a9e0c4486bd57bb2533791 |
| parent | a1b8545265b4fb47fe45287655f8885d092aa9df |
| signature |
Self-hosted backends and linkers refactor: x86_64 + aarch64 + macho + coff10 files changed, 365 insertions(+), 397 deletions(-)
src/arch/aarch64/CodeGen.zig+35-50| ... | ... | @@ -139,21 +139,10 @@ const MCValue = union(enum) { |
| 139 | 139 | /// If the type is a pointer, it means the pointer address is at |
| 140 | 140 | /// this memory location. |
| 141 | 141 | memory: u64, |
| 142 | /// The value is in memory referenced indirectly via a GOT entry | |
| 143 | /// index. | |
| 144 | /// | |
| 145 | /// If the type is a pointer, it means the pointer is referenced | |
| 146 | /// indirectly via GOT. When lowered, linker will emit | |
| 147 | /// relocations of type ARM64_RELOC_GOT_LOAD_PAGE21 and | |
| 148 | /// ARM64_RELOC_GOT_LOAD_PAGEOFF12. | |
| 149 | got_load: u32, | |
| 150 | /// The value is in memory referenced directly via symbol index. | |
| 151 | /// | |
| 152 | /// If the type is a pointer, it means the pointer is referenced | |
| 153 | /// directly via symbol index. When lowered, linker will emit a | |
| 154 | /// relocation of type ARM64_RELOC_PAGE21 and | |
| 155 | /// ARM64_RELOC_PAGEOFF12. | |
| 156 | direct_load: u32, | |
| 142 | /// The value is in memory but requires a linker relocation fixup: | |
| 143 | /// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc) | |
| 144 | /// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc) | |
| 145 | linker_load: struct { @"type": enum { got, direct }, sym_index: u32 }, | |
| 157 | 146 | /// The value is one of the stack variables. |
| 158 | 147 | /// |
| 159 | 148 | /// If the type is a pointer, it means the pointer address is in |
| ... | ... | @@ -2959,8 +2948,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 2959 | 2948 | .memory, |
| 2960 | 2949 | .stack_offset, |
| 2961 | 2950 | .stack_argument_offset, |
| 2962 | .got_load, | |
| 2963 | .direct_load, | |
| 2951 | .linker_load, | |
| 2964 | 2952 | => { |
| 2965 | 2953 | const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr); |
| 2966 | 2954 | try self.load(dst_mcv, .{ .register = addr_reg }, ptr_ty); |
| ... | ... | @@ -3197,8 +3185,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3197 | 3185 | .memory, |
| 3198 | 3186 | .stack_offset, |
| 3199 | 3187 | .stack_argument_offset, |
| 3200 | .got_load, | |
| 3201 | .direct_load, | |
| 3188 | .linker_load, | |
| 3202 | 3189 | => { |
| 3203 | 3190 | const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr); |
| 3204 | 3191 | try self.store(.{ .register = addr_reg }, value, ptr_ty, value_ty); |
| ... | ... | @@ -3493,7 +3480,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3493 | 3480 | const func = func_payload.data; |
| 3494 | 3481 | const fn_owner_decl = mod.declPtr(func.owner_decl); |
| 3495 | 3482 | try self.genSetReg(Type.initTag(.u64), .x30, .{ |
| 3496 | .got_load = fn_owner_decl.link.macho.sym_index, | |
| 3483 | .linker_load = .{ | |
| 3484 | .@"type" = .got, | |
| 3485 | .sym_index = fn_owner_decl.link.macho.sym_index, | |
| 3486 | }, | |
| 3497 | 3487 | }); |
| 3498 | 3488 | // blr x30 |
| 3499 | 3489 | _ = try self.addInst(.{ |
| ... | ... | @@ -4427,8 +4417,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 4427 | 4417 | .register = cond_reg, |
| 4428 | 4418 | }); |
| 4429 | 4419 | }, |
| 4430 | .got_load, | |
| 4431 | .direct_load, | |
| 4420 | .linker_load, | |
| 4432 | 4421 | .memory, |
| 4433 | 4422 | .stack_argument_offset, |
| 4434 | 4423 | .stack_offset, |
| ... | ... | @@ -4479,13 +4468,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 4479 | 4468 | }); |
| 4480 | 4469 | }, |
| 4481 | 4470 | .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = addr }), |
| 4482 | .got_load, | |
| 4483 | .direct_load, | |
| 4484 | => |sym_index| { | |
| 4485 | const tag: Mir.Inst.Tag = switch (mcv) { | |
| 4486 | .got_load => .load_memory_ptr_got, | |
| 4487 | .direct_load => .load_memory_ptr_direct, | |
| 4488 | else => unreachable, | |
| 4471 | .linker_load => |load_struct| { | |
| 4472 | const tag: Mir.Inst.Tag = switch (load_struct.@"type") { | |
| 4473 | .got => .load_memory_ptr_got, | |
| 4474 | .direct => .load_memory_ptr_direct, | |
| 4489 | 4475 | }; |
| 4490 | 4476 | const mod = self.bin_file.options.module.?; |
| 4491 | 4477 | _ = try self.addInst(.{ |
| ... | ... | @@ -4494,7 +4480,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 4494 | 4480 | .payload = try self.addExtra(Mir.LoadMemoryPie{ |
| 4495 | 4481 | .register = @enumToInt(src_reg), |
| 4496 | 4482 | .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.sym_index, |
| 4497 | .sym_index = sym_index, | |
| 4483 | .sym_index = load_struct.sym_index, | |
| 4498 | 4484 | }), |
| 4499 | 4485 | }, |
| 4500 | 4486 | }); |
| ... | ... | @@ -4594,13 +4580,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 4594 | 4580 | }); |
| 4595 | 4581 | }, |
| 4596 | 4582 | .register_with_overflow => unreachable, // doesn't fit into a register |
| 4597 | .got_load, | |
| 4598 | .direct_load, | |
| 4599 | => |sym_index| { | |
| 4600 | const tag: Mir.Inst.Tag = switch (mcv) { | |
| 4601 | .got_load => .load_memory_got, | |
| 4602 | .direct_load => .load_memory_direct, | |
| 4603 | else => unreachable, | |
| 4583 | .linker_load => |load_struct| { | |
| 4584 | const tag: Mir.Inst.Tag = switch (load_struct.@"type") { | |
| 4585 | .got => .load_memory_got, | |
| 4586 | .direct => .load_memory_direct, | |
| 4604 | 4587 | }; |
| 4605 | 4588 | const mod = self.bin_file.options.module.?; |
| 4606 | 4589 | _ = try self.addInst(.{ |
| ... | ... | @@ -4609,7 +4592,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 4609 | 4592 | .payload = try self.addExtra(Mir.LoadMemoryPie{ |
| 4610 | 4593 | .register = @enumToInt(reg), |
| 4611 | 4594 | .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.sym_index, |
| 4612 | .sym_index = sym_index, | |
| 4595 | .sym_index = load_struct.sym_index, | |
| 4613 | 4596 | }), |
| 4614 | 4597 | }, |
| 4615 | 4598 | }); |
| ... | ... | @@ -4741,8 +4724,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 4741 | 4724 | .register_with_overflow => { |
| 4742 | 4725 | return self.fail("TODO implement genSetStackArgument {}", .{mcv}); |
| 4743 | 4726 | }, |
| 4744 | .got_load, | |
| 4745 | .direct_load, | |
| 4727 | .linker_load, | |
| 4746 | 4728 | .memory, |
| 4747 | 4729 | .stack_argument_offset, |
| 4748 | 4730 | .stack_offset, |
| ... | ... | @@ -4785,13 +4767,10 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 4785 | 4767 | }); |
| 4786 | 4768 | }, |
| 4787 | 4769 | .memory => |addr| try self.genSetReg(ptr_ty, src_reg, .{ .immediate = @intCast(u32, addr) }), |
| 4788 | .got_load, | |
| 4789 | .direct_load, | |
| 4790 | => |sym_index| { | |
| 4791 | const tag: Mir.Inst.Tag = switch (mcv) { | |
| 4792 | .got_load => .load_memory_ptr_got, | |
| 4793 | .direct_load => .load_memory_ptr_direct, | |
| 4794 | else => unreachable, | |
| 4770 | .linker_load => |load_struct| { | |
| 4771 | const tag: Mir.Inst.Tag = switch (load_struct.@"type") { | |
| 4772 | .got => .load_memory_ptr_got, | |
| 4773 | .direct => .load_memory_ptr_direct, | |
| 4795 | 4774 | }; |
| 4796 | 4775 | const mod = self.bin_file.options.module.?; |
| 4797 | 4776 | _ = try self.addInst(.{ |
| ... | ... | @@ -4800,7 +4779,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 4800 | 4779 | .payload = try self.addExtra(Mir.LoadMemoryPie{ |
| 4801 | 4780 | .register = @enumToInt(src_reg), |
| 4802 | 4781 | .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.sym_index, |
| 4803 | .sym_index = sym_index, | |
| 4782 | .sym_index = load_struct.sym_index, | |
| 4804 | 4783 | }), |
| 4805 | 4784 | }, |
| 4806 | 4785 | }); |
| ... | ... | @@ -5107,7 +5086,10 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne |
| 5107 | 5086 | // Because MachO is PIE-always-on, we defer memory address resolution until |
| 5108 | 5087 | // the linker has enough info to perform relocations. |
| 5109 | 5088 | assert(decl.link.macho.sym_index != 0); |
| 5110 | return MCValue{ .got_load = decl.link.macho.sym_index }; | |
| 5089 | return MCValue{ .linker_load = .{ | |
| 5090 | .@"type" = .got, | |
| 5091 | .sym_index = decl.link.macho.sym_index, | |
| 5092 | } }; | |
| 5111 | 5093 | } else if (self.bin_file.cast(link.File.Coff)) |_| { |
| 5112 | 5094 | return self.fail("TODO codegen COFF const Decl pointer", .{}); |
| 5113 | 5095 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { |
| ... | ... | @@ -5129,7 +5111,10 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue { |
| 5129 | 5111 | const vaddr = elf_file.local_symbols.items[local_sym_index].st_value; |
| 5130 | 5112 | return MCValue{ .memory = vaddr }; |
| 5131 | 5113 | } else if (self.bin_file.cast(link.File.MachO)) |_| { |
| 5132 | return MCValue{ .direct_load = local_sym_index }; | |
| 5114 | return MCValue{ .linker_load = .{ | |
| 5115 | .@"type" = .direct, | |
| 5116 | .sym_index = local_sym_index, | |
| 5117 | } }; | |
| 5133 | 5118 | } else if (self.bin_file.cast(link.File.Coff)) |_| { |
| 5134 | 5119 | return self.fail("TODO lower unnamed const in COFF", .{}); |
| 5135 | 5120 | } else if (self.bin_file.cast(link.File.Plan9)) |_| { |
src/arch/aarch64/Emit.zig+2-4| ... | ... | @@ -681,12 +681,10 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 681 | 681 | }; |
| 682 | 682 | // Add relocation to the decl. |
| 683 | 683 | const atom = macho_file.atom_by_index_table.get(relocation.atom_index).?; |
| 684 | const target = macho_file.getGlobalByIndex(relocation.sym_index); | |
| 684 | 685 | try atom.relocs.append(emit.bin_file.allocator, .{ |
| 685 | 686 | .offset = offset, |
| 686 | .target = .{ | |
| 687 | .sym_index = relocation.sym_index, | |
| 688 | .file = null, | |
| 689 | }, | |
| 687 | .target = target, | |
| 690 | 688 | .addend = 0, |
| 691 | 689 | .subtractor = null, |
| 692 | 690 | .pcrel = true, |
src/arch/x86_64/CodeGen.zig+67-141| ... | ... | @@ -128,15 +128,11 @@ pub const MCValue = union(enum) { |
| 128 | 128 | /// The value is in memory at a hard-coded address. |
| 129 | 129 | /// If the type is a pointer, it means the pointer address is at this memory location. |
| 130 | 130 | memory: u64, |
| 131 | /// The value is in memory referenced indirectly via a GOT entry index. | |
| 132 | /// If the type is a pointer, it means the pointer is referenced indirectly via GOT. | |
| 133 | /// When lowered, linker will emit a relocation of type X86_64_RELOC_GOT. | |
| 134 | got_load: u32, | |
| 135 | imports_load: u32, | |
| 136 | /// The value is in memory referenced directly via symbol index. | |
| 137 | /// If the type is a pointer, it means the pointer is referenced directly via symbol index. | |
| 138 | /// When lowered, linker will emit a relocation of type X86_64_RELOC_SIGNED. | |
| 139 | direct_load: u32, | |
| 131 | /// The value is in memory but requires a linker relocation fixup: | |
| 132 | /// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc) | |
| 133 | /// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc) | |
| 134 | /// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc) | |
| 135 | linker_load: struct { @"type": enum { got, direct, import }, sym_index: u32 }, | |
| 140 | 136 | /// The value is one of the stack variables. |
| 141 | 137 | /// If the type is a pointer, it means the pointer address is in the stack at this offset. |
| 142 | 138 | stack_offset: i32, |
| ... | ... | @@ -150,9 +146,7 @@ pub const MCValue = union(enum) { |
| 150 | 146 | .memory, |
| 151 | 147 | .stack_offset, |
| 152 | 148 | .ptr_stack_offset, |
| 153 | .direct_load, | |
| 154 | .got_load, | |
| 155 | .imports_load, | |
| 149 | .linker_load, | |
| 156 | 150 | => true, |
| 157 | 151 | else => false, |
| 158 | 152 | }; |
| ... | ... | @@ -165,26 +159,6 @@ pub const MCValue = union(enum) { |
| 165 | 159 | }; |
| 166 | 160 | } |
| 167 | 161 | |
| 168 | fn isMutable(mcv: MCValue) bool { | |
| 169 | return switch (mcv) { | |
| 170 | .none => unreachable, | |
| 171 | .unreach => unreachable, | |
| 172 | .dead => unreachable, | |
| 173 | ||
| 174 | .immediate, | |
| 175 | .memory, | |
| 176 | .eflags, | |
| 177 | .ptr_stack_offset, | |
| 178 | .undef, | |
| 179 | .register_overflow, | |
| 180 | => false, | |
| 181 | ||
| 182 | .register, | |
| 183 | .stack_offset, | |
| 184 | => true, | |
| 185 | }; | |
| 186 | } | |
| 187 | ||
| 188 | 162 | fn isRegister(mcv: MCValue) bool { |
| 189 | 163 | return switch (mcv) { |
| 190 | 164 | .register => true, |
| ... | ... | @@ -2307,11 +2281,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2307 | 2281 | .data = .{ .imm = @bitCast(u32, -off) }, |
| 2308 | 2282 | }); |
| 2309 | 2283 | }, |
| 2310 | .memory, | |
| 2311 | .got_load, | |
| 2312 | .direct_load, | |
| 2313 | .imports_load, | |
| 2314 | => { | |
| 2284 | .memory, .linker_load => { | |
| 2315 | 2285 | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, array); |
| 2316 | 2286 | }, |
| 2317 | 2287 | else => return self.fail("TODO implement array_elem_val when array is {}", .{array}), |
| ... | ... | @@ -2652,11 +2622,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 2652 | 2622 | else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}), |
| 2653 | 2623 | } |
| 2654 | 2624 | }, |
| 2655 | .memory, | |
| 2656 | .got_load, | |
| 2657 | .direct_load, | |
| 2658 | .imports_load, | |
| 2659 | => { | |
| 2625 | .memory, .linker_load => { | |
| 2660 | 2626 | const reg = try self.copyToTmpRegister(ptr_ty, ptr); |
| 2661 | 2627 | try self.load(dst_mcv, .{ .register = reg }, ptr_ty); |
| 2662 | 2628 | }, |
| ... | ... | @@ -2691,10 +2657,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 2691 | 2657 | |
| 2692 | 2658 | fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue) InnerError!void { |
| 2693 | 2659 | switch (ptr) { |
| 2694 | .got_load, | |
| 2695 | .direct_load, | |
| 2696 | .imports_load, | |
| 2697 | => |sym_index| { | |
| 2660 | .linker_load => |load_struct| { | |
| 2698 | 2661 | const abi_size = @intCast(u32, ptr_ty.abiSize(self.target.*)); |
| 2699 | 2662 | const mod = self.bin_file.options.module.?; |
| 2700 | 2663 | const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); |
| ... | ... | @@ -2702,11 +2665,10 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue |
| 2702 | 2665 | fn_owner_decl.link.macho.sym_index |
| 2703 | 2666 | else |
| 2704 | 2667 | fn_owner_decl.link.coff.sym_index; |
| 2705 | const flags: u2 = switch (ptr) { | |
| 2706 | .got_load => 0b00, | |
| 2707 | .direct_load => 0b01, | |
| 2708 | .imports_load => 0b10, | |
| 2709 | else => unreachable, | |
| 2668 | const flags: u2 = switch (load_struct.@"type") { | |
| 2669 | .got => 0b00, | |
| 2670 | .direct => 0b01, | |
| 2671 | .import => 0b10, | |
| 2710 | 2672 | }; |
| 2711 | 2673 | _ = try self.addInst(.{ |
| 2712 | 2674 | .tag = .lea_pic, |
| ... | ... | @@ -2717,7 +2679,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue |
| 2717 | 2679 | .data = .{ |
| 2718 | 2680 | .relocation = .{ |
| 2719 | 2681 | .atom_index = atom_index, |
| 2720 | .sym_index = sym_index, | |
| 2682 | .sym_index = load_struct.sym_index, | |
| 2721 | 2683 | }, |
| 2722 | 2684 | }, |
| 2723 | 2685 | }); |
| ... | ... | @@ -2801,9 +2763,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2801 | 2763 | .register => |src_reg| { |
| 2802 | 2764 | try self.genInlineMemcpyRegisterRegister(value_ty, reg, src_reg, 0); |
| 2803 | 2765 | }, |
| 2804 | .got_load, | |
| 2805 | .direct_load, | |
| 2806 | .imports_load, | |
| 2766 | .linker_load, | |
| 2807 | 2767 | .memory, |
| 2808 | 2768 | .stack_offset, |
| 2809 | 2769 | => { |
| ... | ... | @@ -2822,11 +2782,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2822 | 2782 | }, |
| 2823 | 2783 | } |
| 2824 | 2784 | }, |
| 2825 | .got_load, | |
| 2826 | .direct_load, | |
| 2827 | .imports_load, | |
| 2828 | .memory, | |
| 2829 | => { | |
| 2785 | .linker_load, .memory => { | |
| 2830 | 2786 | const value_lock: ?RegisterLock = switch (value) { |
| 2831 | 2787 | .register => |reg| self.register_manager.lockReg(reg), |
| 2832 | 2788 | else => null, |
| ... | ... | @@ -2894,11 +2850,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2894 | 2850 | .register => { |
| 2895 | 2851 | return self.store(new_ptr, value, ptr_ty, value_ty); |
| 2896 | 2852 | }, |
| 2897 | .got_load, | |
| 2898 | .direct_load, | |
| 2899 | .imports_load, | |
| 2900 | .memory, | |
| 2901 | => { | |
| 2853 | .linker_load, .memory => { | |
| 2902 | 2854 | if (abi_size <= 8) { |
| 2903 | 2855 | const tmp_reg = try self.register_manager.allocReg(null, gp); |
| 2904 | 2856 | const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| ... | ... | @@ -3606,9 +3558,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3606 | 3558 | }); |
| 3607 | 3559 | }, |
| 3608 | 3560 | .memory, |
| 3609 | .got_load, | |
| 3610 | .direct_load, | |
| 3611 | .imports_load, | |
| 3561 | .linker_load, | |
| 3612 | 3562 | .eflags, |
| 3613 | 3563 | => { |
| 3614 | 3564 | assert(abi_size <= 8); |
| ... | ... | @@ -3694,10 +3644,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3694 | 3644 | => { |
| 3695 | 3645 | return self.fail("TODO implement x86 ADD/SUB/CMP source memory", .{}); |
| 3696 | 3646 | }, |
| 3697 | .got_load, | |
| 3698 | .direct_load, | |
| 3699 | .imports_load, | |
| 3700 | => { | |
| 3647 | .linker_load => { | |
| 3701 | 3648 | return self.fail("TODO implement x86 ADD/SUB/CMP source symbol at index in linker", .{}); |
| 3702 | 3649 | }, |
| 3703 | 3650 | .eflags => { |
| ... | ... | @@ -3708,10 +3655,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3708 | 3655 | .memory => { |
| 3709 | 3656 | return self.fail("TODO implement x86 ADD/SUB/CMP destination memory", .{}); |
| 3710 | 3657 | }, |
| 3711 | .got_load, | |
| 3712 | .direct_load, | |
| 3713 | .imports_load, | |
| 3714 | => { | |
| 3658 | .linker_load => { | |
| 3715 | 3659 | return self.fail("TODO implement x86 ADD/SUB/CMP destination symbol at index", .{}); |
| 3716 | 3660 | }, |
| 3717 | 3661 | } |
| ... | ... | @@ -3779,10 +3723,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 3779 | 3723 | .memory => { |
| 3780 | 3724 | return self.fail("TODO implement x86 multiply source memory", .{}); |
| 3781 | 3725 | }, |
| 3782 | .got_load, | |
| 3783 | .direct_load, | |
| 3784 | .imports_load, | |
| 3785 | => { | |
| 3726 | .linker_load => { | |
| 3786 | 3727 | return self.fail("TODO implement x86 multiply source symbol at index in linker", .{}); |
| 3787 | 3728 | }, |
| 3788 | 3729 | .eflags => { |
| ... | ... | @@ -3826,10 +3767,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 3826 | 3767 | .memory, .stack_offset => { |
| 3827 | 3768 | return self.fail("TODO implement x86 multiply source memory", .{}); |
| 3828 | 3769 | }, |
| 3829 | .got_load, | |
| 3830 | .direct_load, | |
| 3831 | .imports_load, | |
| 3832 | => { | |
| 3770 | .linker_load => { | |
| 3833 | 3771 | return self.fail("TODO implement x86 multiply source symbol at index in linker", .{}); |
| 3834 | 3772 | }, |
| 3835 | 3773 | .eflags => { |
| ... | ... | @@ -3840,10 +3778,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 3840 | 3778 | .memory => { |
| 3841 | 3779 | return self.fail("TODO implement x86 multiply destination memory", .{}); |
| 3842 | 3780 | }, |
| 3843 | .got_load, | |
| 3844 | .direct_load, | |
| 3845 | .imports_load, | |
| 3846 | => { | |
| 3781 | .linker_load => { | |
| 3847 | 3782 | return self.fail("TODO implement x86 multiply destination symbol at index in linker", .{}); |
| 3848 | 3783 | }, |
| 3849 | 3784 | } |
| ... | ... | @@ -4006,9 +3941,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 4006 | 3941 | .unreach => unreachable, |
| 4007 | 3942 | .dead => unreachable, |
| 4008 | 3943 | .memory => unreachable, |
| 4009 | .got_load => unreachable, | |
| 4010 | .direct_load => unreachable, | |
| 4011 | .imports_load => unreachable, | |
| 3944 | .linker_load => unreachable, | |
| 4012 | 3945 | .eflags => unreachable, |
| 4013 | 3946 | .register_overflow => unreachable, |
| 4014 | 3947 | } |
| ... | ... | @@ -4066,7 +3999,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 4066 | 3999 | const func = func_payload.data; |
| 4067 | 4000 | const fn_owner_decl = mod.declPtr(func.owner_decl); |
| 4068 | 4001 | try self.genSetReg(Type.initTag(.usize), .rax, .{ |
| 4069 | .got_load = fn_owner_decl.link.coff.sym_index, | |
| 4002 | .linker_load = .{ | |
| 4003 | .@"type" = .got, | |
| 4004 | .sym_index = fn_owner_decl.link.coff.sym_index, | |
| 4005 | }, | |
| 4070 | 4006 | }); |
| 4071 | 4007 | _ = try self.addInst(.{ |
| 4072 | 4008 | .tag = .call, |
| ... | ... | @@ -4087,7 +4023,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 4087 | 4023 | } |
| 4088 | 4024 | const sym_index = try coff_file.getGlobalSymbol(mem.sliceTo(decl_name, 0)); |
| 4089 | 4025 | try self.genSetReg(Type.initTag(.usize), .rax, .{ |
| 4090 | .imports_load = sym_index, | |
| 4026 | .linker_load = .{ | |
| 4027 | .@"type" = .import, | |
| 4028 | .sym_index = sym_index, | |
| 4029 | }, | |
| 4091 | 4030 | }); |
| 4092 | 4031 | _ = try self.addInst(.{ |
| 4093 | 4032 | .tag = .call, |
| ... | ... | @@ -4119,7 +4058,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 4119 | 4058 | const func = func_payload.data; |
| 4120 | 4059 | const fn_owner_decl = mod.declPtr(func.owner_decl); |
| 4121 | 4060 | const sym_index = fn_owner_decl.link.macho.sym_index; |
| 4122 | try self.genSetReg(Type.initTag(.usize), .rax, .{ .got_load = sym_index }); | |
| 4061 | try self.genSetReg(Type.initTag(.usize), .rax, .{ | |
| 4062 | .linker_load = .{ | |
| 4063 | .@"type" = .got, | |
| 4064 | .sym_index = sym_index, | |
| 4065 | }, | |
| 4066 | }); | |
| 4123 | 4067 | // callq *%rax |
| 4124 | 4068 | _ = try self.addInst(.{ |
| 4125 | 4069 | .tag = .call, |
| ... | ... | @@ -4505,11 +4449,7 @@ fn genVarDbgInfo( |
| 4505 | 4449 | leb128.writeILEB128(dbg_info.writer(), -off) catch unreachable; |
| 4506 | 4450 | dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); |
| 4507 | 4451 | }, |
| 4508 | .memory, | |
| 4509 | .got_load, | |
| 4510 | .direct_load, | |
| 4511 | .imports_load, | |
| 4512 | => { | |
| 4452 | .memory, .linker_load => { | |
| 4513 | 4453 | const ptr_width = @intCast(u8, @divExact(self.target.cpu.arch.ptrBitWidth(), 8)); |
| 4514 | 4454 | const is_ptr = switch (tag) { |
| 4515 | 4455 | .dbg_var_ptr => true, |
| ... | ... | @@ -4540,10 +4480,11 @@ fn genVarDbgInfo( |
| 4540 | 4480 | try dbg_info.append(DW.OP.deref); |
| 4541 | 4481 | } |
| 4542 | 4482 | switch (mcv) { |
| 4543 | .got_load, | |
| 4544 | .direct_load, | |
| 4545 | .imports_load, | |
| 4546 | => |index| try dw.addExprlocReloc(index, offset, is_ptr), | |
| 4483 | .linker_load => |load_struct| try dw.addExprlocReloc( | |
| 4484 | load_struct.sym_index, | |
| 4485 | offset, | |
| 4486 | is_ptr, | |
| 4487 | ), | |
| 4547 | 4488 | else => {}, |
| 4548 | 4489 | } |
| 4549 | 4490 | }, |
| ... | ... | @@ -5587,11 +5528,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 5587 | 5528 | else => return self.fail("TODO implement inputs on stack for {} with abi size > 8", .{mcv}), |
| 5588 | 5529 | } |
| 5589 | 5530 | }, |
| 5590 | .memory, | |
| 5591 | .direct_load, | |
| 5592 | .got_load, | |
| 5593 | .imports_load, | |
| 5594 | => { | |
| 5531 | .memory, .linker_load => { | |
| 5595 | 5532 | if (abi_size <= 8) { |
| 5596 | 5533 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 5597 | 5534 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); |
| ... | ... | @@ -5835,11 +5772,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5835 | 5772 | }, |
| 5836 | 5773 | } |
| 5837 | 5774 | }, |
| 5838 | .memory, | |
| 5839 | .got_load, | |
| 5840 | .direct_load, | |
| 5841 | .imports_load, | |
| 5842 | => { | |
| 5775 | .memory, .linker_load => { | |
| 5843 | 5776 | if (abi_size <= 8) { |
| 5844 | 5777 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 5845 | 5778 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts); |
| ... | ... | @@ -5959,11 +5892,7 @@ fn genInlineMemcpy( |
| 5959 | 5892 | const tmp_reg = regs[4].to8(); |
| 5960 | 5893 | |
| 5961 | 5894 | switch (dst_ptr) { |
| 5962 | .memory, | |
| 5963 | .got_load, | |
| 5964 | .direct_load, | |
| 5965 | .imports_load, | |
| 5966 | => { | |
| 5895 | .memory, .linker_load => { | |
| 5967 | 5896 | try self.loadMemPtrIntoRegister(dst_addr_reg, Type.usize, dst_ptr); |
| 5968 | 5897 | }, |
| 5969 | 5898 | .ptr_stack_offset, .stack_offset => |off| { |
| ... | ... | @@ -5992,11 +5921,7 @@ fn genInlineMemcpy( |
| 5992 | 5921 | } |
| 5993 | 5922 | |
| 5994 | 5923 | switch (src_ptr) { |
| 5995 | .memory, | |
| 5996 | .got_load, | |
| 5997 | .direct_load, | |
| 5998 | .imports_load, | |
| 5999 | => { | |
| 5924 | .memory, .linker_load => { | |
| 6000 | 5925 | try self.loadMemPtrIntoRegister(src_addr_reg, Type.usize, src_ptr); |
| 6001 | 5926 | }, |
| 6002 | 5927 | .ptr_stack_offset, .stack_offset => |off| { |
| ... | ... | @@ -6120,11 +6045,7 @@ fn genInlineMemset( |
| 6120 | 6045 | const index_reg = regs[1].to64(); |
| 6121 | 6046 | |
| 6122 | 6047 | switch (dst_ptr) { |
| 6123 | .memory, | |
| 6124 | .got_load, | |
| 6125 | .direct_load, | |
| 6126 | .imports_load, | |
| 6127 | => { | |
| 6048 | .memory, .linker_load => { | |
| 6128 | 6049 | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, dst_ptr); |
| 6129 | 6050 | }, |
| 6130 | 6051 | .ptr_stack_offset, .stack_offset => |off| { |
| ... | ... | @@ -6356,10 +6277,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6356 | 6277 | .data = undefined, |
| 6357 | 6278 | }); |
| 6358 | 6279 | }, |
| 6359 | .direct_load, | |
| 6360 | .got_load, | |
| 6361 | .imports_load, | |
| 6362 | => { | |
| 6280 | .linker_load => { | |
| 6363 | 6281 | switch (ty.zigTypeTag()) { |
| 6364 | 6282 | .Float => { |
| 6365 | 6283 | const base_reg = try self.register_manager.allocReg(null, gp); |
| ... | ... | @@ -6753,11 +6671,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { |
| 6753 | 6671 | // TODO Is this the only condition for pointer dereference for memcpy? |
| 6754 | 6672 | const src: MCValue = blk: { |
| 6755 | 6673 | switch (src_ptr) { |
| 6756 | .got_load, | |
| 6757 | .direct_load, | |
| 6758 | .imports_load, | |
| 6759 | .memory, | |
| 6760 | => { | |
| 6674 | .linker_load, .memory => { | |
| 6761 | 6675 | const reg = try self.register_manager.allocReg(null, gp); |
| 6762 | 6676 | try self.loadMemPtrIntoRegister(reg, src_ty, src_ptr); |
| 6763 | 6677 | _ = try self.addInst(.{ |
| ... | ... | @@ -6997,10 +6911,16 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne |
| 6997 | 6911 | return MCValue{ .memory = got_addr }; |
| 6998 | 6912 | } else if (self.bin_file.cast(link.File.MachO)) |_| { |
| 6999 | 6913 | assert(decl.link.macho.sym_index != 0); |
| 7000 | return MCValue{ .got_load = decl.link.macho.sym_index }; | |
| 6914 | return MCValue{ .linker_load = .{ | |
| 6915 | .@"type" = .got, | |
| 6916 | .sym_index = decl.link.macho.sym_index, | |
| 6917 | } }; | |
| 7001 | 6918 | } else if (self.bin_file.cast(link.File.Coff)) |_| { |
| 7002 | 6919 | assert(decl.link.coff.sym_index != 0); |
| 7003 | return MCValue{ .got_load = decl.link.coff.sym_index }; | |
| 6920 | return MCValue{ .linker_load = .{ | |
| 6921 | .@"type" = .got, | |
| 6922 | .sym_index = decl.link.coff.sym_index, | |
| 6923 | } }; | |
| 7004 | 6924 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { |
| 7005 | 6925 | try p9.seeDecl(decl_index); |
| 7006 | 6926 | const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes; |
| ... | ... | @@ -7019,9 +6939,15 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue { |
| 7019 | 6939 | const vaddr = elf_file.local_symbols.items[local_sym_index].st_value; |
| 7020 | 6940 | return MCValue{ .memory = vaddr }; |
| 7021 | 6941 | } else if (self.bin_file.cast(link.File.MachO)) |_| { |
| 7022 | return MCValue{ .direct_load = local_sym_index }; | |
| 6942 | return MCValue{ .linker_load = .{ | |
| 6943 | .@"type" = .direct, | |
| 6944 | .sym_index = local_sym_index, | |
| 6945 | } }; | |
| 7023 | 6946 | } else if (self.bin_file.cast(link.File.Coff)) |_| { |
| 7024 | return MCValue{ .direct_load = local_sym_index }; | |
| 6947 | return MCValue{ .linker_load = .{ | |
| 6948 | .@"type" = .direct, | |
| 6949 | .sym_index = local_sym_index, | |
| 6950 | } }; | |
| 7025 | 6951 | } else if (self.bin_file.cast(link.File.Plan9)) |_| { |
| 7026 | 6952 | return self.fail("TODO lower unnamed const in Plan9", .{}); |
| 7027 | 6953 | } else { |
src/arch/x86_64/Emit.zig+11-8| ... | ... | @@ -1021,10 +1021,14 @@ fn mirLeaPic(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { |
| 1021 | 1021 | .@"type" = switch (ops.flags) { |
| 1022 | 1022 | 0b00 => .got, |
| 1023 | 1023 | 0b01 => .direct, |
| 1024 | 0b10 => .imports, | |
| 1024 | 0b10 => .import, | |
| 1025 | else => unreachable, | |
| 1026 | }, | |
| 1027 | .target = switch (ops.flags) { | |
| 1028 | 0b00, 0b01 => .{ .sym_index = relocation.sym_index, .file = null }, | |
| 1029 | 0b10 => coff_file.getGlobalByIndex(relocation.sym_index), | |
| 1025 | 1030 | else => unreachable, |
| 1026 | 1031 | }, |
| 1027 | .target = .{ .sym_index = relocation.sym_index, .file = null }, | |
| 1028 | 1032 | .offset = @intCast(u32, end_offset - 4), |
| 1029 | 1033 | .addend = 0, |
| 1030 | 1034 | .pcrel = true, |
| ... | ... | @@ -1142,12 +1146,10 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { |
| 1142 | 1146 | if (emit.bin_file.cast(link.File.MachO)) |macho_file| { |
| 1143 | 1147 | // Add relocation to the decl. |
| 1144 | 1148 | const atom = macho_file.atom_by_index_table.get(relocation.atom_index).?; |
| 1149 | const target = macho_file.getGlobalByIndex(relocation.sym_index); | |
| 1145 | 1150 | try atom.relocs.append(emit.bin_file.allocator, .{ |
| 1146 | 1151 | .offset = offset, |
| 1147 | .target = .{ | |
| 1148 | .sym_index = relocation.sym_index, | |
| 1149 | .file = null, | |
| 1150 | }, | |
| 1152 | .target = target, | |
| 1151 | 1153 | .addend = 0, |
| 1152 | 1154 | .subtractor = null, |
| 1153 | 1155 | .pcrel = true, |
| ... | ... | @@ -1157,16 +1159,17 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { |
| 1157 | 1159 | } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| { |
| 1158 | 1160 | // Add relocation to the decl. |
| 1159 | 1161 | const atom = coff_file.atom_by_index_table.get(relocation.atom_index).?; |
| 1162 | const target = coff_file.getGlobalByIndex(relocation.sym_index); | |
| 1160 | 1163 | try atom.addRelocation(coff_file, .{ |
| 1161 | 1164 | .@"type" = .direct, |
| 1162 | .target = .{ .sym_index = relocation.sym_index, .file = null }, | |
| 1165 | .target = target, | |
| 1163 | 1166 | .offset = offset, |
| 1164 | 1167 | .addend = 0, |
| 1165 | 1168 | .pcrel = true, |
| 1166 | 1169 | .length = 2, |
| 1167 | 1170 | }); |
| 1168 | 1171 | } else { |
| 1169 | return emit.fail("TODO implement call_extern for linking backends different than MachO", .{}); | |
| 1172 | return emit.fail("TODO implement call_extern for linking backends different than MachO and COFF", .{}); | |
| 1170 | 1173 | } |
| 1171 | 1174 | } |
| 1172 | 1175 |
src/link/Coff.zig+61-18| ... | ... | @@ -127,7 +127,7 @@ pub const Reloc = struct { |
| 127 | 127 | @"type": enum { |
| 128 | 128 | got, |
| 129 | 129 | direct, |
| 130 | imports, | |
| 130 | import, | |
| 131 | 131 | }, |
| 132 | 132 | target: SymbolWithLoc, |
| 133 | 133 | offset: u32, |
| ... | ... | @@ -141,7 +141,7 @@ pub const Reloc = struct { |
| 141 | 141 | switch (self.@"type") { |
| 142 | 142 | .got => return coff_file.getGotAtomForSymbol(self.target), |
| 143 | 143 | .direct => return coff_file.getAtomForSymbol(self.target), |
| 144 | .imports => return coff_file.getImportAtomForSymbol(self.target), | |
| 144 | .import => return coff_file.getImportAtomForSymbol(self.target), | |
| 145 | 145 | } |
| 146 | 146 | } |
| 147 | 147 | }; |
| ... | ... | @@ -1423,23 +1423,22 @@ fn resolveGlobalSymbol(self: *Coff, current: SymbolWithLoc) !void { |
| 1423 | 1423 | const sym = self.getSymbol(current); |
| 1424 | 1424 | const sym_name = self.getSymbolName(current); |
| 1425 | 1425 | |
| 1426 | const global_index = self.resolver.get(sym_name) orelse { | |
| 1427 | const name = try gpa.dupe(u8, sym_name); | |
| 1428 | const global_index = try self.allocateGlobal(); | |
| 1429 | self.globals.items[global_index] = current; | |
| 1430 | try self.resolver.putNoClobber(gpa, name, global_index); | |
| 1426 | const gop = try self.getOrPutGlobalPtr(sym_name); | |
| 1427 | if (!gop.found_existing) { | |
| 1428 | gop.value_ptr.* = current; | |
| 1431 | 1429 | if (sym.section_number == .UNDEFINED) { |
| 1432 | try self.unresolved.putNoClobber(gpa, global_index, false); | |
| 1430 | try self.unresolved.putNoClobber(gpa, self.getGlobalIndex(sym_name).?, false); | |
| 1433 | 1431 | } |
| 1434 | 1432 | return; |
| 1435 | }; | |
| 1433 | } | |
| 1436 | 1434 | |
| 1437 | 1435 | log.debug("TODO finish resolveGlobalSymbols implementation", .{}); |
| 1438 | 1436 | |
| 1439 | 1437 | if (sym.section_number == .UNDEFINED) return; |
| 1440 | 1438 | |
| 1441 | _ = self.unresolved.swapRemove(global_index); | |
| 1442 | self.globals.items[global_index] = current; | |
| 1439 | _ = self.unresolved.swapRemove(self.getGlobalIndex(sym_name).?); | |
| 1440 | ||
| 1441 | gop.value_ptr.* = current; | |
| 1443 | 1442 | } |
| 1444 | 1443 | |
| 1445 | 1444 | pub fn flush(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !void { |
| ... | ... | @@ -1544,25 +1543,26 @@ pub fn getDeclVAddr( |
| 1544 | 1543 | } |
| 1545 | 1544 | |
| 1546 | 1545 | pub fn getGlobalSymbol(self: *Coff, name: []const u8) !u32 { |
| 1547 | if (self.resolver.get(name)) |global_index| { | |
| 1548 | return self.globals.items[global_index].sym_index; | |
| 1546 | const gop = try self.getOrPutGlobalPtr(name); | |
| 1547 | const global_index = self.getGlobalIndex(name).?; | |
| 1548 | ||
| 1549 | if (gop.found_existing) { | |
| 1550 | return global_index; | |
| 1549 | 1551 | } |
| 1550 | 1552 | |
| 1551 | const gpa = self.base.allocator; | |
| 1552 | 1553 | const sym_index = try self.allocateSymbol(); |
| 1553 | const global_index = try self.allocateGlobal(); | |
| 1554 | 1554 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null }; |
| 1555 | self.globals.items[global_index] = sym_loc; | |
| 1555 | gop.value_ptr.* = sym_loc; | |
| 1556 | 1556 | |
| 1557 | const gpa = self.base.allocator; | |
| 1557 | 1558 | const sym_name = try gpa.dupe(u8, name); |
| 1558 | 1559 | const sym = self.getSymbolPtr(sym_loc); |
| 1559 | 1560 | try self.setSymbolName(sym, sym_name); |
| 1560 | 1561 | sym.storage_class = .EXTERNAL; |
| 1561 | 1562 | |
| 1562 | try self.resolver.putNoClobber(gpa, sym_name, global_index); | |
| 1563 | 1563 | try self.unresolved.putNoClobber(gpa, global_index, true); |
| 1564 | 1564 | |
| 1565 | return sym_index; | |
| 1565 | return global_index; | |
| 1566 | 1566 | } |
| 1567 | 1567 | |
| 1568 | 1568 | pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !void { |
| ... | ... | @@ -2061,6 +2061,49 @@ pub fn getSymbolName(self: *const Coff, sym_loc: SymbolWithLoc) []const u8 { |
| 2061 | 2061 | return self.strtab.get(offset).?; |
| 2062 | 2062 | } |
| 2063 | 2063 | |
| 2064 | /// Returns pointer to the global entry for `name` if one exists. | |
| 2065 | pub fn getGlobalPtr(self: *Coff, name: []const u8) ?*SymbolWithLoc { | |
| 2066 | const global_index = self.resolver.get(name) orelse return null; | |
| 2067 | return &self.globals.items[global_index]; | |
| 2068 | } | |
| 2069 | ||
| 2070 | /// Returns the global entry for `name` if one exists. | |
| 2071 | pub fn getGlobal(self: *const Coff, name: []const u8) ?SymbolWithLoc { | |
| 2072 | const global_index = self.resolver.get(name) orelse return null; | |
| 2073 | return self.globals.items[global_index]; | |
| 2074 | } | |
| 2075 | ||
| 2076 | /// Returns the index of the global entry for `name` if one exists. | |
| 2077 | pub fn getGlobalIndex(self: *const Coff, name: []const u8) ?u32 { | |
| 2078 | return self.resolver.get(name); | |
| 2079 | } | |
| 2080 | ||
| 2081 | /// Returns global entry at `index`. | |
| 2082 | pub fn getGlobalByIndex(self: *const Coff, index: u32) SymbolWithLoc { | |
| 2083 | assert(index < self.globals.items.len); | |
| 2084 | return self.globals.items[index]; | |
| 2085 | } | |
| 2086 | ||
| 2087 | const GetOrPutGlobalPtrResult = struct { | |
| 2088 | found_existing: bool, | |
| 2089 | value_ptr: *SymbolWithLoc, | |
| 2090 | }; | |
| 2091 | ||
| 2092 | /// Return pointer to the global entry for `name` if one exists. | |
| 2093 | /// Puts a new global entry for `name` if one doesn't exist, and | |
| 2094 | /// returns a pointer to it. | |
| 2095 | pub fn getOrPutGlobalPtr(self: *Coff, name: []const u8) !GetOrPutGlobalPtrResult { | |
| 2096 | if (self.getGlobalPtr(name)) |ptr| { | |
| 2097 | return GetOrPutGlobalPtrResult{ .found_existing = true, .value_ptr = ptr }; | |
| 2098 | } | |
| 2099 | const gpa = self.base.allocator; | |
| 2100 | const global_index = try self.allocateGlobal(); | |
| 2101 | const global_name = try gpa.dupe(u8, name); | |
| 2102 | _ = try self.resolver.put(gpa, global_name, global_index); | |
| 2103 | const ptr = &self.globals.items[global_index]; | |
| 2104 | return GetOrPutGlobalPtrResult{ .found_existing = false, .value_ptr = ptr }; | |
| 2105 | } | |
| 2106 | ||
| 2064 | 2107 | /// Returns atom if there is an atom referenced by the symbol described by `sym_loc` descriptor. |
| 2065 | 2108 | /// Returns null on failure. |
| 2066 | 2109 | pub fn getAtomForSymbol(self: *Coff, sym_loc: SymbolWithLoc) ?*Atom { |
src/link/Coff/Atom.zig-10| ... | ... | @@ -111,13 +111,3 @@ pub fn addBaseRelocation(self: *Atom, coff_file: *Coff, offset: u32) !void { |
| 111 | 111 | } |
| 112 | 112 | try gop.value_ptr.append(gpa, offset); |
| 113 | 113 | } |
| 114 | ||
| 115 | pub fn addBinding(self: *Atom, coff_file: *Coff, target: SymbolWithLoc) !void { | |
| 116 | const gpa = coff_file.base.allocator; | |
| 117 | log.debug(" (adding binding to target %{d} in %{d})", .{ target.sym_index, self.sym_index }); | |
| 118 | const gop = try coff_file.bindings.getOrPut(gpa, self); | |
| 119 | if (!gop.found_existing) { | |
| 120 | gop.value_ptr.* = .{}; | |
| 121 | } | |
| 122 | try gop.value_ptr.append(gpa, target); | |
| 123 | } |
src/link/MachO.zig+182-159| ... | ... | @@ -131,17 +131,12 @@ la_symbol_ptr_section_index: ?u8 = null, |
| 131 | 131 | data_section_index: ?u8 = null, |
| 132 | 132 | |
| 133 | 133 | locals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 134 | globals: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{}, | |
| 135 | // FIXME Jakub | |
| 136 | // TODO storing index into globals might be dangerous if we delete a global | |
| 137 | // while not having everything resolved. Actually, perhaps `unresolved` | |
| 138 | // should not be stored at the global scope? Is this possible? | |
| 139 | // Otherwise, audit if this can be a problem. | |
| 140 | // An alternative, which I still need to investigate for perf reasons is to | |
| 141 | // store all global names in an adapted with context strtab. | |
| 134 | globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{}, | |
| 135 | resolver: std.StringHashMapUnmanaged(u32) = .{}, | |
| 142 | 136 | unresolved: std.AutoArrayHashMapUnmanaged(u32, bool) = .{}, |
| 143 | 137 | |
| 144 | 138 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 139 | globals_free_list: std.ArrayListUnmanaged(u32) = .{}, | |
| 145 | 140 | |
| 146 | 141 | dyld_stub_binder_index: ?u32 = null, |
| 147 | 142 | dyld_private_atom: ?*Atom = null, |
| ... | ... | @@ -1917,7 +1912,7 @@ fn allocateSpecialSymbols(self: *MachO) !void { |
| 1917 | 1912 | "___dso_handle", |
| 1918 | 1913 | "__mh_execute_header", |
| 1919 | 1914 | }) |name| { |
| 1920 | const global = self.globals.get(name) orelse continue; | |
| 1915 | const global = self.getGlobal(name) orelse continue; | |
| 1921 | 1916 | if (global.file != null) continue; |
| 1922 | 1917 | const sym = self.getSymbolPtr(global); |
| 1923 | 1918 | const seg = self.segments.items[self.text_segment_cmd_index.?]; |
| ... | ... | @@ -2048,16 +2043,11 @@ fn writeAtomsIncremental(self: *MachO) !void { |
| 2048 | 2043 | |
| 2049 | 2044 | pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom { |
| 2050 | 2045 | const gpa = self.base.allocator; |
| 2051 | const sym_index = @intCast(u32, self.locals.items.len); | |
| 2052 | try self.locals.append(gpa, .{ | |
| 2053 | .n_strx = 0, | |
| 2054 | .n_type = macho.N_SECT, | |
| 2055 | .n_sect = 0, | |
| 2056 | .n_desc = 0, | |
| 2057 | .n_value = 0, | |
| 2058 | }); | |
| 2059 | ||
| 2046 | const sym_index = try self.allocateSymbol(); | |
| 2060 | 2047 | const atom = try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3); |
| 2048 | const sym = atom.getSymbolPtr(self); | |
| 2049 | sym.n_type = macho.N_SECT; | |
| 2050 | ||
| 2061 | 2051 | try atom.relocs.append(gpa, .{ |
| 2062 | 2052 | .offset = 0, |
| 2063 | 2053 | .target = target, |
| ... | ... | @@ -2074,7 +2064,7 @@ pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom { |
| 2074 | 2064 | |
| 2075 | 2065 | const target_sym = self.getSymbol(target); |
| 2076 | 2066 | if (target_sym.undf()) { |
| 2077 | const global = self.globals.get(self.getSymbolName(target)).?; | |
| 2067 | const global = self.getGlobal(self.getSymbolName(target)).?; | |
| 2078 | 2068 | try atom.bindings.append(gpa, .{ |
| 2079 | 2069 | .target = global, |
| 2080 | 2070 | .offset = 0, |
| ... | ... | @@ -2093,20 +2083,15 @@ pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom { |
| 2093 | 2083 | |
| 2094 | 2084 | pub fn createTlvPtrAtom(self: *MachO, target: SymbolWithLoc) !*Atom { |
| 2095 | 2085 | const gpa = self.base.allocator; |
| 2096 | const sym_index = @intCast(u32, self.locals.items.len); | |
| 2097 | try self.locals.append(gpa, .{ | |
| 2098 | .n_strx = 0, | |
| 2099 | .n_type = macho.N_SECT, | |
| 2100 | .n_sect = 0, | |
| 2101 | .n_desc = 0, | |
| 2102 | .n_value = 0, | |
| 2103 | }); | |
| 2104 | ||
| 2086 | const sym_index = try self.allocateSymbol(); | |
| 2105 | 2087 | const atom = try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3); |
| 2088 | const sym = atom.getSymbolPtr(self); | |
| 2089 | sym.n_type = macho.N_SECT; | |
| 2090 | ||
| 2106 | 2091 | const target_sym = self.getSymbol(target); |
| 2107 | 2092 | assert(target_sym.undf()); |
| 2108 | 2093 | |
| 2109 | const global = self.globals.get(self.getSymbolName(target)).?; | |
| 2094 | const global = self.getGlobal(self.getSymbolName(target)).?; | |
| 2110 | 2095 | try atom.bindings.append(gpa, .{ |
| 2111 | 2096 | .target = global, |
| 2112 | 2097 | .offset = 0, |
| ... | ... | @@ -2130,15 +2115,10 @@ fn createDyldPrivateAtom(self: *MachO) !void { |
| 2130 | 2115 | if (self.dyld_private_atom != null) return; |
| 2131 | 2116 | |
| 2132 | 2117 | const gpa = self.base.allocator; |
| 2133 | const sym_index = @intCast(u32, self.locals.items.len); | |
| 2134 | try self.locals.append(gpa, .{ | |
| 2135 | .n_strx = 0, | |
| 2136 | .n_type = macho.N_SECT, | |
| 2137 | .n_sect = 0, | |
| 2138 | .n_desc = 0, | |
| 2139 | .n_value = 0, | |
| 2140 | }); | |
| 2118 | const sym_index = try self.allocateSymbol(); | |
| 2141 | 2119 | const atom = try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3); |
| 2120 | const sym = atom.getSymbolPtr(self); | |
| 2121 | sym.n_type = macho.N_SECT; | |
| 2142 | 2122 | self.dyld_private_atom = atom; |
| 2143 | 2123 | |
| 2144 | 2124 | try self.allocateAtomCommon(atom, self.data_section_index.?); |
| ... | ... | @@ -2163,15 +2143,11 @@ fn createStubHelperPreambleAtom(self: *MachO) !void { |
| 2163 | 2143 | .aarch64 => 2, |
| 2164 | 2144 | else => unreachable, |
| 2165 | 2145 | }; |
| 2166 | const sym_index = @intCast(u32, self.locals.items.len); | |
| 2167 | try self.locals.append(gpa, .{ | |
| 2168 | .n_strx = 0, | |
| 2169 | .n_type = macho.N_SECT, | |
| 2170 | .n_sect = 0, | |
| 2171 | .n_desc = 0, | |
| 2172 | .n_value = 0, | |
| 2173 | }); | |
| 2146 | const sym_index = try self.allocateSymbol(); | |
| 2174 | 2147 | const atom = try MachO.createEmptyAtom(gpa, sym_index, size, alignment); |
| 2148 | const sym = atom.getSymbolPtr(self); | |
| 2149 | sym.n_type = macho.N_SECT; | |
| 2150 | ||
| 2175 | 2151 | const dyld_private_sym_index = self.dyld_private_atom.?.sym_index; |
| 2176 | 2152 | switch (arch) { |
| 2177 | 2153 | .x86_64 => { |
| ... | ... | @@ -2288,15 +2264,11 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { |
| 2288 | 2264 | .aarch64 => 2, |
| 2289 | 2265 | else => unreachable, |
| 2290 | 2266 | }; |
| 2291 | const sym_index = @intCast(u32, self.locals.items.len); | |
| 2292 | try self.locals.append(gpa, .{ | |
| 2293 | .n_strx = 0, | |
| 2294 | .n_type = macho.N_SECT, | |
| 2295 | .n_sect = 0, | |
| 2296 | .n_desc = 0, | |
| 2297 | .n_value = 0, | |
| 2298 | }); | |
| 2267 | const sym_index = try self.allocateSymbol(); | |
| 2299 | 2268 | const atom = try MachO.createEmptyAtom(gpa, sym_index, stub_size, alignment); |
| 2269 | const sym = atom.getSymbolPtr(self); | |
| 2270 | sym.n_type = macho.N_SECT; | |
| 2271 | ||
| 2300 | 2272 | try atom.relocs.ensureTotalCapacity(gpa, 1); |
| 2301 | 2273 | |
| 2302 | 2274 | switch (arch) { |
| ... | ... | @@ -2352,15 +2324,11 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { |
| 2352 | 2324 | |
| 2353 | 2325 | pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWithLoc) !*Atom { |
| 2354 | 2326 | const gpa = self.base.allocator; |
| 2355 | const sym_index = @intCast(u32, self.locals.items.len); | |
| 2356 | try self.locals.append(gpa, .{ | |
| 2357 | .n_strx = 0, | |
| 2358 | .n_type = macho.N_SECT, | |
| 2359 | .n_sect = 0, | |
| 2360 | .n_desc = 0, | |
| 2361 | .n_value = 0, | |
| 2362 | }); | |
| 2327 | const sym_index = try self.allocateSymbol(); | |
| 2363 | 2328 | const atom = try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3); |
| 2329 | const sym = atom.getSymbolPtr(self); | |
| 2330 | sym.n_type = macho.N_SECT; | |
| 2331 | ||
| 2364 | 2332 | try atom.relocs.append(gpa, .{ |
| 2365 | 2333 | .offset = 0, |
| 2366 | 2334 | .target = .{ .sym_index = stub_sym_index, .file = null }, |
| ... | ... | @@ -2376,7 +2344,7 @@ pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWi |
| 2376 | 2344 | }); |
| 2377 | 2345 | try atom.rebases.append(gpa, 0); |
| 2378 | 2346 | |
| 2379 | const global = self.globals.get(self.getSymbolName(target)).?; | |
| 2347 | const global = self.getGlobal(self.getSymbolName(target)).?; | |
| 2380 | 2348 | try atom.lazy_bindings.append(gpa, .{ |
| 2381 | 2349 | .target = global, |
| 2382 | 2350 | .offset = 0, |
| ... | ... | @@ -2403,15 +2371,11 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom { |
| 2403 | 2371 | .aarch64 => 3 * @sizeOf(u32), |
| 2404 | 2372 | else => unreachable, // unhandled architecture type |
| 2405 | 2373 | }; |
| 2406 | const sym_index = @intCast(u32, self.locals.items.len); | |
| 2407 | try self.locals.append(gpa, .{ | |
| 2408 | .n_strx = 0, | |
| 2409 | .n_type = macho.N_SECT, | |
| 2410 | .n_sect = 0, | |
| 2411 | .n_desc = 0, | |
| 2412 | .n_value = 0, | |
| 2413 | }); | |
| 2374 | const sym_index = try self.allocateSymbol(); | |
| 2414 | 2375 | const atom = try MachO.createEmptyAtom(gpa, sym_index, stub_size, alignment); |
| 2376 | const sym = atom.getSymbolPtr(self); | |
| 2377 | sym.n_type = macho.N_SECT; | |
| 2378 | ||
| 2415 | 2379 | switch (arch) { |
| 2416 | 2380 | .x86_64 => { |
| 2417 | 2381 | // jmp |
| ... | ... | @@ -2472,7 +2436,7 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom { |
| 2472 | 2436 | fn createTentativeDefAtoms(self: *MachO) !void { |
| 2473 | 2437 | const gpa = self.base.allocator; |
| 2474 | 2438 | |
| 2475 | for (self.globals.values()) |global| { | |
| 2439 | for (self.globals.items) |global| { | |
| 2476 | 2440 | const sym = self.getSymbolPtr(global); |
| 2477 | 2441 | if (!sym.tentative()) continue; |
| 2478 | 2442 | |
| ... | ... | @@ -2516,51 +2480,44 @@ fn createTentativeDefAtoms(self: *MachO) !void { |
| 2516 | 2480 | |
| 2517 | 2481 | fn createMhExecuteHeaderSymbol(self: *MachO) !void { |
| 2518 | 2482 | if (self.base.options.output_mode != .Exe) return; |
| 2519 | if (self.globals.get("__mh_execute_header")) |global| { | |
| 2483 | if (self.getGlobal("__mh_execute_header")) |global| { | |
| 2520 | 2484 | const sym = self.getSymbol(global); |
| 2521 | 2485 | if (!sym.undf() and !(sym.pext() or sym.weakDef())) return; |
| 2522 | 2486 | } |
| 2523 | 2487 | |
| 2524 | 2488 | const gpa = self.base.allocator; |
| 2525 | const n_strx = try self.strtab.insert(gpa, "__mh_execute_header"); | |
| 2526 | const sym_index = @intCast(u32, self.locals.items.len); | |
| 2527 | try self.locals.append(gpa, .{ | |
| 2528 | .n_strx = n_strx, | |
| 2489 | const sym_index = try self.allocateSymbol(); | |
| 2490 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null }; | |
| 2491 | const sym = self.getSymbolPtr(sym_loc); | |
| 2492 | sym.* = .{ | |
| 2493 | .n_strx = try self.strtab.insert(gpa, "__mh_execute_header"), | |
| 2529 | 2494 | .n_type = macho.N_SECT | macho.N_EXT, |
| 2530 | 2495 | .n_sect = 0, |
| 2531 | 2496 | .n_desc = macho.REFERENCED_DYNAMICALLY, |
| 2532 | 2497 | .n_value = 0, |
| 2533 | }); | |
| 2534 | ||
| 2535 | const name = try gpa.dupe(u8, "__mh_execute_header"); | |
| 2536 | const gop = try self.globals.getOrPut(gpa, name); | |
| 2537 | defer if (gop.found_existing) gpa.free(name); | |
| 2538 | gop.value_ptr.* = .{ | |
| 2539 | .sym_index = sym_index, | |
| 2540 | .file = null, | |
| 2541 | 2498 | }; |
| 2499 | ||
| 2500 | const gop = try self.getOrPutGlobalPtr("__mh_execute_header"); | |
| 2501 | gop.value_ptr.* = sym_loc; | |
| 2542 | 2502 | } |
| 2543 | 2503 | |
| 2544 | 2504 | fn createDsoHandleSymbol(self: *MachO) !void { |
| 2545 | const global = self.globals.getPtr("___dso_handle") orelse return; | |
| 2546 | const sym = self.getSymbolPtr(global.*); | |
| 2547 | if (!sym.undf()) return; | |
| 2505 | const global = self.getGlobalPtr("___dso_handle") orelse return; | |
| 2506 | if (!self.getSymbol(global.*).undf()) return; | |
| 2548 | 2507 | |
| 2549 | 2508 | const gpa = self.base.allocator; |
| 2550 | const n_strx = try self.strtab.insert(gpa, "___dso_handle"); | |
| 2551 | const sym_index = @intCast(u32, self.locals.items.len); | |
| 2552 | try self.locals.append(gpa, .{ | |
| 2553 | .n_strx = n_strx, | |
| 2509 | const sym_index = try self.allocateSymbol(); | |
| 2510 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null }; | |
| 2511 | const sym = self.getSymbolPtr(sym_loc); | |
| 2512 | sym.* = .{ | |
| 2513 | .n_strx = try self.strtab.insert(gpa, "___dso_handle"), | |
| 2554 | 2514 | .n_type = macho.N_SECT | macho.N_EXT, |
| 2555 | 2515 | .n_sect = 0, |
| 2556 | 2516 | .n_desc = macho.N_WEAK_DEF, |
| 2557 | 2517 | .n_value = 0, |
| 2558 | }); | |
| 2559 | global.* = .{ | |
| 2560 | .sym_index = sym_index, | |
| 2561 | .file = null, | |
| 2562 | 2518 | }; |
| 2563 | _ = self.unresolved.swapRemove(@intCast(u32, self.globals.getIndex("___dso_handle").?)); | |
| 2519 | global.* = sym_loc; | |
| 2520 | _ = self.unresolved.swapRemove(self.getGlobalIndex("___dso_handle").?); | |
| 2564 | 2521 | } |
| 2565 | 2522 | |
| 2566 | 2523 | fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void { |
| ... | ... | @@ -2568,19 +2525,14 @@ fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void { |
| 2568 | 2525 | const sym = self.getSymbol(current); |
| 2569 | 2526 | const sym_name = self.getSymbolName(current); |
| 2570 | 2527 | |
| 2571 | const name = try gpa.dupe(u8, sym_name); | |
| 2572 | const global_index = @intCast(u32, self.globals.values().len); | |
| 2573 | const gop = try self.globals.getOrPut(gpa, name); | |
| 2574 | defer if (gop.found_existing) gpa.free(name); | |
| 2575 | ||
| 2528 | const gop = try self.getOrPutGlobalPtr(sym_name); | |
| 2576 | 2529 | if (!gop.found_existing) { |
| 2577 | 2530 | gop.value_ptr.* = current; |
| 2578 | 2531 | if (sym.undf() and !sym.tentative()) { |
| 2579 | try self.unresolved.putNoClobber(gpa, global_index, false); | |
| 2532 | try self.unresolved.putNoClobber(gpa, self.getGlobalIndex(sym_name).?, false); | |
| 2580 | 2533 | } |
| 2581 | 2534 | return; |
| 2582 | 2535 | } |
| 2583 | ||
| 2584 | 2536 | const global = gop.value_ptr.*; |
| 2585 | 2537 | const global_sym = self.getSymbol(global); |
| 2586 | 2538 | |
| ... | ... | @@ -2619,7 +2571,7 @@ fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void { |
| 2619 | 2571 | } |
| 2620 | 2572 | if (sym.undf() and !sym.tentative()) return; |
| 2621 | 2573 | |
| 2622 | _ = self.unresolved.swapRemove(@intCast(u32, self.globals.getIndex(name).?)); | |
| 2574 | _ = self.unresolved.swapRemove(self.getGlobalIndex(sym_name).?); | |
| 2623 | 2575 | |
| 2624 | 2576 | gop.value_ptr.* = current; |
| 2625 | 2577 | } |
| ... | ... | @@ -2664,7 +2616,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2664 | 2616 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = object_id }; |
| 2665 | 2617 | self.resolveGlobalSymbol(sym_loc) catch |err| switch (err) { |
| 2666 | 2618 | error.MultipleSymbolDefinitions => { |
| 2667 | const global = self.globals.get(sym_name).?; | |
| 2619 | const global = self.getGlobal(sym_name).?; | |
| 2668 | 2620 | log.err("symbol '{s}' defined multiple times", .{sym_name}); |
| 2669 | 2621 | if (global.file) |file| { |
| 2670 | 2622 | log.err(" first definition in '{s}'", .{self.objects.items[file].name}); |
| ... | ... | @@ -2684,7 +2636,8 @@ fn resolveSymbolsInArchives(self: *MachO) !void { |
| 2684 | 2636 | const cpu_arch = self.base.options.target.cpu.arch; |
| 2685 | 2637 | var next_sym: usize = 0; |
| 2686 | 2638 | loop: while (next_sym < self.unresolved.count()) { |
| 2687 | const global = self.globals.values()[self.unresolved.keys()[next_sym]]; | |
| 2639 | const global_index = self.unresolved.keys()[next_sym]; | |
| 2640 | const global = self.globals.items[global_index]; | |
| 2688 | 2641 | const sym_name = self.getSymbolName(global); |
| 2689 | 2642 | |
| 2690 | 2643 | for (self.archives.items) |archive| { |
| ... | ... | @@ -2710,10 +2663,11 @@ fn resolveSymbolsInArchives(self: *MachO) !void { |
| 2710 | 2663 | fn resolveSymbolsInDylibs(self: *MachO) !void { |
| 2711 | 2664 | if (self.dylibs.items.len == 0) return; |
| 2712 | 2665 | |
| 2666 | const gpa = self.base.allocator; | |
| 2713 | 2667 | var next_sym: usize = 0; |
| 2714 | 2668 | loop: while (next_sym < self.unresolved.count()) { |
| 2715 | 2669 | const global_index = self.unresolved.keys()[next_sym]; |
| 2716 | const global = self.globals.values()[global_index]; | |
| 2670 | const global = self.globals.items[global_index]; | |
| 2717 | 2671 | const sym = self.getSymbolPtr(global); |
| 2718 | 2672 | const sym_name = self.getSymbolName(global); |
| 2719 | 2673 | |
| ... | ... | @@ -2722,7 +2676,7 @@ fn resolveSymbolsInDylibs(self: *MachO) !void { |
| 2722 | 2676 | |
| 2723 | 2677 | const dylib_id = @intCast(u16, id); |
| 2724 | 2678 | if (!self.referenced_dylibs.contains(dylib_id)) { |
| 2725 | try self.referenced_dylibs.putNoClobber(self.base.allocator, dylib_id, {}); | |
| 2679 | try self.referenced_dylibs.putNoClobber(gpa, dylib_id, {}); | |
| 2726 | 2680 | } |
| 2727 | 2681 | |
| 2728 | 2682 | const ordinal = self.referenced_dylibs.getIndex(dylib_id) orelse unreachable; |
| ... | ... | @@ -2760,7 +2714,7 @@ fn resolveSymbolsAtLoading(self: *MachO) !void { |
| 2760 | 2714 | var next_sym: usize = 0; |
| 2761 | 2715 | while (next_sym < self.unresolved.count()) { |
| 2762 | 2716 | const global_index = self.unresolved.keys()[next_sym]; |
| 2763 | const global = self.globals.values()[global_index]; | |
| 2717 | const global = self.globals.items[global_index]; | |
| 2764 | 2718 | const sym = self.getSymbolPtr(global); |
| 2765 | 2719 | const sym_name = self.getSymbolName(global); |
| 2766 | 2720 | |
| ... | ... | @@ -2800,26 +2754,27 @@ fn resolveDyldStubBinder(self: *MachO) !void { |
| 2800 | 2754 | if (self.unresolved.count() == 0) return; // no need for a stub binder if we don't have any imports |
| 2801 | 2755 | |
| 2802 | 2756 | const gpa = self.base.allocator; |
| 2803 | const n_strx = try self.strtab.insert(gpa, "dyld_stub_binder"); | |
| 2804 | const sym_index = @intCast(u32, self.locals.items.len); | |
| 2805 | try self.locals.append(gpa, .{ | |
| 2806 | .n_strx = n_strx, | |
| 2757 | const sym_index = try self.allocateSymbol(); | |
| 2758 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null }; | |
| 2759 | const sym = self.getSymbolPtr(sym_loc); | |
| 2760 | const sym_name = "dyld_stub_binder"; | |
| 2761 | sym.* = .{ | |
| 2762 | .n_strx = try self.strtab.insert(gpa, sym_name), | |
| 2807 | 2763 | .n_type = macho.N_UNDF, |
| 2808 | 2764 | .n_sect = 0, |
| 2809 | 2765 | .n_desc = 0, |
| 2810 | 2766 | .n_value = 0, |
| 2811 | }); | |
| 2812 | const sym_name = try gpa.dupe(u8, "dyld_stub_binder"); | |
| 2813 | const global = SymbolWithLoc{ .sym_index = sym_index, .file = null }; | |
| 2814 | try self.globals.putNoClobber(gpa, sym_name, global); | |
| 2815 | const sym = &self.locals.items[sym_index]; | |
| 2767 | }; | |
| 2768 | const gop = try self.getOrPutGlobalPtr(sym_name); | |
| 2769 | gop.value_ptr.* = sym_loc; | |
| 2770 | const global = gop.value_ptr.*; | |
| 2816 | 2771 | |
| 2817 | 2772 | for (self.dylibs.items) |dylib, id| { |
| 2818 | 2773 | if (!dylib.symbols.contains(sym_name)) continue; |
| 2819 | 2774 | |
| 2820 | 2775 | const dylib_id = @intCast(u16, id); |
| 2821 | 2776 | if (!self.referenced_dylibs.contains(dylib_id)) { |
| 2822 | try self.referenced_dylibs.putNoClobber(self.base.allocator, dylib_id, {}); | |
| 2777 | try self.referenced_dylibs.putNoClobber(gpa, dylib_id, {}); | |
| 2823 | 2778 | } |
| 2824 | 2779 | |
| 2825 | 2780 | const ordinal = self.referenced_dylibs.getIndex(dylib_id) orelse unreachable; |
| ... | ... | @@ -3050,14 +3005,20 @@ pub fn deinit(self: *MachO) void { |
| 3050 | 3005 | self.stubs_free_list.deinit(gpa); |
| 3051 | 3006 | self.stubs_table.deinit(gpa); |
| 3052 | 3007 | self.strtab.deinit(gpa); |
| 3008 | ||
| 3053 | 3009 | self.locals.deinit(gpa); |
| 3010 | self.globals.deinit(gpa); | |
| 3054 | 3011 | self.locals_free_list.deinit(gpa); |
| 3012 | self.globals_free_list.deinit(gpa); | |
| 3055 | 3013 | self.unresolved.deinit(gpa); |
| 3056 | 3014 | |
| 3057 | for (self.globals.keys()) |key| { | |
| 3058 | gpa.free(key); | |
| 3015 | { | |
| 3016 | var it = self.resolver.keyIterator(); | |
| 3017 | while (it.next()) |key_ptr| { | |
| 3018 | gpa.free(key_ptr.*); | |
| 3019 | } | |
| 3020 | self.resolver.deinit(gpa); | |
| 3059 | 3021 | } |
| 3060 | self.globals.deinit(gpa); | |
| 3061 | 3022 | |
| 3062 | 3023 | for (self.objects.items) |*object| { |
| 3063 | 3024 | object.deinit(gpa); |
| ... | ... | @@ -3211,6 +3172,29 @@ fn allocateSymbol(self: *MachO) !u32 { |
| 3211 | 3172 | return index; |
| 3212 | 3173 | } |
| 3213 | 3174 | |
| 3175 | fn allocateGlobal(self: *MachO) !u32 { | |
| 3176 | try self.globals.ensureUnusedCapacity(self.base.allocator, 1); | |
| 3177 | ||
| 3178 | const index = blk: { | |
| 3179 | if (self.globals_free_list.popOrNull()) |index| { | |
| 3180 | log.debug(" (reusing global index {d})", .{index}); | |
| 3181 | break :blk index; | |
| 3182 | } else { | |
| 3183 | log.debug(" (allocating symbol index {d})", .{self.globals.items.len}); | |
| 3184 | const index = @intCast(u32, self.globals.items.len); | |
| 3185 | _ = self.globals.addOneAssumeCapacity(); | |
| 3186 | break :blk index; | |
| 3187 | } | |
| 3188 | }; | |
| 3189 | ||
| 3190 | self.globals.items[index] = .{ | |
| 3191 | .sym_index = 0, | |
| 3192 | .file = null, | |
| 3193 | }; | |
| 3194 | ||
| 3195 | return index; | |
| 3196 | } | |
| 3197 | ||
| 3214 | 3198 | pub fn allocateGotEntry(self: *MachO, target: SymbolWithLoc) !u32 { |
| 3215 | 3199 | const gpa = self.base.allocator; |
| 3216 | 3200 | try self.got_entries.ensureUnusedCapacity(gpa, 1); |
| ... | ... | @@ -3832,7 +3816,7 @@ pub fn updateDeclExports( |
| 3832 | 3816 | |
| 3833 | 3817 | self.resolveGlobalSymbol(sym_loc) catch |err| switch (err) { |
| 3834 | 3818 | error.MultipleSymbolDefinitions => { |
| 3835 | const global = self.globals.get(exp_name).?; | |
| 3819 | const global = self.getGlobal(exp_name).?; | |
| 3836 | 3820 | if (sym_loc.sym_index != global.sym_index and global.file != null) { |
| 3837 | 3821 | _ = try module.failed_exports.put(module.gpa, exp, try Module.ErrorMsg.create( |
| 3838 | 3822 | gpa, |
| ... | ... | @@ -3869,11 +3853,13 @@ pub fn deleteExport(self: *MachO, exp: Export) void { |
| 3869 | 3853 | }; |
| 3870 | 3854 | self.locals_free_list.append(gpa, sym_index) catch {}; |
| 3871 | 3855 | |
| 3872 | if (self.globals.get(sym_name)) |global| blk: { | |
| 3873 | if (global.sym_index != sym_index) break :blk; | |
| 3874 | if (global.file != null) break :blk; | |
| 3875 | const kv = self.globals.fetchSwapRemove(sym_name); | |
| 3876 | gpa.free(kv.?.key); | |
| 3856 | if (self.resolver.fetchRemove(sym_name)) |entry| { | |
| 3857 | defer gpa.free(entry.key); | |
| 3858 | self.globals_free_list.append(gpa, entry.value) catch {}; | |
| 3859 | self.globals.items[entry.value] = .{ | |
| 3860 | .sym_index = 0, | |
| 3861 | .file = null, | |
| 3862 | }; | |
| 3877 | 3863 | } |
| 3878 | 3864 | } |
| 3879 | 3865 | |
| ... | ... | @@ -4864,32 +4850,26 @@ pub fn addAtomToSection(self: *MachO, atom: *Atom, sect_id: u8) !void { |
| 4864 | 4850 | |
| 4865 | 4851 | pub fn getGlobalSymbol(self: *MachO, name: []const u8) !u32 { |
| 4866 | 4852 | const gpa = self.base.allocator; |
| 4853 | ||
| 4867 | 4854 | const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name}); |
| 4868 | const global_index = @intCast(u32, self.globals.values().len); | |
| 4869 | const gop = try self.globals.getOrPut(gpa, sym_name); | |
| 4870 | defer if (gop.found_existing) gpa.free(sym_name); | |
| 4855 | defer gpa.free(sym_name); | |
| 4856 | const gop = try self.getOrPutGlobalPtr(sym_name); | |
| 4857 | const global_index = self.getGlobalIndex(sym_name).?; | |
| 4871 | 4858 | |
| 4872 | 4859 | if (gop.found_existing) { |
| 4873 | // TODO audit this: can we ever reference anything from outside the Zig module? | |
| 4874 | assert(gop.value_ptr.file == null); | |
| 4875 | return gop.value_ptr.sym_index; | |
| 4860 | return global_index; | |
| 4876 | 4861 | } |
| 4877 | 4862 | |
| 4878 | const sym_index = @intCast(u32, self.locals.items.len); | |
| 4879 | try self.locals.append(gpa, .{ | |
| 4880 | .n_strx = try self.strtab.insert(gpa, sym_name), | |
| 4881 | .n_type = macho.N_UNDF, | |
| 4882 | .n_sect = 0, | |
| 4883 | .n_desc = 0, | |
| 4884 | .n_value = 0, | |
| 4885 | }); | |
| 4886 | gop.value_ptr.* = .{ | |
| 4887 | .sym_index = sym_index, | |
| 4888 | .file = null, | |
| 4889 | }; | |
| 4863 | const sym_index = try self.allocateSymbol(); | |
| 4864 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null }; | |
| 4865 | gop.value_ptr.* = sym_loc; | |
| 4866 | ||
| 4867 | const sym = self.getSymbolPtr(sym_loc); | |
| 4868 | sym.n_strx = try self.strtab.insert(gpa, sym_name); | |
| 4869 | ||
| 4890 | 4870 | try self.unresolved.putNoClobber(gpa, global_index, true); |
| 4891 | 4871 | |
| 4892 | return sym_index; | |
| 4872 | return global_index; | |
| 4893 | 4873 | } |
| 4894 | 4874 | |
| 4895 | 4875 | fn getSegmentAllocBase(self: MachO, indices: []const ?u8) struct { vmaddr: u64, fileoff: u64 } { |
| ... | ... | @@ -5055,7 +5035,7 @@ fn writeDyldInfoData(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { |
| 5055 | 5035 | if (self.base.options.output_mode == .Exe) { |
| 5056 | 5036 | for (&[_]SymbolWithLoc{ |
| 5057 | 5037 | try self.getEntryPoint(), |
| 5058 | self.globals.get("__mh_execute_header").?, | |
| 5038 | self.getGlobal("__mh_execute_header").?, | |
| 5059 | 5039 | }) |global| { |
| 5060 | 5040 | const sym = self.getSymbol(global); |
| 5061 | 5041 | const sym_name = self.getSymbolName(global); |
| ... | ... | @@ -5068,7 +5048,7 @@ fn writeDyldInfoData(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { |
| 5068 | 5048 | } |
| 5069 | 5049 | } else { |
| 5070 | 5050 | assert(self.base.options.output_mode == .Lib); |
| 5071 | for (self.globals.values()) |global| { | |
| 5051 | for (self.globals.items) |global| { | |
| 5072 | 5052 | const sym = self.getSymbol(global); |
| 5073 | 5053 | |
| 5074 | 5054 | if (sym.undf()) continue; |
| ... | ... | @@ -5271,9 +5251,9 @@ fn writeFunctionStarts(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { |
| 5271 | 5251 | // We need to sort by address first |
| 5272 | 5252 | var addresses = std.ArrayList(u64).init(gpa); |
| 5273 | 5253 | defer addresses.deinit(); |
| 5274 | try addresses.ensureTotalCapacityPrecise(self.globals.count()); | |
| 5254 | try addresses.ensureTotalCapacityPrecise(self.globals.items.len); | |
| 5275 | 5255 | |
| 5276 | for (self.globals.values()) |global| { | |
| 5256 | for (self.globals.items) |global| { | |
| 5277 | 5257 | const sym = self.getSymbol(global); |
| 5278 | 5258 | if (sym.undf()) continue; |
| 5279 | 5259 | if (sym.n_desc == N_DESC_GCED) continue; |
| ... | ... | @@ -5453,7 +5433,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx { |
| 5453 | 5433 | if (sym.n_desc == N_DESC_GCED) continue; // GCed, skip |
| 5454 | 5434 | const sym_loc = SymbolWithLoc{ .sym_index = @intCast(u32, sym_id), .file = null }; |
| 5455 | 5435 | if (self.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip |
| 5456 | if (self.globals.contains(self.getSymbolName(sym_loc))) continue; // global symbol is either an export or import, skip | |
| 5436 | if (self.getGlobal(self.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip | |
| 5457 | 5437 | try locals.append(sym); |
| 5458 | 5438 | } |
| 5459 | 5439 | |
| ... | ... | @@ -5463,7 +5443,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx { |
| 5463 | 5443 | if (sym.n_desc == N_DESC_GCED) continue; // GCed, skip |
| 5464 | 5444 | const sym_loc = SymbolWithLoc{ .sym_index = @intCast(u32, sym_id), .file = @intCast(u32, object_id) }; |
| 5465 | 5445 | if (self.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip |
| 5466 | if (self.globals.contains(self.getSymbolName(sym_loc))) continue; // global symbol is either an export or import, skip | |
| 5446 | if (self.getGlobal(self.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip | |
| 5467 | 5447 | var out_sym = sym; |
| 5468 | 5448 | out_sym.n_strx = try self.strtab.insert(gpa, self.getSymbolName(sym_loc)); |
| 5469 | 5449 | try locals.append(out_sym); |
| ... | ... | @@ -5477,7 +5457,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx { |
| 5477 | 5457 | var exports = std.ArrayList(macho.nlist_64).init(gpa); |
| 5478 | 5458 | defer exports.deinit(); |
| 5479 | 5459 | |
| 5480 | for (self.globals.values()) |global| { | |
| 5460 | for (self.globals.items) |global| { | |
| 5481 | 5461 | const sym = self.getSymbol(global); |
| 5482 | 5462 | if (sym.undf()) continue; // import, skip |
| 5483 | 5463 | if (sym.n_desc == N_DESC_GCED) continue; // GCed, skip |
| ... | ... | @@ -5491,7 +5471,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx { |
| 5491 | 5471 | |
| 5492 | 5472 | var imports_table = std.AutoHashMap(SymbolWithLoc, u32).init(gpa); |
| 5493 | 5473 | |
| 5494 | for (self.globals.values()) |global| { | |
| 5474 | for (self.globals.items) |global| { | |
| 5495 | 5475 | const sym = self.getSymbol(global); |
| 5496 | 5476 | if (sym.n_strx == 0) continue; // no name, skip |
| 5497 | 5477 | if (!sym.undf()) continue; // not an import, skip |
| ... | ... | @@ -5798,6 +5778,49 @@ pub fn getSymbolName(self: *MachO, sym_with_loc: SymbolWithLoc) []const u8 { |
| 5798 | 5778 | } |
| 5799 | 5779 | } |
| 5800 | 5780 | |
| 5781 | /// Returns pointer to the global entry for `name` if one exists. | |
| 5782 | pub fn getGlobalPtr(self: *MachO, name: []const u8) ?*SymbolWithLoc { | |
| 5783 | const global_index = self.resolver.get(name) orelse return null; | |
| 5784 | return &self.globals.items[global_index]; | |
| 5785 | } | |
| 5786 | ||
| 5787 | /// Returns the global entry for `name` if one exists. | |
| 5788 | pub fn getGlobal(self: *const MachO, name: []const u8) ?SymbolWithLoc { | |
| 5789 | const global_index = self.resolver.get(name) orelse return null; | |
| 5790 | return self.globals.items[global_index]; | |
| 5791 | } | |
| 5792 | ||
| 5793 | /// Returns the index of the global entry for `name` if one exists. | |
| 5794 | pub fn getGlobalIndex(self: *const MachO, name: []const u8) ?u32 { | |
| 5795 | return self.resolver.get(name); | |
| 5796 | } | |
| 5797 | ||
| 5798 | /// Returns global entry at `index`. | |
| 5799 | pub fn getGlobalByIndex(self: *const MachO, index: u32) SymbolWithLoc { | |
| 5800 | assert(index < self.globals.items.len); | |
| 5801 | return self.globals.items[index]; | |
| 5802 | } | |
| 5803 | ||
| 5804 | const GetOrPutGlobalPtrResult = struct { | |
| 5805 | found_existing: bool, | |
| 5806 | value_ptr: *SymbolWithLoc, | |
| 5807 | }; | |
| 5808 | ||
| 5809 | /// Return pointer to the global entry for `name` if one exists. | |
| 5810 | /// Puts a new global entry for `name` if one doesn't exist, and | |
| 5811 | /// returns a pointer to it. | |
| 5812 | pub fn getOrPutGlobalPtr(self: *MachO, name: []const u8) !GetOrPutGlobalPtrResult { | |
| 5813 | if (self.getGlobalPtr(name)) |ptr| { | |
| 5814 | return GetOrPutGlobalPtrResult{ .found_existing = true, .value_ptr = ptr }; | |
| 5815 | } | |
| 5816 | const gpa = self.base.allocator; | |
| 5817 | const global_index = try self.allocateGlobal(); | |
| 5818 | const global_name = try gpa.dupe(u8, name); | |
| 5819 | _ = try self.resolver.put(gpa, global_name, global_index); | |
| 5820 | const ptr = &self.globals.items[global_index]; | |
| 5821 | return GetOrPutGlobalPtrResult{ .found_existing = false, .value_ptr = ptr }; | |
| 5822 | } | |
| 5823 | ||
| 5801 | 5824 | /// Returns atom if there is an atom referenced by the symbol described by `sym_with_loc` descriptor. |
| 5802 | 5825 | /// Returns null on failure. |
| 5803 | 5826 | pub fn getAtomForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?*Atom { |
| ... | ... | @@ -5834,7 +5857,7 @@ pub fn getTlvPtrAtomForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?*Atom |
| 5834 | 5857 | /// Asserts output mode is executable. |
| 5835 | 5858 | pub fn getEntryPoint(self: MachO) error{MissingMainEntrypoint}!SymbolWithLoc { |
| 5836 | 5859 | const entry_name = self.base.options.entry orelse "_main"; |
| 5837 | const global = self.globals.get(entry_name) orelse { | |
| 5860 | const global = self.getGlobal(entry_name) orelse { | |
| 5838 | 5861 | log.err("entrypoint '{s}' not found", .{entry_name}); |
| 5839 | 5862 | return error.MissingMainEntrypoint; |
| 5840 | 5863 | }; |
| ... | ... | @@ -6342,9 +6365,9 @@ fn logSymtab(self: *MachO) void { |
| 6342 | 6365 | } |
| 6343 | 6366 | |
| 6344 | 6367 | log.debug("globals table:", .{}); |
| 6345 | for (self.globals.keys()) |name, id| { | |
| 6346 | const value = self.globals.values()[id]; | |
| 6347 | log.debug(" {s} => %{d} in object({?d})", .{ name, value.sym_index, value.file }); | |
| 6368 | for (self.globals.items) |global| { | |
| 6369 | const name = self.getSymbolName(global); | |
| 6370 | log.debug(" {s} => %{d} in object({?d})", .{ name, global.sym_index, global.file }); | |
| 6348 | 6371 | } |
| 6349 | 6372 | |
| 6350 | 6373 | log.debug("GOT entries:", .{}); |
src/link/MachO/Atom.zig+3-3| ... | ... | @@ -272,7 +272,7 @@ pub fn parseRelocs(self: *Atom, relocs: []align(1) const macho.relocation_info, |
| 272 | 272 | subtractor = sym_loc; |
| 273 | 273 | } else { |
| 274 | 274 | const sym_name = context.macho_file.getSymbolName(sym_loc); |
| 275 | subtractor = context.macho_file.globals.get(sym_name).?; | |
| 275 | subtractor = context.macho_file.getGlobal(sym_name).?; | |
| 276 | 276 | } |
| 277 | 277 | // Verify that *_SUBTRACTOR is followed by *_UNSIGNED. |
| 278 | 278 | if (relocs.len <= i + 1) { |
| ... | ... | @@ -339,7 +339,7 @@ pub fn parseRelocs(self: *Atom, relocs: []align(1) const macho.relocation_info, |
| 339 | 339 | break :target sym_loc; |
| 340 | 340 | } else { |
| 341 | 341 | const sym_name = context.macho_file.getSymbolName(sym_loc); |
| 342 | break :target context.macho_file.globals.get(sym_name).?; | |
| 342 | break :target context.macho_file.getGlobal(sym_name).?; | |
| 343 | 343 | } |
| 344 | 344 | }; |
| 345 | 345 | const offset = @intCast(u32, rel.r_address - context.base_offset); |
| ... | ... | @@ -579,7 +579,7 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void { |
| 579 | 579 | // If there is no atom for target, we still need to check for special, atom-less |
| 580 | 580 | // symbols such as `___dso_handle`. |
| 581 | 581 | const target_name = macho_file.getSymbolName(rel.target); |
| 582 | assert(macho_file.globals.contains(target_name)); | |
| 582 | assert(macho_file.getGlobal(target_name) != null); | |
| 583 | 583 | const atomless_sym = macho_file.getSymbol(rel.target); |
| 584 | 584 | log.debug(" | atomless target '{s}'", .{target_name}); |
| 585 | 585 | break :blk atomless_sym.n_value; |
src/link/MachO/DebugSymbols.zig+2-2| ... | ... | @@ -480,7 +480,7 @@ fn writeSymtab(self: *DebugSymbols, lc: *macho.symtab_command) !void { |
| 480 | 480 | if (sym.n_desc == MachO.N_DESC_GCED) continue; // GCed, skip |
| 481 | 481 | const sym_loc = MachO.SymbolWithLoc{ .sym_index = @intCast(u32, sym_id), .file = null }; |
| 482 | 482 | if (self.base.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip |
| 483 | if (self.base.globals.contains(self.base.getSymbolName(sym_loc))) continue; // global symbol is either an export or import, skip | |
| 483 | if (self.base.getGlobal(self.base.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip | |
| 484 | 484 | var out_sym = sym; |
| 485 | 485 | out_sym.n_strx = try self.strtab.insert(gpa, self.base.getSymbolName(sym_loc)); |
| 486 | 486 | try locals.append(out_sym); |
| ... | ... | @@ -489,7 +489,7 @@ fn writeSymtab(self: *DebugSymbols, lc: *macho.symtab_command) !void { |
| 489 | 489 | var exports = std.ArrayList(macho.nlist_64).init(gpa); |
| 490 | 490 | defer exports.deinit(); |
| 491 | 491 | |
| 492 | for (self.base.globals.values()) |global| { | |
| 492 | for (self.base.globals.items) |global| { | |
| 493 | 493 | const sym = self.base.getSymbol(global); |
| 494 | 494 | if (sym.undf()) continue; // import, skip |
| 495 | 495 | if (sym.n_desc == MachO.N_DESC_GCED) continue; // GCed, skip |
src/link/MachO/dead_strip.zig+2-2| ... | ... | @@ -62,7 +62,7 @@ fn collectRoots(roots: *std.AutoHashMap(*Atom, void), macho_file: *MachO) !void |
| 62 | 62 | else => |other| { |
| 63 | 63 | assert(other == .Lib); |
| 64 | 64 | // Add exports as GC roots |
| 65 | for (macho_file.globals.values()) |global| { | |
| 65 | for (macho_file.globals.items) |global| { | |
| 66 | 66 | const sym = macho_file.getSymbol(global); |
| 67 | 67 | if (!sym.sect()) continue; |
| 68 | 68 | const atom = macho_file.getAtomForSymbol(global) orelse { |
| ... | ... | @@ -77,7 +77,7 @@ fn collectRoots(roots: *std.AutoHashMap(*Atom, void), macho_file: *MachO) !void |
| 77 | 77 | } |
| 78 | 78 | |
| 79 | 79 | // TODO just a temp until we learn how to parse unwind records |
| 80 | if (macho_file.globals.get("___gxx_personality_v0")) |global| { | |
| 80 | if (macho_file.getGlobal("___gxx_personality_v0")) |global| { | |
| 81 | 81 | if (macho_file.getAtomForSymbol(global)) |atom| { |
| 82 | 82 | _ = try roots.getOrPut(atom); |
| 83 | 83 | log.debug("adding root", .{}); |