| 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 | 143 | CLANG = 0x1, |
| 144 | 144 | SWIFT = 0x2, |
| 145 | 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 | 3340 | const exec_segment = self.segments.items[self.header_segment_cmd_index.?]; |
| 3341 | 3341 | const base_address = exec_segment.vmaddr; |
| 3342 | 3342 | |
| 3343 | if (self.base.options.output_mode == .Exe) { | |
| 3344 | for (&[_]SymbolWithLoc{ | |
| 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); | |
| 3343 | for (self.globals.items) |global| { | |
| 3344 | const sym = self.getSymbol(global); | |
| 3361 | 3345 | |
| 3362 | if (sym.undf()) continue; | |
| 3363 | if (!sym.ext()) continue; | |
| 3346 | if (sym.undf()) continue; | |
| 3347 | if (!sym.ext()) continue; | |
| 3364 | 3348 | |
| 3365 | const sym_name = self.getSymbolName(global); | |
| 3366 | log.debug(" (putting '{s}' defined at 0x{x})", .{ sym_name, sym.n_value }); | |
| 3367 | try trie.put(gpa, .{ | |
| 3368 | .name = sym_name, | |
| 3369 | .vmaddr_offset = sym.n_value - base_address, | |
| 3370 | .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR, | |
| 3371 | }); | |
| 3372 | } | |
| 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 | }); | |
| 3373 | 3356 | } |
| 3374 | 3357 | |
| 3375 | 3358 | try trie.finalize(gpa); |
src/link/MachO/DwarfInfo.zig+3-18| ... | ... | @@ -27,7 +27,7 @@ const CompileUnitIterator = struct { |
| 27 | 27 | pub fn next(self: *CompileUnitIterator) !?CompileUnit { |
| 28 | 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 | 31 | var creader = std.io.countingReader(stream.reader()); |
| 32 | 32 | const reader = creader.reader(); |
| 33 | 33 | |
| ... | ... | @@ -37,7 +37,7 @@ const CompileUnitIterator = struct { |
| 37 | 37 | |
| 38 | 38 | const cu = CompileUnit{ |
| 39 | 39 | .cuh = cuh, |
| 40 | .debug_info_off = offset, | |
| 40 | .debug_info_off = self.pos + offset, | |
| 41 | 41 | }; |
| 42 | 42 | |
| 43 | 43 | self.pos += (math.cast(usize, total_length) orelse return error.Overflow); |
| ... | ... | @@ -188,7 +188,7 @@ const AbbrevEntryIterator = struct { |
| 188 | 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 | 192 | const len = try findAbbrevEntrySize( |
| 193 | 193 | self.ctx, |
| 194 | 194 | abbrev_pos.pos, |
| ... | ... | @@ -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 | 293 | pub fn getAddr(self: Attribute, ctx: DwarfInfo, cuh: CompileUnit.Header) ?u64 { |
| 309 | 294 | if (self.form != dwarf.FORM.addr) return null; |
| 310 | 295 | const debug_info = self.getDebugInfo(ctx); |
src/link/MachO/Object.zig+55-43| ... | ... | @@ -50,7 +50,7 @@ reverse_symtab_lookup: []u32 = undefined, |
| 50 | 50 | /// Can be undefined as set together with in_symtab. |
| 51 | 51 | source_address_lookup: []i64 = undefined, |
| 52 | 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 | 54 | /// Can be undefined as set together with in_symtab. |
| 55 | 55 | strtab_lookup: []u32 = undefined, |
| 56 | 56 | /// Can be undefined as set together with in_symtab. |
| ... | ... | @@ -58,7 +58,7 @@ atom_by_index_table: []AtomIndex = undefined, |
| 58 | 58 | /// Can be undefined as set together with in_symtab. |
| 59 | 59 | globals_lookup: []i64 = undefined, |
| 60 | 60 | /// Can be undefined as set together with in_symtab. |
| 61 | relocs_lookup: []RelocEntry = undefined, | |
| 61 | relocs_lookup: []Entry = undefined, | |
| 62 | 62 | |
| 63 | 63 | /// All relocations sorted and flatened, sorted by address descending |
| 64 | 64 | /// per section. |
| ... | ... | @@ -81,11 +81,14 @@ unwind_info_sect_id: ?u8 = null, |
| 81 | 81 | unwind_relocs_lookup: []Record = undefined, |
| 82 | 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 | 89 | const Record = struct { |
| 87 | 90 | dead: bool, |
| 88 | reloc: RelocEntry, | |
| 91 | reloc: Entry, | |
| 89 | 92 | }; |
| 90 | 93 | |
| 91 | 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 | 173 | self.strtab_lookup = try allocator.alloc(u32, self.in_symtab.?.len); |
| 171 | 174 | self.globals_lookup = try allocator.alloc(i64, self.in_symtab.?.len); |
| 172 | 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 | 177 | // This is wasteful but we need to be able to lookup source symbol address after stripping and |
| 175 | 178 | // allocating of sections. |
| 176 | 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 | 182 | for (self.symtab) |*sym| { |
| 180 | 183 | sym.* = .{ |
| ... | ... | @@ -188,11 +191,8 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) |
| 188 | 191 | |
| 189 | 192 | mem.set(i64, self.globals_lookup, -1); |
| 190 | 193 | mem.set(AtomIndex, self.atom_by_index_table, 0); |
| 191 | mem.set(i64, self.source_section_index_lookup, -1); | |
| 192 | mem.set(RelocEntry, self.relocs_lookup, .{ | |
| 193 | .start = 0, | |
| 194 | .len = 0, | |
| 195 | }); | |
| 194 | mem.set(Entry, self.source_section_index_lookup, .{}); | |
| 195 | mem.set(Entry, self.relocs_lookup, .{}); | |
| 196 | 196 | |
| 197 | 197 | // You would expect that the symbol table is at least pre-sorted based on symbol's type: |
| 198 | 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 | 211 | // is kind enough to specify the symbols in the correct order. |
| 212 | 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 | 216 | for (sorted_all_syms.items, 0..) |sym_id, i| { |
| 215 | 217 | const sym = sym_id.getSymbol(self); |
| 216 | 218 | |
| 217 | if (sym.sect() and self.source_section_index_lookup[sym.n_sect - 1] == -1) { | |
| 218 | self.source_section_index_lookup[sym.n_sect - 1] = @intCast(i64, i); | |
| 219 | if (section_index_lookup) |*lookup| { | |
| 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 | 233 | self.symtab[i] = sym; |
| 222 | 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 | 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 | 248 | // Parse __TEXT,__eh_frame header if one exists |
| 231 | 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 | 252 | self.unwind_info_sect_id = self.getSourceSectionIndexByName("__LD", "__compact_unwind"); |
| 235 | 253 | if (self.hasUnwindRecords()) { |
| 236 | 254 | self.unwind_relocs_lookup = try allocator.alloc(Record, self.getUnwindRecords().len); |
| 237 | mem.set(Record, self.unwind_relocs_lookup, .{ | |
| 238 | .dead = true, | |
| 239 | .reloc = .{ | |
| 240 | .start = 0, | |
| 241 | .len = 0, | |
| 242 | }, | |
| 243 | }); | |
| 255 | mem.set(Record, self.unwind_relocs_lookup, .{ .dead = true, .reloc = .{} }); | |
| 244 | 256 | } |
| 245 | 257 | } |
| 246 | 258 | |
| ... | ... | @@ -620,7 +632,7 @@ fn filterRelocs( |
| 620 | 632 | relocs: []align(1) const macho.relocation_info, |
| 621 | 633 | start_addr: u64, |
| 622 | 634 | end_addr: u64, |
| 623 | ) RelocEntry { | |
| 635 | ) Entry { | |
| 624 | 636 | const Predicate = struct { |
| 625 | 637 | addr: u64, |
| 626 | 638 | |
| ... | ... | @@ -712,9 +724,9 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void { |
| 712 | 724 | |
| 713 | 725 | while (try it.next()) |record| { |
| 714 | 726 | const offset = it.pos - record.getSize(); |
| 715 | const rel_pos = switch (cpu_arch) { | |
| 727 | const rel_pos: Entry = switch (cpu_arch) { | |
| 716 | 728 | .aarch64 => filterRelocs(relocs, offset, offset + record.getSize()), |
| 717 | .x86_64 => RelocEntry{ .start = 0, .len = 0 }, | |
| 729 | .x86_64 => .{}, | |
| 718 | 730 | else => unreachable, |
| 719 | 731 | }; |
| 720 | 732 | self.eh_frame_relocs_lookup.putAssumeCapacityNoClobber(offset, .{ |
| ... | ... | @@ -729,13 +741,12 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void { |
| 729 | 741 | assert(rel_pos.len > 0); // TODO convert to an error as the FDE eh frame is malformed |
| 730 | 742 | // Find function symbol that this record describes |
| 731 | 743 | const rel = relocs[rel_pos.start..][rel_pos.len - 1]; |
| 732 | const target = UnwindInfo.parseRelocTarget( | |
| 733 | zld, | |
| 734 | object_id, | |
| 735 | rel, | |
| 736 | it.data[offset..], | |
| 737 | @intCast(i32, offset), | |
| 738 | ); | |
| 744 | const target = Atom.parseRelocTarget(zld, .{ | |
| 745 | .object_id = object_id, | |
| 746 | .rel = rel, | |
| 747 | .code = it.data[offset..], | |
| 748 | .base_offset = @intCast(i32, offset), | |
| 749 | }); | |
| 739 | 750 | break :blk target; |
| 740 | 751 | }, |
| 741 | 752 | .x86_64 => { |
| ... | ... | @@ -819,13 +830,12 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void { |
| 819 | 830 | |
| 820 | 831 | // Find function symbol that this record describes |
| 821 | 832 | const rel = relocs[rel_pos.start..][rel_pos.len - 1]; |
| 822 | const target = UnwindInfo.parseRelocTarget( | |
| 823 | zld, | |
| 824 | object_id, | |
| 825 | rel, | |
| 826 | mem.asBytes(&record), | |
| 827 | @intCast(i32, offset), | |
| 828 | ); | |
| 833 | const target = Atom.parseRelocTarget(zld, .{ | |
| 834 | .object_id = object_id, | |
| 835 | .rel = rel, | |
| 836 | .code = mem.asBytes(&record), | |
| 837 | .base_offset = @intCast(i32, offset), | |
| 838 | }); | |
| 829 | 839 | log.debug("unwind record {d} tracks {s}", .{ record_id, zld.getSymbolName(target) }); |
| 830 | 840 | if (target.getFile() != object_id) { |
| 831 | 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 | 1000 | }; |
| 991 | 1001 | |
| 992 | 1002 | if (sect_hint) |sect_id| { |
| 993 | if (self.source_section_index_lookup[sect_id] > -1) { | |
| 994 | const first_sym_index = @intCast(usize, 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{ | |
| 996 | .addr = @intCast(i64, addr), | |
| 997 | }); | |
| 1003 | if (self.source_section_index_lookup[sect_id].len > 0) { | |
| 1004 | const lookup = self.source_section_index_lookup[sect_id]; | |
| 1005 | const target_sym_index = @import("zld.zig").lsearch( | |
| 1006 | i64, | |
| 1007 | self.source_address_lookup[lookup.start..][0..lookup.len], | |
| 1008 | Predicate{ .addr = @intCast(i64, addr) }, | |
| 1009 | ); | |
| 998 | 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 | 1014 | return self.getSectionAliasSymbolIndex(sect_id); |
src/link/MachO/UnwindInfo.zig+18-56| ... | ... | @@ -218,13 +218,12 @@ pub fn scanRelocs(zld: *Zld) !void { |
| 218 | 218 | record_id, |
| 219 | 219 | )) |rel| { |
| 220 | 220 | // Personality function; add GOT pointer. |
| 221 | const target = parseRelocTarget( | |
| 222 | zld, | |
| 223 | @intCast(u32, object_id), | |
| 224 | rel, | |
| 225 | mem.asBytes(&record), | |
| 226 | @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), | |
| 227 | ); | |
| 221 | const target = Atom.parseRelocTarget(zld, .{ | |
| 222 | .object_id = @intCast(u32, object_id), | |
| 223 | .rel = rel, | |
| 224 | .code = mem.asBytes(&record), | |
| 225 | .base_offset = @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), | |
| 226 | }); | |
| 228 | 227 | try Atom.addGotEntry(zld, target); |
| 229 | 228 | } |
| 230 | 229 | } |
| ... | ... | @@ -266,13 +265,12 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void { |
| 266 | 265 | @intCast(u32, object_id), |
| 267 | 266 | record_id, |
| 268 | 267 | )) |rel| { |
| 269 | const target = parseRelocTarget( | |
| 270 | zld, | |
| 271 | @intCast(u32, object_id), | |
| 272 | rel, | |
| 273 | mem.asBytes(&record), | |
| 274 | @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), | |
| 275 | ); | |
| 268 | const target = Atom.parseRelocTarget(zld, .{ | |
| 269 | .object_id = @intCast(u32, object_id), | |
| 270 | .rel = rel, | |
| 271 | .code = mem.asBytes(&record), | |
| 272 | .base_offset = @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), | |
| 273 | }); | |
| 276 | 274 | const personality_index = info.getPersonalityFunction(target) orelse inner: { |
| 277 | 275 | const personality_index = info.personalities_count; |
| 278 | 276 | info.personalities[personality_index] = target; |
| ... | ... | @@ -285,13 +283,12 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void { |
| 285 | 283 | } |
| 286 | 284 | |
| 287 | 285 | if (getLsdaReloc(zld, @intCast(u32, object_id), record_id)) |rel| { |
| 288 | const target = parseRelocTarget( | |
| 289 | zld, | |
| 290 | @intCast(u32, object_id), | |
| 291 | rel, | |
| 292 | mem.asBytes(&record), | |
| 293 | @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), | |
| 294 | ); | |
| 286 | const target = Atom.parseRelocTarget(zld, .{ | |
| 287 | .object_id = @intCast(u32, object_id), | |
| 288 | .rel = rel, | |
| 289 | .code = mem.asBytes(&record), | |
| 290 | .base_offset = @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), | |
| 291 | }); | |
| 295 | 292 | record.lsda = @bitCast(u64, target); |
| 296 | 293 | } |
| 297 | 294 | } |
| ... | ... | @@ -668,41 +665,6 @@ pub fn write(info: *UnwindInfo, zld: *Zld) !void { |
| 668 | 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 | 668 | fn getRelocs(zld: *Zld, object_id: u32, record_id: usize) []const macho.relocation_info { |
| 707 | 669 | const object = &zld.objects.items[object_id]; |
| 708 | 670 | assert(object.hasUnwindRecords()); |
src/link/MachO/ZldAtom.zig+76-34| ... | ... | @@ -15,6 +15,7 @@ const macho = std.macho; |
| 15 | 15 | const math = std.math; |
| 16 | 16 | const mem = std.mem; |
| 17 | 17 | const meta = std.meta; |
| 18 | const trace = @import("../../tracy.zig").trace; | |
| 18 | 19 | |
| 19 | 20 | const Allocator = mem.Allocator; |
| 20 | 21 | const Arch = std.Target.Cpu.Arch; |
| ... | ... | @@ -163,7 +164,7 @@ pub fn scanAtomRelocs(zld: *Zld, atom_index: AtomIndex, relocs: []align(1) const |
| 163 | 164 | } |
| 164 | 165 | |
| 165 | 166 | const RelocContext = struct { |
| 166 | base_addr: u64 = 0, | |
| 167 | base_addr: i64 = 0, | |
| 167 | 168 | base_offset: i32 = 0, |
| 168 | 169 | }; |
| 169 | 170 | |
| ... | ... | @@ -175,7 +176,7 @@ pub fn getRelocContext(zld: *Zld, atom_index: AtomIndex) RelocContext { |
| 175 | 176 | if (object.getSourceSymbol(atom.sym_index)) |source_sym| { |
| 176 | 177 | const source_sect = object.getSourceSection(source_sym.n_sect - 1); |
| 177 | 178 | return .{ |
| 178 | .base_addr = source_sect.addr, | |
| 179 | .base_addr = @intCast(i64, source_sect.addr), | |
| 179 | 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 | 184 | const sect_id = @intCast(u8, atom.sym_index - nbase); |
| 184 | 185 | const source_sect = object.getSourceSection(sect_id); |
| 185 | 186 | return .{ |
| 186 | .base_addr = source_sect.addr, | |
| 187 | .base_addr = @intCast(i64, source_sect.addr), | |
| 187 | 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 | const atom = zld.getAtom(atom_index); | |
| 193 | const object = &zld.objects.items[atom.getFile().?]; | |
| 192 | pub fn parseRelocTarget(zld: *Zld, ctx: struct { | |
| 193 | object_id: u32, | |
| 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: { | |
| 196 | const sect_id = @intCast(u8, rel.r_symbolnum - 1); | |
| 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); | |
| 202 | const object = &zld.objects.items[ctx.object_id]; | |
| 203 | log.debug("parsing reloc target in object({d}) '{s}' ", .{ ctx.object_id, object.name }); | |
| 200 | 204 | |
| 201 | const address_in_section = if (rel.r_pcrel == 0) blk: { | |
| 202 | break :blk if (rel.r_length == 3) | |
| 203 | mem.readIntLittle(u64, atom_code[rel_offset..][0..8]) | |
| 205 | const sym_index = if (ctx.rel.r_extern == 0) sym_index: { | |
| 206 | const sect_id = @intCast(u8, ctx.rel.r_symbolnum - 1); | |
| 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 | 212 | else |
| 205 | mem.readIntLittle(u32, atom_code[rel_offset..][0..4]); | |
| 213 | mem.readIntLittle(u32, ctx.code[rel_offset..][0..4]); | |
| 206 | 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 | 217 | .X86_64_RELOC_SIGNED => 0, |
| 209 | 218 | .X86_64_RELOC_SIGNED_1 => 1, |
| 210 | 219 | .X86_64_RELOC_SIGNED_2 => 2, |
| 211 | 220 | .X86_64_RELOC_SIGNED_4 => 4, |
| 212 | 221 | else => unreachable, |
| 213 | 222 | }; |
| 214 | const addend = mem.readIntLittle(i32, atom_code[rel_offset..][0..4]); | |
| 215 | const target_address = @intCast(i64, ctx.base_addr) + rel.r_address + 4 + correction + addend; | |
| 223 | const addend = mem.readIntLittle(i32, ctx.code[rel_offset..][0..4]); | |
| 224 | const target_address = @intCast(i64, ctx.base_addr) + ctx.rel.r_address + 4 + correction + addend; | |
| 216 | 225 | break :blk @intCast(u64, target_address); |
| 217 | 226 | }; |
| 218 | 227 | |
| 219 | 228 | // Find containing atom |
| 229 | log.debug(" | locating symbol by address @{x} in section {d}", .{ address_in_section, sect_id }); | |
| 220 | 230 | const sym_index = object.getSymbolByAddress(address_in_section, sect_id); |
| 221 | 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{ | |
| 225 | .sym_index = sym_index, | |
| 226 | .file = atom.file, | |
| 227 | }; | |
| 234 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = ctx.object_id + 1 }; | |
| 228 | 235 | const sym = zld.getSymbol(sym_loc); |
| 229 | ||
| 230 | if (sym.sect() and !sym.ext()) { | |
| 231 | return sym_loc; | |
| 232 | } else if (object.getGlobal(sym_index)) |global_index| { | |
| 233 | return zld.globals.items[global_index]; | |
| 234 | } else return sym_loc; | |
| 236 | const target = target: { | |
| 237 | if (sym.sect() and !sym.ext()) { | |
| 238 | // Make sure we are not dealing with a local alias. | |
| 239 | const atom_index = object.getAtomIndexForSymbol(sym_index) orelse break :target sym_loc; | |
| 240 | const atom = zld.getAtom(atom_index); | |
| 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 | 254 | pub fn getRelocTargetAtomIndex(zld: *Zld, target: SymbolWithLoc, is_via_got: bool) ?AtomIndex { |
| ... | ... | @@ -499,13 +516,25 @@ fn resolveRelocsArm64( |
| 499 | 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 | 526 | continue; |
| 504 | 527 | }, |
| 505 | 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 | 538 | const rel_offset = @intCast(u32, rel.r_address - context.base_offset); |
| 510 | 539 | |
| 511 | 540 | log.debug(" RELA({s}) @ {x} => %{d} ('{s}') in object({?})", .{ |
| ... | ... | @@ -781,19 +810,32 @@ fn resolveRelocsX86( |
| 781 | 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 | 820 | continue; |
| 786 | 821 | }, |
| 787 | 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 | 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 | 835 | @tagName(rel_type), |
| 795 | 836 | rel.r_address, |
| 796 | 837 | target.sym_index, |
| 838 | zld.getSymbolName(target), | |
| 797 | 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 | 102 | }; |
| 103 | 103 | |
| 104 | 104 | if (is_gc_root) { |
| 105 | try roots.putNoClobber(atom_index, {}); | |
| 105 | _ = try roots.getOrPut(atom_index); | |
| 106 | 106 | |
| 107 | 107 | log.debug("root(ATOM({d}, %{d}, {?d}))", .{ |
| 108 | 108 | atom_index, |
| ... | ... | @@ -130,14 +130,29 @@ fn markLive(zld: *Zld, atom_index: AtomIndex, alive: *AtomTable) void { |
| 130 | 130 | const header = zld.sections.items(.header)[sym.n_sect - 1]; |
| 131 | 131 | if (header.isZerofill()) return; |
| 132 | 132 | |
| 133 | const code = Atom.getAtomCode(zld, atom_index); | |
| 133 | 134 | const relocs = Atom.getAtomRelocs(zld, atom_index); |
| 135 | const ctx = Atom.getRelocContext(zld, atom_index); | |
| 136 | ||
| 134 | 137 | for (relocs) |rel| { |
| 135 | 138 | const target = switch (cpu_arch) { |
| 136 | 139 | .aarch64 => switch (@intToEnum(macho.reloc_type_arm64, rel.r_type)) { |
| 137 | 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 | 156 | else => unreachable, |
| 142 | 157 | }; |
| 143 | 158 | const target_sym = zld.getSymbol(target); |
| ... | ... | @@ -175,14 +190,29 @@ fn refersLive(zld: *Zld, atom_index: AtomIndex, alive: AtomTable) bool { |
| 175 | 190 | const header = zld.sections.items(.header)[sym.n_sect - 1]; |
| 176 | 191 | assert(!header.isZerofill()); |
| 177 | 192 | |
| 193 | const code = Atom.getAtomCode(zld, atom_index); | |
| 178 | 194 | const relocs = Atom.getAtomRelocs(zld, atom_index); |
| 195 | const ctx = Atom.getRelocContext(zld, atom_index); | |
| 196 | ||
| 179 | 197 | for (relocs) |rel| { |
| 180 | 198 | const target = switch (cpu_arch) { |
| 181 | 199 | .aarch64 => switch (@intToEnum(macho.reloc_type_arm64, rel.r_type)) { |
| 182 | 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 | 216 | else => unreachable, |
| 187 | 217 | }; |
| 188 | 218 | |
| ... | ... | @@ -283,13 +313,12 @@ fn markUnwindRecords(zld: *Zld, object_id: u32, alive: *AtomTable) !void { |
| 283 | 313 | try markEhFrameRecord(zld, object_id, atom_index, alive); |
| 284 | 314 | } else { |
| 285 | 315 | if (UnwindInfo.getPersonalityFunctionReloc(zld, object_id, record_id)) |rel| { |
| 286 | const target = UnwindInfo.parseRelocTarget( | |
| 287 | zld, | |
| 288 | object_id, | |
| 289 | rel, | |
| 290 | mem.asBytes(&record), | |
| 291 | @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), | |
| 292 | ); | |
| 316 | const target = Atom.parseRelocTarget(zld, .{ | |
| 317 | .object_id = object_id, | |
| 318 | .rel = rel, | |
| 319 | .code = mem.asBytes(&record), | |
| 320 | .base_offset = @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), | |
| 321 | }); | |
| 293 | 322 | const target_sym = zld.getSymbol(target); |
| 294 | 323 | if (!target_sym.undf()) { |
| 295 | 324 | const target_object = zld.objects.items[target.getFile().?]; |
| ... | ... | @@ -299,13 +328,12 @@ fn markUnwindRecords(zld: *Zld, object_id: u32, alive: *AtomTable) !void { |
| 299 | 328 | } |
| 300 | 329 | |
| 301 | 330 | if (UnwindInfo.getLsdaReloc(zld, object_id, record_id)) |rel| { |
| 302 | const target = UnwindInfo.parseRelocTarget( | |
| 303 | zld, | |
| 304 | object_id, | |
| 305 | rel, | |
| 306 | mem.asBytes(&record), | |
| 307 | @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), | |
| 308 | ); | |
| 331 | const target = Atom.parseRelocTarget(zld, .{ | |
| 332 | .object_id = object_id, | |
| 333 | .rel = rel, | |
| 334 | .code = mem.asBytes(&record), | |
| 335 | .base_offset = @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)), | |
| 336 | }); | |
| 309 | 337 | const target_object = zld.objects.items[target.getFile().?]; |
| 310 | 338 | const target_atom_index = target_object.getAtomIndexForSymbol(target.sym_index).?; |
| 311 | 339 | markLive(zld, target_atom_index, alive); |
| ... | ... | @@ -333,13 +361,12 @@ fn markEhFrameRecord(zld: *Zld, object_id: u32, atom_index: AtomIndex, alive: *A |
| 333 | 361 | // Mark FDE references which should include any referenced LSDA record |
| 334 | 362 | const relocs = eh_frame.getRelocs(zld, object_id, fde_offset); |
| 335 | 363 | for (relocs) |rel| { |
| 336 | const target = UnwindInfo.parseRelocTarget( | |
| 337 | zld, | |
| 338 | object_id, | |
| 339 | rel, | |
| 340 | fde.data, | |
| 341 | @intCast(i32, fde_offset) + 4, | |
| 342 | ); | |
| 364 | const target = Atom.parseRelocTarget(zld, .{ | |
| 365 | .object_id = object_id, | |
| 366 | .rel = rel, | |
| 367 | .code = fde.data, | |
| 368 | .base_offset = @intCast(i32, fde_offset) + 4, | |
| 369 | }); | |
| 343 | 370 | const target_sym = zld.getSymbol(target); |
| 344 | 371 | if (!target_sym.undf()) blk: { |
| 345 | 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 | 308 | }, |
| 309 | 309 | else => unreachable, |
| 310 | 310 | } |
| 311 | const target = UnwindInfo.parseRelocTarget( | |
| 312 | zld, | |
| 313 | object_id, | |
| 314 | rel, | |
| 315 | rec.data, | |
| 316 | @intCast(i32, source_offset) + 4, | |
| 317 | ); | |
| 311 | const target = Atom.parseRelocTarget(zld, .{ | |
| 312 | .object_id = object_id, | |
| 313 | .rel = rel, | |
| 314 | .code = rec.data, | |
| 315 | .base_offset = @intCast(i32, source_offset) + 4, | |
| 316 | }); | |
| 318 | 317 | return target; |
| 319 | 318 | } |
| 320 | 319 | return null; |
| ... | ... | @@ -331,13 +330,12 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type { |
| 331 | 330 | const relocs = getRelocs(zld, object_id, ctx.source_offset); |
| 332 | 331 | |
| 333 | 332 | for (relocs) |rel| { |
| 334 | const target = UnwindInfo.parseRelocTarget( | |
| 335 | zld, | |
| 336 | object_id, | |
| 337 | rel, | |
| 338 | rec.data, | |
| 339 | @intCast(i32, ctx.source_offset) + 4, | |
| 340 | ); | |
| 333 | const target = Atom.parseRelocTarget(zld, .{ | |
| 334 | .object_id = object_id, | |
| 335 | .rel = rel, | |
| 336 | .code = rec.data, | |
| 337 | .base_offset = @intCast(i32, ctx.source_offset) + 4, | |
| 338 | }); | |
| 341 | 339 | const rel_offset = @intCast(u32, rel.r_address - @intCast(i32, ctx.source_offset) - 4); |
| 342 | 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 | 294 | .ntools = 1, |
| 295 | 295 | }); |
| 296 | 296 | try lc_writer.writeAll(mem.asBytes(&macho.build_tool_version{ |
| 297 | .tool = .LD, | |
| 297 | .tool = .ZIG, | |
| 298 | 298 | .version = 0x0, |
| 299 | 299 | })); |
| 300 | 300 | } |
src/link/MachO/thunks.zig+10-1| ... | ... | @@ -225,11 +225,20 @@ fn scanRelocs( |
| 225 | 225 | break :blk @intCast(i32, source_sym.n_value - source_sect.addr); |
| 226 | 226 | } else 0; |
| 227 | 227 | |
| 228 | const code = Atom.getAtomCode(zld, atom_index); | |
| 228 | 229 | const relocs = Atom.getAtomRelocs(zld, atom_index); |
| 230 | const ctx = Atom.getRelocContext(zld, atom_index); | |
| 231 | ||
| 229 | 232 | for (relocs) |rel| { |
| 230 | 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 | 242 | if (isReachable(zld, atom_index, rel, base_offset, target, allocated)) continue; |
| 234 | 243 | |
| 235 | 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 | 477 | mem.eql(u8, sectname, "__gosymtab") or |
| 478 | 478 | mem.eql(u8, sectname, "__gopclntab")) |
| 479 | 479 | { |
| 480 | break :blk self.getSectionByName("__DATA_CONST", "__const") orelse try self.initSection( | |
| 481 | "__DATA_CONST", | |
| 482 | "__const", | |
| 480 | break :blk self.getSectionByName("__TEXT", sectname) orelse try self.initSection( | |
| 481 | "__TEXT", | |
| 482 | sectname, | |
| 483 | 483 | .{}, |
| 484 | 484 | ); |
| 485 | 485 | } |
| ... | ... | @@ -490,15 +490,13 @@ pub const Zld = struct { |
| 490 | 490 | mem.eql(u8, sectname, "__objc_classlist") or |
| 491 | 491 | mem.eql(u8, sectname, "__objc_imageinfo")) |
| 492 | 492 | { |
| 493 | break :blk self.getSectionByName("__DATA_CONST", sectname) orelse | |
| 494 | try self.initSection( | |
| 493 | break :blk self.getSectionByName("__DATA_CONST", sectname) orelse try self.initSection( | |
| 495 | 494 | "__DATA_CONST", |
| 496 | 495 | sectname, |
| 497 | 496 | .{}, |
| 498 | 497 | ); |
| 499 | 498 | } else if (mem.eql(u8, sectname, "__data")) { |
| 500 | break :blk self.getSectionByName("__DATA", "__data") orelse | |
| 501 | try self.initSection( | |
| 499 | break :blk self.getSectionByName("__DATA", "__data") orelse try self.initSection( | |
| 502 | 500 | "__DATA", |
| 503 | 501 | "__data", |
| 504 | 502 | .{}, |
| ... | ... | @@ -1886,13 +1884,9 @@ pub const Zld = struct { |
| 1886 | 1884 | if (should_rebase) { |
| 1887 | 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().?]; | |
| 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 | }; | |
| 1887 | const code = Atom.getAtomCode(self, atom_index); | |
| 1895 | 1888 | const relocs = Atom.getAtomRelocs(self, atom_index); |
| 1889 | const ctx = Atom.getRelocContext(self, atom_index); | |
| 1896 | 1890 | |
| 1897 | 1891 | for (relocs) |rel| { |
| 1898 | 1892 | switch (cpu_arch) { |
| ... | ... | @@ -1908,12 +1902,18 @@ pub const Zld = struct { |
| 1908 | 1902 | }, |
| 1909 | 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 | 1912 | const target_sym = self.getSymbol(target); |
| 1913 | 1913 | if (target_sym.undf()) continue; |
| 1914 | 1914 | |
| 1915 | 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 | 1917 | const offset = @intCast(u64, base_offset + rel_offset); |
| 1918 | 1918 | log.debug(" | rebase at {x}", .{offset}); |
| 1919 | 1919 | |
| ... | ... | @@ -2023,13 +2023,9 @@ pub const Zld = struct { |
| 2023 | 2023 | }; |
| 2024 | 2024 | |
| 2025 | 2025 | if (should_bind) { |
| 2026 | const object = self.objects.items[atom.getFile().?]; | |
| 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 | }; | |
| 2026 | const code = Atom.getAtomCode(self, atom_index); | |
| 2032 | 2027 | const relocs = Atom.getAtomRelocs(self, atom_index); |
| 2028 | const ctx = Atom.getRelocContext(self, atom_index); | |
| 2033 | 2029 | |
| 2034 | 2030 | for (relocs) |rel| { |
| 2035 | 2031 | switch (cpu_arch) { |
| ... | ... | @@ -2046,15 +2042,20 @@ pub const Zld = struct { |
| 2046 | 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 | 2052 | const bind_sym_name = self.getSymbolName(global); |
| 2051 | 2053 | const bind_sym = self.getSymbol(global); |
| 2052 | 2054 | if (!bind_sym.undf()) continue; |
| 2053 | 2055 | |
| 2054 | 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 | 2058 | const offset = @intCast(u64, base_offset + rel_offset); |
| 2057 | const code = Atom.getAtomCode(self, atom_index); | |
| 2058 | 2059 | const addend = mem.readIntLittle(i64, code[rel_offset..][0..8]); |
| 2059 | 2060 | |
| 2060 | 2061 | const dylib_ordinal = @divTrunc(@bitCast(i16, bind_sym.n_desc), macho.N_SYMBOL_RESOLVER); |
| ... | ... | @@ -2143,43 +2144,24 @@ pub const Zld = struct { |
| 2143 | 2144 | const exec_segment = self.segments.items[segment_index]; |
| 2144 | 2145 | const base_address = exec_segment.vmaddr; |
| 2145 | 2146 | |
| 2146 | if (self.options.output_mode == .Exe) { | |
| 2147 | for (&[_]SymbolWithLoc{ | |
| 2148 | self.getEntryPoint(), | |
| 2149 | self.globals.items[self.mh_execute_header_index.?], | |
| 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; | |
| 2147 | for (self.globals.items) |global| { | |
| 2148 | const sym = self.getSymbol(global); | |
| 2149 | if (sym.undf()) continue; | |
| 2150 | if (sym.n_desc == N_DEAD) continue; | |
| 2166 | 2151 | |
| 2167 | const sym_name = self.getSymbolName(global); | |
| 2168 | log.debug(" (putting '{s}' defined at 0x{x})", .{ sym_name, sym.n_value }); | |
| 2169 | try trie.put(gpa, .{ | |
| 2170 | .name = sym_name, | |
| 2171 | .vmaddr_offset = sym.n_value - base_address, | |
| 2172 | .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR, | |
| 2173 | }); | |
| 2174 | } | |
| 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 | }); | |
| 2175 | 2159 | } |
| 2176 | 2160 | |
| 2177 | 2161 | try trie.finalize(gpa); |
| 2178 | 2162 | } |
| 2179 | 2163 | |
| 2180 | fn writeDyldInfoData( | |
| 2181 | self: *Zld, | |
| 2182 | ) !void { | |
| 2164 | fn writeDyldInfoData(self: *Zld) !void { | |
| 2183 | 2165 | const gpa = self.gpa; |
| 2184 | 2166 | |
| 2185 | 2167 | var rebase = Rebase{}; |
| ... | ... | @@ -2300,9 +2282,16 @@ pub const Zld = struct { |
| 2300 | 2282 | |
| 2301 | 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 | 2293 | fn writeFunctionStarts(self: *Zld) !void { |
| 2304 | 2294 | const text_seg_index = self.getSegmentByName("__TEXT") orelse return; |
| 2305 | const text_sect_index = self.getSectionByName("__TEXT", "__text") orelse return; | |
| 2306 | 2295 | const text_seg = self.segments.items[text_seg_index]; |
| 2307 | 2296 | |
| 2308 | 2297 | const gpa = self.gpa; |
| ... | ... | @@ -2310,17 +2299,18 @@ pub const Zld = struct { |
| 2310 | 2299 | // We need to sort by address first |
| 2311 | 2300 | var addresses = std.ArrayList(u64).init(gpa); |
| 2312 | 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; | |
| 2321 | if (sect_id != text_sect_index) continue; | |
| 2303 | for (self.objects.items) |object| { | |
| 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 | 2316 | std.sort.sort(u64, addresses.items, {}, asc_u64); |
| ... | ... | @@ -2456,6 +2446,18 @@ pub const Zld = struct { |
| 2456 | 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 | 2461 | fn writeSymtab(self: *Zld) !SymtabCtx { |
| 2460 | 2462 | const gpa = self.gpa; |
| 2461 | 2463 | |
| ... | ... | @@ -2466,14 +2468,12 @@ pub const Zld = struct { |
| 2466 | 2468 | for (object.atoms.items) |atom_index| { |
| 2467 | 2469 | const atom = self.getAtom(atom_index); |
| 2468 | 2470 | const sym_loc = atom.getSymbolWithLoc(); |
| 2469 | const sym = self.getSymbol(sym_loc); | |
| 2470 | if (sym.n_strx == 0) continue; // no name, skip | |
| 2471 | if (sym.ext()) continue; // an export lands in its own symtab section, skip | |
| 2472 | if (self.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip | |
| 2473 | ||
| 2474 | var out_sym = sym; | |
| 2475 | out_sym.n_strx = try self.strtab.insert(gpa, self.getSymbolName(sym_loc)); | |
| 2476 | try locals.append(out_sym); | |
| 2471 | try self.addLocalToSymtab(sym_loc, &locals); | |
| 2472 | ||
| 2473 | var it = Atom.getInnerSymbolsIterator(self, atom_index); | |
| 2474 | while (it.next()) |inner_sym_loc| { | |
| 2475 | try self.addLocalToSymtab(inner_sym_loc, &locals); | |
| 2476 | } | |
| 2477 | 2477 | } |
| 2478 | 2478 | } |
| 2479 | 2479 |