macho: in relocatable mode, macho emit __DWARF directly

This commit is contained in:
Jakub Konka 2024-02-08 12:15:46 +01:00
parent 37033a96ac
commit ce207caa24
3 changed files with 312 additions and 106 deletions

View File

@ -1282,10 +1282,17 @@ pub fn commitDeclState(
try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, src_fn.len);
},
.macho => {
const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;
const debug_line_sect = d_sym.getSectionPtr(d_sym.debug_line_section_index.?);
const file_pos = debug_line_sect.offset + src_fn.off;
try pwriteDbgLineNops(d_sym.file, file_pos, 0, &[0]u8{}, src_fn.len);
const macho_file = self.bin_file.cast(File.MachO).?;
if (macho_file.base.isRelocatable()) {
const debug_line_sect = &macho_file.sections.items(.header)[macho_file.debug_line_sect_index.?];
const file_pos = debug_line_sect.offset + src_fn.off;
try pwriteDbgLineNops(macho_file.base.file.?, file_pos, 0, &[0]u8{}, src_fn.len);
} else {
const d_sym = macho_file.getDebugSymbols().?;
const debug_line_sect = d_sym.getSectionPtr(d_sym.debug_line_section_index.?);
const file_pos = debug_line_sect.offset + src_fn.off;
try pwriteDbgLineNops(d_sym.file, file_pos, 0, &[0]u8{}, src_fn.len);
}
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
@ -1352,18 +1359,32 @@ pub fn commitDeclState(
.macho => {
const macho_file = self.bin_file.cast(File.MachO).?;
const d_sym = macho_file.getDebugSymbols().?;
const sect_index = d_sym.debug_line_section_index.?;
try d_sym.growSection(sect_index, needed_size, true, macho_file);
const sect = d_sym.getSection(sect_index);
const file_pos = sect.offset + src_fn.off;
try pwriteDbgLineNops(
d_sym.file,
file_pos,
prev_padding_size,
dbg_line_buffer.items,
next_padding_size,
);
if (macho_file.base.isRelocatable()) {
const sect_index = macho_file.debug_line_sect_index.?;
try macho_file.growSection(sect_index, needed_size);
const sect = macho_file.sections.items(.header)[sect_index];
const file_pos = sect.offset + src_fn.off;
try pwriteDbgLineNops(
macho_file.base.file.?,
file_pos,
prev_padding_size,
dbg_line_buffer.items,
next_padding_size,
);
} else {
const d_sym = macho_file.getDebugSymbols().?;
const sect_index = d_sym.debug_line_section_index.?;
try d_sym.growSection(sect_index, needed_size, true, macho_file);
const sect = d_sym.getSection(sect_index);
const file_pos = sect.offset + src_fn.off;
try pwriteDbgLineNops(
d_sym.file,
file_pos,
prev_padding_size,
dbg_line_buffer.items,
next_padding_size,
);
}
},
.wasm => {
@ -1460,16 +1481,21 @@ pub fn commitDeclState(
while (decl_state.exprloc_relocs.popOrNull()) |reloc| {
switch (self.bin_file.tag) {
.macho => {
const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;
try d_sym.relocs.append(d_sym.allocator, .{
.type = switch (reloc.type) {
.direct_load => .direct_load,
.got_load => .got_load,
},
.target = reloc.target,
.offset = reloc.offset + self.getAtom(.di_atom, di_atom_index).off,
.addend = 0,
});
const macho_file = self.bin_file.cast(File.MachO).?;
if (macho_file.base.isRelocatable()) {
// TODO
} else {
const d_sym = macho_file.getDebugSymbols().?;
try d_sym.relocs.append(d_sym.allocator, .{
.type = switch (reloc.type) {
.direct_load => .direct_load,
.got_load => .got_load,
},
.target = reloc.target,
.offset = reloc.offset + self.getAtom(.di_atom, di_atom_index).off,
.addend = 0,
});
}
},
.elf => {}, // TODO
else => unreachable,
@ -1512,10 +1538,17 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, atom_index: Atom.Index, len: u32)
try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, atom.len, false);
},
.macho => {
const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;
const debug_info_sect = d_sym.getSectionPtr(d_sym.debug_info_section_index.?);
const file_pos = debug_info_sect.offset + atom.off;
try pwriteDbgInfoNops(d_sym.file, file_pos, 0, &[0]u8{}, atom.len, false);
const macho_file = self.bin_file.cast(File.MachO).?;
if (macho_file.base.isRelocatable()) {
const debug_info_sect = macho_file.sections.items(.header)[macho_file.debug_info_sect_index.?];
const file_pos = debug_info_sect.offset + atom.off;
try pwriteDbgInfoNops(macho_file.base.file.?, file_pos, 0, &[0]u8{}, atom.len, false);
} else {
const d_sym = macho_file.getDebugSymbols().?;
const debug_info_sect = d_sym.getSectionPtr(d_sym.debug_info_section_index.?);
const file_pos = debug_info_sect.offset + atom.off;
try pwriteDbgInfoNops(d_sym.file, file_pos, 0, &[0]u8{}, atom.len, false);
}
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
@ -1599,19 +1632,34 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons
.macho => {
const macho_file = self.bin_file.cast(File.MachO).?;
const d_sym = macho_file.getDebugSymbols().?;
const sect_index = d_sym.debug_info_section_index.?;
try d_sym.growSection(sect_index, needed_size, true, macho_file);
const sect = d_sym.getSection(sect_index);
const file_pos = sect.offset + atom.off;
try pwriteDbgInfoNops(
d_sym.file,
file_pos,
prev_padding_size,
dbg_info_buf,
next_padding_size,
trailing_zero,
);
if (macho_file.base.isRelocatable()) {
const sect_index = macho_file.debug_info_sect_index.?;
try macho_file.growSection(sect_index, needed_size);
const sect = macho_file.sections.items(.header)[sect_index];
const file_pos = sect.offset + atom.off;
try pwriteDbgInfoNops(
macho_file.base.file.?,
file_pos,
prev_padding_size,
dbg_info_buf,
next_padding_size,
trailing_zero,
);
} else {
const d_sym = macho_file.getDebugSymbols().?;
const sect_index = d_sym.debug_info_section_index.?;
try d_sym.growSection(sect_index, needed_size, true, macho_file);
const sect = d_sym.getSection(sect_index);
const file_pos = sect.offset + atom.off;
try pwriteDbgInfoNops(
d_sym.file,
file_pos,
prev_padding_size,
dbg_info_buf,
next_padding_size,
trailing_zero,
);
}
},
.wasm => {
@ -1672,10 +1720,17 @@ pub fn updateDeclLineNumber(self: *Dwarf, mod: *Module, decl_index: InternPool.D
try elf_file.base.file.?.pwriteAll(&data, file_pos);
},
.macho => {
const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;
const sect = d_sym.getSection(d_sym.debug_line_section_index.?);
const file_pos = sect.offset + atom.off + self.getRelocDbgLineOff();
try d_sym.file.pwriteAll(&data, file_pos);
const macho_file = self.bin_file.cast(File.MachO).?;
if (macho_file.base.isRelocatable()) {
const sect = macho_file.sections.items(.header)[macho_file.debug_line_sect_index.?];
const file_pos = sect.offset + atom.off + self.getRelocDbgLineOff();
try macho_file.base.file.?.pwriteAll(&data, file_pos);
} else {
const d_sym = macho_file.getDebugSymbols().?;
const sect = d_sym.getSection(d_sym.debug_line_section_index.?);
const file_pos = sect.offset + atom.off + self.getRelocDbgLineOff();
try d_sym.file.pwriteAll(&data, file_pos);
}
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
@ -1880,12 +1935,20 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
},
.macho => {
const macho_file = self.bin_file.cast(File.MachO).?;
const d_sym = macho_file.getDebugSymbols().?;
const sect_index = d_sym.debug_abbrev_section_index.?;
try d_sym.growSection(sect_index, needed_size, false, macho_file);
const sect = d_sym.getSection(sect_index);
const file_pos = sect.offset + abbrev_offset;
try d_sym.file.pwriteAll(&abbrev_buf, file_pos);
if (macho_file.base.isRelocatable()) {
const sect_index = macho_file.debug_abbrev_sect_index.?;
try macho_file.growSection(sect_index, needed_size);
const sect = macho_file.sections.items(.header)[sect_index];
const file_pos = sect.offset + abbrev_offset;
try macho_file.base.file.?.pwriteAll(&abbrev_buf, file_pos);
} else {
const d_sym = macho_file.getDebugSymbols().?;
const sect_index = d_sym.debug_abbrev_section_index.?;
try d_sym.growSection(sect_index, needed_size, false, macho_file);
const sect = d_sym.getSection(sect_index);
const file_pos = sect.offset + abbrev_offset;
try d_sym.file.pwriteAll(&abbrev_buf, file_pos);
}
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
@ -1970,10 +2033,17 @@ pub fn writeDbgInfoHeader(self: *Dwarf, zcu: *Module, low_pc: u64, high_pc: u64)
try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt, false);
},
.macho => {
const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;
const debug_info_sect = d_sym.getSection(d_sym.debug_info_section_index.?);
const file_pos = debug_info_sect.offset;
try pwriteDbgInfoNops(d_sym.file, file_pos, 0, di_buf.items, jmp_amt, false);
const macho_file = self.bin_file.cast(File.MachO).?;
if (macho_file.base.isRelocatable()) {
const debug_info_sect = macho_file.sections.items(.header)[macho_file.debug_info_sect_index.?];
const file_pos = debug_info_sect.offset;
try pwriteDbgInfoNops(macho_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt, false);
} else {
const d_sym = macho_file.getDebugSymbols().?;
const debug_info_sect = d_sym.getSection(d_sym.debug_info_section_index.?);
const file_pos = debug_info_sect.offset;
try pwriteDbgInfoNops(d_sym.file, file_pos, 0, di_buf.items, jmp_amt, false);
}
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
@ -2296,12 +2366,20 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
},
.macho => {
const macho_file = self.bin_file.cast(File.MachO).?;
const d_sym = macho_file.getDebugSymbols().?;
const sect_index = d_sym.debug_aranges_section_index.?;
try d_sym.growSection(sect_index, needed_size, false, macho_file);
const sect = d_sym.getSection(sect_index);
const file_pos = sect.offset;
try d_sym.file.pwriteAll(di_buf.items, file_pos);
if (macho_file.base.isRelocatable()) {
const sect_index = macho_file.debug_aranges_sect_index.?;
try macho_file.growSection(sect_index, needed_size);
const sect = macho_file.sections.items(.header)[sect_index];
const file_pos = sect.offset;
try macho_file.base.file.?.pwriteAll(di_buf.items, file_pos);
} else {
const d_sym = macho_file.getDebugSymbols().?;
const sect_index = d_sym.debug_aranges_section_index.?;
try d_sym.growSection(sect_index, needed_size, false, macho_file);
const sect = d_sym.getSection(sect_index);
const file_pos = sect.offset;
try d_sym.file.pwriteAll(di_buf.items, file_pos);
}
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
@ -2437,16 +2515,28 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
},
.macho => {
const macho_file = self.bin_file.cast(File.MachO).?;
const d_sym = macho_file.getDebugSymbols().?;
const sect_index = d_sym.debug_line_section_index.?;
const needed_size: u32 = @intCast(d_sym.getSection(sect_index).size + delta);
try d_sym.growSection(sect_index, needed_size, true, macho_file);
const file_pos = d_sym.getSection(sect_index).offset + first_fn.off;
if (macho_file.base.isRelocatable()) {
const sect_index = macho_file.debug_line_sect_index.?;
const needed_size: u32 = @intCast(macho_file.sections.items(.header)[sect_index].size + delta);
try macho_file.growSection(sect_index, needed_size);
const file_pos = macho_file.sections.items(.header)[sect_index].offset + first_fn.off;
const amt = try d_sym.file.preadAll(buffer, file_pos);
if (amt != buffer.len) return error.InputOutput;
const amt = try macho_file.base.file.?.preadAll(buffer, file_pos);
if (amt != buffer.len) return error.InputOutput;
try d_sym.file.pwriteAll(buffer, file_pos + delta);
try macho_file.base.file.?.pwriteAll(buffer, file_pos + delta);
} else {
const d_sym = macho_file.getDebugSymbols().?;
const sect_index = d_sym.debug_line_section_index.?;
const needed_size: u32 = @intCast(d_sym.getSection(sect_index).size + delta);
try d_sym.growSection(sect_index, needed_size, true, macho_file);
const file_pos = d_sym.getSection(sect_index).offset + first_fn.off;
const amt = try d_sym.file.preadAll(buffer, file_pos);
if (amt != buffer.len) return error.InputOutput;
try d_sym.file.pwriteAll(buffer, file_pos + delta);
}
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
@ -2492,10 +2582,17 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt);
},
.macho => {
const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;
const debug_line_sect = d_sym.getSection(d_sym.debug_line_section_index.?);
const file_pos = debug_line_sect.offset;
try pwriteDbgLineNops(d_sym.file, file_pos, 0, di_buf.items, jmp_amt);
const macho_file = self.bin_file.cast(File.MachO).?;
if (macho_file.base.isRelocatable()) {
const debug_line_sect = macho_file.sections.items(.header)[macho_file.debug_line_sect_index.?];
const file_pos = debug_line_sect.offset;
try pwriteDbgLineNops(macho_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt);
} else {
const d_sym = macho_file.getDebugSymbols().?;
const debug_line_sect = d_sym.getSection(d_sym.debug_line_section_index.?);
const file_pos = debug_line_sect.offset;
try pwriteDbgLineNops(d_sym.file, file_pos, 0, di_buf.items, jmp_amt);
}
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
@ -2613,9 +2710,15 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
break :pos debug_info_sect.sh_offset;
},
.macho => pos: {
const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;
const debug_info_sect = d_sym.getSectionPtr(d_sym.debug_info_section_index.?);
break :pos debug_info_sect.offset;
const macho_file = self.bin_file.cast(File.MachO).?;
if (macho_file.base.isRelocatable()) {
const debug_info_sect = &macho_file.sections.items(.header)[macho_file.debug_info_sect_index.?];
break :pos debug_info_sect.offset;
} else {
const d_sym = macho_file.getDebugSymbols().?;
const debug_info_sect = d_sym.getSectionPtr(d_sym.debug_info_section_index.?);
break :pos debug_info_sect.offset;
}
},
// for wasm, the offset is always 0 as we write to memory first
.wasm => 0,
@ -2633,8 +2736,13 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
try elf_file.base.file.?.pwriteAll(&buf, file_pos + atom.off + reloc.offset);
},
.macho => {
const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;
try d_sym.file.pwriteAll(&buf, file_pos + atom.off + reloc.offset);
const macho_file = self.bin_file.cast(File.MachO).?;
if (macho_file.base.isRelocatable()) {
try macho_file.base.file.?.pwriteAll(&buf, file_pos + atom.off + reloc.offset);
} else {
const d_sym = macho_file.getDebugSymbols().?;
try d_sym.file.pwriteAll(&buf, file_pos + atom.off + reloc.offset);
}
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
@ -2659,8 +2767,12 @@ fn addDIFile(self: *Dwarf, mod: *Module, decl_index: InternPool.DeclIndex) !u28
},
.macho => {
const macho_file = self.bin_file.cast(File.MachO).?;
const d_sym = macho_file.getDebugSymbols().?;
d_sym.markDirty(d_sym.debug_line_section_index.?, macho_file);
if (macho_file.base.isRelocatable()) {
macho_file.markDirty(macho_file.debug_line_sect_index.?);
} else {
const d_sym = macho_file.getDebugSymbols().?;
d_sym.markDirty(d_sym.debug_line_section_index.?, macho_file);
}
},
.wasm => {},
else => unreachable,

View File

@ -103,6 +103,14 @@ zig_const_sect_index: ?u8 = null,
zig_data_sect_index: ?u8 = null,
zig_bss_sect_index: ?u8 = null,
/// Tracked DWARF section headers that apply only when we emit relocatable.
/// For executable and loadable images, DWARF is tracked directly by dSYM bundle object.
debug_info_sect_index: ?u8 = null,
debug_abbrev_sect_index: ?u8 = null,
debug_str_sect_index: ?u8 = null,
debug_aranges_sect_index: ?u8 = null,
debug_line_sect_index: ?u8 = null,
has_tlv: bool = false,
binds_to_weak: bool = false,
weak_defines: bool = false,
@ -259,32 +267,11 @@ pub fn createEmpty(
try zo.init(self);
try self.initMetadata(.{
.emit = emit,
.zo = zo,
.symbol_count_hint = options.symbol_count_hint,
.program_code_size_hint = options.program_code_size_hint,
});
if (zo.dwarf != null and !self.base.isRelocatable()) {
// Create dSYM bundle.
log.debug("creating {s}.dSYM bundle", .{emit.sub_path});
const sep = fs.path.sep_str;
const d_sym_path = try std.fmt.allocPrint(
arena,
"{s}.dSYM" ++ sep ++ "Contents" ++ sep ++ "Resources" ++ sep ++ "DWARF",
.{emit.sub_path},
);
var d_sym_bundle = try emit.directory.handle.makeOpenPath(d_sym_path, .{});
defer d_sym_bundle.close();
const d_sym_file = try d_sym_bundle.createFile(emit.sub_path, .{
.truncate = false,
.read = true,
});
self.d_sym = .{ .allocator = gpa, .file = d_sym_file };
try self.d_sym.?.initMetadata(self);
}
}
}
@ -2007,6 +1994,11 @@ pub fn sortSections(self: *MachO) !void {
&self.eh_frame_sect_index,
&self.unwind_info_sect_index,
&self.objc_stubs_sect_index,
&self.debug_info_sect_index,
&self.debug_str_sect_index,
&self.debug_line_sect_index,
&self.debug_abbrev_sect_index,
&self.debug_info_sect_index,
}) |maybe_index| {
if (maybe_index.*) |*index| {
index.* = backlinks[index.*];
@ -3317,6 +3309,8 @@ fn copyRangeAllZeroOut(self: *MachO, old_offset: u64, new_offset: u64, size: u64
}
const InitMetadataOptions = struct {
emit: Compilation.Emit,
zo: *ZigObject,
symbol_count_hint: u64,
program_code_size_hint: u64,
};
@ -3385,6 +3379,31 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
.prot = macho.PROT.READ | macho.PROT.WRITE,
});
}
if (options.zo.dwarf) |_| {
// Create dSYM bundle.
log.debug("creating {s}.dSYM bundle", .{options.emit.sub_path});
const gpa = self.base.comp.gpa;
const sep = fs.path.sep_str;
const d_sym_path = try std.fmt.allocPrint(
gpa,
"{s}.dSYM" ++ sep ++ "Contents" ++ sep ++ "Resources" ++ sep ++ "DWARF",
.{options.emit.sub_path},
);
defer gpa.free(d_sym_path);
var d_sym_bundle = try options.emit.directory.handle.makeOpenPath(d_sym_path, .{});
defer d_sym_bundle.close();
const d_sym_file = try d_sym_bundle.createFile(options.emit.sub_path, .{
.truncate = false,
.read = true,
});
self.d_sym = .{ .allocator = gpa, .file = d_sym_file };
try self.d_sym.?.initMetadata(self);
}
}
const appendSect = struct {
@ -3462,6 +3481,44 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
appendSect(self, self.zig_bss_sect_index.?, self.zig_bss_seg_index.?);
}
}
if (self.base.isRelocatable()) {
{
self.debug_str_sect_index = try self.addSection("__DWARF", "__debug_str", .{
.flags = macho.S_ATTR_DEBUG,
});
try allocSect(self, self.debug_str_sect_index.?, 200);
}
{
self.debug_info_sect_index = try self.addSection("__DWARF", "__debug_info", .{
.flags = macho.S_ATTR_DEBUG,
});
try allocSect(self, self.debug_info_sect_index.?, 200);
}
{
self.debug_abbrev_sect_index = try self.addSection("__DWARF", "__debug_abbrev", .{
.flags = macho.S_ATTR_DEBUG,
});
try allocSect(self, self.debug_abbrev_sect_index.?, 128);
}
{
self.debug_aranges_sect_index = try self.addSection("__DWARF", "__debug_aranges", .{
.alignment = 4,
.flags = macho.S_ATTR_DEBUG,
});
try allocSect(self, self.debug_aranges_sect_index.?, 160);
}
{
self.debug_line_sect_index = try self.addSection("__DWARF", "__debug_line", .{
.flags = macho.S_ATTR_DEBUG,
});
try allocSect(self, self.debug_line_sect_index.?, 250);
}
}
}
pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void {
@ -3549,6 +3606,22 @@ fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void
sect.size = needed_size;
}
pub fn markDirty(self: *MachO, sect_index: u8) void {
if (self.getZigObject()) |zo| {
if (self.debug_info_sect_index.? == sect_index) {
zo.debug_info_header_dirty = true;
} else if (self.debug_line_sect_index.? == sect_index) {
zo.debug_line_header_dirty = true;
} else if (self.debug_abbrev_sect_index.? == sect_index) {
zo.debug_abbrev_dirty = true;
} else if (self.debug_str_sect_index.? == sect_index) {
zo.debug_strtab_dirty = true;
} else if (self.debug_aranges_sect_index.? == sect_index) {
zo.debug_aranges_dirty = true;
}
}
}
pub fn getTarget(self: MachO) std.Target {
return self.base.comp.root_mod.resolved_target.result;
}
@ -3624,6 +3697,21 @@ pub fn isZigSection(self: MachO, sect_id: u8) bool {
return false;
}
pub fn isDebugSection(self: MachO, sect_id: u8) bool {
inline for (&[_]?u8{
self.debug_info_sect_index,
self.debug_abbrev_sect_index,
self.debug_str_sect_index,
self.debug_aranges_sect_index,
self.debug_line_sect_index,
}) |maybe_index| {
if (maybe_index) |index| {
if (index == sect_id) return true;
}
}
return false;
}
pub fn addSegment(self: *MachO, name: []const u8, opts: struct {
vmaddr: u64 = 0,
vmsize: u64 = 0,

View File

@ -471,7 +471,13 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO) !void {
self.debug_strtab_dirty = false;
}
} else {
// TODO: relocatable
const sect_index = macho_file.debug_str_sect_index.?;
if (self.debug_strtab_dirty or dw.strtab.buffer.items.len != macho_file.sections.items(.header)[sect_index].size) {
const needed_size = @as(u32, @intCast(dw.strtab.buffer.items.len));
try macho_file.growSection(sect_index, needed_size);
try macho_file.base.file.?.pwriteAll(dw.strtab.buffer.items, macho_file.sections.items(.header)[sect_index].offset);
self.debug_strtab_dirty = false;
}
}
}