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 {...@@ -65,6 +65,16 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
65 const rec = macho_file.getUnwindRecord(index);65 const rec = macho_file.getUnwindRecord(index);
66 if (rec.getFde(macho_file)) |fde| {66 if (rec.getFde(macho_file)) |fde| {
67 rec.enc.setDwarfSectionOffset(@intCast(fde.out_offset));67 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 }
68 } else if (rec.getPersonality(macho_file)) |_| {78 } else if (rec.getPersonality(macho_file)) |_| {
69 const personality_index = try info.getOrPutPersonalityFunction(rec.personality.?); // TODO handle error79 const personality_index = try info.getOrPutPersonalityFunction(rec.personality.?); // TODO handle error
70 rec.enc.setPersonalityIndex(personality_index + 1);80 rec.enc.setPersonalityIndex(personality_index + 1);
...@@ -232,11 +242,13 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {...@@ -232,11 +242,13 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
232 }242 }
233243
234 // Save records having an LSDA pointer244 // Save records having an LSDA pointer
245 log.debug("LSDA pointers:", .{});
235 try info.lsdas_lookup.ensureTotalCapacityPrecise(gpa, info.records.items.len);246 try info.lsdas_lookup.ensureTotalCapacityPrecise(gpa, info.records.items.len);
236 for (info.records.items, 0..) |index, i| {247 for (info.records.items, 0..) |index, i| {
237 const rec = macho_file.getUnwindRecord(index);248 const rec = macho_file.getUnwindRecord(index);
238 info.lsdas_lookup.appendAssumeCapacity(@intCast(info.lsdas.items.len));249 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 });
240 try info.lsdas.append(gpa, @intCast(i));252 try info.lsdas.append(gpa, @intCast(i));
241 }253 }
242 }254 }
...@@ -367,7 +379,8 @@ pub const Encoding = extern struct {...@@ -367,7 +379,8 @@ pub const Encoding = extern struct {
367379
368 pub fn getMode(enc: Encoding) u4 {380 pub fn getMode(enc: Encoding) u4 {
369 comptime assert(macho.UNWIND_ARM64_MODE_MASK == macho.UNWIND_X86_64_MODE_MASK);381 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));
371 }384 }
372385
373 pub fn isDwarf(enc: Encoding, macho_file: *MachO) bool {386 pub fn isDwarf(enc: Encoding, macho_file: *MachO) bool {
...@@ -380,26 +393,32 @@ pub const Encoding = extern struct {...@@ -380,26 +393,32 @@ pub const Encoding = extern struct {
380 }393 }
381394
382 pub fn setMode(enc: *Encoding, mode: anytype) void {395 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;
384 }399 }
385400
386 pub fn hasLsda(enc: Encoding) bool {401 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));
388 return has_lsda == 1;404 return has_lsda == 1;
389 }405 }
390406
391 pub fn setHasLsda(enc: *Encoding, has_lsda: bool) void {407 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;
393 enc.enc |= mask;410 enc.enc |= mask;
394 }411 }
395412
396 pub fn getPersonalityIndex(enc: Encoding) u2 {413 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));
398 return index;416 return index;
399 }417 }
400418
401 pub fn setPersonalityIndex(enc: *Encoding, index: u2) void {419 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;
403 enc.enc |= mask;422 enc.enc |= mask;
404 }423 }
405424
src/link/MachO/eh_frame.zig+2-2
...@@ -426,9 +426,9 @@ pub fn write(macho_file: *MachO, buffer: []u8) void {...@@ -426,9 +426,9 @@ pub fn write(macho_file: *MachO, buffer: []u8) void {
426 }426 }
427427
428 if (fde.getLsdaAtom(macho_file)) |atom| {428 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;
430 const saddr = sect.addr + offset;430 const saddr = sect.addr + offset;
431 const taddr = atom.value;431 const taddr = atom.value + fde.lsda_offset;
432 switch (fde.getCie(macho_file).lsda_size.?) {432 switch (fde.getCie(macho_file).lsda_size.?) {
433 .p32 => std.mem.writeInt(433 .p32 => std.mem.writeInt(
434 i32,434 i32,
test/link/macho/unwind_info/build.zig+1-1
...@@ -46,7 +46,7 @@ fn testUnwindInfo(...@@ -46,7 +46,7 @@ fn testUnwindInfo(
46 }46 }
4747
48 check.checkInSymtab();48 check.checkInSymtab();
49 check.checkContains("(__TEXT,__text) private external ___gxx_personality_v0");49 check.checkContains("(was private external) ___gxx_personality_v0");
50 test_step.dependOn(&check.step);50 test_step.dependOn(&check.step);
5151
52 const run = b.addRunArtifact(exe);52 const run = b.addRunArtifact(exe);