| author | |
| committer | |
| log | c984201ddb10d2977290c6f1d6857e78573a2dff |
| tree | 438b3484fc41bb253da66c24e6618e995f4a6eb6 |
| parent | 8bffe87e9eeaf602d06eec60dffc955a86228fbd |
7 files changed, 198 insertions(+), 160 deletions(-)
src/link/MachO/Object.zig+12-14| ... | @@ -735,13 +735,12 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void { | ... | @@ -735,13 +735,12 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void { |
| 735 | assert(rel_pos.len > 0); // TODO convert to an error as the FDE eh frame is malformed | 735 | assert(rel_pos.len > 0); // TODO convert to an error as the FDE eh frame is malformed |
| 736 | // Find function symbol that this record describes | 736 | // Find function symbol that this record describes |
| 737 | const rel = relocs[rel_pos.start..][rel_pos.len - 1]; | 737 | const rel = relocs[rel_pos.start..][rel_pos.len - 1]; |
| 738 | const target = UnwindInfo.parseRelocTarget( | 738 | const target = Atom.parseRelocTarget(zld, .{ |
| 739 | zld, | 739 | .object_id = object_id, |
| 740 | object_id, | 740 | .rel = rel, |
| 741 | rel, | 741 | .code = it.data[offset..], |
| 742 | it.data[offset..], | 742 | .base_offset = @intCast(i32, offset), |
| 743 | @intCast(i32, offset), | 743 | }); |
| 744 | ); | ||
| 745 | break :blk target; | 744 | break :blk target; |
| 746 | }, | 745 | }, |
| 747 | .x86_64 => { | 746 | .x86_64 => { |
| ... | @@ -825,13 +824,12 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void { | ... | @@ -825,13 +824,12 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void { |
| 825 | 824 | ||
| 826 | // Find function symbol that this record describes | 825 | // Find function symbol that this record describes |
| 827 | const rel = relocs[rel_pos.start..][rel_pos.len - 1]; | 826 | const rel = relocs[rel_pos.start..][rel_pos.len - 1]; |
| 828 | const target = UnwindInfo.parseRelocTarget( | 827 | const target = Atom.parseRelocTarget(zld, .{ |
| 829 | zld, | 828 | .object_id = object_id, |
| 830 | object_id, | 829 | .rel = rel, |
| 831 | rel, | 830 | .code = mem.asBytes(&record), |
| 832 | mem.asBytes(&record), | 831 | .base_offset = @intCast(i32, offset), |
| 833 | @intCast(i32, offset), | 832 | }); |
| 834 | ); | ||
| 835 | log.debug("unwind record {d} tracks {s}", .{ record_id, zld.getSymbolName(target) }); | 833 | log.debug("unwind record {d} tracks {s}", .{ record_id, zld.getSymbolName(target) }); |
| 836 | if (target.getFile() != object_id) { | 834 | if (target.getFile() != object_id) { |
| 837 | self.unwind_relocs_lookup[record_id].dead = true; | 835 | self.unwind_relocs_lookup[record_id].dead = true; |
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+74-33| ... | @@ -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(); | ||
| 201 | |||
| 202 | const object = &zld.objects.items[ctx.object_id]; | ||
| 203 | log.debug("parsing reloc target in object({d}) '{s}' ", .{ ctx.object_id, object.name }); | ||
| 194 | 204 | ||
| 195 | const sym_index = if (rel.r_extern == 0) sym_index: { | 205 | const sym_index = if (ctx.rel.r_extern == 0) sym_index: { |
| 196 | const sect_id = @intCast(u8, rel.r_symbolnum - 1); | 206 | const sect_id = @intCast(u8, ctx.rel.r_symbolnum - 1); |
| 197 | const ctx = getRelocContext(zld, atom_index); | 207 | const rel_offset = @intCast(u32, ctx.rel.r_address - ctx.base_offset); |
| 198 | const atom_code = getAtomCode(zld, atom_index); | ||
| 199 | const rel_offset = @intCast(u32, rel.r_address - ctx.base_offset); | ||
| 200 | 208 | ||
| 201 | const address_in_section = if (rel.r_pcrel == 0) blk: { | 209 | const address_in_section = if (ctx.rel.r_pcrel == 0) blk: { |
| 202 | break :blk if (rel.r_length == 3) | 210 | break :blk if (ctx.rel.r_length == 3) |
| 203 | mem.readIntLittle(u64, atom_code[rel_offset..][0..8]) | 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,13 +810,25 @@ fn resolveRelocsX86( | ... | @@ -781,13 +810,25 @@ 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} ('{s}') in object({?})", .{ | 834 | log.debug(" RELA({s}) @ {x} => %{d} ('{s}') in object({?})", .{ |
src/link/MachO/dead_strip.zig+52-25| ... | @@ -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/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+20-17| ... | @@ -1884,13 +1884,9 @@ pub const Zld = struct { | ... | @@ -1884,13 +1884,9 @@ pub const Zld = struct { |
| 1884 | if (should_rebase) { | 1884 | if (should_rebase) { |
| 1885 | 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()) }); |
| 1886 | 1886 | ||
| 1887 | const object = self.objects.items[atom.getFile().?]; | 1887 | const code = Atom.getAtomCode(self, atom_index); |
| 1888 | const base_rel_offset: i32 = blk: { | ||
| 1889 | const source_sym = object.getSourceSymbol(atom.sym_index) orelse break :blk 0; | ||
| 1890 | const source_sect = object.getSourceSection(source_sym.n_sect - 1); | ||
| 1891 | break :blk @intCast(i32, source_sym.n_value - source_sect.addr); | ||
| 1892 | }; | ||
| 1893 | const relocs = Atom.getAtomRelocs(self, atom_index); | 1888 | const relocs = Atom.getAtomRelocs(self, atom_index); |
| 1889 | const ctx = Atom.getRelocContext(self, atom_index); | ||
| 1894 | 1890 | ||
| 1895 | for (relocs) |rel| { | 1891 | for (relocs) |rel| { |
| 1896 | switch (cpu_arch) { | 1892 | switch (cpu_arch) { |
| ... | @@ -1906,12 +1902,18 @@ pub const Zld = struct { | ... | @@ -1906,12 +1902,18 @@ pub const Zld = struct { |
| 1906 | }, | 1902 | }, |
| 1907 | else => unreachable, | 1903 | else => unreachable, |
| 1908 | } | 1904 | } |
| 1909 | 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 | }); | ||
| 1910 | const target_sym = self.getSymbol(target); | 1912 | const target_sym = self.getSymbol(target); |
| 1911 | if (target_sym.undf()) continue; | 1913 | if (target_sym.undf()) continue; |
| 1912 | 1914 | ||
| 1913 | const base_offset = @intCast(i32, sym.n_value - segment.vmaddr); | 1915 | const base_offset = @intCast(i32, sym.n_value - segment.vmaddr); |
| 1914 | const rel_offset = rel.r_address - base_rel_offset; | 1916 | const rel_offset = rel.r_address - ctx.base_offset; |
| 1915 | const offset = @intCast(u64, base_offset + rel_offset); | 1917 | const offset = @intCast(u64, base_offset + rel_offset); |
| 1916 | log.debug(" | rebase at {x}", .{offset}); | 1918 | log.debug(" | rebase at {x}", .{offset}); |
| 1917 | 1919 | ||
| ... | @@ -2021,13 +2023,9 @@ pub const Zld = struct { | ... | @@ -2021,13 +2023,9 @@ pub const Zld = struct { |
| 2021 | }; | 2023 | }; |
| 2022 | 2024 | ||
| 2023 | if (should_bind) { | 2025 | if (should_bind) { |
| 2024 | const object = self.objects.items[atom.getFile().?]; | 2026 | const code = Atom.getAtomCode(self, atom_index); |
| 2025 | const base_rel_offset: i32 = blk: { | ||
| 2026 | const source_sym = object.getSourceSymbol(atom.sym_index) orelse break :blk 0; | ||
| 2027 | const source_sect = object.getSourceSection(source_sym.n_sect - 1); | ||
| 2028 | break :blk @intCast(i32, source_sym.n_value - source_sect.addr); | ||
| 2029 | }; | ||
| 2030 | const relocs = Atom.getAtomRelocs(self, atom_index); | 2027 | const relocs = Atom.getAtomRelocs(self, atom_index); |
| 2028 | const ctx = Atom.getRelocContext(self, atom_index); | ||
| 2031 | 2029 | ||
| 2032 | for (relocs) |rel| { | 2030 | for (relocs) |rel| { |
| 2033 | switch (cpu_arch) { | 2031 | switch (cpu_arch) { |
| ... | @@ -2044,15 +2042,20 @@ pub const Zld = struct { | ... | @@ -2044,15 +2042,20 @@ pub const Zld = struct { |
| 2044 | else => unreachable, | 2042 | else => unreachable, |
| 2045 | } | 2043 | } |
| 2046 | 2044 | ||
| 2047 | 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 | }); | ||
| 2048 | const bind_sym_name = self.getSymbolName(global); | 2052 | const bind_sym_name = self.getSymbolName(global); |
| 2049 | const bind_sym = self.getSymbol(global); | 2053 | const bind_sym = self.getSymbol(global); |
| 2050 | if (!bind_sym.undf()) continue; | 2054 | if (!bind_sym.undf()) continue; |
| 2051 | 2055 | ||
| 2052 | const base_offset = sym.n_value - segment.vmaddr; | 2056 | const base_offset = sym.n_value - segment.vmaddr; |
| 2053 | const rel_offset = @intCast(u32, rel.r_address - base_rel_offset); | 2057 | const rel_offset = @intCast(u32, rel.r_address - ctx.base_offset); |
| 2054 | const offset = @intCast(u64, base_offset + rel_offset); | 2058 | const offset = @intCast(u64, base_offset + rel_offset); |
| 2055 | const code = Atom.getAtomCode(self, atom_index); | ||
| 2056 | const addend = mem.readIntLittle(i64, code[rel_offset..][0..8]); | 2059 | const addend = mem.readIntLittle(i64, code[rel_offset..][0..8]); |
| 2057 | 2060 | ||
| 2058 | 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); |