authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-22 13:57:43+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-22 15:13:17+01:00
logc984201ddb10d2977290c6f1d6857e78573a2dff
tree438b3484fc41bb253da66c24e6618e995f4a6eb6
parent8bffe87e9eeaf602d06eec60dffc955a86228fbd

macho+zld: refactor parsing of relocation target


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 malformed735 assert(rel_pos.len > 0); // TODO convert to an error as the FDE eh frame is malformed
736 // Find function symbol that this record describes736 // 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 {
825824
826 // Find function symbol that this record describes825 // 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 }
286284
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}
670667
671pub 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
706fn getRelocs(zld: *Zld, object_id: u32, record_id: usize) []const macho.relocation_info {668fn 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;
15const math = std.math;15const math = std.math;
16const mem = std.mem;16const mem = std.mem;
17const meta = std.meta;17const meta = std.meta;
18const trace = @import("../../tracy.zig").trace;
1819
19const Allocator = mem.Allocator;20const Allocator = mem.Allocator;
20const Arch = std.Target.Cpu.Arch;21const 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}
164165
165const RelocContext = struct {166const RelocContext = struct {
166 base_addr: u64 = 0,167 base_addr: i64 = 0,
167 base_offset: i32 = 0,168 base_offset: i32 = 0,
168};169};
169170
...@@ -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}
190191
191pub fn parseRelocTarget(zld: *Zld, atom_index: AtomIndex, rel: macho.relocation_info) SymbolWithLoc {192pub 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 });
194204
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);
200208
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 else212 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 };
218227
219 // Find containing atom228 // 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];
223233
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);
229236 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}
236253
237pub fn getRelocTargetAtomIndex(zld: *Zld, target: SymbolWithLoc, is_via_got: bool) ?AtomIndex {254pub 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 });
501518
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 }
507530
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);
510539
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 });
783812
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 }
789824
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);
792833
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;
132132
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());
177192
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 };
188218
...@@ -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 }
300329
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 record361 // 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);
332331
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;
343341
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;
227227
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;
231234
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;
234243
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()) });
18861886
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);
18941890
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;
19121914
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});
19171919
...@@ -2021,13 +2023,9 @@ pub const Zld = struct {...@@ -2021,13 +2023,9 @@ pub const Zld = struct {
2021 };2023 };
20222024
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);
20312029
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 }
20462044
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;
20512055
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]);
20572060
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);