| ... | ... | @@ -1,8 +1,10 @@ |
| 1 | | archive: ?InArchive = null, |
| 1 | /// Non-zero for fat object files or archives |
| 2 | offset: u64, |
| 2 | 3 | path: []const u8, |
| 3 | 4 | file_handle: File.HandleIndex, |
| 4 | 5 | mtime: u64, |
| 5 | 6 | index: File.Index, |
| 7 | in_archive: ?InArchive = null, |
| 6 | 8 | |
| 7 | 9 | header: ?macho.mach_header_64 = null, |
| 8 | 10 | sections: std.MultiArrayList(Section) = .{}, |
| ... | ... | @@ -21,7 +23,8 @@ compact_unwind_sect_index: ?u8 = null, |
| 21 | 23 | cies: std.ArrayListUnmanaged(Cie) = .{}, |
| 22 | 24 | fdes: std.ArrayListUnmanaged(Fde) = .{}, |
| 23 | 25 | eh_frame_data: std.ArrayListUnmanaged(u8) = .{}, |
| 24 | | unwind_records: std.ArrayListUnmanaged(UnwindInfo.Record.Index) = .{}, |
| 26 | unwind_records: std.ArrayListUnmanaged(UnwindInfo.Record) = .{}, |
| 27 | unwind_records_indexes: std.ArrayListUnmanaged(UnwindInfo.Record.Index) = .{}, |
| 25 | 28 | data_in_code: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{}, |
| 26 | 29 | |
| 27 | 30 | alive: bool = true, |
| ... | ... | @@ -39,7 +42,7 @@ pub fn isObject(path: []const u8) !bool { |
| 39 | 42 | } |
| 40 | 43 | |
| 41 | 44 | pub fn deinit(self: *Object, allocator: Allocator) void { |
| 42 | | if (self.archive) |*ar| allocator.free(ar.path); |
| 45 | if (self.in_archive) |*ar| allocator.free(ar.path); |
| 43 | 46 | allocator.free(self.path); |
| 44 | 47 | for (self.sections.items(.relocs), self.sections.items(.subsections)) |*relocs, *sub| { |
| 45 | 48 | relocs.deinit(allocator); |
| ... | ... | @@ -54,6 +57,7 @@ pub fn deinit(self: *Object, allocator: Allocator) void { |
| 54 | 57 | self.fdes.deinit(allocator); |
| 55 | 58 | self.eh_frame_data.deinit(allocator); |
| 56 | 59 | self.unwind_records.deinit(allocator); |
| 60 | self.unwind_records_indexes.deinit(allocator); |
| 57 | 61 | for (self.stab_files.items) |*sf| { |
| 58 | 62 | sf.stabs.deinit(allocator); |
| 59 | 63 | } |
| ... | ... | @@ -66,12 +70,11 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { |
| 66 | 70 | defer tracy.end(); |
| 67 | 71 | |
| 68 | 72 | const gpa = macho_file.base.comp.gpa; |
| 69 | | const offset = if (self.archive) |ar| ar.offset else 0; |
| 70 | 73 | const handle = macho_file.getFileHandle(self.file_handle); |
| 71 | 74 | |
| 72 | 75 | var header_buffer: [@sizeOf(macho.mach_header_64)]u8 = undefined; |
| 73 | 76 | { |
| 74 | | const amt = try handle.preadAll(&header_buffer, offset); |
| 77 | const amt = try handle.preadAll(&header_buffer, self.offset); |
| 75 | 78 | if (amt != @sizeOf(macho.mach_header_64)) return error.InputOutput; |
| 76 | 79 | } |
| 77 | 80 | self.header = @as(*align(1) const macho.mach_header_64, @ptrCast(&header_buffer)).*; |
| ... | ... | @@ -92,7 +95,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { |
| 92 | 95 | const lc_buffer = try gpa.alloc(u8, self.header.?.sizeofcmds); |
| 93 | 96 | defer gpa.free(lc_buffer); |
| 94 | 97 | { |
| 95 | | const amt = try handle.preadAll(lc_buffer, offset + @sizeOf(macho.mach_header_64)); |
| 98 | const amt = try handle.preadAll(lc_buffer, self.offset + @sizeOf(macho.mach_header_64)); |
| 96 | 99 | if (amt != self.header.?.sizeofcmds) return error.InputOutput; |
| 97 | 100 | } |
| 98 | 101 | |
| ... | ... | @@ -119,14 +122,14 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { |
| 119 | 122 | const cmd = lc.cast(macho.symtab_command).?; |
| 120 | 123 | try self.strtab.resize(gpa, cmd.strsize); |
| 121 | 124 | { |
| 122 | | const amt = try handle.preadAll(self.strtab.items, cmd.stroff + offset); |
| 125 | const amt = try handle.preadAll(self.strtab.items, cmd.stroff + self.offset); |
| 123 | 126 | if (amt != self.strtab.items.len) return error.InputOutput; |
| 124 | 127 | } |
| 125 | 128 | |
| 126 | 129 | const symtab_buffer = try gpa.alloc(u8, cmd.nsyms * @sizeOf(macho.nlist_64)); |
| 127 | 130 | defer gpa.free(symtab_buffer); |
| 128 | 131 | { |
| 129 | | const amt = try handle.preadAll(symtab_buffer, cmd.symoff + offset); |
| 132 | const amt = try handle.preadAll(symtab_buffer, cmd.symoff + self.offset); |
| 130 | 133 | if (amt != symtab_buffer.len) return error.InputOutput; |
| 131 | 134 | } |
| 132 | 135 | const symtab = @as([*]align(1) const macho.nlist_64, @ptrCast(symtab_buffer.ptr))[0..cmd.nsyms]; |
| ... | ... | @@ -144,7 +147,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { |
| 144 | 147 | const buffer = try gpa.alloc(u8, cmd.datasize); |
| 145 | 148 | defer gpa.free(buffer); |
| 146 | 149 | { |
| 147 | | const amt = try handle.preadAll(buffer, offset + cmd.dataoff); |
| 150 | const amt = try handle.preadAll(buffer, self.offset + cmd.dataoff); |
| 148 | 151 | if (amt != buffer.len) return error.InputOutput; |
| 149 | 152 | } |
| 150 | 153 | const ndice = @divExact(cmd.datasize, @sizeOf(macho.data_in_code_entry)); |
| ... | ... | @@ -218,11 +221,11 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { |
| 218 | 221 | |
| 219 | 222 | // Parse Apple's __LD,__compact_unwind section |
| 220 | 223 | if (self.compact_unwind_sect_index) |index| { |
| 221 | | try self.initUnwindRecords(index, macho_file); |
| 224 | try self.initUnwindRecords(gpa, index, handle, macho_file); |
| 222 | 225 | } |
| 223 | 226 | |
| 224 | 227 | if (self.hasUnwindRecords() or self.hasEhFrameRecords()) { |
| 225 | | try self.parseUnwindRecords(macho_file); |
| 228 | try self.parseUnwindRecords(gpa, macho_file.getTarget().cpu.arch, macho_file); |
| 226 | 229 | } |
| 227 | 230 | |
| 228 | 231 | if (self.platform) |platform| { |
| ... | ... | @@ -987,7 +990,7 @@ fn initEhFrameRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { |
| 987 | 990 | } |
| 988 | 991 | } |
| 989 | 992 | |
| 990 | | fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { |
| 993 | fn initUnwindRecords(self: *Object, allocator: Allocator, sect_id: u8, file: File.Handle, macho_file: *MachO) !void { |
| 991 | 994 | const tracy = trace(@src()); |
| 992 | 995 | defer tracy.end(); |
| 993 | 996 | |
| ... | ... | @@ -1003,19 +1006,22 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { |
| 1003 | 1006 | } |
| 1004 | 1007 | }; |
| 1005 | 1008 | |
| 1006 | | const gpa = macho_file.base.comp.gpa; |
| 1007 | | const data = try self.getSectionData(sect_id, macho_file); |
| 1008 | | defer gpa.free(data); |
| 1009 | const header = self.sections.items(.header)[sect_id]; |
| 1010 | const data = try allocator.alloc(u8, header.size); |
| 1011 | defer allocator.free(data); |
| 1012 | const amt = try file.preadAll(data, header.offset + self.offset); |
| 1013 | if (amt != data.len) return error.InputOutput; |
| 1014 | |
| 1009 | 1015 | const nrecs = @divExact(data.len, @sizeOf(macho.compact_unwind_entry)); |
| 1010 | 1016 | const recs = @as([*]align(1) const macho.compact_unwind_entry, @ptrCast(data.ptr))[0..nrecs]; |
| 1011 | 1017 | const sym_lookup = SymbolLookup{ .ctx = self }; |
| 1012 | 1018 | |
| 1013 | | try self.unwind_records.resize(gpa, nrecs); |
| 1019 | try self.unwind_records.ensureTotalCapacityPrecise(allocator, nrecs); |
| 1020 | try self.unwind_records_indexes.ensureTotalCapacityPrecise(allocator, nrecs); |
| 1014 | 1021 | |
| 1015 | | const header = self.sections.items(.header)[sect_id]; |
| 1016 | 1022 | const relocs = self.sections.items(.relocs)[sect_id].items; |
| 1017 | 1023 | var reloc_idx: usize = 0; |
| 1018 | | for (recs, self.unwind_records.items, 0..) |rec, *out_index, rec_idx| { |
| 1024 | for (recs, 0..) |rec, rec_idx| { |
| 1019 | 1025 | const rec_start = rec_idx * @sizeOf(macho.compact_unwind_entry); |
| 1020 | 1026 | const rec_end = rec_start + @sizeOf(macho.compact_unwind_entry); |
| 1021 | 1027 | const reloc_start = reloc_idx; |
| ... | ... | @@ -1023,11 +1029,11 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { |
| 1023 | 1029 | relocs[reloc_idx].offset < rec_end) : (reloc_idx += 1) |
| 1024 | 1030 | {} |
| 1025 | 1031 | |
| 1026 | | out_index.* = try macho_file.addUnwindRecord(); |
| 1027 | | const out = macho_file.getUnwindRecord(out_index.*); |
| 1032 | const out_index = self.addUnwindRecordAssumeCapacity(); |
| 1033 | self.unwind_records_indexes.appendAssumeCapacity(out_index); |
| 1034 | const out = self.getUnwindRecord(out_index); |
| 1028 | 1035 | out.length = rec.rangeLength; |
| 1029 | 1036 | out.enc = .{ .enc = rec.compactUnwindEncoding }; |
| 1030 | | out.file = self.index; |
| 1031 | 1037 | |
| 1032 | 1038 | for (relocs[reloc_start..reloc_idx]) |rel| { |
| 1033 | 1039 | if (rel.type != .unsigned or rel.meta.length != 3) { |
| ... | ... | @@ -1090,7 +1096,7 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { |
| 1090 | 1096 | } |
| 1091 | 1097 | } |
| 1092 | 1098 | |
| 1093 | | fn parseUnwindRecords(self: *Object, macho_file: *MachO) !void { |
| 1099 | fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch, macho_file: *MachO) !void { |
| 1094 | 1100 | // Synthesise missing unwind records. |
| 1095 | 1101 | // The logic here is as follows: |
| 1096 | 1102 | // 1. if an atom has unwind info record that is not DWARF, FDE is marked dead |
| ... | ... | @@ -1100,8 +1106,7 @@ fn parseUnwindRecords(self: *Object, macho_file: *MachO) !void { |
| 1100 | 1106 | |
| 1101 | 1107 | const Superposition = struct { atom: Atom.Index, size: u64, cu: ?UnwindInfo.Record.Index = null, fde: ?Fde.Index = null }; |
| 1102 | 1108 | |
| 1103 | | const gpa = macho_file.base.comp.gpa; |
| 1104 | | var superposition = std.AutoArrayHashMap(u64, Superposition).init(gpa); |
| 1109 | var superposition = std.AutoArrayHashMap(u64, Superposition).init(allocator); |
| 1105 | 1110 | defer superposition.deinit(); |
| 1106 | 1111 | |
| 1107 | 1112 | const slice = self.symtab.slice(); |
| ... | ... | @@ -1119,8 +1124,8 @@ fn parseUnwindRecords(self: *Object, macho_file: *MachO) !void { |
| 1119 | 1124 | } |
| 1120 | 1125 | } |
| 1121 | 1126 | |
| 1122 | | for (self.unwind_records.items) |rec_index| { |
| 1123 | | const rec = macho_file.getUnwindRecord(rec_index); |
| 1127 | for (self.unwind_records_indexes.items) |rec_index| { |
| 1128 | const rec = self.getUnwindRecord(rec_index); |
| 1124 | 1129 | const atom = rec.getAtom(macho_file); |
| 1125 | 1130 | const addr = atom.getInputAddress(macho_file) + rec.atom_offset; |
| 1126 | 1131 | superposition.getPtr(addr).?.cu = rec_index; |
| ... | ... | @@ -1137,7 +1142,7 @@ fn parseUnwindRecords(self: *Object, macho_file: *MachO) !void { |
| 1137 | 1142 | const fde = &self.fdes.items[fde_index]; |
| 1138 | 1143 | |
| 1139 | 1144 | if (meta.cu) |rec_index| { |
| 1140 | | const rec = macho_file.getUnwindRecord(rec_index); |
| 1145 | const rec = self.getUnwindRecord(rec_index); |
| 1141 | 1146 | if (!rec.enc.isDwarf(macho_file)) { |
| 1142 | 1147 | // Mark FDE dead |
| 1143 | 1148 | fde.alive = false; |
| ... | ... | @@ -1147,15 +1152,14 @@ fn parseUnwindRecords(self: *Object, macho_file: *MachO) !void { |
| 1147 | 1152 | } |
| 1148 | 1153 | } else { |
| 1149 | 1154 | // Synthesise new unwind info record |
| 1150 | | const rec_index = try macho_file.addUnwindRecord(); |
| 1151 | | const rec = macho_file.getUnwindRecord(rec_index); |
| 1152 | | try self.unwind_records.append(gpa, rec_index); |
| 1155 | const rec_index = try self.addUnwindRecord(allocator); |
| 1156 | const rec = self.getUnwindRecord(rec_index); |
| 1157 | try self.unwind_records_indexes.append(allocator, rec_index); |
| 1153 | 1158 | rec.length = @intCast(meta.size); |
| 1154 | 1159 | rec.atom = fde.atom; |
| 1155 | 1160 | rec.atom_offset = fde.atom_offset; |
| 1156 | 1161 | rec.fde = fde_index; |
| 1157 | | rec.file = fde.file; |
| 1158 | | switch (macho_file.getTarget().cpu.arch) { |
| 1162 | switch (cpu_arch) { |
| 1159 | 1163 | .x86_64 => rec.enc.setMode(macho.UNWIND_X86_64_MODE.DWARF), |
| 1160 | 1164 | .aarch64 => rec.enc.setMode(macho.UNWIND_ARM64_MODE.DWARF), |
| 1161 | 1165 | else => unreachable, |
| ... | ... | @@ -1163,10 +1167,10 @@ fn parseUnwindRecords(self: *Object, macho_file: *MachO) !void { |
| 1163 | 1167 | } |
| 1164 | 1168 | } else if (meta.cu == null and meta.fde == null) { |
| 1165 | 1169 | // Create a null record |
| 1166 | | const rec_index = try macho_file.addUnwindRecord(); |
| 1167 | | const rec = macho_file.getUnwindRecord(rec_index); |
| 1170 | const rec_index = try self.addUnwindRecord(allocator); |
| 1171 | const rec = self.getUnwindRecord(rec_index); |
| 1168 | 1172 | const atom = macho_file.getAtom(meta.atom).?; |
| 1169 | | try self.unwind_records.append(gpa, rec_index); |
| 1173 | try self.unwind_records_indexes.append(allocator, rec_index); |
| 1170 | 1174 | rec.length = @intCast(meta.size); |
| 1171 | 1175 | rec.atom = meta.atom; |
| 1172 | 1176 | rec.atom_offset = @intCast(addr - atom.getInputAddress(macho_file)); |
| ... | ... | @@ -1174,25 +1178,31 @@ fn parseUnwindRecords(self: *Object, macho_file: *MachO) !void { |
| 1174 | 1178 | } |
| 1175 | 1179 | } |
| 1176 | 1180 | |
| 1177 | | const sortFn = struct { |
| 1178 | | fn sortFn(ctx: *MachO, lhs_index: UnwindInfo.Record.Index, rhs_index: UnwindInfo.Record.Index) bool { |
| 1179 | | const lhs = ctx.getUnwindRecord(lhs_index); |
| 1180 | | const rhs = ctx.getUnwindRecord(rhs_index); |
| 1181 | | const lhsa = lhs.getAtom(ctx); |
| 1182 | | const rhsa = rhs.getAtom(ctx); |
| 1183 | | return lhsa.getInputAddress(ctx) + lhs.atom_offset < rhsa.getInputAddress(ctx) + rhs.atom_offset; |
| 1181 | const SortCtx = struct { |
| 1182 | object: *Object, |
| 1183 | mfile: *MachO, |
| 1184 | |
| 1185 | fn sort(ctx: @This(), lhs_index: UnwindInfo.Record.Index, rhs_index: UnwindInfo.Record.Index) bool { |
| 1186 | const lhs = ctx.object.getUnwindRecord(lhs_index); |
| 1187 | const rhs = ctx.object.getUnwindRecord(rhs_index); |
| 1188 | const lhsa = lhs.getAtom(ctx.mfile); |
| 1189 | const rhsa = rhs.getAtom(ctx.mfile); |
| 1190 | return lhsa.getInputAddress(ctx.mfile) + lhs.atom_offset < rhsa.getInputAddress(ctx.mfile) + rhs.atom_offset; |
| 1184 | 1191 | } |
| 1185 | | }.sortFn; |
| 1186 | | mem.sort(UnwindInfo.Record.Index, self.unwind_records.items, macho_file, sortFn); |
| 1192 | }; |
| 1193 | mem.sort(UnwindInfo.Record.Index, self.unwind_records_indexes.items, SortCtx{ |
| 1194 | .object = self, |
| 1195 | .mfile = macho_file, |
| 1196 | }, SortCtx.sort); |
| 1187 | 1197 | |
| 1188 | 1198 | // Associate unwind records to atoms |
| 1189 | 1199 | var next_cu: u32 = 0; |
| 1190 | | while (next_cu < self.unwind_records.items.len) { |
| 1200 | while (next_cu < self.unwind_records_indexes.items.len) { |
| 1191 | 1201 | const start = next_cu; |
| 1192 | | const rec_index = self.unwind_records.items[start]; |
| 1193 | | const rec = macho_file.getUnwindRecord(rec_index); |
| 1194 | | while (next_cu < self.unwind_records.items.len and |
| 1195 | | macho_file.getUnwindRecord(self.unwind_records.items[next_cu]).atom == rec.atom) : (next_cu += 1) |
| 1202 | const rec_index = self.unwind_records_indexes.items[start]; |
| 1203 | const rec = self.getUnwindRecord(rec_index); |
| 1204 | while (next_cu < self.unwind_records_indexes.items.len and |
| 1205 | self.getUnwindRecord(self.unwind_records_indexes.items[next_cu]).atom == rec.atom) : (next_cu += 1) |
| 1196 | 1206 | {} |
| 1197 | 1207 | |
| 1198 | 1208 | const atom = rec.getAtom(macho_file); |
| ... | ... | @@ -1441,7 +1451,7 @@ pub fn checkDuplicates(self: *Object, dupes: anytype, macho_file: *MachO) error{ |
| 1441 | 1451 | } |
| 1442 | 1452 | } |
| 1443 | 1453 | |
| 1444 | | pub fn scanRelocs(self: Object, macho_file: *MachO) !void { |
| 1454 | pub fn scanRelocs(self: *Object, macho_file: *MachO) !void { |
| 1445 | 1455 | const tracy = trace(@src()); |
| 1446 | 1456 | defer tracy.end(); |
| 1447 | 1457 | |
| ... | ... | @@ -1453,8 +1463,8 @@ pub fn scanRelocs(self: Object, macho_file: *MachO) !void { |
| 1453 | 1463 | try atom.scanRelocs(macho_file); |
| 1454 | 1464 | } |
| 1455 | 1465 | |
| 1456 | | for (self.unwind_records.items) |rec_index| { |
| 1457 | | const rec = macho_file.getUnwindRecord(rec_index); |
| 1466 | for (self.unwind_records_indexes.items) |rec_index| { |
| 1467 | const rec = self.getUnwindRecord(rec_index); |
| 1458 | 1468 | if (!rec.alive) continue; |
| 1459 | 1469 | if (rec.getFde(macho_file)) |fde| { |
| 1460 | 1470 | if (fde.getCie(macho_file).getPersonality(macho_file)) |sym| { |
| ... | ... | @@ -1532,12 +1542,11 @@ pub fn parseAr(self: *Object, macho_file: *MachO) !void { |
| 1532 | 1542 | defer tracy.end(); |
| 1533 | 1543 | |
| 1534 | 1544 | const gpa = macho_file.base.comp.gpa; |
| 1535 | | const offset = if (self.archive) |ar| ar.offset else 0; |
| 1536 | 1545 | const handle = macho_file.getFileHandle(self.file_handle); |
| 1537 | 1546 | |
| 1538 | 1547 | var header_buffer: [@sizeOf(macho.mach_header_64)]u8 = undefined; |
| 1539 | 1548 | { |
| 1540 | | const amt = try handle.preadAll(&header_buffer, offset); |
| 1549 | const amt = try handle.preadAll(&header_buffer, self.offset); |
| 1541 | 1550 | if (amt != @sizeOf(macho.mach_header_64)) return error.InputOutput; |
| 1542 | 1551 | } |
| 1543 | 1552 | self.header = @as(*align(1) const macho.mach_header_64, @ptrCast(&header_buffer)).*; |
| ... | ... | @@ -1558,7 +1567,7 @@ pub fn parseAr(self: *Object, macho_file: *MachO) !void { |
| 1558 | 1567 | const lc_buffer = try gpa.alloc(u8, self.header.?.sizeofcmds); |
| 1559 | 1568 | defer gpa.free(lc_buffer); |
| 1560 | 1569 | { |
| 1561 | | const amt = try handle.preadAll(lc_buffer, offset + @sizeOf(macho.mach_header_64)); |
| 1570 | const amt = try handle.preadAll(lc_buffer, self.offset + @sizeOf(macho.mach_header_64)); |
| 1562 | 1571 | if (amt != self.header.?.sizeofcmds) return error.InputOutput; |
| 1563 | 1572 | } |
| 1564 | 1573 | |
| ... | ... | @@ -1571,14 +1580,14 @@ pub fn parseAr(self: *Object, macho_file: *MachO) !void { |
| 1571 | 1580 | const cmd = lc.cast(macho.symtab_command).?; |
| 1572 | 1581 | try self.strtab.resize(gpa, cmd.strsize); |
| 1573 | 1582 | { |
| 1574 | | const amt = try handle.preadAll(self.strtab.items, cmd.stroff + offset); |
| 1583 | const amt = try handle.preadAll(self.strtab.items, cmd.stroff + self.offset); |
| 1575 | 1584 | if (amt != self.strtab.items.len) return error.InputOutput; |
| 1576 | 1585 | } |
| 1577 | 1586 | |
| 1578 | 1587 | const symtab_buffer = try gpa.alloc(u8, cmd.nsyms * @sizeOf(macho.nlist_64)); |
| 1579 | 1588 | defer gpa.free(symtab_buffer); |
| 1580 | 1589 | { |
| 1581 | | const amt = try handle.preadAll(symtab_buffer, cmd.symoff + offset); |
| 1590 | const amt = try handle.preadAll(symtab_buffer, cmd.symoff + self.offset); |
| 1582 | 1591 | if (amt != symtab_buffer.len) return error.InputOutput; |
| 1583 | 1592 | } |
| 1584 | 1593 | const symtab = @as([*]align(1) const macho.nlist_64, @ptrCast(symtab_buffer.ptr))[0..cmd.nsyms]; |
| ... | ... | @@ -1613,7 +1622,7 @@ pub fn updateArSymtab(self: Object, ar_symtab: *Archive.ArSymtab, macho_file: *M |
| 1613 | 1622 | } |
| 1614 | 1623 | |
| 1615 | 1624 | pub fn updateArSize(self: *Object, macho_file: *MachO) !void { |
| 1616 | | self.output_ar_state.size = if (self.archive) |ar| ar.size else size: { |
| 1625 | self.output_ar_state.size = if (self.in_archive) |ar| ar.size else size: { |
| 1617 | 1626 | const file = macho_file.getFileHandle(self.file_handle); |
| 1618 | 1627 | break :size (try file.stat()).size; |
| 1619 | 1628 | }; |
| ... | ... | @@ -1622,7 +1631,6 @@ pub fn updateArSize(self: *Object, macho_file: *MachO) !void { |
| 1622 | 1631 | pub fn writeAr(self: Object, ar_format: Archive.Format, macho_file: *MachO, writer: anytype) !void { |
| 1623 | 1632 | // Header |
| 1624 | 1633 | const size = std.math.cast(usize, self.output_ar_state.size) orelse return error.Overflow; |
| 1625 | | const offset: u64 = if (self.archive) |ar| ar.offset else 0; |
| 1626 | 1634 | try Archive.writeHeader(self.path, size, ar_format, writer); |
| 1627 | 1635 | // Data |
| 1628 | 1636 | const file = macho_file.getFileHandle(self.file_handle); |
| ... | ... | @@ -1630,7 +1638,7 @@ pub fn writeAr(self: Object, ar_format: Archive.Format, macho_file: *MachO, writ |
| 1630 | 1638 | const gpa = macho_file.base.comp.gpa; |
| 1631 | 1639 | const data = try gpa.alloc(u8, size); |
| 1632 | 1640 | defer gpa.free(data); |
| 1633 | | const amt = try file.preadAll(data, offset); |
| 1641 | const amt = try file.preadAll(data, self.offset); |
| 1634 | 1642 | if (amt != size) return error.InputOutput; |
| 1635 | 1643 | try writer.writeAll(data); |
| 1636 | 1644 | } |
| ... | ... | @@ -1680,7 +1688,7 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) error{Overflow}!void { |
| 1680 | 1688 | self.output_symtab_ctx.strsize += @as(u32, @intCast(comp_dir.len + 1)); // comp_dir |
| 1681 | 1689 | self.output_symtab_ctx.strsize += @as(u32, @intCast(tu_name.len + 1)); // tu_name |
| 1682 | 1690 | |
| 1683 | | if (self.archive) |ar| { |
| 1691 | if (self.in_archive) |ar| { |
| 1684 | 1692 | self.output_symtab_ctx.strsize += @as(u32, @intCast(ar.path.len + 1 + self.path.len + 1 + 1)); |
| 1685 | 1693 | } else { |
| 1686 | 1694 | self.output_symtab_ctx.strsize += @as(u32, @intCast(self.path.len + 1)); |
| ... | ... | @@ -1820,7 +1828,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO, ctx: anytype) error{O |
| 1820 | 1828 | index += 1; |
| 1821 | 1829 | // N_OSO path |
| 1822 | 1830 | n_strx = @as(u32, @intCast(ctx.strtab.items.len)); |
| 1823 | | if (self.archive) |ar| { |
| 1831 | if (self.in_archive) |ar| { |
| 1824 | 1832 | ctx.strtab.appendSliceAssumeCapacity(ar.path); |
| 1825 | 1833 | ctx.strtab.appendAssumeCapacity('('); |
| 1826 | 1834 | ctx.strtab.appendSliceAssumeCapacity(self.path); |
| ... | ... | @@ -1989,11 +1997,10 @@ fn getSectionData(self: *const Object, index: u32, macho_file: *MachO) ![]u8 { |
| 1989 | 1997 | assert(index < slice.items(.header).len); |
| 1990 | 1998 | const sect = slice.items(.header)[index]; |
| 1991 | 1999 | const handle = macho_file.getFileHandle(self.file_handle); |
| 1992 | | const offset = if (self.archive) |ar| ar.offset else 0; |
| 1993 | 2000 | const size = math.cast(usize, sect.size) orelse return error.Overflow; |
| 1994 | 2001 | const buffer = try gpa.alloc(u8, size); |
| 1995 | 2002 | errdefer gpa.free(buffer); |
| 1996 | | const amt = try handle.preadAll(buffer, sect.offset + offset); |
| 2003 | const amt = try handle.preadAll(buffer, sect.offset + self.offset); |
| 1997 | 2004 | if (amt != buffer.len) return error.InputOutput; |
| 1998 | 2005 | return buffer; |
| 1999 | 2006 | } |
| ... | ... | @@ -2002,9 +2009,8 @@ pub fn getAtomData(self: *const Object, macho_file: *MachO, atom: Atom, buffer: |
| 2002 | 2009 | assert(buffer.len == atom.size); |
| 2003 | 2010 | const slice = self.sections.slice(); |
| 2004 | 2011 | const handle = macho_file.getFileHandle(self.file_handle); |
| 2005 | | const offset = if (self.archive) |ar| ar.offset else 0; |
| 2006 | 2012 | const sect = slice.items(.header)[atom.n_sect]; |
| 2007 | | const amt = try handle.preadAll(buffer, sect.offset + offset + atom.off); |
| 2013 | const amt = try handle.preadAll(buffer, sect.offset + self.offset + atom.off); |
| 2008 | 2014 | if (amt != buffer.len) return error.InputOutput; |
| 2009 | 2015 | } |
| 2010 | 2016 | |
| ... | ... | @@ -2068,6 +2074,23 @@ pub fn asFile(self: *Object) File { |
| 2068 | 2074 | return .{ .object = self }; |
| 2069 | 2075 | } |
| 2070 | 2076 | |
| 2077 | fn addUnwindRecord(self: *Object, allocator: Allocator) !UnwindInfo.Record.Index { |
| 2078 | try self.unwind_records.ensureUnusedCapacity(allocator, 1); |
| 2079 | return self.addUnwindRecordAssumeCapacity(); |
| 2080 | } |
| 2081 | |
| 2082 | fn addUnwindRecordAssumeCapacity(self: *Object) UnwindInfo.Record.Index { |
| 2083 | const index = @as(UnwindInfo.Record.Index, @intCast(self.unwind_records.items.len)); |
| 2084 | const rec = self.unwind_records.addOneAssumeCapacity(); |
| 2085 | rec.* = .{ .file = self.index }; |
| 2086 | return index; |
| 2087 | } |
| 2088 | |
| 2089 | pub fn getUnwindRecord(self: *Object, index: UnwindInfo.Record.Index) *UnwindInfo.Record { |
| 2090 | assert(index < self.unwind_records.items.len); |
| 2091 | return &self.unwind_records.items[index]; |
| 2092 | } |
| 2093 | |
| 2071 | 2094 | pub fn format( |
| 2072 | 2095 | self: *Object, |
| 2073 | 2096 | comptime unused_fmt_string: []const u8, |
| ... | ... | @@ -2171,8 +2194,8 @@ fn formatUnwindRecords( |
| 2171 | 2194 | const object = ctx.object; |
| 2172 | 2195 | const macho_file = ctx.macho_file; |
| 2173 | 2196 | try writer.writeAll(" unwind records\n"); |
| 2174 | | for (object.unwind_records.items) |rec| { |
| 2175 | | try writer.print(" rec({d}) : {}\n", .{ rec, macho_file.getUnwindRecord(rec).fmt(macho_file) }); |
| 2197 | for (object.unwind_records_indexes.items) |rec| { |
| 2198 | try writer.print(" rec({d}) : {}\n", .{ rec, object.getUnwindRecord(rec).fmt(macho_file) }); |
| 2176 | 2199 | } |
| 2177 | 2200 | } |
| 2178 | 2201 | |
| ... | ... | @@ -2211,7 +2234,7 @@ fn formatPath( |
| 2211 | 2234 | ) !void { |
| 2212 | 2235 | _ = unused_fmt_string; |
| 2213 | 2236 | _ = options; |
| 2214 | | if (object.archive) |ar| { |
| 2237 | if (object.in_archive) |ar| { |
| 2215 | 2238 | try writer.writeAll(ar.path); |
| 2216 | 2239 | try writer.writeByte('('); |
| 2217 | 2240 | try writer.writeAll(object.path); |
| ... | ... | @@ -2285,7 +2308,6 @@ const CompileUnit = struct { |
| 2285 | 2308 | |
| 2286 | 2309 | const InArchive = struct { |
| 2287 | 2310 | path: []const u8, |
| 2288 | | offset: u64, |
| 2289 | 2311 | size: u32, |
| 2290 | 2312 | }; |
| 2291 | 2313 | |
| ... | ... | @@ -2300,11 +2322,10 @@ const x86_64 = struct { |
| 2300 | 2322 | const gpa = macho_file.base.comp.gpa; |
| 2301 | 2323 | |
| 2302 | 2324 | const handle = macho_file.getFileHandle(self.file_handle); |
| 2303 | | const offset = if (self.archive) |ar| ar.offset else 0; |
| 2304 | 2325 | const relocs_buffer = try gpa.alloc(u8, sect.nreloc * @sizeOf(macho.relocation_info)); |
| 2305 | 2326 | defer gpa.free(relocs_buffer); |
| 2306 | 2327 | { |
| 2307 | | const amt = try handle.preadAll(relocs_buffer, sect.reloff + offset); |
| 2328 | const amt = try handle.preadAll(relocs_buffer, sect.reloff + self.offset); |
| 2308 | 2329 | if (amt != relocs_buffer.len) return error.InputOutput; |
| 2309 | 2330 | } |
| 2310 | 2331 | const relocs = @as([*]align(1) const macho.relocation_info, @ptrCast(relocs_buffer.ptr))[0..sect.nreloc]; |
| ... | ... | @@ -2463,11 +2484,10 @@ const aarch64 = struct { |
| 2463 | 2484 | const gpa = macho_file.base.comp.gpa; |
| 2464 | 2485 | |
| 2465 | 2486 | const handle = macho_file.getFileHandle(self.file_handle); |
| 2466 | | const offset = if (self.archive) |ar| ar.offset else 0; |
| 2467 | 2487 | const relocs_buffer = try gpa.alloc(u8, sect.nreloc * @sizeOf(macho.relocation_info)); |
| 2468 | 2488 | defer gpa.free(relocs_buffer); |
| 2469 | 2489 | { |
| 2470 | | const amt = try handle.preadAll(relocs_buffer, sect.reloff + offset); |
| 2490 | const amt = try handle.preadAll(relocs_buffer, sect.reloff + self.offset); |
| 2471 | 2491 | if (amt != relocs_buffer.len) return error.InputOutput; |
| 2472 | 2492 | } |
| 2473 | 2493 | const relocs = @as([*]align(1) const macho.relocation_info, @ptrCast(relocs_buffer.ptr))[0..sect.nreloc]; |