Commit 5391541f11
Changed files (2)
src
link
src/link/MachO/dead_strip.zig
@@ -179,7 +179,9 @@ fn prune(arena: Allocator, alive: std.AutoHashMap(*Atom, void), macho_file: *Mac
loop = false;
for (macho_file.objects.items) |object| {
- for (object.in_symtab) |_, source_index| {
+ const in_symtab = object.in_symtab orelse continue;
+
+ for (in_symtab) |_, source_index| {
const atom = object.getAtomForSymbol(@intCast(u32, source_index)) orelse continue;
if (alive.contains(atom)) continue;
src/link/MachO/Object.zig
@@ -24,8 +24,11 @@ mtime: u64,
contents: []align(@alignOf(u64)) const u8,
header: macho.mach_header_64 = undefined,
-in_symtab: []align(1) const macho.nlist_64 = undefined,
-in_strtab: []const u8 = undefined,
+
+/// Symtab and strtab might not exist for empty object files so we use an optional
+/// to signal this.
+in_symtab: ?[]align(1) const macho.nlist_64 = null,
+in_strtab: ?[]const u8 = null,
symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},
sections: std.ArrayListUnmanaged(macho.section_64) = .{},
@@ -105,7 +108,7 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch)
self.contents.ptr + symtab.symoff,
)[0..symtab.nsyms];
self.in_strtab = self.contents[symtab.stroff..][0..symtab.strsize];
- try self.symtab.appendUnalignedSlice(allocator, self.in_symtab);
+ try self.symtab.appendUnalignedSlice(allocator, self.in_symtab.?);
},
else => {},
}
@@ -243,6 +246,50 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32)
log.debug("splitting object({d}, {s}) into atoms: one-shot mode", .{ object_id, self.name });
+ const in_symtab = self.in_symtab orelse {
+ for (self.sections.items) |sect, id| {
+ if (sect.isDebug()) continue;
+ const match = (try macho_file.getOutputSection(sect)) orelse {
+ log.debug(" unhandled section", .{});
+ continue;
+ };
+ if (sect.size == 0) continue;
+
+ const sect_id = @intCast(u8, id);
+ const sym_index = self.sections_as_symbols.get(sect_id) orelse blk: {
+ const sym_index = @intCast(u32, self.symtab.items.len);
+ try self.symtab.append(gpa, .{
+ .n_strx = 0,
+ .n_type = macho.N_SECT,
+ .n_sect = match + 1,
+ .n_desc = 0,
+ .n_value = sect.addr,
+ });
+ try self.sections_as_symbols.putNoClobber(gpa, sect_id, sym_index);
+ break :blk sym_index;
+ };
+ const code: ?[]const u8 = if (!sect.isZerofill()) try self.getSectionContents(sect) else null;
+ const relocs = @ptrCast(
+ [*]align(1) const macho.relocation_info,
+ self.contents.ptr + sect.reloff,
+ )[0..sect.nreloc];
+ const atom = try self.createAtomFromSubsection(
+ macho_file,
+ object_id,
+ sym_index,
+ sect.size,
+ sect.@"align",
+ code,
+ relocs,
+ &.{},
+ match,
+ sect,
+ );
+ try macho_file.addAtomToSection(atom, match);
+ }
+ return;
+ };
+
// You would expect that the symbol table is at least pre-sorted based on symbol's type:
// local < extern defined < undefined. Unfortunately, this is not guaranteed! For instance,
// 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)
const context = Context{
.object = self,
};
- var sorted_all_syms = try std.ArrayList(SymbolAtIndex).initCapacity(gpa, self.in_symtab.len);
+ var sorted_all_syms = try std.ArrayList(SymbolAtIndex).initCapacity(gpa, in_symtab.len);
defer sorted_all_syms.deinit();
- for (self.in_symtab) |_, index| {
+ for (in_symtab) |_, index| {
sorted_all_syms.appendAssumeCapacity(.{ .index = @intCast(u32, index) });
}
@@ -282,6 +329,8 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32)
const subsections_via_symbols = self.header.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0;
for (self.sections.items) |sect, id| {
+ if (sect.isDebug()) continue;
+
const sect_id = @intCast(u8, id);
log.debug("splitting section '{s},{s}' into atoms", .{ sect.segName(), sect.sectName() });
@@ -530,8 +579,9 @@ fn createAtomFromSubsection(
}
pub fn getSourceSymbol(self: Object, index: u32) ?macho.nlist_64 {
- if (index >= self.in_symtab.len) return null;
- return self.in_symtab[index];
+ const symtab = self.in_symtab.?;
+ if (index >= symtab.len) return null;
+ return symtab[index];
}
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}!
}
pub fn getString(self: Object, off: u32) []const u8 {
- assert(off < self.in_strtab.len);
- return mem.sliceTo(@ptrCast([*:0]const u8, self.in_strtab.ptr + off), 0);
+ const strtab = self.in_strtab.?;
+ assert(off < strtab.len);
+ return mem.sliceTo(@ptrCast([*:0]const u8, strtab.ptr + off), 0);
}
pub fn getAtomForSymbol(self: Object, sym_index: u32) ?*Atom {