| ... | ... | @@ -29,7 +29,7 @@ pub fn scanRelocs(zld: *Zld) !void { |
| 29 | 29 | it.seekTo(fde_offset); |
| 30 | 30 | const fde = (try it.next()).?; |
| 31 | 31 | |
| 32 | | const cie_ptr = fde.getCiePointer(); |
| 32 | const cie_ptr = fde.getCiePointerSource(@intCast(object_id), zld, fde_offset); |
| 33 | 33 | const cie_offset = fde_offset + 4 - cie_ptr; |
| 34 | 34 | |
| 35 | 35 | if (!cies.contains(cie_offset)) { |
| ... | ... | @@ -52,7 +52,7 @@ pub fn calcSectionSize(zld: *Zld, unwind_info: *const UnwindInfo) !void { |
| 52 | 52 | const gpa = zld.gpa; |
| 53 | 53 | var size: u32 = 0; |
| 54 | 54 | |
| 55 | | for (zld.objects.items) |*object| { |
| 55 | for (zld.objects.items, 0..) |*object, object_id| { |
| 56 | 56 | var cies = std.AutoHashMap(u32, u32).init(gpa); |
| 57 | 57 | defer cies.deinit(); |
| 58 | 58 | |
| ... | ... | @@ -72,7 +72,7 @@ pub fn calcSectionSize(zld: *Zld, unwind_info: *const UnwindInfo) !void { |
| 72 | 72 | eh_it.seekTo(fde_record_offset); |
| 73 | 73 | const source_fde_record = (try eh_it.next()).?; |
| 74 | 74 | |
| 75 | | const cie_ptr = source_fde_record.getCiePointer(); |
| 75 | const cie_ptr = source_fde_record.getCiePointerSource(@intCast(object_id), zld, fde_record_offset); |
| 76 | 76 | const cie_offset = fde_record_offset + 4 - cie_ptr; |
| 77 | 77 | |
| 78 | 78 | const gop = try cies.getOrPut(cie_offset); |
| ... | ... | @@ -131,7 +131,7 @@ pub fn write(zld: *Zld, unwind_info: *UnwindInfo) !void { |
| 131 | 131 | eh_it.seekTo(fde_record_offset); |
| 132 | 132 | const source_fde_record = (try eh_it.next()).?; |
| 133 | 133 | |
| 134 | | const cie_ptr = source_fde_record.getCiePointer(); |
| 134 | const cie_ptr = source_fde_record.getCiePointerSource(@intCast(object_id), zld, fde_record_offset); |
| 135 | 135 | const cie_offset = fde_record_offset + 4 - cie_ptr; |
| 136 | 136 | |
| 137 | 137 | const gop = try cies.getOrPut(cie_offset); |
| ... | ... | @@ -150,12 +150,12 @@ pub fn write(zld: *Zld, unwind_info: *UnwindInfo) !void { |
| 150 | 150 | } |
| 151 | 151 | |
| 152 | 152 | var fde_record = try source_fde_record.toOwned(gpa); |
| 153 | | fde_record.setCiePointer(eh_frame_offset + 4 - gop.value_ptr.*); |
| 154 | 153 | try fde_record.relocate(zld, @as(u32, @intCast(object_id)), .{ |
| 155 | 154 | .source_offset = fde_record_offset, |
| 156 | 155 | .out_offset = eh_frame_offset, |
| 157 | 156 | .sect_addr = sect.addr, |
| 158 | 157 | }); |
| 158 | fde_record.setCiePointer(eh_frame_offset + 4 - gop.value_ptr.*); |
| 159 | 159 | |
| 160 | 160 | switch (cpu_arch) { |
| 161 | 161 | .aarch64 => {}, // relocs take care of LSDA pointers |
| ... | ... | @@ -380,6 +380,29 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type { |
| 380 | 380 | } |
| 381 | 381 | } |
| 382 | 382 | |
| 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 | 406 | pub fn getCiePointer(rec: Record) u32 { |
| 384 | 407 | assert(rec.tag == .fde); |
| 385 | 408 | return mem.readIntLittle(u32, rec.data[0..4]); |