diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-02-03 12:49:40 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-02-03 12:49:40 -0700 |
| commit | fab9b7110ed1fa7bb082aad5e095047441db2b24 (patch) | |
| tree | 81fef60aa45e7980dab8f3e23e5b5e92b40ee0a9 /src/link/MachO | |
| parent | d20d69b59e6b65a99f45cb6a45c14e887034dd18 (diff) | |
| parent | 60935decd318498529a016eeb1379d943a7e830d (diff) | |
| download | zig-fab9b7110ed1fa7bb082aad5e095047441db2b24.tar.gz zig-fab9b7110ed1fa7bb082aad5e095047441db2b24.zip | |
Merge remote-tracking branch 'origin/master' into llvm16
Diffstat (limited to 'src/link/MachO')
| -rw-r--r-- | src/link/MachO/Atom.zig | 92 | ||||
| -rw-r--r-- | src/link/MachO/DebugSymbols.zig | 12 | ||||
| -rw-r--r-- | src/link/MachO/Relocation.zig | 16 | ||||
| -rw-r--r-- | src/link/MachO/load_commands.zig | 2 | ||||
| -rw-r--r-- | src/link/MachO/zld.zig | 11 |
5 files changed, 77 insertions, 56 deletions
diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index 47ef974cb1..5fb94b7c13 100644 --- a/src/link/MachO/Atom.zig +++ b/src/link/MachO/Atom.zig @@ -13,7 +13,6 @@ const trace = @import("../../tracy.zig").trace; const Allocator = mem.Allocator; const Arch = std.Target.Cpu.Arch; -const Dwarf = @import("../Dwarf.zig"); const MachO = @import("../MachO.zig"); const Relocation = @import("Relocation.zig"); const SymbolWithLoc = MachO.SymbolWithLoc; @@ -39,10 +38,11 @@ size: u64, alignment: u32, /// Points to the previous and next neighbours -next: ?*Atom, -prev: ?*Atom, +/// TODO use the same trick as with symbols: reserve index 0 as null atom +next_index: ?Index, +prev_index: ?Index, -dbg_info_atom: Dwarf.Atom, +pub const Index = u32; pub const Binding = struct { target: SymbolWithLoc, @@ -54,15 +54,10 @@ pub const SymbolAtOffset = struct { offset: u64, }; -pub const empty = Atom{ - .sym_index = 0, - .file = null, - .size = 0, - .alignment = 0, - .prev = null, - .next = null, - .dbg_info_atom = undefined, -}; +pub fn getSymbolIndex(self: Atom) ?u32 { + if (self.sym_index == 0) return null; + return self.sym_index; +} /// Returns symbol referencing this atom. pub fn getSymbol(self: Atom, macho_file: *MachO) macho.nlist_64 { @@ -71,20 +66,23 @@ pub fn getSymbol(self: Atom, macho_file: *MachO) macho.nlist_64 { /// Returns pointer-to-symbol referencing this atom. pub fn getSymbolPtr(self: Atom, macho_file: *MachO) *macho.nlist_64 { + const sym_index = self.getSymbolIndex().?; return macho_file.getSymbolPtr(.{ - .sym_index = self.sym_index, + .sym_index = sym_index, .file = self.file, }); } pub fn getSymbolWithLoc(self: Atom) SymbolWithLoc { - return .{ .sym_index = self.sym_index, .file = self.file }; + const sym_index = self.getSymbolIndex().?; + return .{ .sym_index = sym_index, .file = self.file }; } /// Returns the name of this atom. pub fn getName(self: Atom, macho_file: *MachO) []const u8 { + const sym_index = self.getSymbolIndex().?; return macho_file.getSymbolName(.{ - .sym_index = self.sym_index, + .sym_index = sym_index, .file = self.file, }); } @@ -94,7 +92,8 @@ pub fn getName(self: Atom, macho_file: *MachO) []const u8 { /// this calculation. pub fn capacity(self: Atom, macho_file: *MachO) u64 { const self_sym = self.getSymbol(macho_file); - if (self.next) |next| { + if (self.next_index) |next_index| { + const next = macho_file.getAtom(next_index); const next_sym = next.getSymbol(macho_file); return next_sym.n_value - self_sym.n_value; } else { @@ -106,7 +105,8 @@ pub fn capacity(self: Atom, macho_file: *MachO) u64 { pub fn freeListEligible(self: Atom, macho_file: *MachO) bool { // No need to keep a free list node for the last atom. - const next = self.next orelse return false; + const next_index = self.next_index orelse return false; + const next = macho_file.getAtom(next_index); const self_sym = self.getSymbol(macho_file); const next_sym = next.getSymbol(macho_file); const cap = next_sym.n_value - self_sym.n_value; @@ -116,19 +116,19 @@ pub fn freeListEligible(self: Atom, macho_file: *MachO) bool { return surplus >= MachO.min_text_capacity; } -pub fn addRelocation(self: *Atom, macho_file: *MachO, reloc: Relocation) !void { - return self.addRelocations(macho_file, 1, .{reloc}); +pub fn addRelocation(macho_file: *MachO, atom_index: Index, reloc: Relocation) !void { + return addRelocations(macho_file, atom_index, 1, .{reloc}); } pub fn addRelocations( - self: *Atom, macho_file: *MachO, + atom_index: Index, comptime count: comptime_int, relocs: [count]Relocation, ) !void { const gpa = macho_file.base.allocator; const target = macho_file.base.options.target; - const gop = try macho_file.relocs.getOrPut(gpa, self); + const gop = try macho_file.relocs.getOrPut(gpa, atom_index); if (!gop.found_existing) { gop.value_ptr.* = .{}; } @@ -142,56 +142,72 @@ pub fn addRelocations( } } -pub fn addRebase(self: *Atom, macho_file: *MachO, offset: u32) !void { +pub fn addRebase(macho_file: *MachO, atom_index: Index, offset: u32) !void { const gpa = macho_file.base.allocator; - log.debug(" (adding rebase at offset 0x{x} in %{d})", .{ offset, self.sym_index }); - const gop = try macho_file.rebases.getOrPut(gpa, self); + const atom = macho_file.getAtom(atom_index); + log.debug(" (adding rebase at offset 0x{x} in %{?d})", .{ offset, atom.getSymbolIndex() }); + const gop = try macho_file.rebases.getOrPut(gpa, atom_index); if (!gop.found_existing) { gop.value_ptr.* = .{}; } try gop.value_ptr.append(gpa, offset); } -pub fn addBinding(self: *Atom, macho_file: *MachO, binding: Binding) !void { +pub fn addBinding(macho_file: *MachO, atom_index: Index, binding: Binding) !void { const gpa = macho_file.base.allocator; - log.debug(" (adding binding to symbol {s} at offset 0x{x} in %{d})", .{ + const atom = macho_file.getAtom(atom_index); + log.debug(" (adding binding to symbol {s} at offset 0x{x} in %{?d})", .{ macho_file.getSymbolName(binding.target), binding.offset, - self.sym_index, + atom.getSymbolIndex(), }); - const gop = try macho_file.bindings.getOrPut(gpa, self); + const gop = try macho_file.bindings.getOrPut(gpa, atom_index); if (!gop.found_existing) { gop.value_ptr.* = .{}; } try gop.value_ptr.append(gpa, binding); } -pub fn addLazyBinding(self: *Atom, macho_file: *MachO, binding: Binding) !void { +pub fn addLazyBinding(macho_file: *MachO, atom_index: Index, binding: Binding) !void { const gpa = macho_file.base.allocator; - log.debug(" (adding lazy binding to symbol {s} at offset 0x{x} in %{d})", .{ + const atom = macho_file.getAtom(atom_index); + log.debug(" (adding lazy binding to symbol {s} at offset 0x{x} in %{?d})", .{ macho_file.getSymbolName(binding.target), binding.offset, - self.sym_index, + atom.getSymbolIndex(), }); - const gop = try macho_file.lazy_bindings.getOrPut(gpa, self); + const gop = try macho_file.lazy_bindings.getOrPut(gpa, atom_index); if (!gop.found_existing) { gop.value_ptr.* = .{}; } try gop.value_ptr.append(gpa, binding); } -pub fn resolveRelocations(self: *Atom, macho_file: *MachO) !void { - const relocs = macho_file.relocs.get(self) orelse return; - const source_sym = self.getSymbol(macho_file); +pub fn resolveRelocations(macho_file: *MachO, atom_index: Index) !void { + const atom = macho_file.getAtom(atom_index); + const relocs = macho_file.relocs.get(atom_index) orelse return; + const source_sym = atom.getSymbol(macho_file); const source_section = macho_file.sections.get(source_sym.n_sect - 1).header; const file_offset = source_section.offset + source_sym.n_value - source_section.addr; - log.debug("relocating '{s}'", .{self.getName(macho_file)}); + log.debug("relocating '{s}'", .{atom.getName(macho_file)}); for (relocs.items) |*reloc| { if (!reloc.dirty) continue; - try reloc.resolve(self, macho_file, file_offset); + try reloc.resolve(macho_file, atom_index, file_offset); reloc.dirty = false; } } + +pub fn freeRelocations(macho_file: *MachO, atom_index: Index) void { + const gpa = macho_file.base.allocator; + var removed_relocs = macho_file.relocs.fetchOrderedRemove(atom_index); + if (removed_relocs) |*relocs| relocs.value.deinit(gpa); + var removed_rebases = macho_file.rebases.fetchOrderedRemove(atom_index); + if (removed_rebases) |*rebases| rebases.value.deinit(gpa); + var removed_bindings = macho_file.bindings.fetchOrderedRemove(atom_index); + if (removed_bindings) |*bindings| bindings.value.deinit(gpa); + var removed_lazy_bindings = macho_file.lazy_bindings.fetchOrderedRemove(atom_index); + if (removed_lazy_bindings) |*lazy_bindings| lazy_bindings.value.deinit(gpa); +} diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig index 7c22f441cd..0a5c8b0372 100644 --- a/src/link/MachO/DebugSymbols.zig +++ b/src/link/MachO/DebugSymbols.zig @@ -82,11 +82,11 @@ pub fn populateMissingMetadata(self: *DebugSymbols) !void { } if (self.debug_str_section_index == null) { - assert(self.dwarf.strtab.items.len == 0); - try self.dwarf.strtab.append(self.allocator, 0); + assert(self.dwarf.strtab.buffer.items.len == 0); + try self.dwarf.strtab.buffer.append(self.allocator, 0); self.debug_str_section_index = try self.allocateSection( "__debug_str", - @intCast(u32, self.dwarf.strtab.items.len), + @intCast(u32, self.dwarf.strtab.buffer.items.len), 0, ); self.debug_string_table_dirty = true; @@ -291,10 +291,10 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { { const sect_index = self.debug_str_section_index.?; - if (self.debug_string_table_dirty or self.dwarf.strtab.items.len != self.getSection(sect_index).size) { - const needed_size = @intCast(u32, self.dwarf.strtab.items.len); + if (self.debug_string_table_dirty or self.dwarf.strtab.buffer.items.len != self.getSection(sect_index).size) { + const needed_size = @intCast(u32, self.dwarf.strtab.buffer.items.len); try self.growSection(sect_index, needed_size, false); - try self.file.pwriteAll(self.dwarf.strtab.items, self.getSection(sect_index).offset); + try self.file.pwriteAll(self.dwarf.strtab.buffer.items, self.getSection(sect_index).offset); self.debug_string_table_dirty = false; } } diff --git a/src/link/MachO/Relocation.zig b/src/link/MachO/Relocation.zig index ca6bf9d681..07e5cf1aa2 100644 --- a/src/link/MachO/Relocation.zig +++ b/src/link/MachO/Relocation.zig @@ -29,33 +29,35 @@ pub fn fmtType(self: Relocation, target: std.Target) []const u8 { } } -pub fn getTargetAtom(self: Relocation, macho_file: *MachO) ?*Atom { +pub fn getTargetAtomIndex(self: Relocation, macho_file: *MachO) ?Atom.Index { switch (macho_file.base.options.target.cpu.arch) { .aarch64 => switch (@intToEnum(macho.reloc_type_arm64, self.type)) { .ARM64_RELOC_GOT_LOAD_PAGE21, .ARM64_RELOC_GOT_LOAD_PAGEOFF12, .ARM64_RELOC_POINTER_TO_GOT, - => return macho_file.getGotAtomForSymbol(self.target), + => return macho_file.getGotAtomIndexForSymbol(self.target), else => {}, }, .x86_64 => switch (@intToEnum(macho.reloc_type_x86_64, self.type)) { .X86_64_RELOC_GOT, .X86_64_RELOC_GOT_LOAD, - => return macho_file.getGotAtomForSymbol(self.target), + => return macho_file.getGotAtomIndexForSymbol(self.target), else => {}, }, else => unreachable, } - if (macho_file.getStubsAtomForSymbol(self.target)) |stubs_atom| return stubs_atom; - return macho_file.getAtomForSymbol(self.target); + if (macho_file.getStubsAtomIndexForSymbol(self.target)) |stubs_atom| return stubs_atom; + return macho_file.getAtomIndexForSymbol(self.target); } -pub fn resolve(self: Relocation, atom: *Atom, macho_file: *MachO, base_offset: u64) !void { +pub fn resolve(self: Relocation, macho_file: *MachO, atom_index: Atom.Index, base_offset: u64) !void { const arch = macho_file.base.options.target.cpu.arch; + const atom = macho_file.getAtom(atom_index); const source_sym = atom.getSymbol(macho_file); const source_addr = source_sym.n_value + self.offset; - const target_atom = self.getTargetAtom(macho_file) orelse return; + const target_atom_index = self.getTargetAtomIndex(macho_file) orelse return; + const target_atom = macho_file.getAtom(target_atom_index); const target_addr = @intCast(i64, target_atom.getSymbol(macho_file).n_value) + self.addend; log.debug(" ({x}: [() => 0x{x} ({s})) ({s})", .{ diff --git a/src/link/MachO/load_commands.zig b/src/link/MachO/load_commands.zig index 0e3760526c..a452551a0a 100644 --- a/src/link/MachO/load_commands.zig +++ b/src/link/MachO/load_commands.zig @@ -12,7 +12,7 @@ pub const default_dyld_path: [*:0]const u8 = "/usr/lib/dyld"; fn calcInstallNameLen(cmd_size: u64, name: []const u8, assume_max_path_len: bool) u64 { const darwin_path_max = 1024; - const name_len = if (assume_max_path_len) darwin_path_max else std.mem.len(name) + 1; + const name_len = if (assume_max_path_len) darwin_path_max else name.len + 1; return mem.alignForwardGeneric(u64, cmd_size + name_len, @alignOf(u64)); } diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index 4cb346aa47..81fae399ef 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -3596,7 +3596,8 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr man.hash.addOptionalBytes(options.sysroot); try man.addOptionalFile(options.entitlements); - // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. + // We don't actually care whether it's a cache hit or miss; we just + // need the digest and the lock. _ = try man.hit(); digest = man.final(); @@ -4177,9 +4178,11 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr log.debug("failed to save linking hash digest file: {s}", .{@errorName(err)}); }; // Again failure here only means an unnecessary cache miss. - man.writeManifest() catch |err| { - log.debug("failed to write cache manifest when linking: {s}", .{@errorName(err)}); - }; + if (man.have_exclusive_lock) { + man.writeManifest() catch |err| { + log.debug("failed to write cache manifest when linking: {s}", .{@errorName(err)}); + }; + } // We hang on to this lock so that the output file path can be used without // other processes clobbering it. macho_file.base.lock = man.toOwnedLock(); |
