authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-13 12:39:24+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-24 12:34:39+01:00
log56303d770e8330eb47c12a395ce45e3d448f892d
tree5debf80280237cae2f9f390b9df8fe7d0fa2b88f
parent11524e4d0c1e924d49dccc03eb8b0beb71872792

macho: fix invalid generation of FDE records


3 files changed, 29 insertions(+), 10 deletions(-)

src/link/MachO/UnwindInfo.zig+26-7
......@@ -65,6 +65,16 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
6565 const rec = macho_file.getUnwindRecord(index);
6666 if (rec.getFde(macho_file)) |fde| {
6767 rec.enc.setDwarfSectionOffset(@intCast(fde.out_offset));
68 if (fde.getLsdaAtom(macho_file)) |lsda| {
69 rec.lsda = lsda.atom_index;
70 rec.lsda_offset = fde.lsda_offset;
71 rec.enc.setHasLsda(true);
72 }
73 const cie = fde.getCie(macho_file);
74 if (cie.getPersonality(macho_file)) |_| {
75 const personality_index = try info.getOrPutPersonalityFunction(cie.personality.?.index); // TODO handle error
76 rec.enc.setPersonalityIndex(personality_index + 1);
77 }
6878 } else if (rec.getPersonality(macho_file)) |_| {
6979 const personality_index = try info.getOrPutPersonalityFunction(rec.personality.?); // TODO handle error
7080 rec.enc.setPersonalityIndex(personality_index + 1);
......@@ -232,11 +242,13 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
232242 }
233243
234244 // Save records having an LSDA pointer
245 log.debug("LSDA pointers:", .{});
235246 try info.lsdas_lookup.ensureTotalCapacityPrecise(gpa, info.records.items.len);
236247 for (info.records.items, 0..) |index, i| {
237248 const rec = macho_file.getUnwindRecord(index);
238249 info.lsdas_lookup.appendAssumeCapacity(@intCast(info.lsdas.items.len));
239 if (rec.getLsdaAtom(macho_file)) |_| {
250 if (rec.getLsdaAtom(macho_file)) |lsda| {
251 log.debug(" @{x} => lsda({d})", .{ rec.getAtomAddress(macho_file), lsda.atom_index });
240252 try info.lsdas.append(gpa, @intCast(i));
241253 }
242254 }
......@@ -367,7 +379,8 @@ pub const Encoding = extern struct {
367379
368380 pub fn getMode(enc: Encoding) u4 {
369381 comptime assert(macho.UNWIND_ARM64_MODE_MASK == macho.UNWIND_X86_64_MODE_MASK);
370 return @as(u4, @truncate((enc.enc & macho.UNWIND_ARM64_MODE_MASK) >> 24));
382 const shift = comptime @ctz(macho.UNWIND_ARM64_MODE_MASK);
383 return @as(u4, @truncate((enc.enc & macho.UNWIND_ARM64_MODE_MASK) >> shift));
371384 }
372385
373386 pub fn isDwarf(enc: Encoding, macho_file: *MachO) bool {
......@@ -380,26 +393,32 @@ pub const Encoding = extern struct {
380393 }
381394
382395 pub fn setMode(enc: *Encoding, mode: anytype) void {
383 enc.enc |= @as(u32, @intCast(@intFromEnum(mode))) << 24;
396 comptime assert(macho.UNWIND_ARM64_MODE_MASK == macho.UNWIND_X86_64_MODE_MASK);
397 const shift = comptime @ctz(macho.UNWIND_ARM64_MODE_MASK);
398 enc.enc |= @as(u32, @intCast(@intFromEnum(mode))) << shift;
384399 }
385400
386401 pub fn hasLsda(enc: Encoding) bool {
387 const has_lsda = @as(u1, @truncate((enc.enc & macho.UNWIND_HAS_LSDA) >> 31));
402 const shift = comptime @ctz(macho.UNWIND_HAS_LSDA);
403 const has_lsda = @as(u1, @truncate((enc.enc & macho.UNWIND_HAS_LSDA) >> shift));
388404 return has_lsda == 1;
389405 }
390406
391407 pub fn setHasLsda(enc: *Encoding, has_lsda: bool) void {
392 const mask = @as(u32, @intCast(@intFromBool(has_lsda))) << 31;
408 const shift = comptime @ctz(macho.UNWIND_HAS_LSDA);
409 const mask = @as(u32, @intCast(@intFromBool(has_lsda))) << shift;
393410 enc.enc |= mask;
394411 }
395412
396413 pub fn getPersonalityIndex(enc: Encoding) u2 {
397 const index = @as(u2, @truncate((enc.enc & macho.UNWIND_PERSONALITY_MASK) >> 28));
414 const shift = comptime @ctz(macho.UNWIND_PERSONALITY_MASK);
415 const index = @as(u2, @truncate((enc.enc & macho.UNWIND_PERSONALITY_MASK) >> shift));
398416 return index;
399417 }
400418
401419 pub fn setPersonalityIndex(enc: *Encoding, index: u2) void {
402 const mask = @as(u32, @intCast(index)) << 28;
420 const shift = comptime @ctz(macho.UNWIND_PERSONALITY_MASK);
421 const mask = @as(u32, @intCast(index)) << shift;
403422 enc.enc |= mask;
404423 }
405424
src/link/MachO/eh_frame.zig+2-2
......@@ -426,9 +426,9 @@ pub fn write(macho_file: *MachO, buffer: []u8) void {
426426 }
427427
428428 if (fde.getLsdaAtom(macho_file)) |atom| {
429 const offset = fde.out_offset + fde.lsda_offset;
429 const offset = fde.out_offset + fde.lsda_ptr_offset;
430430 const saddr = sect.addr + offset;
431 const taddr = atom.value;
431 const taddr = atom.value + fde.lsda_offset;
432432 switch (fde.getCie(macho_file).lsda_size.?) {
433433 .p32 => std.mem.writeInt(
434434 i32,
test/link/macho/unwind_info/build.zig+1-1
......@@ -46,7 +46,7 @@ fn testUnwindInfo(
4646 }
4747
4848 check.checkInSymtab();
49 check.checkContains("(__TEXT,__text) private external ___gxx_personality_v0");
49 check.checkContains("(was private external) ___gxx_personality_v0");
5050 test_step.dependOn(&check.step);
5151
5252 const run = b.addRunArtifact(exe);