authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-06-25 16:36:59+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-25 14:33:00-07:00
log852eb272bf895ee6fc242e298e31d666caa9d0df
treecef7aa1fe4ecbe34d4e92559c1e89fa67e32fced
parentdf389b62de4430434a6518580e27208101ae2fc8

macho: add fixes to __eh_frame parsing emitted by Nix C++ compiler


4 files changed, 35 insertions(+), 8 deletions(-)

src/link/MachO/Object.zig+5-1
...@@ -740,7 +740,11 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void {...@@ -740,7 +740,11 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void {
740 .aarch64 => {740 .aarch64 => {
741 assert(rel_pos.len > 0); // TODO convert to an error as the FDE eh frame is malformed741 assert(rel_pos.len > 0); // TODO convert to an error as the FDE eh frame is malformed
742 // Find function symbol that this record describes742 // Find function symbol that this record describes
743 const rel = relocs[rel_pos.start..][rel_pos.len - 1];743 const rel = for (relocs[rel_pos.start..][0..rel_pos.len]) |rel| {
744 if (rel.r_address - @as(i32, @intCast(offset)) == 8 and
745 @as(macho.reloc_type_arm64, @enumFromInt(rel.r_type)) == .ARM64_RELOC_UNSIGNED)
746 break rel;
747 } else unreachable;
744 const target = Atom.parseRelocTarget(zld, .{748 const target = Atom.parseRelocTarget(zld, .{
745 .object_id = object_id,749 .object_id = object_id,
746 .rel = rel,750 .rel = rel,
src/link/MachO/UnwindInfo.zig+1-1
...@@ -499,7 +499,7 @@ fn collectPersonalityFromDwarf(...@@ -499,7 +499,7 @@ fn collectPersonalityFromDwarf(
499 const fde_offset = object.eh_frame_records_lookup.get(atom_index).?;499 const fde_offset = object.eh_frame_records_lookup.get(atom_index).?;
500 it.seekTo(fde_offset);500 it.seekTo(fde_offset);
501 const fde = (try it.next()).?;501 const fde = (try it.next()).?;
502 const cie_ptr = fde.getCiePointer();502 const cie_ptr = fde.getCiePointerSource(object_id, zld, fde_offset);
503 const cie_offset = fde_offset + 4 - cie_ptr;503 const cie_offset = fde_offset + 4 - cie_ptr;
504 it.seekTo(cie_offset);504 it.seekTo(cie_offset);
505 const cie = (try it.next()).?;505 const cie = (try it.next()).?;
src/link/MachO/dead_strip.zig+1-1
...@@ -363,7 +363,7 @@ fn markEhFrameRecord(zld: *Zld, object_id: u32, atom_index: AtomIndex, alive: *A...@@ -363,7 +363,7 @@ fn markEhFrameRecord(zld: *Zld, object_id: u32, atom_index: AtomIndex, alive: *A
363 it.seekTo(fde_offset);363 it.seekTo(fde_offset);
364 const fde = (try it.next()).?;364 const fde = (try it.next()).?;
365365
366 const cie_ptr = fde.getCiePointer();366 const cie_ptr = fde.getCiePointerSource(object_id, zld, fde_offset);
367 const cie_offset = fde_offset + 4 - cie_ptr;367 const cie_offset = fde_offset + 4 - cie_ptr;
368 it.seekTo(cie_offset);368 it.seekTo(cie_offset);
369 const cie = (try it.next()).?;369 const cie = (try it.next()).?;
src/link/MachO/eh_frame.zig+28-5
...@@ -29,7 +29,7 @@ pub fn scanRelocs(zld: *Zld) !void {...@@ -29,7 +29,7 @@ pub fn scanRelocs(zld: *Zld) !void {
29 it.seekTo(fde_offset);29 it.seekTo(fde_offset);
30 const fde = (try it.next()).?;30 const fde = (try it.next()).?;
3131
32 const cie_ptr = fde.getCiePointer();32 const cie_ptr = fde.getCiePointerSource(@intCast(object_id), zld, fde_offset);
33 const cie_offset = fde_offset + 4 - cie_ptr;33 const cie_offset = fde_offset + 4 - cie_ptr;
3434
35 if (!cies.contains(cie_offset)) {35 if (!cies.contains(cie_offset)) {
...@@ -52,7 +52,7 @@ pub fn calcSectionSize(zld: *Zld, unwind_info: *const UnwindInfo) !void {...@@ -52,7 +52,7 @@ pub fn calcSectionSize(zld: *Zld, unwind_info: *const UnwindInfo) !void {
52 const gpa = zld.gpa;52 const gpa = zld.gpa;
53 var size: u32 = 0;53 var size: u32 = 0;
5454
55 for (zld.objects.items) |*object| {55 for (zld.objects.items, 0..) |*object, object_id| {
56 var cies = std.AutoHashMap(u32, u32).init(gpa);56 var cies = std.AutoHashMap(u32, u32).init(gpa);
57 defer cies.deinit();57 defer cies.deinit();
5858
...@@ -72,7 +72,7 @@ pub fn calcSectionSize(zld: *Zld, unwind_info: *const UnwindInfo) !void {...@@ -72,7 +72,7 @@ pub fn calcSectionSize(zld: *Zld, unwind_info: *const UnwindInfo) !void {
72 eh_it.seekTo(fde_record_offset);72 eh_it.seekTo(fde_record_offset);
73 const source_fde_record = (try eh_it.next()).?;73 const source_fde_record = (try eh_it.next()).?;
7474
75 const cie_ptr = source_fde_record.getCiePointer();75 const cie_ptr = source_fde_record.getCiePointerSource(@intCast(object_id), zld, fde_record_offset);
76 const cie_offset = fde_record_offset + 4 - cie_ptr;76 const cie_offset = fde_record_offset + 4 - cie_ptr;
7777
78 const gop = try cies.getOrPut(cie_offset);78 const gop = try cies.getOrPut(cie_offset);
...@@ -131,7 +131,7 @@ pub fn write(zld: *Zld, unwind_info: *UnwindInfo) !void {...@@ -131,7 +131,7 @@ pub fn write(zld: *Zld, unwind_info: *UnwindInfo) !void {
131 eh_it.seekTo(fde_record_offset);131 eh_it.seekTo(fde_record_offset);
132 const source_fde_record = (try eh_it.next()).?;132 const source_fde_record = (try eh_it.next()).?;
133133
134 const cie_ptr = source_fde_record.getCiePointer();134 const cie_ptr = source_fde_record.getCiePointerSource(@intCast(object_id), zld, fde_record_offset);
135 const cie_offset = fde_record_offset + 4 - cie_ptr;135 const cie_offset = fde_record_offset + 4 - cie_ptr;
136136
137 const gop = try cies.getOrPut(cie_offset);137 const gop = try cies.getOrPut(cie_offset);
...@@ -150,12 +150,12 @@ pub fn write(zld: *Zld, unwind_info: *UnwindInfo) !void {...@@ -150,12 +150,12 @@ pub fn write(zld: *Zld, unwind_info: *UnwindInfo) !void {
150 }150 }
151151
152 var fde_record = try source_fde_record.toOwned(gpa);152 var fde_record = try source_fde_record.toOwned(gpa);
153 fde_record.setCiePointer(eh_frame_offset + 4 - gop.value_ptr.*);
154 try fde_record.relocate(zld, @as(u32, @intCast(object_id)), .{153 try fde_record.relocate(zld, @as(u32, @intCast(object_id)), .{
155 .source_offset = fde_record_offset,154 .source_offset = fde_record_offset,
156 .out_offset = eh_frame_offset,155 .out_offset = eh_frame_offset,
157 .sect_addr = sect.addr,156 .sect_addr = sect.addr,
158 });157 });
158 fde_record.setCiePointer(eh_frame_offset + 4 - gop.value_ptr.*);
159159
160 switch (cpu_arch) {160 switch (cpu_arch) {
161 .aarch64 => {}, // relocs take care of LSDA pointers161 .aarch64 => {}, // relocs take care of LSDA pointers
...@@ -380,6 +380,29 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type {...@@ -380,6 +380,29 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type {
380 }380 }
381 }381 }
382382
383 pub fn getCiePointerSource(rec: Record, object_id: u32, zld: *Zld, offset: u32) u32 {
384 assert(rec.tag == .fde);
385 const cpu_arch = zld.options.target.cpu.arch;
386 const addend = mem.readIntLittle(u32, rec.data[0..4]);
387 switch (cpu_arch) {
388 .aarch64 => {
389 const relocs = getRelocs(zld, object_id, offset);
390 const maybe_rel = for (relocs) |rel| {
391 if (rel.r_address - @as(i32, @intCast(offset)) == 4 and
392 @as(macho.reloc_type_arm64, @enumFromInt(rel.r_type)) == .ARM64_RELOC_SUBTRACTOR)
393 break rel;
394 } else null;
395 const rel = maybe_rel orelse return addend;
396 const object = &zld.objects.items[object_id];
397 const target_addr = object.in_symtab.?[rel.r_symbolnum].n_value;
398 const sect = object.getSourceSection(object.eh_frame_sect_id.?);
399 return @intCast(sect.addr + offset - target_addr + addend);
400 },
401 .x86_64 => return addend,
402 else => unreachable,
403 }
404 }
405
383 pub fn getCiePointer(rec: Record) u32 {406 pub fn getCiePointer(rec: Record) u32 {
384 assert(rec.tag == .fde);407 assert(rec.tag == .fde);
385 return mem.readIntLittle(u32, rec.data[0..4]);408 return mem.readIntLittle(u32, rec.data[0..4]);