| author | |
| committer | |
| log | 7e4c386f6ab5546898b94d80f54e88d45dc6c7b9 |
| tree | a856f1921d6353ad0e0034a731d3b39c817fdea9 |
| parent | f1267e02c49f5d571420d687a6337a85ab76767d |
| parent | e835b864e8e5d2ff33b9f59f9f65c74f86093dfc |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/30768
Reviewed-by: Andrew Kelley <andrew@ziglang.org>4 files changed, 58 insertions(+), 14 deletions(-)
src/link/MachO.zig+3-1| ... | ... | @@ -1707,7 +1707,9 @@ fn initSyntheticSections(self: *MachO) !void { |
| 1707 | 1707 | } else false; |
| 1708 | 1708 | if (needs_eh_frame) { |
| 1709 | 1709 | assert(needs_unwind_info); |
| 1710 | self.eh_frame_sect_index = try self.addSection("__TEXT", "__eh_frame", .{}); | |
| 1710 | self.eh_frame_sect_index = try self.addSection("__TEXT", "__eh_frame", .{ | |
| 1711 | .flags = macho.S_COALESCED | macho.S_ATTR_NO_TOC | macho.S_ATTR_STRIP_STATIC_SYMS | macho.S_ATTR_LIVE_SUPPORT, | |
| 1712 | }); | |
| 1711 | 1713 | } |
| 1712 | 1714 | |
| 1713 | 1715 | if (self.getInternalObject()) |obj| { |
src/link/MachO/Object.zig+45-9| ... | ... | @@ -1298,10 +1298,18 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target. |
| 1298 | 1298 | superposition.getPtr(addr).?.cu = rec_index; |
| 1299 | 1299 | } |
| 1300 | 1300 | |
| 1301 | const FdeRange = struct { start: u64, end: u64 }; | |
| 1302 | var fde_ranges = try std.ArrayList(FdeRange).initCapacity(allocator, self.fdes.items.len); | |
| 1303 | defer fde_ranges.deinit(allocator); | |
| 1304 | ||
| 1301 | 1305 | for (self.fdes.items, 0..) |fde, fde_index| { |
| 1302 | 1306 | const atom = fde.getAtom(macho_file); |
| 1303 | 1307 | const addr = atom.getInputAddress(macho_file) + fde.atom_offset; |
| 1304 | 1308 | superposition.getPtr(addr).?.fde = @intCast(fde_index); |
| 1309 | ||
| 1310 | // Build FDE range for coverage check | |
| 1311 | const pc_range = fde.pc_range; | |
| 1312 | fde_ranges.appendAssumeCapacity(.{ .start = addr, .end = addr + pc_range }); | |
| 1305 | 1313 | } |
| 1306 | 1314 | |
| 1307 | 1315 | for (superposition.keys(), superposition.values()) |addr, meta| { |
| ... | ... | @@ -1333,15 +1341,43 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target. |
| 1333 | 1341 | } |
| 1334 | 1342 | } |
| 1335 | 1343 | } else if (meta.cu == null and meta.fde == null) { |
| 1336 | // Create a null record | |
| 1337 | const rec_index = try self.addUnwindRecord(allocator); | |
| 1338 | const rec = self.getUnwindRecord(rec_index); | |
| 1339 | const atom = self.getAtom(meta.atom).?; | |
| 1340 | try self.unwind_records_indexes.append(allocator, rec_index); | |
| 1341 | rec.length = @intCast(meta.size); | |
| 1342 | rec.atom = meta.atom; | |
| 1343 | rec.atom_offset = @intCast(addr - atom.getInputAddress(macho_file)); | |
| 1344 | rec.file = self.index; | |
| 1344 | // Check if this address is covered by an existing FDE. | |
| 1345 | // If so, don't create a null record - let the unwinder fall back to DWARF. | |
| 1346 | // This is important for local labels within a function that has DWARF unwind info. | |
| 1347 | const is_covered_by_fde = blk: { | |
| 1348 | if (fde_ranges.items.len == 0) break :blk false; | |
| 1349 | ||
| 1350 | // Binary search: find the last FDE where start <= addr | |
| 1351 | var left: usize = 0; | |
| 1352 | var right: usize = fde_ranges.items.len; | |
| 1353 | while (left < right) { | |
| 1354 | const mid = left + (right - left) / 2; | |
| 1355 | if (fde_ranges.items[mid].start <= addr) { | |
| 1356 | left = mid + 1; | |
| 1357 | } else { | |
| 1358 | right = mid; | |
| 1359 | } | |
| 1360 | } | |
| 1361 | ||
| 1362 | // Check if the FDE before insertion point covers this address | |
| 1363 | if (left > 0) { | |
| 1364 | const range = fde_ranges.items[left - 1]; | |
| 1365 | break :blk addr < range.end; | |
| 1366 | } | |
| 1367 | break :blk false; | |
| 1368 | }; | |
| 1369 | ||
| 1370 | if (!is_covered_by_fde) { | |
| 1371 | // Create a null record only if not covered by DWARF | |
| 1372 | const rec_index = try self.addUnwindRecord(allocator); | |
| 1373 | const rec = self.getUnwindRecord(rec_index); | |
| 1374 | const atom = self.getAtom(meta.atom).?; | |
| 1375 | try self.unwind_records_indexes.append(allocator, rec_index); | |
| 1376 | rec.length = @intCast(meta.size); | |
| 1377 | rec.atom = meta.atom; | |
| 1378 | rec.atom_offset = @intCast(addr - atom.getInputAddress(macho_file)); | |
| 1379 | rec.file = self.index; | |
| 1380 | } | |
| 1345 | 1381 | } |
| 1346 | 1382 | } |
| 1347 | 1383 |
src/link/MachO/eh_frame.zig+7-3| ... | ... | @@ -116,6 +116,7 @@ pub const Fde = struct { |
| 116 | 116 | cie: Cie.Index, |
| 117 | 117 | atom: Atom.Index = 0, |
| 118 | 118 | atom_offset: u32 = 0, |
| 119 | pc_range: u64 = 0, | |
| 119 | 120 | lsda: Atom.Index = 0, |
| 120 | 121 | lsda_offset: u32 = 0, |
| 121 | 122 | lsda_ptr_offset: u32 = 0, |
| ... | ... | @@ -142,6 +143,9 @@ pub const Fde = struct { |
| 142 | 143 | const atom = fde.getAtom(macho_file); |
| 143 | 144 | fde.atom_offset = @intCast(taddr - atom.getInputAddress(macho_file)); |
| 144 | 145 | |
| 146 | // Parse pc_range (function size) | |
| 147 | fde.pc_range = std.mem.readInt(u64, data[16..][0..8], .little); | |
| 148 | ||
| 145 | 149 | // Associate with a CIE |
| 146 | 150 | const cie_ptr = std.mem.readInt(u32, data[4..8], .little); |
| 147 | 151 | const cie_offset = fde.offset + 4 - cie_ptr; |
| ... | ... | @@ -350,7 +354,7 @@ pub fn write(macho_file: *MachO, buffer: []u8) void { |
| 350 | 354 | std.mem.writeInt( |
| 351 | 355 | i32, |
| 352 | 356 | buffer[offset..][0..4], |
| 353 | @intCast(@as(i64, @intCast(taddr)) - @as(i64, @intCast(saddr)) + addend), | |
| 357 | @intCast(@as(i64, @intCast(taddr)) - @as(i64, @intCast(saddr))), | |
| 354 | 358 | .little, |
| 355 | 359 | ); |
| 356 | 360 | } |
| ... | ... | @@ -373,7 +377,7 @@ pub fn write(macho_file: *MachO, buffer: []u8) void { |
| 373 | 377 | { |
| 374 | 378 | const offset = fde.out_offset + 8; |
| 375 | 379 | const saddr = sect.addr + offset; |
| 376 | const taddr = fde.getAtom(macho_file).getAddress(macho_file); | |
| 380 | const taddr = fde.getAtom(macho_file).getAddress(macho_file) + fde.atom_offset; | |
| 377 | 381 | std.mem.writeInt( |
| 378 | 382 | i64, |
| 379 | 383 | buffer[offset..][0..8], |
| ... | ... | @@ -460,7 +464,7 @@ pub fn writeRelocs(macho_file: *MachO, code: []u8, relocs: []macho.relocation_in |
| 460 | 464 | { |
| 461 | 465 | const offset = fde.out_offset + 8; |
| 462 | 466 | const saddr = sect.addr + offset; |
| 463 | const taddr = fde.getAtom(macho_file).getAddress(macho_file); | |
| 467 | const taddr = fde.getAtom(macho_file).getAddress(macho_file) + fde.atom_offset; | |
| 464 | 468 | std.mem.writeInt( |
| 465 | 469 | i64, |
| 466 | 470 | code[offset..][0..8], |
src/link/MachO/relocatable.zig+3-1| ... | ... | @@ -289,7 +289,9 @@ fn initOutputSections(macho_file: *MachO) !void { |
| 289 | 289 | } else false; |
| 290 | 290 | if (needs_eh_frame) { |
| 291 | 291 | assert(needs_unwind_info); |
| 292 | macho_file.eh_frame_sect_index = try macho_file.addSection("__TEXT", "__eh_frame", .{}); | |
| 292 | macho_file.eh_frame_sect_index = try macho_file.addSection("__TEXT", "__eh_frame", .{ | |
| 293 | .flags = std.macho.S_COALESCED | std.macho.S_ATTR_NO_TOC | std.macho.S_ATTR_STRIP_STATIC_SYMS | std.macho.S_ATTR_LIVE_SUPPORT, | |
| 294 | }); | |
| 293 | 295 | } |
| 294 | 296 | } |
| 295 | 297 |