| ... | @@ -164,6 +164,10 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { | ... | @@ -164,6 +164,10 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { |
| 164 | try self.initUnwindRecords(index, macho_file); | 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 | self.initPlatform(); | 171 | self.initPlatform(); |
| 168 | | 172 | |
| 169 | if (self.platform) |platform| { | 173 | if (self.platform) |platform| { |
| ... | @@ -816,36 +820,9 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { | ... | @@ -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 | // Synthesise missing unwind records. | 826 | // Synthesise missing unwind records. |
| 850 | // The logic here is as follows: | 827 | // The logic here is as follows: |
| 851 | // 1. if an atom has unwind info record that is not DWARF, FDE is marked dead | 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,12 +879,10 @@ fn synthesiseNullUnwindRecords(self: *Object, macho_file: *MachO) !void { |
| 902 | } | 879 | } |
| 903 | } else { | 880 | } else { |
| 904 | // Synthesise new unwind info record | 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 | const rec_index = try macho_file.addUnwindRecord(); | 882 | const rec_index = try macho_file.addUnwindRecord(); |
| 908 | const rec = macho_file.getUnwindRecord(rec_index); | 883 | const rec = macho_file.getUnwindRecord(rec_index); |
| 909 | try self.unwind_records.append(gpa, rec_index); | 884 | try self.unwind_records.append(gpa, rec_index); |
| 910 | rec.length = @intCast(atom_size); | 885 | rec.length = @intCast(meta.size); |
| 911 | rec.atom = fde.atom; | 886 | rec.atom = fde.atom; |
| 912 | rec.atom_offset = fde.atom_offset; | 887 | rec.atom_offset = fde.atom_offset; |
| 913 | rec.fde = fde_index; | 888 | rec.fde = fde_index; |
| ... | @@ -930,6 +905,31 @@ fn synthesiseNullUnwindRecords(self: *Object, macho_file: *MachO) !void { | ... | @@ -930,6 +905,31 @@ fn synthesiseNullUnwindRecords(self: *Object, macho_file: *MachO) !void { |
| 930 | rec.file = self.index; | 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 | fn initPlatform(self: *Object) void { | 935 | fn initPlatform(self: *Object) void { |
| ... | @@ -1566,6 +1566,14 @@ fn getString(self: Object, off: u32) [:0]const u8 { | ... | @@ -1566,6 +1566,14 @@ fn getString(self: Object, off: u32) [:0]const u8 { |
| 1566 | return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.ptr + off)), 0); | 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 | /// TODO handle multiple CUs | 1577 | /// TODO handle multiple CUs |
| 1570 | pub fn hasDebugInfo(self: Object) bool { | 1578 | pub fn hasDebugInfo(self: Object) bool { |
| 1571 | if (self.dwarf_info) |dw| { | 1579 | if (self.dwarf_info) |dw| { |