mirror of
https://github.com/ziglang/zig.git
synced 2026-01-06 21:43:25 +00:00
Merge pull request #18722 from ziglang/macho-debug-info
macho: reinstate DWARF in self-hosted x86_64-macho
This commit is contained in:
commit
3e939e6153
@ -1468,7 +1468,6 @@ pub fn commitDeclState(
|
||||
.target = reloc.target,
|
||||
.offset = reloc.offset + self.getAtom(.di_atom, di_atom_index).off,
|
||||
.addend = 0,
|
||||
.prev_vaddr = 0,
|
||||
});
|
||||
},
|
||||
.elf => {}, // TODO
|
||||
|
||||
@ -256,32 +256,39 @@ pub fn createEmpty(
|
||||
.program_code_size_hint = options.program_code_size_hint,
|
||||
});
|
||||
|
||||
// TODO init dwarf
|
||||
switch (comp.config.debug_format) {
|
||||
.strip => {},
|
||||
.dwarf => if (!self.base.isRelocatable()) {
|
||||
// Create dSYM bundle.
|
||||
log.debug("creating {s}.dSYM bundle", .{emit.sub_path});
|
||||
|
||||
// if (comp.config.debug_format != .strip) {
|
||||
// // 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},
|
||||
);
|
||||
|
||||
// const d_sym_path = try std.fmt.allocPrint(
|
||||
// arena,
|
||||
// "{s}.dSYM" ++ fs.path.sep_str ++ "Contents" ++ fs.path.sep_str ++ "Resources" ++ fs.path.sep_str ++ "DWARF",
|
||||
// .{emit.sub_path},
|
||||
// );
|
||||
var d_sym_bundle = try emit.directory.handle.makeOpenPath(d_sym_path, .{});
|
||||
defer d_sym_bundle.close();
|
||||
|
||||
// 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,
|
||||
});
|
||||
|
||||
// const d_sym_file = try d_sym_bundle.createFile(emit.sub_path, .{
|
||||
// .truncate = false,
|
||||
// .read = true,
|
||||
// });
|
||||
|
||||
// self.d_sym = .{
|
||||
// .allocator = gpa,
|
||||
// .dwarf = link.File.Dwarf.init(&self.base, .dwarf32),
|
||||
// .file = d_sym_file,
|
||||
// };
|
||||
// }
|
||||
self.d_sym = .{
|
||||
.allocator = gpa,
|
||||
.dwarf = link.File.Dwarf.init(&self.base, .dwarf32),
|
||||
.file = d_sym_file,
|
||||
};
|
||||
try self.d_sym.?.initMetadata(self);
|
||||
} else {
|
||||
try self.reportUnexpectedError("TODO: implement generating and emitting __DWARF in .o file", .{});
|
||||
return error.Unexpected;
|
||||
},
|
||||
.code_view => unreachable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -692,6 +699,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
|
||||
const ncmds, const sizeofcmds, const uuid_cmd_offset = try self.writeLoadCommands();
|
||||
try self.writeHeader(ncmds, sizeofcmds);
|
||||
try self.writeUuid(uuid_cmd_offset, self.requiresCodeSig());
|
||||
if (self.getDebugSymbols()) |dsym| try dsym.flushModule(self);
|
||||
|
||||
if (codesig) |*csig| {
|
||||
try self.writeCodeSignature(csig); // code signing always comes last
|
||||
@ -731,9 +739,6 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {
|
||||
try argv.append("-r");
|
||||
}
|
||||
|
||||
try argv.append("-o");
|
||||
try argv.append(full_out_path);
|
||||
|
||||
if (self.base.isRelocatable()) {
|
||||
for (comp.objects) |obj| {
|
||||
try argv.append(obj.path);
|
||||
@ -2047,7 +2052,11 @@ pub fn sortSections(self: *MachO) !void {
|
||||
for (&[_]*?u8{
|
||||
&self.data_sect_index,
|
||||
&self.got_sect_index,
|
||||
&self.zig_text_sect_index,
|
||||
&self.zig_got_sect_index,
|
||||
&self.zig_const_sect_index,
|
||||
&self.zig_data_sect_index,
|
||||
&self.zig_bss_sect_index,
|
||||
&self.stubs_sect_index,
|
||||
&self.stubs_helper_sect_index,
|
||||
&self.la_symbol_ptr_sect_index,
|
||||
@ -2901,16 +2910,16 @@ pub fn writeSymtab(self: *MachO, off: u32) !u32 {
|
||||
try self.strtab.ensureUnusedCapacity(gpa, cmd.strsize - 1);
|
||||
|
||||
if (self.getZigObject()) |zo| {
|
||||
zo.writeSymtab(self);
|
||||
zo.writeSymtab(self, self);
|
||||
}
|
||||
for (self.objects.items) |index| {
|
||||
try self.getFile(index).?.writeSymtab(self);
|
||||
try self.getFile(index).?.writeSymtab(self, self);
|
||||
}
|
||||
for (self.dylibs.items) |index| {
|
||||
try self.getFile(index).?.writeSymtab(self);
|
||||
try self.getFile(index).?.writeSymtab(self, self);
|
||||
}
|
||||
if (self.getInternalObject()) |internal| {
|
||||
internal.writeSymtab(self);
|
||||
internal.writeSymtab(self, self);
|
||||
}
|
||||
|
||||
assert(self.strtab.items.len == cmd.strsize);
|
||||
@ -3176,7 +3185,7 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex)
|
||||
|
||||
pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl_index: InternPool.DeclIndex) !void {
|
||||
if (self.llvm_object) |_| return;
|
||||
return self.getZigObject().?.updateDeclLineNumber(module, decl_index);
|
||||
return self.getZigObject().?.updateDeclLineNumber(self, module, decl_index);
|
||||
}
|
||||
|
||||
pub fn updateExports(
|
||||
@ -3909,9 +3918,8 @@ fn reportDuplicates(self: *MachO, dupes: anytype) error{ HasDuplicates, OutOfMem
|
||||
}
|
||||
|
||||
pub fn getDebugSymbols(self: *MachO) ?*DebugSymbols {
|
||||
if (self.d_sym) |*ds| {
|
||||
return ds;
|
||||
} else return null;
|
||||
if (self.d_sym) |*ds| return ds;
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn ptraceAttach(self: *MachO, pid: std.os.pid_t) !void {
|
||||
|
||||
@ -3,6 +3,7 @@ dwarf: Dwarf,
|
||||
file: fs.File,
|
||||
|
||||
symtab_cmd: macho.symtab_command = .{},
|
||||
uuid_cmd: macho.uuid_command = .{ .uuid = [_]u8{0} ** 16 },
|
||||
|
||||
segments: std.ArrayListUnmanaged(macho.segment_command_64) = .{},
|
||||
sections: std.ArrayListUnmanaged(macho.section_64) = .{},
|
||||
@ -22,9 +23,12 @@ debug_aranges_section_dirty: bool = false,
|
||||
debug_info_header_dirty: bool = false,
|
||||
debug_line_header_dirty: bool = false,
|
||||
|
||||
strtab: StringTable = .{},
|
||||
relocs: std.ArrayListUnmanaged(Reloc) = .{},
|
||||
|
||||
/// Output synthetic sections
|
||||
symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},
|
||||
strtab: std.ArrayListUnmanaged(u8) = .{},
|
||||
|
||||
pub const Reloc = struct {
|
||||
type: enum {
|
||||
direct_load,
|
||||
@ -33,18 +37,17 @@ pub const Reloc = struct {
|
||||
target: u32,
|
||||
offset: u64,
|
||||
addend: u32,
|
||||
prev_vaddr: u64,
|
||||
};
|
||||
|
||||
/// You must call this function *after* `MachO.populateMissingMetadata()`
|
||||
/// You must call this function *after* `ZigObject.initMetadata()`
|
||||
/// has been called to get a viable debug symbols output.
|
||||
pub fn populateMissingMetadata(self: *DebugSymbols, macho_file: *MachO) !void {
|
||||
const target = macho_file.base.comp.root_mod.resolved_target.result;
|
||||
pub fn initMetadata(self: *DebugSymbols, macho_file: *MachO) !void {
|
||||
try self.strtab.append(self.allocator, 0);
|
||||
|
||||
if (self.dwarf_segment_cmd_index == null) {
|
||||
self.dwarf_segment_cmd_index = @as(u8, @intCast(self.segments.items.len));
|
||||
|
||||
const page_size = MachO.getPageSize(target.cpu.arch);
|
||||
const page_size = macho_file.getPageSize();
|
||||
const off = @as(u64, @intCast(page_size));
|
||||
const ideal_size: u16 = 200 + 128 + 160 + 250;
|
||||
const needed_size = mem.alignForward(u64, padToIdeal(ideal_size), page_size);
|
||||
@ -203,35 +206,24 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
|
||||
// and it corresponds to the Zig source code.
|
||||
const zcu = comp.module orelse return error.LinkingWithoutZigSourceUnimplemented;
|
||||
|
||||
for (self.relocs.items) |*reloc| {
|
||||
const sym = switch (reloc.type) {
|
||||
.direct_load => macho_file.getSymbol(.{ .sym_index = reloc.target }),
|
||||
.got_load => blk: {
|
||||
const got_index = macho_file.got_table.lookup.get(.{ .sym_index = reloc.target }).?;
|
||||
const got_entry = macho_file.got_table.entries.items[got_index];
|
||||
break :blk macho_file.getSymbol(got_entry);
|
||||
},
|
||||
};
|
||||
if (sym.n_value == reloc.prev_vaddr) continue;
|
||||
try self.dwarf.flushModule(zcu);
|
||||
|
||||
const sym_name = switch (reloc.type) {
|
||||
.direct_load => macho_file.getSymbolName(.{ .sym_index = reloc.target }),
|
||||
.got_load => blk: {
|
||||
const got_index = macho_file.got_table.lookup.get(.{ .sym_index = reloc.target }).?;
|
||||
const got_entry = macho_file.got_table.entries.items[got_index];
|
||||
break :blk macho_file.getSymbolName(got_entry);
|
||||
},
|
||||
for (self.relocs.items) |*reloc| {
|
||||
const sym = macho_file.getSymbol(reloc.target);
|
||||
const sym_name = sym.getName(macho_file);
|
||||
const addr = switch (reloc.type) {
|
||||
.direct_load => sym.getAddress(.{}, macho_file),
|
||||
.got_load => sym.getGotAddress(macho_file),
|
||||
};
|
||||
const sect = &self.sections.items[self.debug_info_section_index.?];
|
||||
const file_offset = sect.offset + reloc.offset;
|
||||
log.debug("resolving relocation: {d}@{x} ('{s}') at offset {x}", .{
|
||||
reloc.target,
|
||||
sym.n_value,
|
||||
addr,
|
||||
sym_name,
|
||||
file_offset,
|
||||
});
|
||||
try self.file.pwriteAll(mem.asBytes(&sym.n_value), file_offset);
|
||||
reloc.prev_vaddr = sym.n_value;
|
||||
try self.file.pwriteAll(mem.asBytes(&addr), file_offset);
|
||||
}
|
||||
|
||||
if (self.debug_abbrev_section_dirty) {
|
||||
@ -242,7 +234,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
|
||||
if (self.debug_info_header_dirty) {
|
||||
// Currently only one compilation unit is supported, so the address range is simply
|
||||
// identical to the main program header virtual address and memory size.
|
||||
const text_section = macho_file.sections.items(.header)[macho_file.text_section_index.?];
|
||||
const text_section = macho_file.sections.items(.header)[macho_file.zig_text_sect_index.?];
|
||||
const low_pc = text_section.addr;
|
||||
const high_pc = text_section.addr + text_section.size;
|
||||
try self.dwarf.writeDbgInfoHeader(zcu, low_pc, high_pc);
|
||||
@ -252,7 +244,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
|
||||
if (self.debug_aranges_section_dirty) {
|
||||
// Currently only one compilation unit is supported, so the address range is simply
|
||||
// identical to the main program header virtual address and memory size.
|
||||
const text_section = macho_file.sections.items(.header)[macho_file.text_section_index.?];
|
||||
const text_section = macho_file.sections.items(.header)[macho_file.zig_text_sect_index.?];
|
||||
try self.dwarf.writeDbgAranges(text_section.addr, text_section.size);
|
||||
self.debug_aranges_section_dirty = false;
|
||||
}
|
||||
@ -276,17 +268,8 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
|
||||
try self.writeLinkeditSegmentData(macho_file);
|
||||
|
||||
// Write load commands
|
||||
var lc_buffer = std.ArrayList(u8).init(self.allocator);
|
||||
defer lc_buffer.deinit();
|
||||
const lc_writer = lc_buffer.writer();
|
||||
|
||||
try self.writeSegmentHeaders(macho_file, lc_writer);
|
||||
try lc_writer.writeStruct(self.symtab_cmd);
|
||||
try lc_writer.writeStruct(macho_file.uuid_cmd);
|
||||
|
||||
const ncmds = load_commands.calcNumOfLCs(lc_buffer.items);
|
||||
try self.file.pwriteAll(lc_buffer.items, @sizeOf(macho.mach_header_64));
|
||||
try self.writeHeader(macho_file, ncmds, @as(u32, @intCast(lc_buffer.items.len)));
|
||||
const ncmds, const sizeofcmds = try self.writeLoadCommands(macho_file);
|
||||
try self.writeHeader(macho_file, ncmds, sizeofcmds);
|
||||
|
||||
assert(!self.debug_abbrev_section_dirty);
|
||||
assert(!self.debug_aranges_section_dirty);
|
||||
@ -299,8 +282,9 @@ pub fn deinit(self: *DebugSymbols) void {
|
||||
self.segments.deinit(gpa);
|
||||
self.sections.deinit(gpa);
|
||||
self.dwarf.deinit();
|
||||
self.strtab.deinit(gpa);
|
||||
self.relocs.deinit(gpa);
|
||||
self.symtab.deinit(gpa);
|
||||
self.strtab.deinit(gpa);
|
||||
}
|
||||
|
||||
pub fn swapRemoveRelocs(self: *DebugSymbols, target: u32) void {
|
||||
@ -324,7 +308,7 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void {
|
||||
// however at the cost of having LINKEDIT preceed DWARF in dSYM binary which we
|
||||
// do not want as we want to be able to incrementally move DWARF sections in the
|
||||
// file as we please.
|
||||
const last_seg = macho_file.getLinkeditSegmentPtr();
|
||||
const last_seg = macho_file.getLinkeditSegment();
|
||||
break :blk last_seg.vmaddr + last_seg.vmsize;
|
||||
};
|
||||
const dwarf_segment = self.getDwarfSegmentPtr();
|
||||
@ -334,8 +318,7 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void {
|
||||
file_size = @max(file_size, header.offset + header.size);
|
||||
}
|
||||
|
||||
const target = macho_file.base.comp.root_mod.resolved_target.result;
|
||||
const page_size = MachO.getPageSize(target.cpu.arch);
|
||||
const page_size = macho_file.getPageSize();
|
||||
const aligned_size = mem.alignForward(u64, file_size, page_size);
|
||||
dwarf_segment.vmaddr = base_vmaddr;
|
||||
dwarf_segment.filesize = aligned_size;
|
||||
@ -355,54 +338,70 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void {
|
||||
log.debug("found __LINKEDIT segment free space at 0x{x}", .{linkedit.fileoff});
|
||||
}
|
||||
|
||||
fn writeSegmentHeaders(self: *DebugSymbols, macho_file: *MachO, writer: anytype) !void {
|
||||
// Write segment/section headers from the binary file first.
|
||||
const end = macho_file.linkedit_segment_cmd_index.?;
|
||||
for (macho_file.segments.items[0..end], 0..) |seg, i| {
|
||||
const indexes = macho_file.getSectionIndexes(@as(u8, @intCast(i)));
|
||||
var out_seg = seg;
|
||||
out_seg.fileoff = 0;
|
||||
out_seg.filesize = 0;
|
||||
out_seg.cmdsize = @sizeOf(macho.segment_command_64);
|
||||
out_seg.nsects = 0;
|
||||
fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, usize } {
|
||||
const gpa = self.allocator;
|
||||
const needed_size = load_commands.calcLoadCommandsSizeDsym(macho_file, self);
|
||||
const buffer = try gpa.alloc(u8, needed_size);
|
||||
defer gpa.free(buffer);
|
||||
|
||||
// Update section headers count; any section with size of 0 is excluded
|
||||
// since it doesn't have any data in the final binary file.
|
||||
for (macho_file.sections.items(.header)[indexes.start..indexes.end]) |header| {
|
||||
if (header.size == 0) continue;
|
||||
out_seg.cmdsize += @sizeOf(macho.section_64);
|
||||
out_seg.nsects += 1;
|
||||
var stream = std.io.fixedBufferStream(buffer);
|
||||
var cwriter = std.io.countingWriter(stream.writer());
|
||||
const writer = cwriter.writer();
|
||||
|
||||
var ncmds: usize = 0;
|
||||
|
||||
// UUID comes first presumably to speed up lookup by the consumer like lldb.
|
||||
@memcpy(&self.uuid_cmd.uuid, &macho_file.uuid_cmd.uuid);
|
||||
try writer.writeStruct(self.uuid_cmd);
|
||||
ncmds += 1;
|
||||
|
||||
// Segment and section load commands
|
||||
{
|
||||
// Write segment/section headers from the binary file first.
|
||||
const slice = macho_file.sections.slice();
|
||||
var sect_id: usize = 0;
|
||||
for (macho_file.segments.items, 0..) |seg, seg_id| {
|
||||
if (seg_id == macho_file.linkedit_seg_index.?) break;
|
||||
var out_seg = seg;
|
||||
out_seg.fileoff = 0;
|
||||
out_seg.filesize = 0;
|
||||
try writer.writeStruct(out_seg);
|
||||
for (slice.items(.header)[sect_id..][0..seg.nsects]) |header| {
|
||||
var out_header = header;
|
||||
out_header.offset = 0;
|
||||
try writer.writeStruct(out_header);
|
||||
}
|
||||
sect_id += seg.nsects;
|
||||
}
|
||||
ncmds += macho_file.segments.items.len - 1;
|
||||
|
||||
if (out_seg.nsects == 0 and
|
||||
(mem.eql(u8, out_seg.segName(), "__DATA_CONST") or
|
||||
mem.eql(u8, out_seg.segName(), "__DATA"))) continue;
|
||||
|
||||
try writer.writeStruct(out_seg);
|
||||
for (macho_file.sections.items(.header)[indexes.start..indexes.end]) |header| {
|
||||
if (header.size == 0) continue;
|
||||
var out_header = header;
|
||||
out_header.offset = 0;
|
||||
try writer.writeStruct(out_header);
|
||||
}
|
||||
}
|
||||
// Next, commit DSYM's __LINKEDIT and __DWARF segments headers.
|
||||
for (self.segments.items, 0..) |seg, i| {
|
||||
const indexes = self.getSectionIndexes(@as(u8, @intCast(i)));
|
||||
try writer.writeStruct(seg);
|
||||
for (self.sections.items[indexes.start..indexes.end]) |header| {
|
||||
try writer.writeStruct(header);
|
||||
// Next, commit DSYM's __LINKEDIT and __DWARF segments headers.
|
||||
sect_id = 0;
|
||||
for (self.segments.items) |seg| {
|
||||
try writer.writeStruct(seg);
|
||||
for (self.sections.items[sect_id..][0..seg.nsects]) |header| {
|
||||
try writer.writeStruct(header);
|
||||
}
|
||||
sect_id += seg.nsects;
|
||||
}
|
||||
ncmds += self.segments.items.len;
|
||||
}
|
||||
|
||||
try writer.writeStruct(self.symtab_cmd);
|
||||
ncmds += 1;
|
||||
|
||||
assert(cwriter.bytes_written == needed_size);
|
||||
|
||||
try self.file.pwriteAll(buffer, @sizeOf(macho.mach_header_64));
|
||||
|
||||
return .{ ncmds, buffer.len };
|
||||
}
|
||||
|
||||
fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: u32, sizeofcmds: u32) !void {
|
||||
const target = macho_file.base.comp.root_mod.resolved_target.result;
|
||||
|
||||
fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: usize, sizeofcmds: usize) !void {
|
||||
var header: macho.mach_header_64 = .{};
|
||||
header.filetype = macho.MH_DSYM;
|
||||
|
||||
switch (target.cpu.arch) {
|
||||
switch (macho_file.getTarget().cpu.arch) {
|
||||
.aarch64 => {
|
||||
header.cputype = macho.CPU_TYPE_ARM64;
|
||||
header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL;
|
||||
@ -414,8 +413,8 @@ fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: u32, sizeofcmds:
|
||||
else => return error.UnsupportedCpuArchitecture,
|
||||
}
|
||||
|
||||
header.ncmds = ncmds;
|
||||
header.sizeofcmds = sizeofcmds;
|
||||
header.ncmds = @intCast(ncmds);
|
||||
header.sizeofcmds = @intCast(sizeofcmds);
|
||||
|
||||
log.debug("writing Mach-O header {}", .{header});
|
||||
|
||||
@ -437,91 +436,56 @@ fn writeLinkeditSegmentData(self: *DebugSymbols, macho_file: *MachO) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
try self.writeSymtab(macho_file);
|
||||
try self.writeStrtab();
|
||||
|
||||
const target = macho_file.base.comp.root_mod.resolved_target.result;
|
||||
const page_size = MachO.getPageSize(target.cpu.arch);
|
||||
const page_size = macho_file.getPageSize();
|
||||
const seg = &self.segments.items[self.linkedit_segment_cmd_index.?];
|
||||
|
||||
var off = math.cast(u32, seg.fileoff) orelse return error.Overflow;
|
||||
off = try self.writeSymtab(off, macho_file);
|
||||
off = mem.alignForward(u32, off, @alignOf(u64));
|
||||
off = try self.writeStrtab(off);
|
||||
seg.filesize = off - seg.fileoff;
|
||||
|
||||
const aligned_size = mem.alignForward(u64, seg.filesize, page_size);
|
||||
seg.vmsize = aligned_size;
|
||||
}
|
||||
|
||||
fn writeSymtab(self: *DebugSymbols, macho_file: *MachO) !void {
|
||||
pub fn writeSymtab(self: *DebugSymbols, off: u32, macho_file: *MachO) !u32 {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const gpa = self.allocator;
|
||||
const cmd = &self.symtab_cmd;
|
||||
cmd.nsyms = macho_file.symtab_cmd.nsyms;
|
||||
cmd.strsize = macho_file.symtab_cmd.strsize;
|
||||
cmd.symoff = off;
|
||||
|
||||
var locals = std.ArrayList(macho.nlist_64).init(gpa);
|
||||
defer locals.deinit();
|
||||
try self.symtab.resize(gpa, cmd.nsyms);
|
||||
try self.strtab.ensureUnusedCapacity(gpa, cmd.strsize - 1);
|
||||
|
||||
for (macho_file.locals.items, 0..) |sym, sym_id| {
|
||||
if (sym.n_strx == 0) continue; // no name, skip
|
||||
const sym_loc = MachO.SymbolWithLoc{ .sym_index = @as(u32, @intCast(sym_id)) };
|
||||
if (macho_file.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip
|
||||
if (macho_file.getGlobal(macho_file.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip
|
||||
var out_sym = sym;
|
||||
out_sym.n_strx = try self.strtab.insert(gpa, macho_file.getSymbolName(sym_loc));
|
||||
try locals.append(out_sym);
|
||||
if (macho_file.getZigObject()) |zo| {
|
||||
zo.writeSymtab(macho_file, self);
|
||||
}
|
||||
for (macho_file.objects.items) |index| {
|
||||
try macho_file.getFile(index).?.writeSymtab(macho_file, self);
|
||||
}
|
||||
for (macho_file.dylibs.items) |index| {
|
||||
try macho_file.getFile(index).?.writeSymtab(macho_file, self);
|
||||
}
|
||||
if (macho_file.getInternalObject()) |internal| {
|
||||
internal.writeSymtab(macho_file, self);
|
||||
}
|
||||
|
||||
var exports = std.ArrayList(macho.nlist_64).init(gpa);
|
||||
defer exports.deinit();
|
||||
assert(self.strtab.items.len == cmd.strsize);
|
||||
|
||||
for (macho_file.globals.items) |global| {
|
||||
const sym = macho_file.getSymbol(global);
|
||||
if (sym.undf()) continue; // import, skip
|
||||
var out_sym = sym;
|
||||
out_sym.n_strx = try self.strtab.insert(gpa, macho_file.getSymbolName(global));
|
||||
try exports.append(out_sym);
|
||||
}
|
||||
try self.file.pwriteAll(mem.sliceAsBytes(self.symtab.items), cmd.symoff);
|
||||
|
||||
const nlocals = locals.items.len;
|
||||
const nexports = exports.items.len;
|
||||
const nsyms = nlocals + nexports;
|
||||
|
||||
const seg = &self.segments.items[self.linkedit_segment_cmd_index.?];
|
||||
const offset = mem.alignForward(u64, seg.fileoff, @alignOf(macho.nlist_64));
|
||||
const needed_size = nsyms * @sizeOf(macho.nlist_64);
|
||||
seg.filesize = offset + needed_size - seg.fileoff;
|
||||
|
||||
self.symtab_cmd.symoff = @as(u32, @intCast(offset));
|
||||
self.symtab_cmd.nsyms = @as(u32, @intCast(nsyms));
|
||||
|
||||
const locals_off = @as(u32, @intCast(offset));
|
||||
const locals_size = nlocals * @sizeOf(macho.nlist_64);
|
||||
const exports_off = locals_off + locals_size;
|
||||
const exports_size = nexports * @sizeOf(macho.nlist_64);
|
||||
|
||||
log.debug("writing local symbols from 0x{x} to 0x{x}", .{ locals_off, locals_size + locals_off });
|
||||
try self.file.pwriteAll(mem.sliceAsBytes(locals.items), locals_off);
|
||||
|
||||
log.debug("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off });
|
||||
try self.file.pwriteAll(mem.sliceAsBytes(exports.items), exports_off);
|
||||
return off + cmd.nsyms * @sizeOf(macho.nlist_64);
|
||||
}
|
||||
|
||||
fn writeStrtab(self: *DebugSymbols) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const seg = &self.segments.items[self.linkedit_segment_cmd_index.?];
|
||||
const symtab_size = @as(u32, @intCast(self.symtab_cmd.nsyms * @sizeOf(macho.nlist_64)));
|
||||
const offset = mem.alignForward(u64, self.symtab_cmd.symoff + symtab_size, @alignOf(u64));
|
||||
const needed_size = mem.alignForward(u64, self.strtab.buffer.items.len, @alignOf(u64));
|
||||
|
||||
seg.filesize = offset + needed_size - seg.fileoff;
|
||||
self.symtab_cmd.stroff = @as(u32, @intCast(offset));
|
||||
self.symtab_cmd.strsize = @as(u32, @intCast(needed_size));
|
||||
|
||||
log.debug("writing string table from 0x{x} to 0x{x}", .{ offset, offset + needed_size });
|
||||
|
||||
try self.file.pwriteAll(self.strtab.buffer.items, offset);
|
||||
|
||||
if (self.strtab.buffer.items.len < needed_size) {
|
||||
// Ensure we are always padded to the actual length of the file.
|
||||
try self.file.pwriteAll(&[_]u8{0}, offset + needed_size);
|
||||
}
|
||||
pub fn writeStrtab(self: *DebugSymbols, off: u32) !u32 {
|
||||
const cmd = &self.symtab_cmd;
|
||||
cmd.stroff = off;
|
||||
try self.file.pwriteAll(self.strtab.items, cmd.stroff);
|
||||
return off + cmd.strsize;
|
||||
}
|
||||
|
||||
pub fn getSectionIndexes(self: *DebugSymbols, segment_index: u8) struct { start: u8, end: u8 } {
|
||||
@ -561,7 +525,7 @@ const assert = std.debug.assert;
|
||||
const fs = std.fs;
|
||||
const link = @import("../../link.zig");
|
||||
const load_commands = @import("load_commands.zig");
|
||||
const log = std.log.scoped(.dsym);
|
||||
const log = std.log.scoped(.link_dsym);
|
||||
const macho = std.macho;
|
||||
const makeStaticString = MachO.makeStaticString;
|
||||
const math = std.math;
|
||||
|
||||
@ -576,7 +576,7 @@ pub fn calcSymtabSize(self: *Dylib, macho_file: *MachO) !void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn writeSymtab(self: Dylib, macho_file: *MachO) void {
|
||||
pub fn writeSymtab(self: Dylib, macho_file: *MachO, ctx: anytype) void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
@ -585,10 +585,10 @@ pub fn writeSymtab(self: Dylib, macho_file: *MachO) void {
|
||||
const file = global.getFile(macho_file) orelse continue;
|
||||
if (file.getIndex() != self.index) continue;
|
||||
const idx = global.getOutputSymtabIndex(macho_file) orelse continue;
|
||||
const n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
|
||||
macho_file.strtab.appendSliceAssumeCapacity(global.getName(macho_file));
|
||||
macho_file.strtab.appendAssumeCapacity(0);
|
||||
const out_sym = &macho_file.symtab.items[idx];
|
||||
const n_strx = @as(u32, @intCast(ctx.strtab.items.len));
|
||||
ctx.strtab.appendSliceAssumeCapacity(global.getName(macho_file));
|
||||
ctx.strtab.appendAssumeCapacity(0);
|
||||
const out_sym = &ctx.symtab.items[idx];
|
||||
out_sym.n_strx = n_strx;
|
||||
global.setOutputSym(macho_file, out_sym);
|
||||
}
|
||||
|
||||
@ -139,15 +139,15 @@ pub fn calcSymtabSize(self: *InternalObject, macho_file: *MachO) !void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn writeSymtab(self: InternalObject, macho_file: *MachO) void {
|
||||
pub fn writeSymtab(self: InternalObject, macho_file: *MachO, ctx: anytype) void {
|
||||
for (self.symbols.items) |sym_index| {
|
||||
const sym = macho_file.getSymbol(sym_index);
|
||||
if (sym.getFile(macho_file)) |file| if (file.getIndex() != self.index) continue;
|
||||
const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;
|
||||
const n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
|
||||
macho_file.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));
|
||||
macho_file.strtab.appendAssumeCapacity(0);
|
||||
const out_sym = &macho_file.symtab.items[idx];
|
||||
const n_strx = @as(u32, @intCast(ctx.strtab.items.len));
|
||||
ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));
|
||||
ctx.strtab.appendAssumeCapacity(0);
|
||||
const out_sym = &ctx.symtab.items[idx];
|
||||
out_sym.n_strx = n_strx;
|
||||
sym.setOutputSym(macho_file, out_sym);
|
||||
}
|
||||
|
||||
@ -1320,7 +1320,7 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) error{Overflow}!void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn writeSymtab(self: Object, macho_file: *MachO) error{Overflow}!void {
|
||||
pub fn writeSymtab(self: Object, macho_file: *MachO, ctx: anytype) error{Overflow}!void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
@ -1329,19 +1329,19 @@ pub fn writeSymtab(self: Object, macho_file: *MachO) error{Overflow}!void {
|
||||
const file = sym.getFile(macho_file) orelse continue;
|
||||
if (file.getIndex() != self.index) continue;
|
||||
const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;
|
||||
const n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
|
||||
macho_file.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));
|
||||
macho_file.strtab.appendAssumeCapacity(0);
|
||||
const out_sym = &macho_file.symtab.items[idx];
|
||||
const n_strx = @as(u32, @intCast(ctx.strtab.items.len));
|
||||
ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));
|
||||
ctx.strtab.appendAssumeCapacity(0);
|
||||
const out_sym = &ctx.symtab.items[idx];
|
||||
out_sym.n_strx = n_strx;
|
||||
sym.setOutputSym(macho_file, out_sym);
|
||||
}
|
||||
|
||||
if (macho_file.base.comp.config.debug_format != .strip and self.hasDebugInfo())
|
||||
try self.writeStabs(macho_file);
|
||||
try self.writeStabs(macho_file, ctx);
|
||||
}
|
||||
|
||||
pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void {
|
||||
pub fn writeStabs(self: *const Object, macho_file: *MachO, ctx: anytype) error{Overflow}!void {
|
||||
const writeFuncStab = struct {
|
||||
inline fn writeFuncStab(
|
||||
n_strx: u32,
|
||||
@ -1349,30 +1349,30 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
|
||||
n_value: u64,
|
||||
size: u64,
|
||||
index: u32,
|
||||
ctx: *MachO,
|
||||
context: anytype,
|
||||
) void {
|
||||
ctx.symtab.items[index] = .{
|
||||
context.symtab.items[index] = .{
|
||||
.n_strx = 0,
|
||||
.n_type = macho.N_BNSYM,
|
||||
.n_sect = n_sect,
|
||||
.n_desc = 0,
|
||||
.n_value = n_value,
|
||||
};
|
||||
ctx.symtab.items[index + 1] = .{
|
||||
context.symtab.items[index + 1] = .{
|
||||
.n_strx = n_strx,
|
||||
.n_type = macho.N_FUN,
|
||||
.n_sect = n_sect,
|
||||
.n_desc = 0,
|
||||
.n_value = n_value,
|
||||
};
|
||||
ctx.symtab.items[index + 2] = .{
|
||||
context.symtab.items[index + 2] = .{
|
||||
.n_strx = 0,
|
||||
.n_type = macho.N_FUN,
|
||||
.n_sect = 0,
|
||||
.n_desc = 0,
|
||||
.n_value = size,
|
||||
};
|
||||
ctx.symtab.items[index + 3] = .{
|
||||
context.symtab.items[index + 3] = .{
|
||||
.n_strx = 0,
|
||||
.n_type = macho.N_ENSYM,
|
||||
.n_sect = n_sect,
|
||||
@ -1392,10 +1392,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
|
||||
|
||||
// Open scope
|
||||
// N_SO comp_dir
|
||||
var n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
|
||||
macho_file.strtab.appendSliceAssumeCapacity(comp_dir);
|
||||
macho_file.strtab.appendAssumeCapacity(0);
|
||||
macho_file.symtab.items[index] = .{
|
||||
var n_strx = @as(u32, @intCast(ctx.strtab.items.len));
|
||||
ctx.strtab.appendSliceAssumeCapacity(comp_dir);
|
||||
ctx.strtab.appendAssumeCapacity(0);
|
||||
ctx.symtab.items[index] = .{
|
||||
.n_strx = n_strx,
|
||||
.n_type = macho.N_SO,
|
||||
.n_sect = 0,
|
||||
@ -1404,10 +1404,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
|
||||
};
|
||||
index += 1;
|
||||
// N_SO tu_name
|
||||
n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
|
||||
macho_file.strtab.appendSliceAssumeCapacity(tu_name);
|
||||
macho_file.strtab.appendAssumeCapacity(0);
|
||||
macho_file.symtab.items[index] = .{
|
||||
n_strx = @as(u32, @intCast(ctx.strtab.items.len));
|
||||
ctx.strtab.appendSliceAssumeCapacity(tu_name);
|
||||
ctx.strtab.appendAssumeCapacity(0);
|
||||
ctx.symtab.items[index] = .{
|
||||
.n_strx = n_strx,
|
||||
.n_type = macho.N_SO,
|
||||
.n_sect = 0,
|
||||
@ -1416,18 +1416,18 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
|
||||
};
|
||||
index += 1;
|
||||
// N_OSO path
|
||||
n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
|
||||
n_strx = @as(u32, @intCast(ctx.strtab.items.len));
|
||||
if (self.archive) |ar| {
|
||||
macho_file.strtab.appendSliceAssumeCapacity(ar.path);
|
||||
macho_file.strtab.appendAssumeCapacity('(');
|
||||
macho_file.strtab.appendSliceAssumeCapacity(self.path);
|
||||
macho_file.strtab.appendAssumeCapacity(')');
|
||||
macho_file.strtab.appendAssumeCapacity(0);
|
||||
ctx.strtab.appendSliceAssumeCapacity(ar.path);
|
||||
ctx.strtab.appendAssumeCapacity('(');
|
||||
ctx.strtab.appendSliceAssumeCapacity(self.path);
|
||||
ctx.strtab.appendAssumeCapacity(')');
|
||||
ctx.strtab.appendAssumeCapacity(0);
|
||||
} else {
|
||||
macho_file.strtab.appendSliceAssumeCapacity(self.path);
|
||||
macho_file.strtab.appendAssumeCapacity(0);
|
||||
ctx.strtab.appendSliceAssumeCapacity(self.path);
|
||||
ctx.strtab.appendAssumeCapacity(0);
|
||||
}
|
||||
macho_file.symtab.items[index] = .{
|
||||
ctx.symtab.items[index] = .{
|
||||
.n_strx = n_strx,
|
||||
.n_type = macho.N_OSO,
|
||||
.n_sect = 0,
|
||||
@ -1448,17 +1448,17 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
|
||||
const sect = macho_file.sections.items(.header)[sym.out_n_sect];
|
||||
const sym_n_strx = n_strx: {
|
||||
const symtab_index = sym.getOutputSymtabIndex(macho_file).?;
|
||||
const osym = macho_file.symtab.items[symtab_index];
|
||||
const osym = ctx.symtab.items[symtab_index];
|
||||
break :n_strx osym.n_strx;
|
||||
};
|
||||
const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.out_n_sect + 1) else 0;
|
||||
const sym_n_value = sym.getAddress(.{}, macho_file);
|
||||
const sym_size = sym.getSize(macho_file);
|
||||
if (sect.isCode()) {
|
||||
writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, macho_file);
|
||||
writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, ctx);
|
||||
index += 4;
|
||||
} else if (sym.visibility == .global) {
|
||||
macho_file.symtab.items[index] = .{
|
||||
ctx.symtab.items[index] = .{
|
||||
.n_strx = sym_n_strx,
|
||||
.n_type = macho.N_GSYM,
|
||||
.n_sect = sym_n_sect,
|
||||
@ -1467,7 +1467,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
|
||||
};
|
||||
index += 1;
|
||||
} else {
|
||||
macho_file.symtab.items[index] = .{
|
||||
ctx.symtab.items[index] = .{
|
||||
.n_strx = sym_n_strx,
|
||||
.n_type = macho.N_STSYM,
|
||||
.n_sect = sym_n_sect,
|
||||
@ -1480,7 +1480,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
|
||||
|
||||
// Close scope
|
||||
// N_SO
|
||||
macho_file.symtab.items[index] = .{
|
||||
ctx.symtab.items[index] = .{
|
||||
.n_strx = 0,
|
||||
.n_type = macho.N_SO,
|
||||
.n_sect = 0,
|
||||
@ -1493,10 +1493,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
|
||||
for (self.stab_files.items) |sf| {
|
||||
// Open scope
|
||||
// N_SO comp_dir
|
||||
var n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
|
||||
macho_file.strtab.appendSliceAssumeCapacity(sf.getCompDir(self));
|
||||
macho_file.strtab.appendAssumeCapacity(0);
|
||||
macho_file.symtab.items[index] = .{
|
||||
var n_strx = @as(u32, @intCast(ctx.strtab.items.len));
|
||||
ctx.strtab.appendSliceAssumeCapacity(sf.getCompDir(self));
|
||||
ctx.strtab.appendAssumeCapacity(0);
|
||||
ctx.symtab.items[index] = .{
|
||||
.n_strx = n_strx,
|
||||
.n_type = macho.N_SO,
|
||||
.n_sect = 0,
|
||||
@ -1505,10 +1505,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
|
||||
};
|
||||
index += 1;
|
||||
// N_SO tu_name
|
||||
n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
|
||||
macho_file.strtab.appendSliceAssumeCapacity(sf.getTuName(self));
|
||||
macho_file.strtab.appendAssumeCapacity(0);
|
||||
macho_file.symtab.items[index] = .{
|
||||
n_strx = @as(u32, @intCast(ctx.strtab.items.len));
|
||||
ctx.strtab.appendSliceAssumeCapacity(sf.getTuName(self));
|
||||
ctx.strtab.appendAssumeCapacity(0);
|
||||
ctx.symtab.items[index] = .{
|
||||
.n_strx = n_strx,
|
||||
.n_type = macho.N_SO,
|
||||
.n_sect = 0,
|
||||
@ -1517,10 +1517,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
|
||||
};
|
||||
index += 1;
|
||||
// N_OSO path
|
||||
n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
|
||||
macho_file.strtab.appendSliceAssumeCapacity(sf.getOsoPath(self));
|
||||
macho_file.strtab.appendAssumeCapacity(0);
|
||||
macho_file.symtab.items[index] = .{
|
||||
n_strx = @as(u32, @intCast(ctx.strtab.items.len));
|
||||
ctx.strtab.appendSliceAssumeCapacity(sf.getOsoPath(self));
|
||||
ctx.strtab.appendAssumeCapacity(0);
|
||||
ctx.symtab.items[index] = .{
|
||||
.n_strx = n_strx,
|
||||
.n_type = macho.N_OSO,
|
||||
.n_sect = 0,
|
||||
@ -1536,7 +1536,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
|
||||
if (!sym.flags.output_symtab) continue;
|
||||
const sym_n_strx = n_strx: {
|
||||
const symtab_index = sym.getOutputSymtabIndex(macho_file).?;
|
||||
const osym = macho_file.symtab.items[symtab_index];
|
||||
const osym = ctx.symtab.items[symtab_index];
|
||||
break :n_strx osym.n_strx;
|
||||
};
|
||||
const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.out_n_sect + 1) else 0;
|
||||
@ -1544,11 +1544,11 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
|
||||
const sym_size = sym.getSize(macho_file);
|
||||
switch (stab.tag) {
|
||||
.func => {
|
||||
writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, macho_file);
|
||||
writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, ctx);
|
||||
index += 4;
|
||||
},
|
||||
.global => {
|
||||
macho_file.symtab.items[index] = .{
|
||||
ctx.symtab.items[index] = .{
|
||||
.n_strx = sym_n_strx,
|
||||
.n_type = macho.N_GSYM,
|
||||
.n_sect = sym_n_sect,
|
||||
@ -1558,7 +1558,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
|
||||
index += 1;
|
||||
},
|
||||
.static => {
|
||||
macho_file.symtab.items[index] = .{
|
||||
ctx.symtab.items[index] = .{
|
||||
.n_strx = sym_n_strx,
|
||||
.n_type = macho.N_STSYM,
|
||||
.n_sect = sym_n_sect,
|
||||
@ -1572,7 +1572,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
|
||||
|
||||
// Close scope
|
||||
// N_SO
|
||||
macho_file.symtab.items[index] = .{
|
||||
ctx.symtab.items[index] = .{
|
||||
.n_strx = 0,
|
||||
.n_type = macho.N_SO,
|
||||
.n_sect = 0,
|
||||
|
||||
@ -310,7 +310,7 @@ pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) !void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void {
|
||||
pub fn writeSymtab(self: ZigObject, macho_file: *MachO, ctx: anytype) void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
@ -319,10 +319,10 @@ pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void {
|
||||
const file = sym.getFile(macho_file) orelse continue;
|
||||
if (file.getIndex() != self.index) continue;
|
||||
const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;
|
||||
const n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
|
||||
macho_file.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));
|
||||
macho_file.strtab.appendAssumeCapacity(0);
|
||||
const out_sym = &macho_file.symtab.items[idx];
|
||||
const n_strx = @as(u32, @intCast(ctx.strtab.items.len));
|
||||
ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));
|
||||
ctx.strtab.appendAssumeCapacity(0);
|
||||
const out_sym = &ctx.symtab.items[idx];
|
||||
out_sym.n_strx = n_strx;
|
||||
sym.setOutputSym(macho_file, out_sym);
|
||||
}
|
||||
@ -531,7 +531,7 @@ pub fn updateFunc(
|
||||
var code_buffer = std.ArrayList(u8).init(gpa);
|
||||
defer code_buffer.deinit();
|
||||
|
||||
var decl_state: ?Dwarf.DeclState = null; // TODO: Dwarf
|
||||
var decl_state: ?Dwarf.DeclState = if (macho_file.getDebugSymbols()) |d_sym| try d_sym.dwarf.initDeclState(mod, decl_index) else null;
|
||||
defer if (decl_state) |*ds| ds.deinit();
|
||||
|
||||
const dio: codegen.DebugInfoOutput = if (decl_state) |*ds| .{ .dwarf = ds } else .none;
|
||||
@ -557,16 +557,16 @@ pub fn updateFunc(
|
||||
const sect_index = try self.getDeclOutputSection(macho_file, decl, code);
|
||||
try self.updateDeclCode(macho_file, decl_index, sym_index, sect_index, code);
|
||||
|
||||
// if (decl_state) |*ds| {
|
||||
// const sym = elf_file.symbol(sym_index);
|
||||
// try self.dwarf.?.commitDeclState(
|
||||
// mod,
|
||||
// decl_index,
|
||||
// sym.value,
|
||||
// sym.atom(elf_file).?.size,
|
||||
// ds,
|
||||
// );
|
||||
// }
|
||||
if (decl_state) |*ds| {
|
||||
const sym = macho_file.getSymbol(sym_index);
|
||||
try macho_file.getDebugSymbols().?.dwarf.commitDeclState(
|
||||
mod,
|
||||
decl_index,
|
||||
sym.getAddress(.{}, macho_file),
|
||||
sym.getAtom(macho_file).?.size,
|
||||
ds,
|
||||
);
|
||||
}
|
||||
|
||||
// Since we updated the vaddr and the size, each corresponding export
|
||||
// symbol also needs to be updated.
|
||||
@ -606,7 +606,7 @@ pub fn updateDecl(
|
||||
var code_buffer = std.ArrayList(u8).init(gpa);
|
||||
defer code_buffer.deinit();
|
||||
|
||||
var decl_state: ?Dwarf.DeclState = null; // TODO: Dwarf
|
||||
var decl_state: ?Dwarf.DeclState = if (macho_file.getDebugSymbols()) |d_sym| try d_sym.dwarf.initDeclState(mod, decl_index) else null;
|
||||
defer if (decl_state) |*ds| ds.deinit();
|
||||
|
||||
const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val;
|
||||
@ -638,15 +638,16 @@ pub fn updateDecl(
|
||||
try self.updateDeclCode(macho_file, decl_index, sym_index, sect_index, code);
|
||||
}
|
||||
|
||||
// if (decl_state) |*ds| {
|
||||
// try self.d_sym.?.dwarf.commitDeclState(
|
||||
// mod,
|
||||
// decl_index,
|
||||
// addr,
|
||||
// self.getAtom(atom_index).size,
|
||||
// ds,
|
||||
// );
|
||||
// }
|
||||
if (decl_state) |*ds| {
|
||||
const sym = macho_file.getSymbol(sym_index);
|
||||
try macho_file.getDebugSymbols().?.dwarf.commitDeclState(
|
||||
mod,
|
||||
decl_index,
|
||||
sym.getAddress(.{}, macho_file),
|
||||
sym.getAtom(macho_file).?.size,
|
||||
ds,
|
||||
);
|
||||
}
|
||||
|
||||
// Since we updated the vaddr and the size, each corresponding export symbol also
|
||||
// needs to be updated.
|
||||
@ -1220,13 +1221,14 @@ fn updateLazySymbol(
|
||||
/// Must be called only after a successful call to `updateDecl`.
|
||||
pub fn updateDeclLineNumber(
|
||||
self: *ZigObject,
|
||||
macho_file: *MachO,
|
||||
mod: *Module,
|
||||
decl_index: InternPool.DeclIndex,
|
||||
) !void {
|
||||
_ = self;
|
||||
_ = mod;
|
||||
_ = decl_index;
|
||||
// TODO: Dwarf
|
||||
if (macho_file.getDebugSymbols()) |d_sym| {
|
||||
try d_sym.dwarf.updateDeclLineNumber(mod, decl_index);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deleteDeclExport(
|
||||
|
||||
@ -90,9 +90,9 @@ pub const File = union(enum) {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn writeSymtab(file: File, macho_file: *MachO) !void {
|
||||
pub fn writeSymtab(file: File, macho_file: *MachO, ctx: anytype) !void {
|
||||
return switch (file) {
|
||||
inline else => |x| x.writeSymtab(macho_file),
|
||||
inline else => |x| x.writeSymtab(macho_file, ctx),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ const macho = std.macho;
|
||||
const mem = std.mem;
|
||||
|
||||
const Allocator = mem.Allocator;
|
||||
const DebugSymbols = @import("DebugSymbols.zig");
|
||||
const Dylib = @import("Dylib.zig");
|
||||
const MachO = @import("../MachO.zig");
|
||||
|
||||
@ -97,6 +98,27 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) u32 {
|
||||
return @as(u32, @intCast(sizeofcmds));
|
||||
}
|
||||
|
||||
pub fn calcLoadCommandsSizeDsym(macho_file: *MachO, dsym: *const DebugSymbols) u32 {
|
||||
var sizeofcmds: u64 = 0;
|
||||
|
||||
// LC_SEGMENT_64
|
||||
sizeofcmds += @sizeOf(macho.segment_command_64) * (macho_file.segments.items.len - 1);
|
||||
for (macho_file.segments.items) |seg| {
|
||||
sizeofcmds += seg.nsects * @sizeOf(macho.section_64);
|
||||
}
|
||||
sizeofcmds += @sizeOf(macho.segment_command_64) * dsym.segments.items.len;
|
||||
for (dsym.segments.items) |seg| {
|
||||
sizeofcmds += seg.nsects * @sizeOf(macho.section_64);
|
||||
}
|
||||
|
||||
// LC_SYMTAB
|
||||
sizeofcmds += @sizeOf(macho.symtab_command);
|
||||
// LC_UUID
|
||||
sizeofcmds += @sizeOf(macho.uuid_command);
|
||||
|
||||
return @as(u32, @intCast(sizeofcmds));
|
||||
}
|
||||
|
||||
pub fn calcLoadCommandsSizeObject(macho_file: *MachO) u32 {
|
||||
var sizeofcmds: u64 = 0;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user