| ... | ... | @@ -24,8 +24,11 @@ mtime: u64, |
| 24 | 24 | contents: []align(@alignOf(u64)) const u8, |
| 25 | 25 | |
| 26 | 26 | header: macho.mach_header_64 = undefined, |
| 27 | | in_symtab: []align(1) const macho.nlist_64 = undefined, |
| 28 | | in_strtab: []const u8 = undefined, |
| 27 | |
| 28 | /// Symtab and strtab might not exist for empty object files so we use an optional |
| 29 | /// to signal this. |
| 30 | in_symtab: ?[]align(1) const macho.nlist_64 = null, |
| 31 | in_strtab: ?[]const u8 = null, |
| 29 | 32 | |
| 30 | 33 | symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 31 | 34 | sections: std.ArrayListUnmanaged(macho.section_64) = .{}, |
| ... | ... | @@ -105,7 +108,7 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) |
| 105 | 108 | self.contents.ptr + symtab.symoff, |
| 106 | 109 | )[0..symtab.nsyms]; |
| 107 | 110 | self.in_strtab = self.contents[symtab.stroff..][0..symtab.strsize]; |
| 108 | | try self.symtab.appendUnalignedSlice(allocator, self.in_symtab); |
| 111 | try self.symtab.appendUnalignedSlice(allocator, self.in_symtab.?); |
| 109 | 112 | }, |
| 110 | 113 | else => {}, |
| 111 | 114 | } |
| ... | ... | @@ -243,6 +246,50 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32) |
| 243 | 246 | |
| 244 | 247 | log.debug("splitting object({d}, {s}) into atoms: one-shot mode", .{ object_id, self.name }); |
| 245 | 248 | |
| 249 | const in_symtab = self.in_symtab orelse { |
| 250 | for (self.sections.items) |sect, id| { |
| 251 | if (sect.isDebug()) continue; |
| 252 | const match = (try macho_file.getOutputSection(sect)) orelse { |
| 253 | log.debug(" unhandled section", .{}); |
| 254 | continue; |
| 255 | }; |
| 256 | if (sect.size == 0) continue; |
| 257 | |
| 258 | const sect_id = @intCast(u8, id); |
| 259 | const sym_index = self.sections_as_symbols.get(sect_id) orelse blk: { |
| 260 | const sym_index = @intCast(u32, self.symtab.items.len); |
| 261 | try self.symtab.append(gpa, .{ |
| 262 | .n_strx = 0, |
| 263 | .n_type = macho.N_SECT, |
| 264 | .n_sect = match + 1, |
| 265 | .n_desc = 0, |
| 266 | .n_value = sect.addr, |
| 267 | }); |
| 268 | try self.sections_as_symbols.putNoClobber(gpa, sect_id, sym_index); |
| 269 | break :blk sym_index; |
| 270 | }; |
| 271 | const code: ?[]const u8 = if (!sect.isZerofill()) try self.getSectionContents(sect) else null; |
| 272 | const relocs = @ptrCast( |
| 273 | [*]align(1) const macho.relocation_info, |
| 274 | self.contents.ptr + sect.reloff, |
| 275 | )[0..sect.nreloc]; |
| 276 | const atom = try self.createAtomFromSubsection( |
| 277 | macho_file, |
| 278 | object_id, |
| 279 | sym_index, |
| 280 | sect.size, |
| 281 | sect.@"align", |
| 282 | code, |
| 283 | relocs, |
| 284 | &.{}, |
| 285 | match, |
| 286 | sect, |
| 287 | ); |
| 288 | try macho_file.addAtomToSection(atom, match); |
| 289 | } |
| 290 | return; |
| 291 | }; |
| 292 | |
| 246 | 293 | // You would expect that the symbol table is at least pre-sorted based on symbol's type: |
| 247 | 294 | // local < extern defined < undefined. Unfortunately, this is not guaranteed! For instance, |
| 248 | 295 | // the GO compiler does not necessarily respect that therefore we sort immediately by type |
| ... | ... | @@ -250,10 +297,10 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32) |
| 250 | 297 | const context = Context{ |
| 251 | 298 | .object = self, |
| 252 | 299 | }; |
| 253 | | var sorted_all_syms = try std.ArrayList(SymbolAtIndex).initCapacity(gpa, self.in_symtab.len); |
| 300 | var sorted_all_syms = try std.ArrayList(SymbolAtIndex).initCapacity(gpa, in_symtab.len); |
| 254 | 301 | defer sorted_all_syms.deinit(); |
| 255 | 302 | |
| 256 | | for (self.in_symtab) |_, index| { |
| 303 | for (in_symtab) |_, index| { |
| 257 | 304 | sorted_all_syms.appendAssumeCapacity(.{ .index = @intCast(u32, index) }); |
| 258 | 305 | } |
| 259 | 306 | |
| ... | ... | @@ -282,6 +329,8 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32) |
| 282 | 329 | const subsections_via_symbols = self.header.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0; |
| 283 | 330 | |
| 284 | 331 | for (self.sections.items) |sect, id| { |
| 332 | if (sect.isDebug()) continue; |
| 333 | |
| 285 | 334 | const sect_id = @intCast(u8, id); |
| 286 | 335 | log.debug("splitting section '{s},{s}' into atoms", .{ sect.segName(), sect.sectName() }); |
| 287 | 336 | |
| ... | ... | @@ -530,8 +579,9 @@ fn createAtomFromSubsection( |
| 530 | 579 | } |
| 531 | 580 | |
| 532 | 581 | pub fn getSourceSymbol(self: Object, index: u32) ?macho.nlist_64 { |
| 533 | | if (index >= self.in_symtab.len) return null; |
| 534 | | return self.in_symtab[index]; |
| 582 | const symtab = self.in_symtab.?; |
| 583 | if (index >= symtab.len) return null; |
| 584 | return symtab[index]; |
| 535 | 585 | } |
| 536 | 586 | |
| 537 | 587 | pub fn getSourceSection(self: Object, index: u16) macho.section_64 { |
| ... | ... | @@ -636,8 +686,9 @@ pub fn getSectionContents(self: Object, sect: macho.section_64) error{Overflow}! |
| 636 | 686 | } |
| 637 | 687 | |
| 638 | 688 | pub fn getString(self: Object, off: u32) []const u8 { |
| 639 | | assert(off < self.in_strtab.len); |
| 640 | | return mem.sliceTo(@ptrCast([*:0]const u8, self.in_strtab.ptr + off), 0); |
| 689 | const strtab = self.in_strtab.?; |
| 690 | assert(off < strtab.len); |
| 691 | return mem.sliceTo(@ptrCast([*:0]const u8, strtab.ptr + off), 0); |
| 641 | 692 | } |
| 642 | 693 | |
| 643 | 694 | pub fn getAtomForSymbol(self: Object, sym_index: u32) ?*Atom { |