| author | |
| committer | |
| log | dc6b05408a4bf0a9a52eb0532b7dddc06914ad5d |
| tree | 00ad49556b68468097f4916d23f91491e07a3a20 |
| parent | d61ac0db8c62f706ea65b70d2772cbb8c4efb416 |
| parent | 1eb4264b7aa9e9e2b8ec46a95b508dfa7a7ab0f7 |
| signature |
macho: fix Go mislinking on aarch64-macos, and misc cleanup11 files changed, 314 insertions(+), 294 deletions(-)
lib/std/macho.zig+2| ... | @@ -143,6 +143,8 @@ pub const TOOL = enum(u32) { | ... | @@ -143,6 +143,8 @@ pub const TOOL = enum(u32) { |
| 143 | CLANG = 0x1, | 143 | CLANG = 0x1, |
| 144 | SWIFT = 0x2, | 144 | SWIFT = 0x2, |
| 145 | LD = 0x3, | 145 | LD = 0x3, |
| 146 | LLD = 0x4, // LLVM's stock LLD linker | ||
| 147 | ZIG = 0x5, // Unofficially Zig | ||
| 146 | _, | 148 | _, |
| 147 | }; | 149 | }; |
| 148 | 150 |
src/link/MachO.zig+11-28| ... | @@ -3340,36 +3340,19 @@ fn collectExportData(self: *MachO, trie: *Trie) !void { | ... | @@ -3340,36 +3340,19 @@ fn collectExportData(self: *MachO, trie: *Trie) !void { |
| 3340 | const exec_segment = self.segments.items[self.header_segment_cmd_index.?]; | 3340 | const exec_segment = self.segments.items[self.header_segment_cmd_index.?]; |
| 3341 | const base_address = exec_segment.vmaddr; | 3341 | const base_address = exec_segment.vmaddr; |
| 3342 | 3342 | ||
| 3343 | if (self.base.options.output_mode == .Exe) { | 3343 | for (self.globals.items) |global| { |
| 3344 | for (&[_]SymbolWithLoc{ | 3344 | const sym = self.getSymbol(global); |
| 3345 | try self.getEntryPoint(), | ||
| 3346 | self.getGlobal("__mh_execute_header").?, | ||
| 3347 | }) |global| { | ||
| 3348 | const sym = self.getSymbol(global); | ||
| 3349 | const sym_name = self.getSymbolName(global); | ||
| 3350 | log.debug(" (putting '{s}' defined at 0x{x})", .{ sym_name, sym.n_value }); | ||
| 3351 | try trie.put(gpa, .{ | ||
| 3352 | .name = sym_name, | ||
| 3353 | .vmaddr_offset = sym.n_value - base_address, | ||
| 3354 | .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR, | ||
| 3355 | }); | ||
| 3356 | } | ||
| 3357 | } else { | ||
| 3358 | assert(self.base.options.output_mode == .Lib); | ||
| 3359 | for (self.globals.items) |global| { | ||
| 3360 | const sym = self.getSymbol(global); | ||
| 3361 | 3345 | ||
| 3362 | if (sym.undf()) continue; | 3346 | if (sym.undf()) continue; |
| 3363 | if (!sym.ext()) continue; | 3347 | if (!sym.ext()) continue; |
| 3364 | 3348 | ||
| 3365 | const sym_name = self.getSymbolName(global); | 3349 | const sym_name = self.getSymbolName(global); |
| 3366 | log.debug(" (putting '{s}' defined at 0x{x})", .{ sym_name, sym.n_value }); | 3350 | log.debug(" (putting '{s}' defined at 0x{x})", .{ sym_name, sym.n_value }); |
| 3367 | try trie.put(gpa, .{ | 3351 | try trie.put(gpa, .{ |
| 3368 | .name = sym_name, | 3352 | .name = sym_name, |
| 3369 | .vmaddr_offset = sym.n_value - base_address, | 3353 | .vmaddr_offset = sym.n_value - base_address, |
| 3370 | .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR, | 3354 | .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR, |
| 3371 | }); | 3355 | }); |
| 3372 | } | ||
| 3373 | } | 3356 | } |
| 3374 | 3357 | ||
| 3375 | try trie.finalize(gpa); | 3358 | try trie.finalize(gpa); |
src/link/MachO/DwarfInfo.zig+3-18| ... | @@ -27,7 +27,7 @@ const CompileUnitIterator = struct { | ... | @@ -27,7 +27,7 @@ const CompileUnitIterator = struct { |
| 27 | pub fn next(self: *CompileUnitIterator) !?CompileUnit { | 27 | pub fn next(self: *CompileUnitIterator) !?CompileUnit { |
| 28 | if (self.pos >= self.ctx.debug_info.len) return null; | 28 | if (self.pos >= self.ctx.debug_info.len) return null; |
| 29 | 29 | ||
| 30 | var stream = std.io.fixedBufferStream(self.ctx.debug_info); | 30 | var stream = std.io.fixedBufferStream(self.ctx.debug_info[self.pos..]); |
| 31 | var creader = std.io.countingReader(stream.reader()); | 31 | var creader = std.io.countingReader(stream.reader()); |
| 32 | const reader = creader.reader(); | 32 | const reader = creader.reader(); |
| 33 | 33 | ||
| ... | @@ -37,7 +37,7 @@ const CompileUnitIterator = struct { | ... | @@ -37,7 +37,7 @@ const CompileUnitIterator = struct { |
| 37 | 37 | ||
| 38 | const cu = CompileUnit{ | 38 | const cu = CompileUnit{ |
| 39 | .cuh = cuh, | 39 | .cuh = cuh, |
| 40 | .debug_info_off = offset, | 40 | .debug_info_off = self.pos + offset, |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | self.pos += (math.cast(usize, total_length) orelse return error.Overflow); | 43 | self.pos += (math.cast(usize, total_length) orelse return error.Overflow); |
| ... | @@ -188,7 +188,7 @@ const AbbrevEntryIterator = struct { | ... | @@ -188,7 +188,7 @@ const AbbrevEntryIterator = struct { |
| 188 | return AbbrevEntry.null(); | 188 | return AbbrevEntry.null(); |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | const abbrev_pos = lookup.get(kind) orelse return error.MalformedDwarf; | 191 | const abbrev_pos = lookup.get(kind) orelse return null; |
| 192 | const len = try findAbbrevEntrySize( | 192 | const len = try findAbbrevEntrySize( |
| 193 | self.ctx, | 193 | self.ctx, |
| 194 | abbrev_pos.pos, | 194 | abbrev_pos.pos, |
| ... | @@ -290,21 +290,6 @@ pub const Attribute = struct { | ... | @@ -290,21 +290,6 @@ pub const Attribute = struct { |
| 290 | }; | 290 | }; |
| 291 | } | 291 | } |
| 292 | 292 | ||
| 293 | pub fn getReference(self: Attribute, ctx: DwarfInfo) !?u64 { | ||
| 294 | const debug_info = self.getDebugInfo(ctx); | ||
| 295 | var stream = std.io.fixedBufferStream(debug_info); | ||
| 296 | const reader = stream.reader(); | ||
| 297 | |||
| 298 | return switch (self.form) { | ||
| 299 | dwarf.FORM.ref1 => debug_info[0], | ||
| 300 | dwarf.FORM.ref2 => mem.readIntLittle(u16, debug_info[0..2]), | ||
| 301 | dwarf.FORM.ref4 => mem.readIntLittle(u32, debug_info[0..4]), | ||
| 302 | dwarf.FORM.ref8 => mem.readIntLittle(u64, debug_info[0..8]), | ||
| 303 | dwarf.FORM.ref_udata => try leb.readULEB128(u64, reader), | ||
| 304 | else => null, | ||
| 305 | }; | ||
| 306 | } | ||
| 307 | |||
| 308 | pub fn getAddr(self: Attribute, ctx: DwarfInfo, cuh: CompileUnit.Header) ?u64 { | 293 | pub fn getAddr(self: Attribute, ctx: DwarfInfo, cuh: CompileUnit.Header) ?u64 { |
| 309 | if (self.form != dwarf.FORM.addr) return null; | 294 | if (self.form != dwarf.FORM.addr) return null; |
| 310 | const debug_info = self.getDebugInfo(ctx); | 295 | const debug_info = self.getDebugInfo(ctx); |
src/link/MachO/Object.zig+55-43| ... | @@ -50,7 +50,7 @@ reverse_symtab_lookup: []u32 = undefined, | ... | @@ -50,7 +50,7 @@ reverse_symtab_lookup: []u32 = undefined, |
| 50 | /// Can be undefined as set together with in_symtab. | 50 | /// Can be undefined as set together with in_symtab. |
| 51 | source_address_lookup: []i64 = undefined, | 51 | source_address_lookup: []i64 = undefined, |
| 52 | /// Can be undefined as set together with in_symtab. | 52 | /// Can be undefined as set together with in_symtab. |
| 53 | source_section_index_lookup: []i64 = undefined, | 53 | source_section_index_lookup: []Entry = undefined, |
| 54 | /// Can be undefined as set together with in_symtab. | 54 | /// Can be undefined as set together with in_symtab. |
| 55 | strtab_lookup: []u32 = undefined, | 55 | strtab_lookup: []u32 = undefined, |
| 56 | /// Can be undefined as set together with in_symtab. | 56 | /// Can be undefined as set together with in_symtab. |
| ... | @@ -58,7 +58,7 @@ atom_by_index_table: []AtomIndex = undefined, | ... | @@ -58,7 +58,7 @@ atom_by_index_table: []AtomIndex = undefined, |
| 58 | /// Can be undefined as set together with in_symtab. | 58 | /// Can be undefined as set together with in_symtab. |
| 59 | globals_lookup: []i64 = undefined, | 59 | globals_lookup: []i64 = undefined, |
| 60 | /// Can be undefined as set together with in_symtab. | 60 | /// Can be undefined as set together with in_symtab. |
| 61 | relocs_lookup: []RelocEntry = undefined, | 61 | relocs_lookup: []Entry = undefined, |
| 62 | 62 | ||
| 63 | /// All relocations sorted and flatened, sorted by address descending | 63 | /// All relocations sorted and flatened, sorted by address descending |
| 64 | /// per section. | 64 | /// per section. |
| ... | @@ -81,11 +81,14 @@ unwind_info_sect_id: ?u8 = null, | ... | @@ -81,11 +81,14 @@ unwind_info_sect_id: ?u8 = null, |
| 81 | unwind_relocs_lookup: []Record = undefined, | 81 | unwind_relocs_lookup: []Record = undefined, |
| 82 | unwind_records_lookup: std.AutoHashMapUnmanaged(AtomIndex, u32) = .{}, | 82 | unwind_records_lookup: std.AutoHashMapUnmanaged(AtomIndex, u32) = .{}, |
| 83 | 83 | ||
| 84 | const RelocEntry = struct { start: u32, len: u32 }; | 84 | const Entry = struct { |
| 85 | start: u32 = 0, | ||
| 86 | len: u32 = 0, | ||
| 87 | }; | ||
| 85 | 88 | ||
| 86 | const Record = struct { | 89 | const Record = struct { |
| 87 | dead: bool, | 90 | dead: bool, |
| 88 | reloc: RelocEntry, | 91 | reloc: Entry, |
| 89 | }; | 92 | }; |
| 90 | 93 | ||
| 91 | pub fn deinit(self: *Object, gpa: Allocator) void { | 94 | pub fn deinit(self: *Object, gpa: Allocator) void { |
| ... | @@ -170,11 +173,11 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) | ... | @@ -170,11 +173,11 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) |
| 170 | self.strtab_lookup = try allocator.alloc(u32, self.in_symtab.?.len); | 173 | self.strtab_lookup = try allocator.alloc(u32, self.in_symtab.?.len); |
| 171 | self.globals_lookup = try allocator.alloc(i64, self.in_symtab.?.len); | 174 | self.globals_lookup = try allocator.alloc(i64, self.in_symtab.?.len); |
| 172 | self.atom_by_index_table = try allocator.alloc(AtomIndex, self.in_symtab.?.len + nsects); | 175 | self.atom_by_index_table = try allocator.alloc(AtomIndex, self.in_symtab.?.len + nsects); |
| 173 | self.relocs_lookup = try allocator.alloc(RelocEntry, self.in_symtab.?.len + nsects); | 176 | self.relocs_lookup = try allocator.alloc(Entry, self.in_symtab.?.len + nsects); |
| 174 | // This is wasteful but we need to be able to lookup source symbol address after stripping and | 177 | // This is wasteful but we need to be able to lookup source symbol address after stripping and |
| 175 | // allocating of sections. | 178 | // allocating of sections. |
| 176 | self.source_address_lookup = try allocator.alloc(i64, self.in_symtab.?.len); | 179 | self.source_address_lookup = try allocator.alloc(i64, self.in_symtab.?.len); |
| 177 | self.source_section_index_lookup = try allocator.alloc(i64, nsects); | 180 | self.source_section_index_lookup = try allocator.alloc(Entry, nsects); |
| 178 | 181 | ||
| 179 | for (self.symtab) |*sym| { | 182 | for (self.symtab) |*sym| { |
| 180 | sym.* = .{ | 183 | sym.* = .{ |
| ... | @@ -188,11 +191,8 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) | ... | @@ -188,11 +191,8 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) |
| 188 | 191 | ||
| 189 | mem.set(i64, self.globals_lookup, -1); | 192 | mem.set(i64, self.globals_lookup, -1); |
| 190 | mem.set(AtomIndex, self.atom_by_index_table, 0); | 193 | mem.set(AtomIndex, self.atom_by_index_table, 0); |
| 191 | mem.set(i64, self.source_section_index_lookup, -1); | 194 | mem.set(Entry, self.source_section_index_lookup, .{}); |
| 192 | mem.set(RelocEntry, self.relocs_lookup, .{ | 195 | mem.set(Entry, self.relocs_lookup, .{}); |
| 193 | .start = 0, | ||
| 194 | .len = 0, | ||
| 195 | }); | ||
| 196 | 196 | ||
| 197 | // You would expect that the symbol table is at least pre-sorted based on symbol's type: | 197 | // You would expect that the symbol table is at least pre-sorted based on symbol's type: |
| 198 | // local < extern defined < undefined. Unfortunately, this is not guaranteed! For instance, | 198 | // local < extern defined < undefined. Unfortunately, this is not guaranteed! For instance, |
| ... | @@ -211,12 +211,24 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) | ... | @@ -211,12 +211,24 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) |
| 211 | // is kind enough to specify the symbols in the correct order. | 211 | // is kind enough to specify the symbols in the correct order. |
| 212 | sort.sort(SymbolAtIndex, sorted_all_syms.items, self, SymbolAtIndex.lessThan); | 212 | sort.sort(SymbolAtIndex, sorted_all_syms.items, self, SymbolAtIndex.lessThan); |
| 213 | 213 | ||
| 214 | var prev_sect_id: u8 = 0; | ||
| 215 | var section_index_lookup: ?Entry = null; | ||
| 214 | for (sorted_all_syms.items, 0..) |sym_id, i| { | 216 | for (sorted_all_syms.items, 0..) |sym_id, i| { |
| 215 | const sym = sym_id.getSymbol(self); | 217 | const sym = sym_id.getSymbol(self); |
| 216 | 218 | ||
| 217 | if (sym.sect() and self.source_section_index_lookup[sym.n_sect - 1] == -1) { | 219 | if (section_index_lookup) |*lookup| { |
| 218 | self.source_section_index_lookup[sym.n_sect - 1] = @intCast(i64, i); | 220 | if (sym.n_sect != prev_sect_id or sym.undf()) { |
| 221 | self.source_section_index_lookup[prev_sect_id - 1] = lookup.*; | ||
| 222 | section_index_lookup = null; | ||
| 223 | } else { | ||
| 224 | lookup.len += 1; | ||
| 225 | } | ||
| 219 | } | 226 | } |
| 227 | if (sym.sect() and section_index_lookup == null) { | ||
| 228 | section_index_lookup = .{ .start = @intCast(u32, i), .len = 1 }; | ||
| 229 | } | ||
| 230 | |||
| 231 | prev_sect_id = sym.n_sect; | ||
| 220 | 232 | ||
| 221 | self.symtab[i] = sym; | 233 | self.symtab[i] = sym; |
| 222 | self.source_symtab_lookup[i] = sym_id.index; | 234 | self.source_symtab_lookup[i] = sym_id.index; |
| ... | @@ -227,6 +239,12 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) | ... | @@ -227,6 +239,12 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) |
| 227 | self.strtab_lookup[i] = @intCast(u32, sym_name_len); | 239 | self.strtab_lookup[i] = @intCast(u32, sym_name_len); |
| 228 | } | 240 | } |
| 229 | 241 | ||
| 242 | // If there were no undefined symbols, make sure we populate the | ||
| 243 | // source section index lookup for the last scanned section. | ||
| 244 | if (section_index_lookup) |lookup| { | ||
| 245 | self.source_section_index_lookup[prev_sect_id - 1] = lookup; | ||
| 246 | } | ||
| 247 | |||
| 230 | // Parse __TEXT,__eh_frame header if one exists | 248 | // Parse __TEXT,__eh_frame header if one exists |
| 231 | self.eh_frame_sect_id = self.getSourceSectionIndexByName("__TEXT", "__eh_frame"); | 249 | self.eh_frame_sect_id = self.getSourceSectionIndexByName("__TEXT", "__eh_frame"); |
| 232 | 250 | ||
| ... | @@ -234,13 +252,7 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) | ... | @@ -234,13 +252,7 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) |
| 234 | self.unwind_info_sect_id = self.getSourceSectionIndexByName("__LD", "__compact_unwind"); | 252 | self.unwind_info_sect_id = self.getSourceSectionIndexByName("__LD", "__compact_unwind"); |
| 235 | if (self.hasUnwindRecords()) { | 253 | if (self.hasUnwindRecords()) { |
| 236 | self.unwind_relocs_lookup = try allocator.alloc(Record, self.getUnwindRecords().len); | 254 | self.unwind_relocs_lookup = try allocator.alloc(Record, self.getUnwindRecords().len); |
| 237 | mem.set(Record, self.unwind_relocs_lookup, .{ | 255 | mem.set(Record, self.unwind_relocs_lookup, .{ .dead = true, .reloc = .{} }); |
| 238 | .dead = true, | ||
| 239 | .reloc = .{ | ||
| 240 | .start = 0, | ||
| 241 | .len = 0, | ||
| 242 | }, | ||
| 243 | }); | ||
| 244 | } | 256 | } |
| 245 | } | 257 | } |
| 246 | 258 | ||
| ... | @@ -620,7 +632,7 @@ fn filterRelocs( | ... | @@ -620,7 +632,7 @@ fn filterRelocs( |
| 620 | relocs: []align(1) const macho.relocation_info, | 632 | relocs: []align(1) const macho.relocation_info, |
| 621 | start_addr: u64, | 633 | start_addr: u64, |
| 622 | end_addr: u64, | 634 | end_addr: u64, |
| 623 | ) RelocEntry { | 635 | ) Entry { |
| 624 | const Predicate = struct { | 636 | const Predicate = struct { |
| 625 | addr: u64, | 637 | addr: u64, |
| 626 | 638 | ||
| ... | @@ -712,9 +724,9 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void { | ... | @@ -712,9 +724,9 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void { |
| 712 | 724 | ||
| 713 | while (try it.next()) |record| { | 725 | while (try it.next()) |record| { |
| 714 | const offset = it.pos - record.getSize(); | 726 | const offset = it.pos - record.getSize(); |
| 715 | const rel_pos = switch (cpu_arch) { | 727 | const rel_pos: Entry = switch (cpu_arch) { |
| 716 | .aarch64 => filterRelocs(relocs, offset, offset + record.getSize()), | 728 | .aarch64 => filterRelocs(relocs, offset, offset + record.getSize()), |
| 717 | .x86_64 => RelocEntry{ .start = 0, .len = 0 }, | 729 | .x86_64 => .{}, |
| 718 | else => unreachable, | 730 | else => unreachable, |
| 719 | }; | 731 | }; |
| 720 | self.eh_frame_relocs_lookup.putAssumeCapacityNoClobber(offset, .{ | 732 | self.eh_frame_relocs_lookup.putAssumeCapacityNoClobber(offset, .{ |
| ... | @@ -729,13 +741,12 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void { | ... | @@ -729,13 +741,12 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void { |
| 729 | assert(rel_pos.len > 0); // TODO convert to an error as the FDE eh frame is malformed | 741 | assert(rel_pos.len > 0); // TODO convert to an error as the FDE eh frame is malformed |
| 730 | // Find function symbol that this record describes | 742 | // Find function symbol that this record describes |
| 731 | const rel = relocs[rel_pos.start..][rel_pos.len - 1]; | 743 | const rel = relocs[rel_pos.start..][rel_pos.len - 1]; |
| 732 | const target = UnwindInfo.parseRelocTarget( | 744 | const target = Atom.parseRelocTarget(zld, .{ |
| 733 | zld, | 745 | .object_id = object_id, |
| 734 | object_id, | 746 | .rel = rel, |
| 735 | rel, | 747 | .code = it.data[offset..], |
| 736 | it.data[offset..], | 748 | .base_offset = @intCast(i32, offset), |
| 737 | @intCast(i32, offset), | 749 | }); |
| 738 | ); | ||
| 739 | break :blk target; | 750 | break :blk target; |
| 740 | }, | 751 | }, |
| 741 | .x86_64 => { | 752 | .x86_64 => { |
| ... | @@ -819,13 +830,12 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void { | ... | @@ -819,13 +830,12 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void { |
| 819 | 830 | ||
| 820 | // Find function symbol that this record describes | 831 | // Find function symbol that this record describes |
| 821 | const rel = relocs[rel_pos.start..][rel_pos.len - 1]; | 832 | const rel = relocs[rel_pos.start..][rel_pos.len - 1]; |
| 822 | const target = UnwindInfo.parseRelocTarget( | 833 | const target = Atom.parseRelocTarget(zld, .{ |
| 823 | zld, | 834 | .object_id = object_id, |
| 824 | object_id, | 835 | .rel = rel, |
| 825 | rel, | 836 | .code = mem.asBytes(&record), |
| 826 | mem.asBytes(&record), | 837 | .base_offset = @intCast(i32, offset), |
| 827 | @intCast(i32, offset), | 838 | }); |
| 828 | ); | ||
| 829 | log.debug("unwind record {d} tracks {s}", .{ record_id, zld.getSymbolName(target) }); | 839 | log.debug("unwind record {d} tracks {s}", .{ record_id, zld.getSymbolName(target) }); |
| 830 | if (target.getFile() != object_id) { | 840 | if (target.getFile() != object_id) { |
| 831 | self.unwind_relocs_lookup[record_id].dead = true; | 841 | self.unwind_relocs_lookup[record_id].dead = true; |
| ... | @@ -990,13 +1000,15 @@ pub fn getSymbolByAddress(self: Object, addr: u64, sect_hint: ?u8) u32 { | ... | @@ -990,13 +1000,15 @@ pub fn getSymbolByAddress(self: Object, addr: u64, sect_hint: ?u8) u32 { |
| 990 | }; | 1000 | }; |
| 991 | 1001 | ||
| 992 | if (sect_hint) |sect_id| { | 1002 | if (sect_hint) |sect_id| { |
| 993 | if (self.source_section_index_lookup[sect_id] > -1) { | 1003 | if (self.source_section_index_lookup[sect_id].len > 0) { |
| 994 | const first_sym_index = @intCast(usize, self.source_section_index_lookup[sect_id]); | 1004 | const lookup = self.source_section_index_lookup[sect_id]; |
| 995 | const target_sym_index = @import("zld.zig").lsearch(i64, self.source_address_lookup[first_sym_index..], Predicate{ | 1005 | const target_sym_index = @import("zld.zig").lsearch( |
| 996 | .addr = @intCast(i64, addr), | 1006 | i64, |
| 997 | }); | 1007 | self.source_address_lookup[lookup.start..][0..lookup.len], |
| 1008 | Predicate{ .addr = @intCast(i64, addr) }, | ||
| 1009 | ); | ||
| 998 | if (target_sym_index > 0) { | 1010 | if (target_sym_index > 0) { |
| 999 | return @intCast(u32, first_sym_index + target_sym_index - 1); | 1011 | return @intCast(u32, lookup.start + target_sym_index - 1); |
| 1000 | } | 1012 | } |
| 1001 | } | 1013 | } |
| 1002 | return self.getSectionAliasSymbolIndex(sect_id); | 1014 | return self.getSectionAliasSymbolIndex(sect_id); |
src/link/MachO/UnwindInfo.zig+18-56| ... | @@ -218,13 +218,12 @@ pub fn scanRelocs(zld: *Zld) !void { | ... | @@ -218,13 +218,12 @@ pub fn scanRelocs(zld: *Zld) !void { |
| 218 | record_id, | 218 | record_id, |
| 219 | )) |rel| { | 219 | )) |rel| { |
| 220 | // Personality function; add GOT pointer. | 220 | // Personality function; add GOT pointer. |
| 221 | const target = parseRelocTarget( | 221 | const target = Atom.parseRelocTarget(zld, .{ |
| 222 | zld, | 222 | .object_id = @intCast(u32, object_id), |
| 223 | @intCast(u32, object_id), | 223 | .rel = rel, |
| 224 | rel, | 224 | .code = mem.asBytes(&record), |
| 225 | mem.asBytes(&record), | 225 | .base_offset = @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), |
| 226 | @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), | 226 | }); |
| 227 | ); | ||
| 228 | try Atom.addGotEntry(zld, target); | 227 | try Atom.addGotEntry(zld, target); |
| 229 | } | 228 | } |
| 230 | } | 229 | } |
| ... | @@ -266,13 +265,12 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void { | ... | @@ -266,13 +265,12 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void { |
| 266 | @intCast(u32, object_id), | 265 | @intCast(u32, object_id), |
| 267 | record_id, | 266 | record_id, |
| 268 | )) |rel| { | 267 | )) |rel| { |
| 269 | const target = parseRelocTarget( | 268 | const target = Atom.parseRelocTarget(zld, .{ |
| 270 | zld, | 269 | .object_id = @intCast(u32, object_id), |
| 271 | @intCast(u32, object_id), | 270 | .rel = rel, |
| 272 | rel, | 271 | .code = mem.asBytes(&record), |
| 273 | mem.asBytes(&record), | 272 | .base_offset = @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), |
| 274 | @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), | 273 | }); |
| 275 | ); | ||
| 276 | const personality_index = info.getPersonalityFunction(target) orelse inner: { | 274 | const personality_index = info.getPersonalityFunction(target) orelse inner: { |
| 277 | const personality_index = info.personalities_count; | 275 | const personality_index = info.personalities_count; |
| 278 | info.personalities[personality_index] = target; | 276 | info.personalities[personality_index] = target; |
| ... | @@ -285,13 +283,12 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void { | ... | @@ -285,13 +283,12 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void { |
| 285 | } | 283 | } |
| 286 | 284 | ||
| 287 | if (getLsdaReloc(zld, @intCast(u32, object_id), record_id)) |rel| { | 285 | if (getLsdaReloc(zld, @intCast(u32, object_id), record_id)) |rel| { |
| 288 | const target = parseRelocTarget( | 286 | const target = Atom.parseRelocTarget(zld, .{ |
| 289 | zld, | 287 | .object_id = @intCast(u32, object_id), |
| 290 | @intCast(u32, object_id), | 288 | .rel = rel, |
| 291 | rel, | 289 | .code = mem.asBytes(&record), |
| 292 | mem.asBytes(&record), | 290 | .base_offset = @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), |
| 293 | @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), | 291 | }); |
| 294 | ); | ||
| 295 | record.lsda = @bitCast(u64, target); | 292 | record.lsda = @bitCast(u64, target); |
| 296 | } | 293 | } |
| 297 | } | 294 | } |
| ... | @@ -668,41 +665,6 @@ pub fn write(info: *UnwindInfo, zld: *Zld) !void { | ... | @@ -668,41 +665,6 @@ pub fn write(info: *UnwindInfo, zld: *Zld) !void { |
| 668 | try zld.file.pwriteAll(buffer.items, sect.offset); | 665 | try zld.file.pwriteAll(buffer.items, sect.offset); |
| 669 | } | 666 | } |
| 670 | 667 | ||
| 671 | pub fn parseRelocTarget( | ||
| 672 | zld: *Zld, | ||
| 673 | object_id: u32, | ||
| 674 | rel: macho.relocation_info, | ||
| 675 | code: []const u8, | ||
| 676 | base_offset: i32, | ||
| 677 | ) SymbolWithLoc { | ||
| 678 | const tracy = trace(@src()); | ||
| 679 | defer tracy.end(); | ||
| 680 | |||
| 681 | const object = &zld.objects.items[object_id]; | ||
| 682 | |||
| 683 | const sym_index = if (rel.r_extern == 0) blk: { | ||
| 684 | const sect_id = @intCast(u8, rel.r_symbolnum - 1); | ||
| 685 | const rel_offset = @intCast(u32, rel.r_address - base_offset); | ||
| 686 | assert(rel.r_pcrel == 0 and rel.r_length == 3); | ||
| 687 | const address_in_section = mem.readIntLittle(u64, code[rel_offset..][0..8]); | ||
| 688 | const sym_index = object.getSymbolByAddress(address_in_section, sect_id); | ||
| 689 | break :blk sym_index; | ||
| 690 | } else object.reverse_symtab_lookup[rel.r_symbolnum]; | ||
| 691 | |||
| 692 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = object_id + 1 }; | ||
| 693 | const sym = zld.getSymbol(sym_loc); | ||
| 694 | |||
| 695 | if (sym.sect() and !sym.ext()) { | ||
| 696 | // Make sure we are not dealing with a local alias. | ||
| 697 | const atom_index = object.getAtomIndexForSymbol(sym_index) orelse | ||
| 698 | return sym_loc; | ||
| 699 | const atom = zld.getAtom(atom_index); | ||
| 700 | return atom.getSymbolWithLoc(); | ||
| 701 | } else if (object.getGlobal(sym_index)) |global_index| { | ||
| 702 | return zld.globals.items[global_index]; | ||
| 703 | } else return sym_loc; | ||
| 704 | } | ||
| 705 | |||
| 706 | fn getRelocs(zld: *Zld, object_id: u32, record_id: usize) []const macho.relocation_info { | 668 | fn getRelocs(zld: *Zld, object_id: u32, record_id: usize) []const macho.relocation_info { |
| 707 | const object = &zld.objects.items[object_id]; | 669 | const object = &zld.objects.items[object_id]; |
| 708 | assert(object.hasUnwindRecords()); | 670 | assert(object.hasUnwindRecords()); |
src/link/MachO/ZldAtom.zig+76-34| ... | @@ -15,6 +15,7 @@ const macho = std.macho; | ... | @@ -15,6 +15,7 @@ const macho = std.macho; |
| 15 | const math = std.math; | 15 | const math = std.math; |
| 16 | const mem = std.mem; | 16 | const mem = std.mem; |
| 17 | const meta = std.meta; | 17 | const meta = std.meta; |
| 18 | const trace = @import("../../tracy.zig").trace; | ||
| 18 | 19 | ||
| 19 | const Allocator = mem.Allocator; | 20 | const Allocator = mem.Allocator; |
| 20 | const Arch = std.Target.Cpu.Arch; | 21 | const Arch = std.Target.Cpu.Arch; |
| ... | @@ -163,7 +164,7 @@ pub fn scanAtomRelocs(zld: *Zld, atom_index: AtomIndex, relocs: []align(1) const | ... | @@ -163,7 +164,7 @@ pub fn scanAtomRelocs(zld: *Zld, atom_index: AtomIndex, relocs: []align(1) const |
| 163 | } | 164 | } |
| 164 | 165 | ||
| 165 | const RelocContext = struct { | 166 | const RelocContext = struct { |
| 166 | base_addr: u64 = 0, | 167 | base_addr: i64 = 0, |
| 167 | base_offset: i32 = 0, | 168 | base_offset: i32 = 0, |
| 168 | }; | 169 | }; |
| 169 | 170 | ||
| ... | @@ -175,7 +176,7 @@ pub fn getRelocContext(zld: *Zld, atom_index: AtomIndex) RelocContext { | ... | @@ -175,7 +176,7 @@ pub fn getRelocContext(zld: *Zld, atom_index: AtomIndex) RelocContext { |
| 175 | if (object.getSourceSymbol(atom.sym_index)) |source_sym| { | 176 | if (object.getSourceSymbol(atom.sym_index)) |source_sym| { |
| 176 | const source_sect = object.getSourceSection(source_sym.n_sect - 1); | 177 | const source_sect = object.getSourceSection(source_sym.n_sect - 1); |
| 177 | return .{ | 178 | return .{ |
| 178 | .base_addr = source_sect.addr, | 179 | .base_addr = @intCast(i64, source_sect.addr), |
| 179 | .base_offset = @intCast(i32, source_sym.n_value - source_sect.addr), | 180 | .base_offset = @intCast(i32, source_sym.n_value - source_sect.addr), |
| 180 | }; | 181 | }; |
| 181 | } | 182 | } |
| ... | @@ -183,55 +184,71 @@ pub fn getRelocContext(zld: *Zld, atom_index: AtomIndex) RelocContext { | ... | @@ -183,55 +184,71 @@ pub fn getRelocContext(zld: *Zld, atom_index: AtomIndex) RelocContext { |
| 183 | const sect_id = @intCast(u8, atom.sym_index - nbase); | 184 | const sect_id = @intCast(u8, atom.sym_index - nbase); |
| 184 | const source_sect = object.getSourceSection(sect_id); | 185 | const source_sect = object.getSourceSection(sect_id); |
| 185 | return .{ | 186 | return .{ |
| 186 | .base_addr = source_sect.addr, | 187 | .base_addr = @intCast(i64, source_sect.addr), |
| 187 | .base_offset = 0, | 188 | .base_offset = 0, |
| 188 | }; | 189 | }; |
| 189 | } | 190 | } |
| 190 | 191 | ||
| 191 | pub fn parseRelocTarget(zld: *Zld, atom_index: AtomIndex, rel: macho.relocation_info) SymbolWithLoc { | 192 | pub fn parseRelocTarget(zld: *Zld, ctx: struct { |
| 192 | const atom = zld.getAtom(atom_index); | 193 | object_id: u32, |
| 193 | const object = &zld.objects.items[atom.getFile().?]; | 194 | rel: macho.relocation_info, |
| 195 | code: []const u8, | ||
| 196 | base_addr: i64 = 0, | ||
| 197 | base_offset: i32 = 0, | ||
| 198 | }) SymbolWithLoc { | ||
| 199 | const tracy = trace(@src()); | ||
| 200 | defer tracy.end(); | ||
| 194 | 201 | ||
| 195 | const sym_index = if (rel.r_extern == 0) sym_index: { | 202 | const object = &zld.objects.items[ctx.object_id]; |
| 196 | const sect_id = @intCast(u8, rel.r_symbolnum - 1); | 203 | log.debug("parsing reloc target in object({d}) '{s}' ", .{ ctx.object_id, object.name }); |
| 197 | const ctx = getRelocContext(zld, atom_index); | ||
| 198 | const atom_code = getAtomCode(zld, atom_index); | ||
| 199 | const rel_offset = @intCast(u32, rel.r_address - ctx.base_offset); | ||
| 200 | 204 | ||
| 201 | const address_in_section = if (rel.r_pcrel == 0) blk: { | 205 | const sym_index = if (ctx.rel.r_extern == 0) sym_index: { |
| 202 | break :blk if (rel.r_length == 3) | 206 | const sect_id = @intCast(u8, ctx.rel.r_symbolnum - 1); |
| 203 | mem.readIntLittle(u64, atom_code[rel_offset..][0..8]) | 207 | const rel_offset = @intCast(u32, ctx.rel.r_address - ctx.base_offset); |
| 208 | |||
| 209 | const address_in_section = if (ctx.rel.r_pcrel == 0) blk: { | ||
| 210 | break :blk if (ctx.rel.r_length == 3) | ||
| 211 | mem.readIntLittle(u64, ctx.code[rel_offset..][0..8]) | ||
| 204 | else | 212 | else |
| 205 | mem.readIntLittle(u32, atom_code[rel_offset..][0..4]); | 213 | mem.readIntLittle(u32, ctx.code[rel_offset..][0..4]); |
| 206 | } else blk: { | 214 | } else blk: { |
| 207 | const correction: u3 = switch (@intToEnum(macho.reloc_type_x86_64, rel.r_type)) { | 215 | assert(zld.options.target.cpu.arch == .x86_64); |
| 216 | const correction: u3 = switch (@intToEnum(macho.reloc_type_x86_64, ctx.rel.r_type)) { | ||
| 208 | .X86_64_RELOC_SIGNED => 0, | 217 | .X86_64_RELOC_SIGNED => 0, |
| 209 | .X86_64_RELOC_SIGNED_1 => 1, | 218 | .X86_64_RELOC_SIGNED_1 => 1, |
| 210 | .X86_64_RELOC_SIGNED_2 => 2, | 219 | .X86_64_RELOC_SIGNED_2 => 2, |
| 211 | .X86_64_RELOC_SIGNED_4 => 4, | 220 | .X86_64_RELOC_SIGNED_4 => 4, |
| 212 | else => unreachable, | 221 | else => unreachable, |
| 213 | }; | 222 | }; |
| 214 | const addend = mem.readIntLittle(i32, atom_code[rel_offset..][0..4]); | 223 | const addend = mem.readIntLittle(i32, ctx.code[rel_offset..][0..4]); |
| 215 | const target_address = @intCast(i64, ctx.base_addr) + rel.r_address + 4 + correction + addend; | 224 | const target_address = @intCast(i64, ctx.base_addr) + ctx.rel.r_address + 4 + correction + addend; |
| 216 | break :blk @intCast(u64, target_address); | 225 | break :blk @intCast(u64, target_address); |
| 217 | }; | 226 | }; |
| 218 | 227 | ||
| 219 | // Find containing atom | 228 | // Find containing atom |
| 229 | log.debug(" | locating symbol by address @{x} in section {d}", .{ address_in_section, sect_id }); | ||
| 220 | const sym_index = object.getSymbolByAddress(address_in_section, sect_id); | 230 | const sym_index = object.getSymbolByAddress(address_in_section, sect_id); |
| 221 | break :sym_index sym_index; | 231 | break :sym_index sym_index; |
| 222 | } else object.reverse_symtab_lookup[rel.r_symbolnum]; | 232 | } else object.reverse_symtab_lookup[ctx.rel.r_symbolnum]; |
| 223 | 233 | ||
| 224 | const sym_loc = SymbolWithLoc{ | 234 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = ctx.object_id + 1 }; |
| 225 | .sym_index = sym_index, | ||
| 226 | .file = atom.file, | ||
| 227 | }; | ||
| 228 | const sym = zld.getSymbol(sym_loc); | 235 | const sym = zld.getSymbol(sym_loc); |
| 229 | 236 | const target = target: { | |
| 230 | if (sym.sect() and !sym.ext()) { | 237 | if (sym.sect() and !sym.ext()) { |
| 231 | return sym_loc; | 238 | // Make sure we are not dealing with a local alias. |
| 232 | } else if (object.getGlobal(sym_index)) |global_index| { | 239 | const atom_index = object.getAtomIndexForSymbol(sym_index) orelse break :target sym_loc; |
| 233 | return zld.globals.items[global_index]; | 240 | const atom = zld.getAtom(atom_index); |
| 234 | } else return sym_loc; | 241 | break :target atom.getSymbolWithLoc(); |
| 242 | } else if (object.getGlobal(sym_index)) |global_index| { | ||
| 243 | break :target zld.globals.items[global_index]; | ||
| 244 | } else break :target sym_loc; | ||
| 245 | }; | ||
| 246 | log.debug(" | target %{d} ('{s}') in object({?d})", .{ | ||
| 247 | target.sym_index, | ||
| 248 | zld.getSymbolName(target), | ||
| 249 | target.getFile(), | ||
| 250 | }); | ||
| 251 | return target; | ||
| 235 | } | 252 | } |
| 236 | 253 | ||
| 237 | pub fn getRelocTargetAtomIndex(zld: *Zld, target: SymbolWithLoc, is_via_got: bool) ?AtomIndex { | 254 | pub fn getRelocTargetAtomIndex(zld: *Zld, target: SymbolWithLoc, is_via_got: bool) ?AtomIndex { |
| ... | @@ -499,13 +516,25 @@ fn resolveRelocsArm64( | ... | @@ -499,13 +516,25 @@ fn resolveRelocsArm64( |
| 499 | atom.getFile(), | 516 | atom.getFile(), |
| 500 | }); | 517 | }); |
| 501 | 518 | ||
| 502 | subtractor = parseRelocTarget(zld, atom_index, rel); | 519 | subtractor = parseRelocTarget(zld, .{ |
| 520 | .object_id = atom.getFile().?, | ||
| 521 | .rel = rel, | ||
| 522 | .code = atom_code, | ||
| 523 | .base_addr = context.base_addr, | ||
| 524 | .base_offset = context.base_offset, | ||
| 525 | }); | ||
| 503 | continue; | 526 | continue; |
| 504 | }, | 527 | }, |
| 505 | else => {}, | 528 | else => {}, |
| 506 | } | 529 | } |
| 507 | 530 | ||
| 508 | const target = parseRelocTarget(zld, atom_index, rel); | 531 | const target = parseRelocTarget(zld, .{ |
| 532 | .object_id = atom.getFile().?, | ||
| 533 | .rel = rel, | ||
| 534 | .code = atom_code, | ||
| 535 | .base_addr = context.base_addr, | ||
| 536 | .base_offset = context.base_offset, | ||
| 537 | }); | ||
| 509 | const rel_offset = @intCast(u32, rel.r_address - context.base_offset); | 538 | const rel_offset = @intCast(u32, rel.r_address - context.base_offset); |
| 510 | 539 | ||
| 511 | log.debug(" RELA({s}) @ {x} => %{d} ('{s}') in object({?})", .{ | 540 | log.debug(" RELA({s}) @ {x} => %{d} ('{s}') in object({?})", .{ |
| ... | @@ -781,19 +810,32 @@ fn resolveRelocsX86( | ... | @@ -781,19 +810,32 @@ fn resolveRelocsX86( |
| 781 | atom.getFile(), | 810 | atom.getFile(), |
| 782 | }); | 811 | }); |
| 783 | 812 | ||
| 784 | subtractor = parseRelocTarget(zld, atom_index, rel); | 813 | subtractor = parseRelocTarget(zld, .{ |
| 814 | .object_id = atom.getFile().?, | ||
| 815 | .rel = rel, | ||
| 816 | .code = atom_code, | ||
| 817 | .base_addr = context.base_addr, | ||
| 818 | .base_offset = context.base_offset, | ||
| 819 | }); | ||
| 785 | continue; | 820 | continue; |
| 786 | }, | 821 | }, |
| 787 | else => {}, | 822 | else => {}, |
| 788 | } | 823 | } |
| 789 | 824 | ||
| 790 | const target = parseRelocTarget(zld, atom_index, rel); | 825 | const target = parseRelocTarget(zld, .{ |
| 826 | .object_id = atom.getFile().?, | ||
| 827 | .rel = rel, | ||
| 828 | .code = atom_code, | ||
| 829 | .base_addr = context.base_addr, | ||
| 830 | .base_offset = context.base_offset, | ||
| 831 | }); | ||
| 791 | const rel_offset = @intCast(u32, rel.r_address - context.base_offset); | 832 | const rel_offset = @intCast(u32, rel.r_address - context.base_offset); |
| 792 | 833 | ||
| 793 | log.debug(" RELA({s}) @ {x} => %{d} in object({?})", .{ | 834 | log.debug(" RELA({s}) @ {x} => %{d} ('{s}') in object({?})", .{ |
| 794 | @tagName(rel_type), | 835 | @tagName(rel_type), |
| 795 | rel.r_address, | 836 | rel.r_address, |
| 796 | target.sym_index, | 837 | target.sym_index, |
| 838 | zld.getSymbolName(target), | ||
| 797 | target.getFile(), | 839 | target.getFile(), |
| 798 | }); | 840 | }); |
| 799 | 841 |
src/link/MachO/dead_strip.zig+53-26| ... | @@ -102,7 +102,7 @@ fn collectRoots(zld: *Zld, roots: *AtomTable) !void { | ... | @@ -102,7 +102,7 @@ fn collectRoots(zld: *Zld, roots: *AtomTable) !void { |
| 102 | }; | 102 | }; |
| 103 | 103 | ||
| 104 | if (is_gc_root) { | 104 | if (is_gc_root) { |
| 105 | try roots.putNoClobber(atom_index, {}); | 105 | _ = try roots.getOrPut(atom_index); |
| 106 | 106 | ||
| 107 | log.debug("root(ATOM({d}, %{d}, {?d}))", .{ | 107 | log.debug("root(ATOM({d}, %{d}, {?d}))", .{ |
| 108 | atom_index, | 108 | atom_index, |
| ... | @@ -130,14 +130,29 @@ fn markLive(zld: *Zld, atom_index: AtomIndex, alive: *AtomTable) void { | ... | @@ -130,14 +130,29 @@ fn markLive(zld: *Zld, atom_index: AtomIndex, alive: *AtomTable) void { |
| 130 | const header = zld.sections.items(.header)[sym.n_sect - 1]; | 130 | const header = zld.sections.items(.header)[sym.n_sect - 1]; |
| 131 | if (header.isZerofill()) return; | 131 | if (header.isZerofill()) return; |
| 132 | 132 | ||
| 133 | const code = Atom.getAtomCode(zld, atom_index); | ||
| 133 | const relocs = Atom.getAtomRelocs(zld, atom_index); | 134 | const relocs = Atom.getAtomRelocs(zld, atom_index); |
| 135 | const ctx = Atom.getRelocContext(zld, atom_index); | ||
| 136 | |||
| 134 | for (relocs) |rel| { | 137 | for (relocs) |rel| { |
| 135 | const target = switch (cpu_arch) { | 138 | const target = switch (cpu_arch) { |
| 136 | .aarch64 => switch (@intToEnum(macho.reloc_type_arm64, rel.r_type)) { | 139 | .aarch64 => switch (@intToEnum(macho.reloc_type_arm64, rel.r_type)) { |
| 137 | .ARM64_RELOC_ADDEND => continue, | 140 | .ARM64_RELOC_ADDEND => continue, |
| 138 | else => Atom.parseRelocTarget(zld, atom_index, rel), | 141 | else => Atom.parseRelocTarget(zld, .{ |
| 142 | .object_id = atom.getFile().?, | ||
| 143 | .rel = rel, | ||
| 144 | .code = code, | ||
| 145 | .base_offset = ctx.base_offset, | ||
| 146 | .base_addr = ctx.base_addr, | ||
| 147 | }), | ||
| 139 | }, | 148 | }, |
| 140 | .x86_64 => Atom.parseRelocTarget(zld, atom_index, rel), | 149 | .x86_64 => Atom.parseRelocTarget(zld, .{ |
| 150 | .object_id = atom.getFile().?, | ||
| 151 | .rel = rel, | ||
| 152 | .code = code, | ||
| 153 | .base_offset = ctx.base_offset, | ||
| 154 | .base_addr = ctx.base_addr, | ||
| 155 | }), | ||
| 141 | else => unreachable, | 156 | else => unreachable, |
| 142 | }; | 157 | }; |
| 143 | const target_sym = zld.getSymbol(target); | 158 | const target_sym = zld.getSymbol(target); |
| ... | @@ -175,14 +190,29 @@ fn refersLive(zld: *Zld, atom_index: AtomIndex, alive: AtomTable) bool { | ... | @@ -175,14 +190,29 @@ fn refersLive(zld: *Zld, atom_index: AtomIndex, alive: AtomTable) bool { |
| 175 | const header = zld.sections.items(.header)[sym.n_sect - 1]; | 190 | const header = zld.sections.items(.header)[sym.n_sect - 1]; |
| 176 | assert(!header.isZerofill()); | 191 | assert(!header.isZerofill()); |
| 177 | 192 | ||
| 193 | const code = Atom.getAtomCode(zld, atom_index); | ||
| 178 | const relocs = Atom.getAtomRelocs(zld, atom_index); | 194 | const relocs = Atom.getAtomRelocs(zld, atom_index); |
| 195 | const ctx = Atom.getRelocContext(zld, atom_index); | ||
| 196 | |||
| 179 | for (relocs) |rel| { | 197 | for (relocs) |rel| { |
| 180 | const target = switch (cpu_arch) { | 198 | const target = switch (cpu_arch) { |
| 181 | .aarch64 => switch (@intToEnum(macho.reloc_type_arm64, rel.r_type)) { | 199 | .aarch64 => switch (@intToEnum(macho.reloc_type_arm64, rel.r_type)) { |
| 182 | .ARM64_RELOC_ADDEND => continue, | 200 | .ARM64_RELOC_ADDEND => continue, |
| 183 | else => Atom.parseRelocTarget(zld, atom_index, rel), | 201 | else => Atom.parseRelocTarget(zld, .{ |
| 202 | .object_id = atom.getFile().?, | ||
| 203 | .rel = rel, | ||
| 204 | .code = code, | ||
| 205 | .base_offset = ctx.base_offset, | ||
| 206 | .base_addr = ctx.base_addr, | ||
| 207 | }), | ||
| 184 | }, | 208 | }, |
| 185 | .x86_64 => Atom.parseRelocTarget(zld, atom_index, rel), | 209 | .x86_64 => Atom.parseRelocTarget(zld, .{ |
| 210 | .object_id = atom.getFile().?, | ||
| 211 | .rel = rel, | ||
| 212 | .code = code, | ||
| 213 | .base_offset = ctx.base_offset, | ||
| 214 | .base_addr = ctx.base_addr, | ||
| 215 | }), | ||
| 186 | else => unreachable, | 216 | else => unreachable, |
| 187 | }; | 217 | }; |
| 188 | 218 | ||
| ... | @@ -283,13 +313,12 @@ fn markUnwindRecords(zld: *Zld, object_id: u32, alive: *AtomTable) !void { | ... | @@ -283,13 +313,12 @@ fn markUnwindRecords(zld: *Zld, object_id: u32, alive: *AtomTable) !void { |
| 283 | try markEhFrameRecord(zld, object_id, atom_index, alive); | 313 | try markEhFrameRecord(zld, object_id, atom_index, alive); |
| 284 | } else { | 314 | } else { |
| 285 | if (UnwindInfo.getPersonalityFunctionReloc(zld, object_id, record_id)) |rel| { | 315 | if (UnwindInfo.getPersonalityFunctionReloc(zld, object_id, record_id)) |rel| { |
| 286 | const target = UnwindInfo.parseRelocTarget( | 316 | const target = Atom.parseRelocTarget(zld, .{ |
| 287 | zld, | 317 | .object_id = object_id, |
| 288 | object_id, | 318 | .rel = rel, |
| 289 | rel, | 319 | .code = mem.asBytes(&record), |
| 290 | mem.asBytes(&record), | 320 | .base_offset = @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), |
| 291 | @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), | 321 | }); |
| 292 | ); | ||
| 293 | const target_sym = zld.getSymbol(target); | 322 | const target_sym = zld.getSymbol(target); |
| 294 | if (!target_sym.undf()) { | 323 | if (!target_sym.undf()) { |
| 295 | const target_object = zld.objects.items[target.getFile().?]; | 324 | const target_object = zld.objects.items[target.getFile().?]; |
| ... | @@ -299,13 +328,12 @@ fn markUnwindRecords(zld: *Zld, object_id: u32, alive: *AtomTable) !void { | ... | @@ -299,13 +328,12 @@ fn markUnwindRecords(zld: *Zld, object_id: u32, alive: *AtomTable) !void { |
| 299 | } | 328 | } |
| 300 | 329 | ||
| 301 | if (UnwindInfo.getLsdaReloc(zld, object_id, record_id)) |rel| { | 330 | if (UnwindInfo.getLsdaReloc(zld, object_id, record_id)) |rel| { |
| 302 | const target = UnwindInfo.parseRelocTarget( | 331 | const target = Atom.parseRelocTarget(zld, .{ |
| 303 | zld, | 332 | .object_id = object_id, |
| 304 | object_id, | 333 | .rel = rel, |
| 305 | rel, | 334 | .code = mem.asBytes(&record), |
| 306 | mem.asBytes(&record), | 335 | .base_offset = @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), |
| 307 | @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), | 336 | }); |
| 308 | ); | ||
| 309 | const target_object = zld.objects.items[target.getFile().?]; | 337 | const target_object = zld.objects.items[target.getFile().?]; |
| 310 | const target_atom_index = target_object.getAtomIndexForSymbol(target.sym_index).?; | 338 | const target_atom_index = target_object.getAtomIndexForSymbol(target.sym_index).?; |
| 311 | markLive(zld, target_atom_index, alive); | 339 | markLive(zld, target_atom_index, alive); |
| ... | @@ -333,13 +361,12 @@ fn markEhFrameRecord(zld: *Zld, object_id: u32, atom_index: AtomIndex, alive: *A | ... | @@ -333,13 +361,12 @@ fn markEhFrameRecord(zld: *Zld, object_id: u32, atom_index: AtomIndex, alive: *A |
| 333 | // Mark FDE references which should include any referenced LSDA record | 361 | // Mark FDE references which should include any referenced LSDA record |
| 334 | const relocs = eh_frame.getRelocs(zld, object_id, fde_offset); | 362 | const relocs = eh_frame.getRelocs(zld, object_id, fde_offset); |
| 335 | for (relocs) |rel| { | 363 | for (relocs) |rel| { |
| 336 | const target = UnwindInfo.parseRelocTarget( | 364 | const target = Atom.parseRelocTarget(zld, .{ |
| 337 | zld, | 365 | .object_id = object_id, |
| 338 | object_id, | 366 | .rel = rel, |
| 339 | rel, | 367 | .code = fde.data, |
| 340 | fde.data, | 368 | .base_offset = @intCast(i32, fde_offset) + 4, |
| 341 | @intCast(i32, fde_offset) + 4, | 369 | }); |
| 342 | ); | ||
| 343 | const target_sym = zld.getSymbol(target); | 370 | const target_sym = zld.getSymbol(target); |
| 344 | if (!target_sym.undf()) blk: { | 371 | if (!target_sym.undf()) blk: { |
| 345 | const target_object = zld.objects.items[target.getFile().?]; | 372 | const target_object = zld.objects.items[target.getFile().?]; |
src/link/MachO/eh_frame.zig+12-14| ... | @@ -308,13 +308,12 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type { | ... | @@ -308,13 +308,12 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type { |
| 308 | }, | 308 | }, |
| 309 | else => unreachable, | 309 | else => unreachable, |
| 310 | } | 310 | } |
| 311 | const target = UnwindInfo.parseRelocTarget( | 311 | const target = Atom.parseRelocTarget(zld, .{ |
| 312 | zld, | 312 | .object_id = object_id, |
| 313 | object_id, | 313 | .rel = rel, |
| 314 | rel, | 314 | .code = rec.data, |
| 315 | rec.data, | 315 | .base_offset = @intCast(i32, source_offset) + 4, |
| 316 | @intCast(i32, source_offset) + 4, | 316 | }); |
| 317 | ); | ||
| 318 | return target; | 317 | return target; |
| 319 | } | 318 | } |
| 320 | return null; | 319 | return null; |
| ... | @@ -331,13 +330,12 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type { | ... | @@ -331,13 +330,12 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type { |
| 331 | const relocs = getRelocs(zld, object_id, ctx.source_offset); | 330 | const relocs = getRelocs(zld, object_id, ctx.source_offset); |
| 332 | 331 | ||
| 333 | for (relocs) |rel| { | 332 | for (relocs) |rel| { |
| 334 | const target = UnwindInfo.parseRelocTarget( | 333 | const target = Atom.parseRelocTarget(zld, .{ |
| 335 | zld, | 334 | .object_id = object_id, |
| 336 | object_id, | 335 | .rel = rel, |
| 337 | rel, | 336 | .code = rec.data, |
| 338 | rec.data, | 337 | .base_offset = @intCast(i32, ctx.source_offset) + 4, |
| 339 | @intCast(i32, ctx.source_offset) + 4, | 338 | }); |
| 340 | ); | ||
| 341 | const rel_offset = @intCast(u32, rel.r_address - @intCast(i32, ctx.source_offset) - 4); | 339 | const rel_offset = @intCast(u32, rel.r_address - @intCast(i32, ctx.source_offset) - 4); |
| 342 | const source_addr = ctx.sect_addr + rel_offset + ctx.out_offset + 4; | 340 | const source_addr = ctx.sect_addr + rel_offset + ctx.out_offset + 4; |
| 343 | 341 |
src/link/MachO/load_commands.zig+1-1| ... | @@ -294,7 +294,7 @@ pub fn writeBuildVersionLC(options: *const link.Options, lc_writer: anytype) !vo | ... | @@ -294,7 +294,7 @@ pub fn writeBuildVersionLC(options: *const link.Options, lc_writer: anytype) !vo |
| 294 | .ntools = 1, | 294 | .ntools = 1, |
| 295 | }); | 295 | }); |
| 296 | try lc_writer.writeAll(mem.asBytes(&macho.build_tool_version{ | 296 | try lc_writer.writeAll(mem.asBytes(&macho.build_tool_version{ |
| 297 | .tool = .LD, | 297 | .tool = .ZIG, |
| 298 | .version = 0x0, | 298 | .version = 0x0, |
| 299 | })); | 299 | })); |
| 300 | } | 300 | } |
src/link/MachO/thunks.zig+10-1| ... | @@ -225,11 +225,20 @@ fn scanRelocs( | ... | @@ -225,11 +225,20 @@ fn scanRelocs( |
| 225 | break :blk @intCast(i32, source_sym.n_value - source_sect.addr); | 225 | break :blk @intCast(i32, source_sym.n_value - source_sect.addr); |
| 226 | } else 0; | 226 | } else 0; |
| 227 | 227 | ||
| 228 | const code = Atom.getAtomCode(zld, atom_index); | ||
| 228 | const relocs = Atom.getAtomRelocs(zld, atom_index); | 229 | const relocs = Atom.getAtomRelocs(zld, atom_index); |
| 230 | const ctx = Atom.getRelocContext(zld, atom_index); | ||
| 231 | |||
| 229 | for (relocs) |rel| { | 232 | for (relocs) |rel| { |
| 230 | if (!relocNeedsThunk(rel)) continue; | 233 | if (!relocNeedsThunk(rel)) continue; |
| 231 | 234 | ||
| 232 | const target = Atom.parseRelocTarget(zld, atom_index, rel); | 235 | const target = Atom.parseRelocTarget(zld, .{ |
| 236 | .object_id = atom.getFile().?, | ||
| 237 | .rel = rel, | ||
| 238 | .code = code, | ||
| 239 | .base_offset = ctx.base_offset, | ||
| 240 | .base_addr = ctx.base_addr, | ||
| 241 | }); | ||
| 233 | if (isReachable(zld, atom_index, rel, base_offset, target, allocated)) continue; | 242 | if (isReachable(zld, atom_index, rel, base_offset, target, allocated)) continue; |
| 234 | 243 | ||
| 235 | log.debug("{x}: source = {s}@{x}, target = {s}@{x} unreachable", .{ | 244 | log.debug("{x}: source = {s}@{x}, target = {s}@{x} unreachable", .{ |
src/link/MachO/zld.zig+73-73| ... | @@ -477,9 +477,9 @@ pub const Zld = struct { | ... | @@ -477,9 +477,9 @@ pub const Zld = struct { |
| 477 | mem.eql(u8, sectname, "__gosymtab") or | 477 | mem.eql(u8, sectname, "__gosymtab") or |
| 478 | mem.eql(u8, sectname, "__gopclntab")) | 478 | mem.eql(u8, sectname, "__gopclntab")) |
| 479 | { | 479 | { |
| 480 | break :blk self.getSectionByName("__DATA_CONST", "__const") orelse try self.initSection( | 480 | break :blk self.getSectionByName("__TEXT", sectname) orelse try self.initSection( |
| 481 | "__DATA_CONST", | 481 | "__TEXT", |
| 482 | "__const", | 482 | sectname, |
| 483 | .{}, | 483 | .{}, |
| 484 | ); | 484 | ); |
| 485 | } | 485 | } |
| ... | @@ -490,15 +490,13 @@ pub const Zld = struct { | ... | @@ -490,15 +490,13 @@ pub const Zld = struct { |
| 490 | mem.eql(u8, sectname, "__objc_classlist") or | 490 | mem.eql(u8, sectname, "__objc_classlist") or |
| 491 | mem.eql(u8, sectname, "__objc_imageinfo")) | 491 | mem.eql(u8, sectname, "__objc_imageinfo")) |
| 492 | { | 492 | { |
| 493 | break :blk self.getSectionByName("__DATA_CONST", sectname) orelse | 493 | break :blk self.getSectionByName("__DATA_CONST", sectname) orelse try self.initSection( |
| 494 | try self.initSection( | ||
| 495 | "__DATA_CONST", | 494 | "__DATA_CONST", |
| 496 | sectname, | 495 | sectname, |
| 497 | .{}, | 496 | .{}, |
| 498 | ); | 497 | ); |
| 499 | } else if (mem.eql(u8, sectname, "__data")) { | 498 | } else if (mem.eql(u8, sectname, "__data")) { |
| 500 | break :blk self.getSectionByName("__DATA", "__data") orelse | 499 | break :blk self.getSectionByName("__DATA", "__data") orelse try self.initSection( |
| 501 | try self.initSection( | ||
| 502 | "__DATA", | 500 | "__DATA", |
| 503 | "__data", | 501 | "__data", |
| 504 | .{}, | 502 | .{}, |
| ... | @@ -1886,13 +1884,9 @@ pub const Zld = struct { | ... | @@ -1886,13 +1884,9 @@ pub const Zld = struct { |
| 1886 | if (should_rebase) { | 1884 | if (should_rebase) { |
| 1887 | log.debug(" ATOM({d}, %{d}, '{s}')", .{ atom_index, atom.sym_index, self.getSymbolName(atom.getSymbolWithLoc()) }); | 1885 | log.debug(" ATOM({d}, %{d}, '{s}')", .{ atom_index, atom.sym_index, self.getSymbolName(atom.getSymbolWithLoc()) }); |
| 1888 | 1886 | ||
| 1889 | const object = self.objects.items[atom.getFile().?]; | 1887 | const code = Atom.getAtomCode(self, atom_index); |
| 1890 | const base_rel_offset: i32 = blk: { | ||
| 1891 | const source_sym = object.getSourceSymbol(atom.sym_index) orelse break :blk 0; | ||
| 1892 | const source_sect = object.getSourceSection(source_sym.n_sect - 1); | ||
| 1893 | break :blk @intCast(i32, source_sym.n_value - source_sect.addr); | ||
| 1894 | }; | ||
| 1895 | const relocs = Atom.getAtomRelocs(self, atom_index); | 1888 | const relocs = Atom.getAtomRelocs(self, atom_index); |
| 1889 | const ctx = Atom.getRelocContext(self, atom_index); | ||
| 1896 | 1890 | ||
| 1897 | for (relocs) |rel| { | 1891 | for (relocs) |rel| { |
| 1898 | switch (cpu_arch) { | 1892 | switch (cpu_arch) { |
| ... | @@ -1908,12 +1902,18 @@ pub const Zld = struct { | ... | @@ -1908,12 +1902,18 @@ pub const Zld = struct { |
| 1908 | }, | 1902 | }, |
| 1909 | else => unreachable, | 1903 | else => unreachable, |
| 1910 | } | 1904 | } |
| 1911 | const target = Atom.parseRelocTarget(self, atom_index, rel); | 1905 | const target = Atom.parseRelocTarget(self, .{ |
| 1906 | .object_id = atom.getFile().?, | ||
| 1907 | .rel = rel, | ||
| 1908 | .code = code, | ||
| 1909 | .base_offset = ctx.base_offset, | ||
| 1910 | .base_addr = ctx.base_addr, | ||
| 1911 | }); | ||
| 1912 | const target_sym = self.getSymbol(target); | 1912 | const target_sym = self.getSymbol(target); |
| 1913 | if (target_sym.undf()) continue; | 1913 | if (target_sym.undf()) continue; |
| 1914 | 1914 | ||
| 1915 | const base_offset = @intCast(i32, sym.n_value - segment.vmaddr); | 1915 | const base_offset = @intCast(i32, sym.n_value - segment.vmaddr); |
| 1916 | const rel_offset = rel.r_address - base_rel_offset; | 1916 | const rel_offset = rel.r_address - ctx.base_offset; |
| 1917 | const offset = @intCast(u64, base_offset + rel_offset); | 1917 | const offset = @intCast(u64, base_offset + rel_offset); |
| 1918 | log.debug(" | rebase at {x}", .{offset}); | 1918 | log.debug(" | rebase at {x}", .{offset}); |
| 1919 | 1919 | ||
| ... | @@ -2023,13 +2023,9 @@ pub const Zld = struct { | ... | @@ -2023,13 +2023,9 @@ pub const Zld = struct { |
| 2023 | }; | 2023 | }; |
| 2024 | 2024 | ||
| 2025 | if (should_bind) { | 2025 | if (should_bind) { |
| 2026 | const object = self.objects.items[atom.getFile().?]; | 2026 | const code = Atom.getAtomCode(self, atom_index); |
| 2027 | const base_rel_offset: i32 = blk: { | ||
| 2028 | const source_sym = object.getSourceSymbol(atom.sym_index) orelse break :blk 0; | ||
| 2029 | const source_sect = object.getSourceSection(source_sym.n_sect - 1); | ||
| 2030 | break :blk @intCast(i32, source_sym.n_value - source_sect.addr); | ||
| 2031 | }; | ||
| 2032 | const relocs = Atom.getAtomRelocs(self, atom_index); | 2027 | const relocs = Atom.getAtomRelocs(self, atom_index); |
| 2028 | const ctx = Atom.getRelocContext(self, atom_index); | ||
| 2033 | 2029 | ||
| 2034 | for (relocs) |rel| { | 2030 | for (relocs) |rel| { |
| 2035 | switch (cpu_arch) { | 2031 | switch (cpu_arch) { |
| ... | @@ -2046,15 +2042,20 @@ pub const Zld = struct { | ... | @@ -2046,15 +2042,20 @@ pub const Zld = struct { |
| 2046 | else => unreachable, | 2042 | else => unreachable, |
| 2047 | } | 2043 | } |
| 2048 | 2044 | ||
| 2049 | const global = Atom.parseRelocTarget(self, atom_index, rel); | 2045 | const global = Atom.parseRelocTarget(self, .{ |
| 2046 | .object_id = atom.getFile().?, | ||
| 2047 | .rel = rel, | ||
| 2048 | .code = code, | ||
| 2049 | .base_offset = ctx.base_offset, | ||
| 2050 | .base_addr = ctx.base_addr, | ||
| 2051 | }); | ||
| 2050 | const bind_sym_name = self.getSymbolName(global); | 2052 | const bind_sym_name = self.getSymbolName(global); |
| 2051 | const bind_sym = self.getSymbol(global); | 2053 | const bind_sym = self.getSymbol(global); |
| 2052 | if (!bind_sym.undf()) continue; | 2054 | if (!bind_sym.undf()) continue; |
| 2053 | 2055 | ||
| 2054 | const base_offset = sym.n_value - segment.vmaddr; | 2056 | const base_offset = sym.n_value - segment.vmaddr; |
| 2055 | const rel_offset = @intCast(u32, rel.r_address - base_rel_offset); | 2057 | const rel_offset = @intCast(u32, rel.r_address - ctx.base_offset); |
| 2056 | const offset = @intCast(u64, base_offset + rel_offset); | 2058 | const offset = @intCast(u64, base_offset + rel_offset); |
| 2057 | const code = Atom.getAtomCode(self, atom_index); | ||
| 2058 | const addend = mem.readIntLittle(i64, code[rel_offset..][0..8]); | 2059 | const addend = mem.readIntLittle(i64, code[rel_offset..][0..8]); |
| 2059 | 2060 | ||
| 2060 | const dylib_ordinal = @divTrunc(@bitCast(i16, bind_sym.n_desc), macho.N_SYMBOL_RESOLVER); | 2061 | const dylib_ordinal = @divTrunc(@bitCast(i16, bind_sym.n_desc), macho.N_SYMBOL_RESOLVER); |
| ... | @@ -2143,43 +2144,24 @@ pub const Zld = struct { | ... | @@ -2143,43 +2144,24 @@ pub const Zld = struct { |
| 2143 | const exec_segment = self.segments.items[segment_index]; | 2144 | const exec_segment = self.segments.items[segment_index]; |
| 2144 | const base_address = exec_segment.vmaddr; | 2145 | const base_address = exec_segment.vmaddr; |
| 2145 | 2146 | ||
| 2146 | if (self.options.output_mode == .Exe) { | 2147 | for (self.globals.items) |global| { |
| 2147 | for (&[_]SymbolWithLoc{ | 2148 | const sym = self.getSymbol(global); |
| 2148 | self.getEntryPoint(), | 2149 | if (sym.undf()) continue; |
| 2149 | self.globals.items[self.mh_execute_header_index.?], | 2150 | if (sym.n_desc == N_DEAD) continue; |
| 2150 | }) |global| { | ||
| 2151 | const sym = self.getSymbol(global); | ||
| 2152 | const sym_name = self.getSymbolName(global); | ||
| 2153 | log.debug(" (putting '{s}' defined at 0x{x})", .{ sym_name, sym.n_value }); | ||
| 2154 | try trie.put(gpa, .{ | ||
| 2155 | .name = sym_name, | ||
| 2156 | .vmaddr_offset = sym.n_value - base_address, | ||
| 2157 | .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR, | ||
| 2158 | }); | ||
| 2159 | } | ||
| 2160 | } else { | ||
| 2161 | assert(self.options.output_mode == .Lib); | ||
| 2162 | for (self.globals.items) |global| { | ||
| 2163 | const sym = self.getSymbol(global); | ||
| 2164 | if (sym.undf()) continue; | ||
| 2165 | if (sym.n_desc == N_DEAD) continue; | ||
| 2166 | 2151 | ||
| 2167 | const sym_name = self.getSymbolName(global); | 2152 | const sym_name = self.getSymbolName(global); |
| 2168 | log.debug(" (putting '{s}' defined at 0x{x})", .{ sym_name, sym.n_value }); | 2153 | log.debug(" (putting '{s}' defined at 0x{x})", .{ sym_name, sym.n_value }); |
| 2169 | try trie.put(gpa, .{ | 2154 | try trie.put(gpa, .{ |
| 2170 | .name = sym_name, | 2155 | .name = sym_name, |
| 2171 | .vmaddr_offset = sym.n_value - base_address, | 2156 | .vmaddr_offset = sym.n_value - base_address, |
| 2172 | .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR, | 2157 | .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR, |
| 2173 | }); | 2158 | }); |
| 2174 | } | ||
| 2175 | } | 2159 | } |
| 2176 | 2160 | ||
| 2177 | try trie.finalize(gpa); | 2161 | try trie.finalize(gpa); |
| 2178 | } | 2162 | } |
| 2179 | 2163 | ||
| 2180 | fn writeDyldInfoData( | 2164 | fn writeDyldInfoData(self: *Zld) !void { |
| 2181 | self: *Zld, | ||
| 2182 | ) !void { | ||
| 2183 | const gpa = self.gpa; | 2165 | const gpa = self.gpa; |
| 2184 | 2166 | ||
| 2185 | var rebase = Rebase{}; | 2167 | var rebase = Rebase{}; |
| ... | @@ -2300,9 +2282,16 @@ pub const Zld = struct { | ... | @@ -2300,9 +2282,16 @@ pub const Zld = struct { |
| 2300 | 2282 | ||
| 2301 | const asc_u64 = std.sort.asc(u64); | 2283 | const asc_u64 = std.sort.asc(u64); |
| 2302 | 2284 | ||
| 2285 | fn addSymbolToFunctionStarts(self: *Zld, sym_loc: SymbolWithLoc, addresses: *std.ArrayList(u64)) !void { | ||
| 2286 | const sym = self.getSymbol(sym_loc); | ||
| 2287 | if (sym.n_strx == 0) return; | ||
| 2288 | if (sym.n_desc == N_DEAD) return; | ||
| 2289 | if (self.symbolIsTemp(sym_loc)) return; | ||
| 2290 | try addresses.append(sym.n_value); | ||
| 2291 | } | ||
| 2292 | |||
| 2303 | fn writeFunctionStarts(self: *Zld) !void { | 2293 | fn writeFunctionStarts(self: *Zld) !void { |
| 2304 | const text_seg_index = self.getSegmentByName("__TEXT") orelse return; | 2294 | const text_seg_index = self.getSegmentByName("__TEXT") orelse return; |
| 2305 | const text_sect_index = self.getSectionByName("__TEXT", "__text") orelse return; | ||
| 2306 | const text_seg = self.segments.items[text_seg_index]; | 2295 | const text_seg = self.segments.items[text_seg_index]; |
| 2307 | 2296 | ||
| 2308 | const gpa = self.gpa; | 2297 | const gpa = self.gpa; |
| ... | @@ -2310,17 +2299,18 @@ pub const Zld = struct { | ... | @@ -2310,17 +2299,18 @@ pub const Zld = struct { |
| 2310 | // We need to sort by address first | 2299 | // We need to sort by address first |
| 2311 | var addresses = std.ArrayList(u64).init(gpa); | 2300 | var addresses = std.ArrayList(u64).init(gpa); |
| 2312 | defer addresses.deinit(); | 2301 | defer addresses.deinit(); |
| 2313 | try addresses.ensureTotalCapacityPrecise(self.globals.items.len); | ||
| 2314 | |||
| 2315 | for (self.globals.items) |global| { | ||
| 2316 | const sym = self.getSymbol(global); | ||
| 2317 | if (sym.undf()) continue; | ||
| 2318 | if (sym.n_desc == N_DEAD) continue; | ||
| 2319 | 2302 | ||
| 2320 | const sect_id = sym.n_sect - 1; | 2303 | for (self.objects.items) |object| { |
| 2321 | if (sect_id != text_sect_index) continue; | 2304 | for (object.exec_atoms.items) |atom_index| { |
| 2305 | const atom = self.getAtom(atom_index); | ||
| 2306 | const sym_loc = atom.getSymbolWithLoc(); | ||
| 2307 | try self.addSymbolToFunctionStarts(sym_loc, &addresses); | ||
| 2322 | 2308 | ||
| 2323 | addresses.appendAssumeCapacity(sym.n_value); | 2309 | var it = Atom.getInnerSymbolsIterator(self, atom_index); |
| 2310 | while (it.next()) |inner_sym_loc| { | ||
| 2311 | try self.addSymbolToFunctionStarts(inner_sym_loc, &addresses); | ||
| 2312 | } | ||
| 2313 | } | ||
| 2324 | } | 2314 | } |
| 2325 | 2315 | ||
| 2326 | std.sort.sort(u64, addresses.items, {}, asc_u64); | 2316 | std.sort.sort(u64, addresses.items, {}, asc_u64); |
| ... | @@ -2456,6 +2446,18 @@ pub const Zld = struct { | ... | @@ -2456,6 +2446,18 @@ pub const Zld = struct { |
| 2456 | try self.writeStrtab(); | 2446 | try self.writeStrtab(); |
| 2457 | } | 2447 | } |
| 2458 | 2448 | ||
| 2449 | fn addLocalToSymtab(self: *Zld, sym_loc: SymbolWithLoc, locals: *std.ArrayList(macho.nlist_64)) !void { | ||
| 2450 | const sym = self.getSymbol(sym_loc); | ||
| 2451 | if (sym.n_strx == 0) return; // no name, skip | ||
| 2452 | if (sym.n_desc == N_DEAD) return; // garbage-collected, skip | ||
| 2453 | if (sym.ext()) return; // an export lands in its own symtab section, skip | ||
| 2454 | if (self.symbolIsTemp(sym_loc)) return; // local temp symbol, skip | ||
| 2455 | |||
| 2456 | var out_sym = sym; | ||
| 2457 | out_sym.n_strx = try self.strtab.insert(self.gpa, self.getSymbolName(sym_loc)); | ||
| 2458 | try locals.append(out_sym); | ||
| 2459 | } | ||
| 2460 | |||
| 2459 | fn writeSymtab(self: *Zld) !SymtabCtx { | 2461 | fn writeSymtab(self: *Zld) !SymtabCtx { |
| 2460 | const gpa = self.gpa; | 2462 | const gpa = self.gpa; |
| 2461 | 2463 | ||
| ... | @@ -2466,14 +2468,12 @@ pub const Zld = struct { | ... | @@ -2466,14 +2468,12 @@ pub const Zld = struct { |
| 2466 | for (object.atoms.items) |atom_index| { | 2468 | for (object.atoms.items) |atom_index| { |
| 2467 | const atom = self.getAtom(atom_index); | 2469 | const atom = self.getAtom(atom_index); |
| 2468 | const sym_loc = atom.getSymbolWithLoc(); | 2470 | const sym_loc = atom.getSymbolWithLoc(); |
| 2469 | const sym = self.getSymbol(sym_loc); | 2471 | try self.addLocalToSymtab(sym_loc, &locals); |
| 2470 | if (sym.n_strx == 0) continue; // no name, skip | 2472 | |
| 2471 | if (sym.ext()) continue; // an export lands in its own symtab section, skip | 2473 | var it = Atom.getInnerSymbolsIterator(self, atom_index); |
| 2472 | if (self.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip | 2474 | while (it.next()) |inner_sym_loc| { |
| 2473 | 2475 | try self.addLocalToSymtab(inner_sym_loc, &locals); | |
| 2474 | var out_sym = sym; | 2476 | } |
| 2475 | out_sym.n_strx = try self.strtab.insert(gpa, self.getSymbolName(sym_loc)); | ||
| 2476 | try locals.append(out_sym); | ||
| 2477 | } | 2477 | } |
| 2478 | } | 2478 | } |
| 2479 | 2479 |