authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-12-30 21:34:49+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-12-31 10:19:04+01:00
log60b3c4ae3ce1359779745392d4fb169fdff158d4
treee1ecdecf6f4949cf248dbec85f3c6228891cfda5
parent364691fa1f5a1c7da024cc58b9b3138425a5e475

macho: refactor and fix stage2 tests


2 files changed, 42 insertions(+), 35 deletions(-)

src/link/MachO.zig+12-9
...@@ -329,10 +329,12 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio...@@ -329,10 +329,12 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
329 }329 }
330330
331 try self.populateMissingMetadata();331 try self.populateMissingMetadata();
332 try self.d_sym.?.populateMissingMetadata(allocator);
333
334 try self.writeLocalSymbol(0);332 try self.writeLocalSymbol(0);
335 try self.d_sym.?.writeLocalSymbol(0);333
334 if (self.d_sym) |*ds| {
335 try ds.populateMissingMetadata(allocator);
336 try ds.writeLocalSymbol(0);
337 }
336338
337 return self;339 return self;
338}340}
...@@ -1276,7 +1278,8 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -1276,7 +1278,8 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1276 symbol.n_desc = 0;1278 symbol.n_desc = 0;
12771279
1278 try self.writeLocalSymbol(decl.link.macho.local_sym_index);1280 try self.writeLocalSymbol(decl.link.macho.local_sym_index);
1279 try self.d_sym.?.writeLocalSymbol(decl.link.macho.local_sym_index);1281 if (self.d_sym) |*ds|
1282 try ds.writeLocalSymbol(decl.link.macho.local_sym_index);
1280 } else {1283 } else {
1281 const decl_name = mem.spanZ(decl.name);1284 const decl_name = mem.spanZ(decl.name);
1282 const name_str_index = try self.makeString(decl_name);1285 const name_str_index = try self.makeString(decl_name);
...@@ -1294,7 +1297,8 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -1294,7 +1297,8 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1294 self.offset_table.items[decl.link.macho.offset_table_index] = addr;1297 self.offset_table.items[decl.link.macho.offset_table_index] = addr;
12951298
1296 try self.writeLocalSymbol(decl.link.macho.local_sym_index);1299 try self.writeLocalSymbol(decl.link.macho.local_sym_index);
1297 try self.d_sym.?.writeLocalSymbol(decl.link.macho.local_sym_index);1300 if (self.d_sym) |*ds|
1301 try ds.writeLocalSymbol(decl.link.macho.local_sym_index);
1298 try self.writeOffsetTableEntry(decl.link.macho.offset_table_index);1302 try self.writeOffsetTableEntry(decl.link.macho.offset_table_index);
1299 }1303 }
13001304
...@@ -1398,9 +1402,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -1398,9 +1402,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1398 const new_offset = dwarf_segment.findFreeSpace(needed_size, 1, null);1402 const new_offset = dwarf_segment.findFreeSpace(needed_size, 1, null);
1399 const existing_size = last_src_fn.off;1403 const existing_size = last_src_fn.off;
14001404
1401 assert(dwarf_segment.inner.fileoff + dwarf_segment.inner.filesize >= new_offset + needed_size);1405 log.debug("moving __debug_line section: {} bytes from 0x{x} to 0x{x}", .{
1402
1403 log.debug("moving __zdebug_line section: {} bytes from 0x{x} to 0x{x}", .{
1404 existing_size,1406 existing_size,
1405 debug_line_sect.offset,1407 debug_line_sect.offset,
1406 new_offset,1408 new_offset,
...@@ -2097,7 +2099,8 @@ fn makeString(self: *MachO, bytes: []const u8) !u32 {...@@ -2097,7 +2099,8 @@ fn makeString(self: *MachO, bytes: []const u8) !u32 {
2097 self.string_table.appendSliceAssumeCapacity(bytes);2099 self.string_table.appendSliceAssumeCapacity(bytes);
2098 self.string_table.appendAssumeCapacity(0);2100 self.string_table.appendAssumeCapacity(0);
2099 self.string_table_dirty = true;2101 self.string_table_dirty = true;
2100 self.d_sym.?.string_table_dirty = true;2102 if (self.d_sym) |*ds|
2103 ds.string_table_dirty = true;
2101 return @intCast(u32, result);2104 return @intCast(u32, result);
2102}2105}
21032106
src/link/MachO/DebugSymbols.zig+30-26
...@@ -94,6 +94,15 @@ pub const abbrev_base_type = 4;...@@ -94,6 +94,15 @@ pub const abbrev_base_type = 4;
94pub const abbrev_pad1 = 5;94pub const abbrev_pad1 = 5;
95pub const abbrev_parameter = 6;95pub const abbrev_parameter = 6;
9696
97/// The reloc offset for the virtual address of a function in its Line Number Program.
98/// Size is a virtual address integer.
99pub const dbg_line_vaddr_reloc_index = 3;
100/// The reloc offset for the virtual address of a function in its .debug_info TAG_subprogram.
101/// Size is a virtual address integer.
102pub const dbg_info_low_pc_reloc_index = 1;
103
104pub const min_nop_size = 2;
105
97/// You must call this function *after* `MachO.populateMissingMetadata()`106/// You must call this function *after* `MachO.populateMissingMetadata()`
98/// has been called to get a viable debug symbols output.107/// has been called to get a viable debug symbols output.
99pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void {108pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void {
...@@ -469,7 +478,7 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt...@@ -469,7 +478,7 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt
469478
470 if (di_buf.items.len > first_dbg_info_decl.dbg_info_off) {479 if (di_buf.items.len > first_dbg_info_decl.dbg_info_off) {
471 // Move the first N decls to the end to make more padding for the header.480 // Move the first N decls to the end to make more padding for the header.
472 @panic("TODO: handle __zdebug_info header exceeding its padding");481 @panic("TODO: handle __debug_info header exceeding its padding");
473 }482 }
474 const jmp_amt = first_dbg_info_decl.dbg_info_off - di_buf.items.len;483 const jmp_amt = first_dbg_info_decl.dbg_info_off - di_buf.items.len;
475 try self.pwriteDbgInfoNops(0, di_buf.items, jmp_amt, false, debug_info_sect.offset);484 try self.pwriteDbgInfoNops(0, di_buf.items, jmp_amt, false, debug_info_sect.offset);
...@@ -648,16 +657,7 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt...@@ -648,16 +657,7 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt
648 }657 }
649658
650 try self.writeStringTable();659 try self.writeStringTable();
651660 self.updateDwarfSegment();
652 {
653 const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
654 var file_size: u64 = 0;
655 for (dwarf_segment.sections.items) |sect| {
656 file_size += sect.size;
657 }
658 dwarf_segment.inner.filesize = file_size;
659 }
660
661 try self.writeLoadCommands(allocator);661 try self.writeLoadCommands(allocator);
662 try self.writeHeader();662 try self.writeHeader();
663663
...@@ -676,6 +676,7 @@ pub fn deinit(self: *DebugSymbols, allocator: *Allocator) void {...@@ -676,6 +676,7 @@ pub fn deinit(self: *DebugSymbols, allocator: *Allocator) void {
676 for (self.load_commands.items) |*lc| {676 for (self.load_commands.items) |*lc| {
677 lc.deinit(allocator);677 lc.deinit(allocator);
678 }678 }
679 self.load_commands.deinit(allocator);
679 self.file.close();680 self.file.close();
680}681}
681682
...@@ -724,6 +725,21 @@ fn copySegmentCommand(self: *DebugSymbols, allocator: *Allocator, base_cmd: Segm...@@ -724,6 +725,21 @@ fn copySegmentCommand(self: *DebugSymbols, allocator: *Allocator, base_cmd: Segm
724 return cmd;725 return cmd;
725}726}
726727
728fn updateDwarfSegment(self: *DebugSymbols) void {
729 const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
730 var file_size: u64 = 0;
731 for (dwarf_segment.sections.items) |sect| {
732 file_size += sect.size;
733 }
734 if (file_size != dwarf_segment.inner.filesize) {
735 dwarf_segment.inner.filesize = file_size;
736 if (dwarf_segment.inner.vmsize < dwarf_segment.inner.filesize) {
737 dwarf_segment.inner.vmsize = mem.alignForwardGeneric(u64, dwarf_segment.inner.filesize, page_size);
738 }
739 self.load_commands_dirty = true;
740 }
741}
742
727/// Writes all load commands and section headers.743/// Writes all load commands and section headers.
728fn writeLoadCommands(self: *DebugSymbols, allocator: *Allocator) !void {744fn writeLoadCommands(self: *DebugSymbols, allocator: *Allocator) !void {
729 if (!self.load_commands_dirty) return;745 if (!self.load_commands_dirty) return;
...@@ -823,7 +839,7 @@ fn relocateSymbolTable(self: *DebugSymbols) !void {...@@ -823,7 +839,7 @@ fn relocateSymbolTable(self: *DebugSymbols) !void {
823 const new_symoff = self.findFreeSpaceLinkedit(needed_size, @alignOf(macho.nlist_64));839 const new_symoff = self.findFreeSpaceLinkedit(needed_size, @alignOf(macho.nlist_64));
824 const existing_size = symtab.nsyms * @sizeOf(macho.nlist_64);840 const existing_size = symtab.nsyms * @sizeOf(macho.nlist_64);
825841
826 assert(new_symoff + existing_size <= self.linkedit_off + self.linkedit_size);842 assert(new_symoff + existing_size <= self.linkedit_off + self.linkedit_size); // TODO expand LINKEDIT segment.
827 log.debug("relocating dSym symbol table from 0x{x}-0x{x} to 0x{x}-0x{x}", .{843 log.debug("relocating dSym symbol table from 0x{x}-0x{x} to 0x{x}-0x{x}", .{
828 symtab.symoff,844 symtab.symoff,
829 symtab.symoff + existing_size,845 symtab.symoff + existing_size,
...@@ -850,7 +866,7 @@ pub fn writeLocalSymbol(self: *DebugSymbols, index: usize) !void {...@@ -850,7 +866,7 @@ pub fn writeLocalSymbol(self: *DebugSymbols, index: usize) !void {
850 try self.file.pwriteAll(mem.asBytes(&self.base.local_symbols.items[index]), off);866 try self.file.pwriteAll(mem.asBytes(&self.base.local_symbols.items[index]), off);
851}867}
852868
853pub fn writeStringTable(self: *DebugSymbols) !void {869fn writeStringTable(self: *DebugSymbols) !void {
854 if (!self.string_table_dirty) return;870 if (!self.string_table_dirty) return;
855871
856 const tracy = trace(@src());872 const tracy = trace(@src());
...@@ -989,10 +1005,7 @@ pub fn writeDeclDebugInfo(self: *DebugSymbols, text_block: *TextBlock, dbg_info_...@@ -989,10 +1005,7 @@ pub fn writeDeclDebugInfo(self: *DebugSymbols, text_block: *TextBlock, dbg_info_
989 const new_offset = dwarf_segment.findFreeSpace(needed_size, 1, null);1005 const new_offset = dwarf_segment.findFreeSpace(needed_size, 1, null);
990 const existing_size = last_decl.dbg_info_off;1006 const existing_size = last_decl.dbg_info_off;
9911007
992 // TODO1008 log.debug("moving __debug_info section: {} bytes from 0x{x} to 0x{x}", .{
993 assert(dwarf_segment.inner.fileoff + dwarf_segment.inner.filesize >= new_offset + needed_size);
994
995 log.debug("moving _debug_info section: {} bytes from 0x{x} to 0x{x}", .{
996 existing_size,1009 existing_size,
997 debug_info_sect.offset,1010 debug_info_sect.offset,
998 new_offset,1011 new_offset,
...@@ -1042,13 +1055,6 @@ fn makeDebugString(self: *DebugSymbols, allocator: *Allocator, bytes: []const u8...@@ -1042,13 +1055,6 @@ fn makeDebugString(self: *DebugSymbols, allocator: *Allocator, bytes: []const u8
1042 return @intCast(u32, result);1055 return @intCast(u32, result);
1043}1056}
10441057
1045/// The reloc offset for the virtual address of a function in its Line Number Program.
1046/// Size is a virtual address integer.
1047pub const dbg_line_vaddr_reloc_index = 3;
1048/// The reloc offset for the virtual address of a function in its .debug_info TAG_subprogram.
1049/// Size is a virtual address integer.
1050pub const dbg_info_low_pc_reloc_index = 1;
1051
1052/// The reloc offset for the line offset of a function from the previous function's line.1058/// The reloc offset for the line offset of a function from the previous function's line.
1053/// It's a fixed-size 4-byte ULEB128.1059/// It's a fixed-size 4-byte ULEB128.
1054pub fn getRelocDbgLineOff() usize {1060pub fn getRelocDbgLineOff() usize {
...@@ -1081,8 +1087,6 @@ fn dbgInfoNeededHeaderBytes(self: DebugSymbols) u32 {...@@ -1081,8 +1087,6 @@ fn dbgInfoNeededHeaderBytes(self: DebugSymbols) u32 {
1081 return 120;1087 return 120;
1082}1088}
10831089
1084pub const min_nop_size = 2;
1085
1086/// Writes to the file a buffer, prefixed and suffixed by the specified number of1090/// Writes to the file a buffer, prefixed and suffixed by the specified number of
1087/// bytes of NOPs. Asserts each padding size is at least `min_nop_size` and total padding bytes1091/// bytes of NOPs. Asserts each padding size is at least `min_nop_size` and total padding bytes
1088/// are less than 126,976 bytes (if this limit is ever reached, this function can be1092/// are less than 126,976 bytes (if this limit is ever reached, this function can be