| ... | ... | @@ -164,6 +164,10 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { |
| 164 | 164 | try self.initUnwindRecords(index, macho_file); |
| 165 | 165 | } |
| 166 | 166 | |
| 167 | if (self.hasUnwindRecords() or self.hasEhFrameRecords()) { |
| 168 | try self.parseUnwindRecords(macho_file); |
| 169 | } |
| 170 | |
| 167 | 171 | self.initPlatform(); |
| 168 | 172 | |
| 169 | 173 | if (self.platform) |platform| { |
| ... | ... | @@ -816,36 +820,9 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { |
| 816 | 820 | } |
| 817 | 821 | } |
| 818 | 822 | } |
| 819 | | |
| 820 | | if (!macho_file.base.isObject()) try self.synthesiseNullUnwindRecords(macho_file); |
| 821 | | |
| 822 | | const sortFn = struct { |
| 823 | | fn sortFn(ctx: *MachO, lhs_index: UnwindInfo.Record.Index, rhs_index: UnwindInfo.Record.Index) bool { |
| 824 | | const lhs = ctx.getUnwindRecord(lhs_index); |
| 825 | | const rhs = ctx.getUnwindRecord(rhs_index); |
| 826 | | const lhsa = lhs.getAtom(ctx); |
| 827 | | const rhsa = rhs.getAtom(ctx); |
| 828 | | return lhsa.getInputAddress(ctx) + lhs.atom_offset < rhsa.getInputAddress(ctx) + rhs.atom_offset; |
| 829 | | } |
| 830 | | }.sortFn; |
| 831 | | mem.sort(UnwindInfo.Record.Index, self.unwind_records.items, macho_file, sortFn); |
| 832 | | |
| 833 | | // Associate unwind records to atoms |
| 834 | | var next_cu: u32 = 0; |
| 835 | | while (next_cu < self.unwind_records.items.len) { |
| 836 | | const start = next_cu; |
| 837 | | const rec_index = self.unwind_records.items[start]; |
| 838 | | const rec = macho_file.getUnwindRecord(rec_index); |
| 839 | | while (next_cu < self.unwind_records.items.len and |
| 840 | | macho_file.getUnwindRecord(self.unwind_records.items[next_cu]).atom == rec.atom) : (next_cu += 1) |
| 841 | | {} |
| 842 | | |
| 843 | | const atom = rec.getAtom(macho_file); |
| 844 | | atom.unwind_records = .{ .pos = start, .len = next_cu - start }; |
| 845 | | } |
| 846 | 823 | } |
| 847 | 824 | |
| 848 | | fn synthesiseNullUnwindRecords(self: *Object, macho_file: *MachO) !void { |
| 825 | fn parseUnwindRecords(self: *Object, macho_file: *MachO) !void { |
| 849 | 826 | // Synthesise missing unwind records. |
| 850 | 827 | // The logic here is as follows: |
| 851 | 828 | // 1. if an atom has unwind info record that is not DWARF, FDE is marked dead |
| ... | ... | @@ -902,12 +879,10 @@ fn synthesiseNullUnwindRecords(self: *Object, macho_file: *MachO) !void { |
| 902 | 879 | } |
| 903 | 880 | } else { |
| 904 | 881 | // Synthesise new unwind info record |
| 905 | | const fde_data = fde.getData(macho_file); |
| 906 | | const atom_size = mem.readInt(u64, fde_data[16..][0..8], .little); |
| 907 | 882 | const rec_index = try macho_file.addUnwindRecord(); |
| 908 | 883 | const rec = macho_file.getUnwindRecord(rec_index); |
| 909 | 884 | try self.unwind_records.append(gpa, rec_index); |
| 910 | | rec.length = @intCast(atom_size); |
| 885 | rec.length = @intCast(meta.size); |
| 911 | 886 | rec.atom = fde.atom; |
| 912 | 887 | rec.atom_offset = fde.atom_offset; |
| 913 | 888 | rec.fde = fde_index; |
| ... | ... | @@ -930,6 +905,31 @@ fn synthesiseNullUnwindRecords(self: *Object, macho_file: *MachO) !void { |
| 930 | 905 | rec.file = self.index; |
| 931 | 906 | } |
| 932 | 907 | } |
| 908 | |
| 909 | const sortFn = struct { |
| 910 | fn sortFn(ctx: *MachO, lhs_index: UnwindInfo.Record.Index, rhs_index: UnwindInfo.Record.Index) bool { |
| 911 | const lhs = ctx.getUnwindRecord(lhs_index); |
| 912 | const rhs = ctx.getUnwindRecord(rhs_index); |
| 913 | const lhsa = lhs.getAtom(ctx); |
| 914 | const rhsa = rhs.getAtom(ctx); |
| 915 | return lhsa.getInputAddress(ctx) + lhs.atom_offset < rhsa.getInputAddress(ctx) + rhs.atom_offset; |
| 916 | } |
| 917 | }.sortFn; |
| 918 | mem.sort(UnwindInfo.Record.Index, self.unwind_records.items, macho_file, sortFn); |
| 919 | |
| 920 | // Associate unwind records to atoms |
| 921 | var next_cu: u32 = 0; |
| 922 | while (next_cu < self.unwind_records.items.len) { |
| 923 | const start = next_cu; |
| 924 | const rec_index = self.unwind_records.items[start]; |
| 925 | const rec = macho_file.getUnwindRecord(rec_index); |
| 926 | while (next_cu < self.unwind_records.items.len and |
| 927 | macho_file.getUnwindRecord(self.unwind_records.items[next_cu]).atom == rec.atom) : (next_cu += 1) |
| 928 | {} |
| 929 | |
| 930 | const atom = rec.getAtom(macho_file); |
| 931 | atom.unwind_records = .{ .pos = start, .len = next_cu - start }; |
| 932 | } |
| 933 | 933 | } |
| 934 | 934 | |
| 935 | 935 | fn initPlatform(self: *Object) void { |
| ... | ... | @@ -1566,6 +1566,14 @@ fn getString(self: Object, off: u32) [:0]const u8 { |
| 1566 | 1566 | return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.ptr + off)), 0); |
| 1567 | 1567 | } |
| 1568 | 1568 | |
| 1569 | pub fn hasUnwindRecords(self: Object) bool { |
| 1570 | return self.unwind_records.items.len > 0; |
| 1571 | } |
| 1572 | |
| 1573 | pub fn hasEhFrameRecords(self: Object) bool { |
| 1574 | return self.cies.items.len > 0; |
| 1575 | } |
| 1576 | |
| 1569 | 1577 | /// TODO handle multiple CUs |
| 1570 | 1578 | pub fn hasDebugInfo(self: Object) bool { |
| 1571 | 1579 | if (self.dwarf_info) |dw| { |