macho: prealloc space for debug sections in dSym

This commit is contained in:
Jakub Konka 2020-12-27 21:51:40 +01:00
parent 3174508903
commit d4725cb40b
2 changed files with 192 additions and 3 deletions

View File

@ -108,6 +108,9 @@ dyld_stub_binder_index: ?u16 = null,
/// Table of symbol names aka the string table.
string_table: std.ArrayListUnmanaged(u8) = .{},
/// Table of debug symbol names aka the debug string table.
debug_string_table: std.ArrayListUnmanaged(u8) = .{},
/// Table of trampolines to the actual symbols in __text section.
offset_table: std.ArrayListUnmanaged(u64) = .{},
@ -980,6 +983,7 @@ pub fn deinit(self: *MachO) void {
self.text_block_free_list.deinit(self.base.allocator);
self.offset_table.deinit(self.base.allocator);
self.offset_table_free_list.deinit(self.base.allocator);
self.debug_string_table.deinit(self.base.allocator);
self.string_table.deinit(self.base.allocator);
self.undef_symbols.deinit(self.base.allocator);
self.global_symbols.deinit(self.base.allocator);

View File

@ -15,9 +15,12 @@ const MachO = @import("../MachO.zig");
const satMul = MachO.satMul;
const alloc_num = MachO.alloc_num;
const alloc_den = MachO.alloc_den;
const makeStaticString = MachO.makeStaticString;
usingnamespace @import("commands.zig");
const page_size: u16 = 0x1000;
base: *MachO,
file: fs.File,
@ -44,12 +47,25 @@ uuid_cmd_index: ?u16 = null,
/// Index into __TEXT,__text section.
text_section_index: ?u16 = null,
linkedit_off: u16 = 0x1000,
linkedit_size: u16 = 0x1000,
linkedit_off: u16 = page_size,
linkedit_size: u16 = page_size,
debug_info_section_index: ?u16 = null,
debug_abbrev_section_index: ?u16 = null,
debug_str_section_index: ?u16 = null,
debug_aranges_section_index: ?u16 = null,
debug_line_section_index: ?u16 = null,
debug_abbrev_table_offset: ?u64 = null,
header_dirty: bool = false,
load_commands_dirty: bool = false,
string_table_dirty: bool = false,
debug_string_table_dirty: bool = false,
debug_abbrev_section_dirty: bool = false,
debug_aranges_section_dirty: bool = false,
debug_info_header_dirty: bool = false,
debug_line_header_dirty: bool = false,
/// You must call this function *after* `MachO.populateMissingMetadata()`
/// has been called to get a viable debug symbols output.
@ -98,7 +114,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
.strsize = base_cmd.strsize,
},
});
try self.writeLocalSymbol(0);
self.header_dirty = true;
self.load_commands_dirty = true;
self.string_table_dirty = true;
@ -139,6 +154,176 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
self.header_dirty = true;
self.load_commands_dirty = true;
}
if (self.dwarf_segment_cmd_index == null) {
self.dwarf_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
const linkedit = self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
const ideal_size: u16 = 200 + 128 + 160 + 250;
const needed_size = mem.alignForwardGeneric(u64, satMul(ideal_size, alloc_num) / alloc_den, page_size);
const off = linkedit.inner.fileoff + linkedit.inner.filesize;
const vmaddr = linkedit.inner.vmaddr + linkedit.inner.vmsize;
log.debug("found dSym __DWARF segment free space 0x{x} to 0x{x}", .{ off, off + needed_size });
try self.load_commands.append(allocator, .{
.Segment = SegmentCommand.empty(.{
.cmd = macho.LC_SEGMENT_64,
.cmdsize = @sizeOf(macho.segment_command_64),
.segname = makeStaticString("__DWARF"),
.vmaddr = vmaddr,
.vmsize = needed_size,
.fileoff = off,
.filesize = needed_size,
.maxprot = 0,
.initprot = 0,
.nsects = 0,
.flags = 0,
}),
});
self.header_dirty = true;
self.load_commands_dirty = true;
}
if (self.debug_str_section_index == null) {
const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
self.debug_str_section_index = @intCast(u16, dwarf_segment.sections.items.len);
assert(self.base.debug_string_table.items.len == 0);
const file_size_hint = 200;
const p_align = 1;
const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
log.debug("found dSym __debug_strtab free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
try dwarf_segment.addSection(allocator, .{
.sectname = makeStaticString("__debug_str"),
.segname = makeStaticString("__DWARF"),
.addr = dwarf_segment.inner.vmaddr + off,
.size = @intCast(u32, self.base.debug_string_table.items.len),
.offset = @intCast(u32, off),
.@"align" = 1,
.reloff = 0,
.nreloc = 0,
.flags = macho.S_REGULAR,
.reserved1 = 0,
.reserved2 = 0,
.reserved3 = 0,
});
self.header_dirty = true;
self.load_commands_dirty = true;
self.debug_string_table_dirty = true;
}
if (self.debug_info_section_index == null) {
const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
self.debug_info_section_index = @intCast(u16, dwarf_segment.sections.items.len);
const file_size_hint = 200;
const p_align = 1;
const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
log.debug("found dSym __debug_info free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
try dwarf_segment.addSection(allocator, .{
.sectname = makeStaticString("__debug_info"),
.segname = makeStaticString("__DWARF"),
.addr = dwarf_segment.inner.vmaddr + off,
.size = file_size_hint,
.offset = @intCast(u32, off),
.@"align" = p_align,
.reloff = 0,
.nreloc = 0,
.flags = macho.S_REGULAR,
.reserved1 = 0,
.reserved2 = 0,
.reserved3 = 0,
});
self.header_dirty = true;
self.load_commands_dirty = true;
self.debug_info_header_dirty = true;
}
if (self.debug_abbrev_section_index == null) {
const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
self.debug_abbrev_section_index = @intCast(u16, dwarf_segment.sections.items.len);
const file_size_hint = 128;
const p_align = 1;
const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
log.debug("found dSym __debug_abbrev free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
try dwarf_segment.addSection(allocator, .{
.sectname = makeStaticString("__debug_abbrev"),
.segname = makeStaticString("__DWARF"),
.addr = dwarf_segment.inner.vmaddr + off,
.size = file_size_hint,
.offset = @intCast(u32, off),
.@"align" = p_align,
.reloff = 0,
.nreloc = 0,
.flags = macho.S_REGULAR,
.reserved1 = 0,
.reserved2 = 0,
.reserved3 = 0,
});
self.header_dirty = true;
self.load_commands_dirty = true;
self.debug_abbrev_section_dirty = true;
}
if (self.debug_aranges_section_index == null) {
const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
self.debug_aranges_section_index = @intCast(u16, dwarf_segment.sections.items.len);
const file_size_hint = 160;
const p_align = 16;
const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
log.debug("found dSym __debug_aranges free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
try dwarf_segment.addSection(allocator, .{
.sectname = makeStaticString("__debug_aranges"),
.segname = makeStaticString("__DWARF"),
.addr = dwarf_segment.inner.vmaddr + off,
.size = file_size_hint,
.offset = @intCast(u32, off),
.@"align" = p_align,
.reloff = 0,
.nreloc = 0,
.flags = macho.S_REGULAR,
.reserved1 = 0,
.reserved2 = 0,
.reserved3 = 0,
});
self.header_dirty = true;
self.load_commands_dirty = true;
self.debug_aranges_section_dirty = true;
}
if (self.debug_line_section_index == null) {
const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
self.debug_line_section_index = @intCast(u16, dwarf_segment.sections.items.len);
const file_size_hint = 250;
const p_align = 1;
const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
log.debug("found dSym __debug_line free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
try dwarf_segment.addSection(allocator, .{
.sectname = makeStaticString("__debug_line"),
.segname = makeStaticString("__DWARF"),
.addr = dwarf_segment.inner.vmaddr + off,
.size = file_size_hint,
.offset = @intCast(u32, off),
.@"align" = p_align,
.reloff = 0,
.nreloc = 0,
.flags = macho.S_REGULAR,
.reserved1 = 0,
.reserved2 = 0,
.reserved3 = 0,
});
self.header_dirty = true;
self.load_commands_dirty = true;
self.debug_line_header_dirty = true;
}
}
pub fn flush(self: *DebugSymbols, allocator: *Allocator) !void {