| author | |
| committer | |
| log | 37033a96ac2e33a56eb2e153462d1a730b426029 |
| tree | 1d599e8f86942a7daed800ad0c8010855a1c0780 |
| parent | 3122fd0ba0eb4cdb17616658b462a255a37f1ad7 |
4 files changed, 157 insertions(+), 167 deletions(-)
src/link/Dwarf.zig+18-12| ... | @@ -1351,9 +1351,10 @@ pub fn commitDeclState( | ... | @@ -1351,9 +1351,10 @@ pub fn commitDeclState( |
| 1351 | }, | 1351 | }, |
| 1352 | 1352 | ||
| 1353 | .macho => { | 1353 | .macho => { |
| 1354 | const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?; | 1354 | const macho_file = self.bin_file.cast(File.MachO).?; |
| 1355 | const d_sym = macho_file.getDebugSymbols().?; | ||
| 1355 | const sect_index = d_sym.debug_line_section_index.?; | 1356 | const sect_index = d_sym.debug_line_section_index.?; |
| 1356 | try d_sym.growSection(sect_index, needed_size, true); | 1357 | try d_sym.growSection(sect_index, needed_size, true, macho_file); |
| 1357 | const sect = d_sym.getSection(sect_index); | 1358 | const sect = d_sym.getSection(sect_index); |
| 1358 | const file_pos = sect.offset + src_fn.off; | 1359 | const file_pos = sect.offset + src_fn.off; |
| 1359 | try pwriteDbgLineNops( | 1360 | try pwriteDbgLineNops( |
| ... | @@ -1597,9 +1598,10 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons | ... | @@ -1597,9 +1598,10 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons |
| 1597 | }, | 1598 | }, |
| 1598 | 1599 | ||
| 1599 | .macho => { | 1600 | .macho => { |
| 1600 | const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?; | 1601 | const macho_file = self.bin_file.cast(File.MachO).?; |
| 1602 | const d_sym = macho_file.getDebugSymbols().?; | ||
| 1601 | const sect_index = d_sym.debug_info_section_index.?; | 1603 | const sect_index = d_sym.debug_info_section_index.?; |
| 1602 | try d_sym.growSection(sect_index, needed_size, true); | 1604 | try d_sym.growSection(sect_index, needed_size, true, macho_file); |
| 1603 | const sect = d_sym.getSection(sect_index); | 1605 | const sect = d_sym.getSection(sect_index); |
| 1604 | const file_pos = sect.offset + atom.off; | 1606 | const file_pos = sect.offset + atom.off; |
| 1605 | try pwriteDbgInfoNops( | 1607 | try pwriteDbgInfoNops( |
| ... | @@ -1877,9 +1879,10 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void { | ... | @@ -1877,9 +1879,10 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void { |
| 1877 | try elf_file.base.file.?.pwriteAll(&abbrev_buf, file_pos); | 1879 | try elf_file.base.file.?.pwriteAll(&abbrev_buf, file_pos); |
| 1878 | }, | 1880 | }, |
| 1879 | .macho => { | 1881 | .macho => { |
| 1880 | const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?; | 1882 | const macho_file = self.bin_file.cast(File.MachO).?; |
| 1883 | const d_sym = macho_file.getDebugSymbols().?; | ||
| 1881 | const sect_index = d_sym.debug_abbrev_section_index.?; | 1884 | const sect_index = d_sym.debug_abbrev_section_index.?; |
| 1882 | try d_sym.growSection(sect_index, needed_size, false); | 1885 | try d_sym.growSection(sect_index, needed_size, false, macho_file); |
| 1883 | const sect = d_sym.getSection(sect_index); | 1886 | const sect = d_sym.getSection(sect_index); |
| 1884 | const file_pos = sect.offset + abbrev_offset; | 1887 | const file_pos = sect.offset + abbrev_offset; |
| 1885 | try d_sym.file.pwriteAll(&abbrev_buf, file_pos); | 1888 | try d_sym.file.pwriteAll(&abbrev_buf, file_pos); |
| ... | @@ -2292,9 +2295,10 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void { | ... | @@ -2292,9 +2295,10 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void { |
| 2292 | try elf_file.base.file.?.pwriteAll(di_buf.items, file_pos); | 2295 | try elf_file.base.file.?.pwriteAll(di_buf.items, file_pos); |
| 2293 | }, | 2296 | }, |
| 2294 | .macho => { | 2297 | .macho => { |
| 2295 | const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?; | 2298 | const macho_file = self.bin_file.cast(File.MachO).?; |
| 2299 | const d_sym = macho_file.getDebugSymbols().?; | ||
| 2296 | const sect_index = d_sym.debug_aranges_section_index.?; | 2300 | const sect_index = d_sym.debug_aranges_section_index.?; |
| 2297 | try d_sym.growSection(sect_index, needed_size, false); | 2301 | try d_sym.growSection(sect_index, needed_size, false, macho_file); |
| 2298 | const sect = d_sym.getSection(sect_index); | 2302 | const sect = d_sym.getSection(sect_index); |
| 2299 | const file_pos = sect.offset; | 2303 | const file_pos = sect.offset; |
| 2300 | try d_sym.file.pwriteAll(di_buf.items, file_pos); | 2304 | try d_sym.file.pwriteAll(di_buf.items, file_pos); |
| ... | @@ -2432,10 +2436,11 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void { | ... | @@ -2432,10 +2436,11 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void { |
| 2432 | try elf_file.base.file.?.pwriteAll(buffer, file_pos + delta); | 2436 | try elf_file.base.file.?.pwriteAll(buffer, file_pos + delta); |
| 2433 | }, | 2437 | }, |
| 2434 | .macho => { | 2438 | .macho => { |
| 2435 | const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?; | 2439 | const macho_file = self.bin_file.cast(File.MachO).?; |
| 2440 | const d_sym = macho_file.getDebugSymbols().?; | ||
| 2436 | const sect_index = d_sym.debug_line_section_index.?; | 2441 | const sect_index = d_sym.debug_line_section_index.?; |
| 2437 | const needed_size: u32 = @intCast(d_sym.getSection(sect_index).size + delta); | 2442 | const needed_size: u32 = @intCast(d_sym.getSection(sect_index).size + delta); |
| 2438 | try d_sym.growSection(sect_index, needed_size, true); | 2443 | try d_sym.growSection(sect_index, needed_size, true, macho_file); |
| 2439 | const file_pos = d_sym.getSection(sect_index).offset + first_fn.off; | 2444 | const file_pos = d_sym.getSection(sect_index).offset + first_fn.off; |
| 2440 | 2445 | ||
| 2441 | const amt = try d_sym.file.preadAll(buffer, file_pos); | 2446 | const amt = try d_sym.file.preadAll(buffer, file_pos); |
| ... | @@ -2653,8 +2658,9 @@ fn addDIFile(self: *Dwarf, mod: *Module, decl_index: InternPool.DeclIndex) !u28 | ... | @@ -2653,8 +2658,9 @@ fn addDIFile(self: *Dwarf, mod: *Module, decl_index: InternPool.DeclIndex) !u28 |
| 2653 | elf_file.markDirty(elf_file.debug_line_section_index.?); | 2658 | elf_file.markDirty(elf_file.debug_line_section_index.?); |
| 2654 | }, | 2659 | }, |
| 2655 | .macho => { | 2660 | .macho => { |
| 2656 | const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?; | 2661 | const macho_file = self.bin_file.cast(File.MachO).?; |
| 2657 | d_sym.markDirty(d_sym.debug_line_section_index.?); | 2662 | const d_sym = macho_file.getDebugSymbols().?; |
| 2663 | d_sym.markDirty(d_sym.debug_line_section_index.?, macho_file); | ||
| 2658 | }, | 2664 | }, |
| 2659 | .wasm => {}, | 2665 | .wasm => {}, |
| 2660 | else => unreachable, | 2666 | else => unreachable, |
src/link/MachO.zig+22-30| ... | @@ -255,43 +255,35 @@ pub fn createEmpty( | ... | @@ -255,43 +255,35 @@ pub fn createEmpty( |
| 255 | )}), | 255 | )}), |
| 256 | } }); | 256 | } }); |
| 257 | self.zig_object = index; | 257 | self.zig_object = index; |
| 258 | try self.getZigObject().?.init(self); | 258 | const zo = self.getZigObject().?; |
| 259 | try zo.init(self); | ||
| 260 | |||
| 259 | try self.initMetadata(.{ | 261 | try self.initMetadata(.{ |
| 260 | .symbol_count_hint = options.symbol_count_hint, | 262 | .symbol_count_hint = options.symbol_count_hint, |
| 261 | .program_code_size_hint = options.program_code_size_hint, | 263 | .program_code_size_hint = options.program_code_size_hint, |
| 262 | }); | 264 | }); |
| 263 | 265 | ||
| 264 | switch (comp.config.debug_format) { | 266 | if (zo.dwarf != null and !self.base.isRelocatable()) { |
| 265 | .strip => {}, | 267 | // Create dSYM bundle. |
| 266 | .dwarf => if (!self.base.isRelocatable()) { | 268 | log.debug("creating {s}.dSYM bundle", .{emit.sub_path}); |
| 267 | // Create dSYM bundle. | ||
| 268 | log.debug("creating {s}.dSYM bundle", .{emit.sub_path}); | ||
| 269 | |||
| 270 | const sep = fs.path.sep_str; | ||
| 271 | const d_sym_path = try std.fmt.allocPrint( | ||
| 272 | arena, | ||
| 273 | "{s}.dSYM" ++ sep ++ "Contents" ++ sep ++ "Resources" ++ sep ++ "DWARF", | ||
| 274 | .{emit.sub_path}, | ||
| 275 | ); | ||
| 276 | 269 | ||
| 277 | var d_sym_bundle = try emit.directory.handle.makeOpenPath(d_sym_path, .{}); | 270 | const sep = fs.path.sep_str; |
| 278 | defer d_sym_bundle.close(); | 271 | const d_sym_path = try std.fmt.allocPrint( |
| 272 | arena, | ||
| 273 | "{s}.dSYM" ++ sep ++ "Contents" ++ sep ++ "Resources" ++ sep ++ "DWARF", | ||
| 274 | .{emit.sub_path}, | ||
| 275 | ); | ||
| 279 | 276 | ||
| 280 | const d_sym_file = try d_sym_bundle.createFile(emit.sub_path, .{ | 277 | var d_sym_bundle = try emit.directory.handle.makeOpenPath(d_sym_path, .{}); |
| 281 | .truncate = false, | 278 | defer d_sym_bundle.close(); |
| 282 | .read = true, | ||
| 283 | }); | ||
| 284 | 279 | ||
| 285 | self.d_sym = .{ | 280 | const d_sym_file = try d_sym_bundle.createFile(emit.sub_path, .{ |
| 286 | .allocator = gpa, | 281 | .truncate = false, |
| 287 | .dwarf = link.File.Dwarf.init(&self.base, .dwarf32), | 282 | .read = true, |
| 288 | .file = d_sym_file, | 283 | }); |
| 289 | }; | 284 | |
| 290 | try self.d_sym.?.initMetadata(self); | 285 | self.d_sym = .{ .allocator = gpa, .file = d_sym_file }; |
| 291 | } else { | 286 | try self.d_sym.?.initMetadata(self); |
| 292 | @panic("TODO: implement generating and emitting __DWARF in .o file"); | ||
| 293 | }, | ||
| 294 | .code_view => unreachable, | ||
| 295 | } | 287 | } |
| 296 | } | 288 | } |
| 297 | } | 289 | } |
| ... | @@ -3152,7 +3144,7 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex) | ... | @@ -3152,7 +3144,7 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex) |
| 3152 | 3144 | ||
| 3153 | pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl_index: InternPool.DeclIndex) !void { | 3145 | pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl_index: InternPool.DeclIndex) !void { |
| 3154 | if (self.llvm_object) |_| return; | 3146 | if (self.llvm_object) |_| return; |
| 3155 | return self.getZigObject().?.updateDeclLineNumber(self, module, decl_index); | 3147 | return self.getZigObject().?.updateDeclLineNumber(module, decl_index); |
| 3156 | } | 3148 | } |
| 3157 | 3149 | ||
| 3158 | pub fn updateExports( | 3150 | pub fn updateExports( |
src/link/MachO/DebugSymbols.zig+35-112| ... | @@ -1,5 +1,4 @@ | ... | @@ -1,5 +1,4 @@ |
| 1 | allocator: Allocator, | 1 | allocator: Allocator, |
| 2 | dwarf: Dwarf, | ||
| 3 | file: fs.File, | 2 | file: fs.File, |
| 4 | 3 | ||
| 5 | symtab_cmd: macho.symtab_command = .{}, | 4 | symtab_cmd: macho.symtab_command = .{}, |
| ... | @@ -17,12 +16,6 @@ debug_str_section_index: ?u8 = null, | ... | @@ -17,12 +16,6 @@ debug_str_section_index: ?u8 = null, |
| 17 | debug_aranges_section_index: ?u8 = null, | 16 | debug_aranges_section_index: ?u8 = null, |
| 18 | debug_line_section_index: ?u8 = null, | 17 | debug_line_section_index: ?u8 = null, |
| 19 | 18 | ||
| 20 | debug_string_table_dirty: bool = false, | ||
| 21 | debug_abbrev_section_dirty: bool = false, | ||
| 22 | debug_aranges_section_dirty: bool = false, | ||
| 23 | debug_info_header_dirty: bool = false, | ||
| 24 | debug_line_header_dirty: bool = false, | ||
| 25 | |||
| 26 | relocs: std.ArrayListUnmanaged(Reloc) = .{}, | 19 | relocs: std.ArrayListUnmanaged(Reloc) = .{}, |
| 27 | 20 | ||
| 28 | /// Output synthetic sections | 21 | /// Output synthetic sections |
| ... | @@ -44,7 +37,7 @@ pub const Reloc = struct { | ... | @@ -44,7 +37,7 @@ pub const Reloc = struct { |
| 44 | pub fn initMetadata(self: *DebugSymbols, macho_file: *MachO) !void { | 37 | pub fn initMetadata(self: *DebugSymbols, macho_file: *MachO) !void { |
| 45 | try self.strtab.append(self.allocator, 0); | 38 | try self.strtab.append(self.allocator, 0); |
| 46 | 39 | ||
| 47 | if (self.dwarf_segment_cmd_index == null) { | 40 | { |
| 48 | self.dwarf_segment_cmd_index = @as(u8, @intCast(self.segments.items.len)); | 41 | self.dwarf_segment_cmd_index = @as(u8, @intCast(self.segments.items.len)); |
| 49 | 42 | ||
| 50 | const page_size = macho_file.getPageSize(); | 43 | const page_size = macho_file.getPageSize(); |
| ... | @@ -63,46 +56,19 @@ pub fn initMetadata(self: *DebugSymbols, macho_file: *MachO) !void { | ... | @@ -63,46 +56,19 @@ pub fn initMetadata(self: *DebugSymbols, macho_file: *MachO) !void { |
| 63 | }); | 56 | }); |
| 64 | } | 57 | } |
| 65 | 58 | ||
| 66 | if (self.debug_str_section_index == null) { | 59 | self.debug_str_section_index = try self.allocateSection("__debug_str", 200, 0); |
| 67 | assert(self.dwarf.strtab.buffer.items.len == 0); | 60 | self.debug_info_section_index = try self.allocateSection("__debug_info", 200, 0); |
| 68 | try self.dwarf.strtab.buffer.append(self.allocator, 0); | 61 | self.debug_abbrev_section_index = try self.allocateSection("__debug_abbrev", 128, 0); |
| 69 | self.debug_str_section_index = try self.allocateSection( | 62 | self.debug_aranges_section_index = try self.allocateSection("__debug_aranges", 160, 4); |
| 70 | "__debug_str", | 63 | self.debug_line_section_index = try self.allocateSection("__debug_line", 250, 0); |
| 71 | @as(u32, @intCast(self.dwarf.strtab.buffer.items.len)), | 64 | |
| 72 | 0, | 65 | self.linkedit_segment_cmd_index = @as(u8, @intCast(self.segments.items.len)); |
| 73 | ); | 66 | try self.segments.append(self.allocator, .{ |
| 74 | self.debug_string_table_dirty = true; | 67 | .segname = makeStaticString("__LINKEDIT"), |
| 75 | } | 68 | .maxprot = macho.PROT.READ, |
| 76 | 69 | .initprot = macho.PROT.READ, | |
| 77 | if (self.debug_info_section_index == null) { | 70 | .cmdsize = @sizeOf(macho.segment_command_64), |
| 78 | self.debug_info_section_index = try self.allocateSection("__debug_info", 200, 0); | 71 | }); |
| 79 | self.debug_info_header_dirty = true; | ||
| 80 | } | ||
| 81 | |||
| 82 | if (self.debug_abbrev_section_index == null) { | ||
| 83 | self.debug_abbrev_section_index = try self.allocateSection("__debug_abbrev", 128, 0); | ||
| 84 | self.debug_abbrev_section_dirty = true; | ||
| 85 | } | ||
| 86 | |||
| 87 | if (self.debug_aranges_section_index == null) { | ||
| 88 | self.debug_aranges_section_index = try self.allocateSection("__debug_aranges", 160, 4); | ||
| 89 | self.debug_aranges_section_dirty = true; | ||
| 90 | } | ||
| 91 | |||
| 92 | if (self.debug_line_section_index == null) { | ||
| 93 | self.debug_line_section_index = try self.allocateSection("__debug_line", 250, 0); | ||
| 94 | self.debug_line_header_dirty = true; | ||
| 95 | } | ||
| 96 | |||
| 97 | if (self.linkedit_segment_cmd_index == null) { | ||
| 98 | self.linkedit_segment_cmd_index = @as(u8, @intCast(self.segments.items.len)); | ||
| 99 | try self.segments.append(self.allocator, .{ | ||
| 100 | .segname = makeStaticString("__LINKEDIT"), | ||
| 101 | .maxprot = macho.PROT.READ, | ||
| 102 | .initprot = macho.PROT.READ, | ||
| 103 | .cmdsize = @sizeOf(macho.segment_command_64), | ||
| 104 | }); | ||
| 105 | } | ||
| 106 | } | 72 | } |
| 107 | 73 | ||
| 108 | fn allocateSection(self: *DebugSymbols, sectname: []const u8, size: u64, alignment: u16) !u8 { | 74 | fn allocateSection(self: *DebugSymbols, sectname: []const u8, size: u64, alignment: u16) !u8 { |
| ... | @@ -133,7 +99,13 @@ fn allocateSection(self: *DebugSymbols, sectname: []const u8, size: u64, alignme | ... | @@ -133,7 +99,13 @@ fn allocateSection(self: *DebugSymbols, sectname: []const u8, size: u64, alignme |
| 133 | return index; | 99 | return index; |
| 134 | } | 100 | } |
| 135 | 101 | ||
| 136 | pub fn growSection(self: *DebugSymbols, sect_index: u8, needed_size: u32, requires_file_copy: bool) !void { | 102 | pub fn growSection( |
| 103 | self: *DebugSymbols, | ||
| 104 | sect_index: u8, | ||
| 105 | needed_size: u32, | ||
| 106 | requires_file_copy: bool, | ||
| 107 | macho_file: *MachO, | ||
| 108 | ) !void { | ||
| 137 | const sect = self.getSectionPtr(sect_index); | 109 | const sect = self.getSectionPtr(sect_index); |
| 138 | 110 | ||
| 139 | if (needed_size > self.allocatedSize(sect.offset)) { | 111 | if (needed_size > self.allocatedSize(sect.offset)) { |
| ... | @@ -162,20 +134,22 @@ pub fn growSection(self: *DebugSymbols, sect_index: u8, needed_size: u32, requir | ... | @@ -162,20 +134,22 @@ pub fn growSection(self: *DebugSymbols, sect_index: u8, needed_size: u32, requir |
| 162 | } | 134 | } |
| 163 | 135 | ||
| 164 | sect.size = needed_size; | 136 | sect.size = needed_size; |
| 165 | self.markDirty(sect_index); | 137 | self.markDirty(sect_index, macho_file); |
| 166 | } | 138 | } |
| 167 | 139 | ||
| 168 | pub fn markDirty(self: *DebugSymbols, sect_index: u8) void { | 140 | pub fn markDirty(self: *DebugSymbols, sect_index: u8, macho_file: *MachO) void { |
| 169 | if (self.debug_info_section_index.? == sect_index) { | 141 | if (macho_file.getZigObject()) |zo| { |
| 170 | self.debug_info_header_dirty = true; | 142 | if (self.debug_info_section_index.? == sect_index) { |
| 171 | } else if (self.debug_line_section_index.? == sect_index) { | 143 | zo.debug_info_header_dirty = true; |
| 172 | self.debug_line_header_dirty = true; | 144 | } else if (self.debug_line_section_index.? == sect_index) { |
| 173 | } else if (self.debug_abbrev_section_index.? == sect_index) { | 145 | zo.debug_line_header_dirty = true; |
| 174 | self.debug_abbrev_section_dirty = true; | 146 | } else if (self.debug_abbrev_section_index.? == sect_index) { |
| 175 | } else if (self.debug_str_section_index.? == sect_index) { | 147 | zo.debug_abbrev_dirty = true; |
| 176 | self.debug_string_table_dirty = true; | 148 | } else if (self.debug_str_section_index.? == sect_index) { |
| 177 | } else if (self.debug_aranges_section_index.? == sect_index) { | 149 | zo.debug_strtab_dirty = true; |
| 178 | self.debug_aranges_section_dirty = true; | 150 | } else if (self.debug_aranges_section_index.? == sect_index) { |
| 151 | zo.debug_aranges_dirty = true; | ||
| 152 | } | ||
| 179 | } | 153 | } |
| 180 | } | 154 | } |
| 181 | 155 | ||
| ... | @@ -201,13 +175,6 @@ fn findFreeSpace(self: *DebugSymbols, object_size: u64, min_alignment: u64) u64 | ... | @@ -201,13 +175,6 @@ fn findFreeSpace(self: *DebugSymbols, object_size: u64, min_alignment: u64) u64 |
| 201 | } | 175 | } |
| 202 | 176 | ||
| 203 | pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { | 177 | pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { |
| 204 | const comp = macho_file.base.comp; | ||
| 205 | // TODO This linker code currently assumes there is only 1 compilation unit | ||
| 206 | // and it corresponds to the Zig source code. | ||
| 207 | const zcu = comp.module orelse return error.LinkingWithoutZigSourceUnimplemented; | ||
| 208 | |||
| 209 | try self.dwarf.flushModule(zcu); | ||
| 210 | |||
| 211 | for (self.relocs.items) |*reloc| { | 178 | for (self.relocs.items) |*reloc| { |
| 212 | const sym = macho_file.getSymbol(reloc.target); | 179 | const sym = macho_file.getSymbol(reloc.target); |
| 213 | const sym_name = sym.getName(macho_file); | 180 | const sym_name = sym.getName(macho_file); |
| ... | @@ -226,54 +193,12 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { | ... | @@ -226,54 +193,12 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { |
| 226 | try self.file.pwriteAll(mem.asBytes(&addr), file_offset); | 193 | try self.file.pwriteAll(mem.asBytes(&addr), file_offset); |
| 227 | } | 194 | } |
| 228 | 195 | ||
| 229 | if (self.debug_abbrev_section_dirty) { | ||
| 230 | try self.dwarf.writeDbgAbbrev(); | ||
| 231 | self.debug_abbrev_section_dirty = false; | ||
| 232 | } | ||
| 233 | |||
| 234 | if (self.debug_info_header_dirty) { | ||
| 235 | // Currently only one compilation unit is supported, so the address range is simply | ||
| 236 | // identical to the main program header virtual address and memory size. | ||
| 237 | const text_section = macho_file.sections.items(.header)[macho_file.zig_text_sect_index.?]; | ||
| 238 | const low_pc = text_section.addr; | ||
| 239 | const high_pc = text_section.addr + text_section.size; | ||
| 240 | try self.dwarf.writeDbgInfoHeader(zcu, low_pc, high_pc); | ||
| 241 | self.debug_info_header_dirty = false; | ||
| 242 | } | ||
| 243 | |||
| 244 | if (self.debug_aranges_section_dirty) { | ||
| 245 | // Currently only one compilation unit is supported, so the address range is simply | ||
| 246 | // identical to the main program header virtual address and memory size. | ||
| 247 | const text_section = macho_file.sections.items(.header)[macho_file.zig_text_sect_index.?]; | ||
| 248 | try self.dwarf.writeDbgAranges(text_section.addr, text_section.size); | ||
| 249 | self.debug_aranges_section_dirty = false; | ||
| 250 | } | ||
| 251 | |||
| 252 | if (self.debug_line_header_dirty) { | ||
| 253 | try self.dwarf.writeDbgLineHeader(); | ||
| 254 | self.debug_line_header_dirty = false; | ||
| 255 | } | ||
| 256 | |||
| 257 | { | ||
| 258 | const sect_index = self.debug_str_section_index.?; | ||
| 259 | if (self.debug_string_table_dirty or self.dwarf.strtab.buffer.items.len != self.getSection(sect_index).size) { | ||
| 260 | const needed_size = @as(u32, @intCast(self.dwarf.strtab.buffer.items.len)); | ||
| 261 | try self.growSection(sect_index, needed_size, false); | ||
| 262 | try self.file.pwriteAll(self.dwarf.strtab.buffer.items, self.getSection(sect_index).offset); | ||
| 263 | self.debug_string_table_dirty = false; | ||
| 264 | } | ||
| 265 | } | ||
| 266 | |||
| 267 | self.finalizeDwarfSegment(macho_file); | 196 | self.finalizeDwarfSegment(macho_file); |
| 268 | try self.writeLinkeditSegmentData(macho_file); | 197 | try self.writeLinkeditSegmentData(macho_file); |
| 269 | 198 | ||
| 270 | // Write load commands | 199 | // Write load commands |
| 271 | const ncmds, const sizeofcmds = try self.writeLoadCommands(macho_file); | 200 | const ncmds, const sizeofcmds = try self.writeLoadCommands(macho_file); |
| 272 | try self.writeHeader(macho_file, ncmds, sizeofcmds); | 201 | try self.writeHeader(macho_file, ncmds, sizeofcmds); |
| 273 | |||
| 274 | assert(!self.debug_abbrev_section_dirty); | ||
| 275 | assert(!self.debug_aranges_section_dirty); | ||
| 276 | assert(!self.debug_string_table_dirty); | ||
| 277 | } | 202 | } |
| 278 | 203 | ||
| 279 | pub fn deinit(self: *DebugSymbols) void { | 204 | pub fn deinit(self: *DebugSymbols) void { |
| ... | @@ -281,7 +206,6 @@ pub fn deinit(self: *DebugSymbols) void { | ... | @@ -281,7 +206,6 @@ pub fn deinit(self: *DebugSymbols) void { |
| 281 | self.file.close(); | 206 | self.file.close(); |
| 282 | self.segments.deinit(gpa); | 207 | self.segments.deinit(gpa); |
| 283 | self.sections.deinit(gpa); | 208 | self.sections.deinit(gpa); |
| 284 | self.dwarf.deinit(); | ||
| 285 | self.relocs.deinit(gpa); | 209 | self.relocs.deinit(gpa); |
| 286 | self.symtab.deinit(gpa); | 210 | self.symtab.deinit(gpa); |
| 287 | self.strtab.deinit(gpa); | 211 | self.strtab.deinit(gpa); |
| ... | @@ -534,7 +458,6 @@ const padToIdeal = MachO.padToIdeal; | ... | @@ -534,7 +458,6 @@ const padToIdeal = MachO.padToIdeal; |
| 534 | const trace = @import("../../tracy.zig").trace; | 458 | const trace = @import("../../tracy.zig").trace; |
| 535 | 459 | ||
| 536 | const Allocator = mem.Allocator; | 460 | const Allocator = mem.Allocator; |
| 537 | const Dwarf = @import("../Dwarf.zig"); | ||
| 538 | const MachO = @import("../MachO.zig"); | 461 | const MachO = @import("../MachO.zig"); |
| 539 | const StringTable = @import("../StringTable.zig"); | 462 | const StringTable = @import("../StringTable.zig"); |
| 540 | const Type = @import("../../type.zig").Type; | 463 | const Type = @import("../../type.zig").Type; |
src/link/MachO/ZigObject.zig+82-13| ... | @@ -46,16 +46,33 @@ tlv_initializers: TlvInitializerTable = .{}, | ... | @@ -46,16 +46,33 @@ tlv_initializers: TlvInitializerTable = .{}, |
| 46 | /// A table of relocations. | 46 | /// A table of relocations. |
| 47 | relocs: RelocationTable = .{}, | 47 | relocs: RelocationTable = .{}, |
| 48 | 48 | ||
| 49 | dwarf: ?Dwarf = null, | ||
| 50 | |||
| 49 | dynamic_relocs: MachO.DynamicRelocs = .{}, | 51 | dynamic_relocs: MachO.DynamicRelocs = .{}, |
| 50 | output_symtab_ctx: MachO.SymtabCtx = .{}, | 52 | output_symtab_ctx: MachO.SymtabCtx = .{}, |
| 51 | output_ar_state: Archive.ArState = .{}, | 53 | output_ar_state: Archive.ArState = .{}, |
| 52 | 54 | ||
| 55 | debug_strtab_dirty: bool = true, | ||
| 56 | debug_abbrev_dirty: bool = true, | ||
| 57 | debug_aranges_dirty: bool = true, | ||
| 58 | debug_info_header_dirty: bool = true, | ||
| 59 | debug_line_header_dirty: bool = true, | ||
| 60 | |||
| 53 | pub fn init(self: *ZigObject, macho_file: *MachO) !void { | 61 | pub fn init(self: *ZigObject, macho_file: *MachO) !void { |
| 54 | const comp = macho_file.base.comp; | 62 | const comp = macho_file.base.comp; |
| 55 | const gpa = comp.gpa; | 63 | const gpa = comp.gpa; |
| 56 | 64 | ||
| 57 | try self.atoms.append(gpa, 0); // null input section | 65 | try self.atoms.append(gpa, 0); // null input section |
| 58 | try self.strtab.buffer.append(gpa, 0); | 66 | try self.strtab.buffer.append(gpa, 0); |
| 67 | |||
| 68 | switch (comp.config.debug_format) { | ||
| 69 | .strip => {}, | ||
| 70 | .dwarf => |v| { | ||
| 71 | assert(v == .@"32"); | ||
| 72 | self.dwarf = Dwarf.init(&macho_file.base, .dwarf32); | ||
| 73 | }, | ||
| 74 | .code_view => unreachable, | ||
| 75 | } | ||
| 59 | } | 76 | } |
| 60 | 77 | ||
| 61 | pub fn deinit(self: *ZigObject, allocator: Allocator) void { | 78 | pub fn deinit(self: *ZigObject, allocator: Allocator) void { |
| ... | @@ -101,6 +118,10 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void { | ... | @@ -101,6 +118,10 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void { |
| 101 | tlv_init.deinit(allocator); | 118 | tlv_init.deinit(allocator); |
| 102 | } | 119 | } |
| 103 | self.tlv_initializers.deinit(allocator); | 120 | self.tlv_initializers.deinit(allocator); |
| 121 | |||
| 122 | if (self.dwarf) |*dw| { | ||
| 123 | dw.deinit(); | ||
| 124 | } | ||
| 104 | } | 125 | } |
| 105 | 126 | ||
| 106 | fn addNlist(self: *ZigObject, allocator: Allocator) !Symbol.Index { | 127 | fn addNlist(self: *ZigObject, allocator: Allocator) !Symbol.Index { |
| ... | @@ -407,6 +428,60 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO) !void { | ... | @@ -407,6 +428,60 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO) !void { |
| 407 | if (metadata.text_state != .unused) metadata.text_state = .flushed; | 428 | if (metadata.text_state != .unused) metadata.text_state = .flushed; |
| 408 | if (metadata.const_state != .unused) metadata.const_state = .flushed; | 429 | if (metadata.const_state != .unused) metadata.const_state = .flushed; |
| 409 | } | 430 | } |
| 431 | |||
| 432 | if (self.dwarf) |*dw| { | ||
| 433 | const zcu = macho_file.base.comp.module.?; | ||
| 434 | try dw.flushModule(zcu); | ||
| 435 | |||
| 436 | if (self.debug_abbrev_dirty) { | ||
| 437 | try dw.writeDbgAbbrev(); | ||
| 438 | self.debug_abbrev_dirty = false; | ||
| 439 | } | ||
| 440 | |||
| 441 | if (self.debug_info_header_dirty) { | ||
| 442 | // Currently only one compilation unit is supported, so the address range is simply | ||
| 443 | // identical to the main program header virtual address and memory size. | ||
| 444 | const text_section = macho_file.sections.items(.header)[macho_file.zig_text_sect_index.?]; | ||
| 445 | const low_pc = text_section.addr; | ||
| 446 | const high_pc = text_section.addr + text_section.size; | ||
| 447 | try dw.writeDbgInfoHeader(zcu, low_pc, high_pc); | ||
| 448 | self.debug_info_header_dirty = false; | ||
| 449 | } | ||
| 450 | |||
| 451 | if (self.debug_aranges_dirty) { | ||
| 452 | // Currently only one compilation unit is supported, so the address range is simply | ||
| 453 | // identical to the main program header virtual address and memory size. | ||
| 454 | const text_section = macho_file.sections.items(.header)[macho_file.zig_text_sect_index.?]; | ||
| 455 | try dw.writeDbgAranges(text_section.addr, text_section.size); | ||
| 456 | self.debug_aranges_dirty = false; | ||
| 457 | } | ||
| 458 | |||
| 459 | if (self.debug_line_header_dirty) { | ||
| 460 | try dw.writeDbgLineHeader(); | ||
| 461 | self.debug_line_header_dirty = false; | ||
| 462 | } | ||
| 463 | |||
| 464 | if (!macho_file.base.isRelocatable()) { | ||
| 465 | const d_sym = macho_file.getDebugSymbols().?; | ||
| 466 | const sect_index = d_sym.debug_str_section_index.?; | ||
| 467 | if (self.debug_strtab_dirty or dw.strtab.buffer.items.len != d_sym.getSection(sect_index).size) { | ||
| 468 | const needed_size = @as(u32, @intCast(dw.strtab.buffer.items.len)); | ||
| 469 | try d_sym.growSection(sect_index, needed_size, false, macho_file); | ||
| 470 | try d_sym.file.pwriteAll(dw.strtab.buffer.items, d_sym.getSection(sect_index).offset); | ||
| 471 | self.debug_strtab_dirty = false; | ||
| 472 | } | ||
| 473 | } else { | ||
| 474 | // TODO: relocatable | ||
| 475 | } | ||
| 476 | } | ||
| 477 | |||
| 478 | // The point of flushModule() is to commit changes, so in theory, nothing should | ||
| 479 | // be dirty after this. However, it is possible for some things to remain | ||
| 480 | // dirty because they fail to be written in the event of compile errors, | ||
| 481 | // such as debug_line_header_dirty and debug_info_header_dirty. | ||
| 482 | assert(!self.debug_abbrev_dirty); | ||
| 483 | assert(!self.debug_aranges_dirty); | ||
| 484 | assert(!self.debug_strtab_dirty); | ||
| 410 | } | 485 | } |
| 411 | 486 | ||
| 412 | pub fn getDeclVAddr( | 487 | pub fn getDeclVAddr( |
| ... | @@ -572,7 +647,7 @@ pub fn updateFunc( | ... | @@ -572,7 +647,7 @@ pub fn updateFunc( |
| 572 | var code_buffer = std.ArrayList(u8).init(gpa); | 647 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 573 | defer code_buffer.deinit(); | 648 | defer code_buffer.deinit(); |
| 574 | 649 | ||
| 575 | var decl_state: ?Dwarf.DeclState = if (macho_file.getDebugSymbols()) |d_sym| try d_sym.dwarf.initDeclState(mod, decl_index) else null; | 650 | var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(mod, decl_index) else null; |
| 576 | defer if (decl_state) |*ds| ds.deinit(); | 651 | defer if (decl_state) |*ds| ds.deinit(); |
| 577 | 652 | ||
| 578 | const dio: codegen.DebugInfoOutput = if (decl_state) |*ds| .{ .dwarf = ds } else .none; | 653 | const dio: codegen.DebugInfoOutput = if (decl_state) |*ds| .{ .dwarf = ds } else .none; |
| ... | @@ -600,7 +675,7 @@ pub fn updateFunc( | ... | @@ -600,7 +675,7 @@ pub fn updateFunc( |
| 600 | 675 | ||
| 601 | if (decl_state) |*ds| { | 676 | if (decl_state) |*ds| { |
| 602 | const sym = macho_file.getSymbol(sym_index); | 677 | const sym = macho_file.getSymbol(sym_index); |
| 603 | try macho_file.getDebugSymbols().?.dwarf.commitDeclState( | 678 | try self.dwarf.?.commitDeclState( |
| 604 | mod, | 679 | mod, |
| 605 | decl_index, | 680 | decl_index, |
| 606 | sym.getAddress(.{}, macho_file), | 681 | sym.getAddress(.{}, macho_file), |
| ... | @@ -647,7 +722,7 @@ pub fn updateDecl( | ... | @@ -647,7 +722,7 @@ pub fn updateDecl( |
| 647 | var code_buffer = std.ArrayList(u8).init(gpa); | 722 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 648 | defer code_buffer.deinit(); | 723 | defer code_buffer.deinit(); |
| 649 | 724 | ||
| 650 | var decl_state: ?Dwarf.DeclState = if (macho_file.getDebugSymbols()) |d_sym| try d_sym.dwarf.initDeclState(mod, decl_index) else null; | 725 | var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(mod, decl_index) else null; |
| 651 | defer if (decl_state) |*ds| ds.deinit(); | 726 | defer if (decl_state) |*ds| ds.deinit(); |
| 652 | 727 | ||
| 653 | const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; | 728 | const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; |
| ... | @@ -681,7 +756,7 @@ pub fn updateDecl( | ... | @@ -681,7 +756,7 @@ pub fn updateDecl( |
| 681 | 756 | ||
| 682 | if (decl_state) |*ds| { | 757 | if (decl_state) |*ds| { |
| 683 | const sym = macho_file.getSymbol(sym_index); | 758 | const sym = macho_file.getSymbol(sym_index); |
| 684 | try macho_file.getDebugSymbols().?.dwarf.commitDeclState( | 759 | try self.dwarf.?.commitDeclState( |
| 685 | mod, | 760 | mod, |
| 686 | decl_index, | 761 | decl_index, |
| 687 | sym.getAddress(.{}, macho_file), | 762 | sym.getAddress(.{}, macho_file), |
| ... | @@ -1257,15 +1332,9 @@ fn updateLazySymbol( | ... | @@ -1257,15 +1332,9 @@ fn updateLazySymbol( |
| 1257 | } | 1332 | } |
| 1258 | 1333 | ||
| 1259 | /// Must be called only after a successful call to `updateDecl`. | 1334 | /// Must be called only after a successful call to `updateDecl`. |
| 1260 | pub fn updateDeclLineNumber( | 1335 | pub fn updateDeclLineNumber(self: *ZigObject, mod: *Module, decl_index: InternPool.DeclIndex) !void { |
| 1261 | self: *ZigObject, | 1336 | if (self.dwarf) |*dw| { |
| 1262 | macho_file: *MachO, | 1337 | try dw.updateDeclLineNumber(mod, decl_index); |
| 1263 | mod: *Module, | ||
| 1264 | decl_index: InternPool.DeclIndex, | ||
| 1265 | ) !void { | ||
| 1266 | _ = self; | ||
| 1267 | if (macho_file.getDebugSymbols()) |d_sym| { | ||
| 1268 | try d_sym.dwarf.updateDeclLineNumber(mod, decl_index); | ||
| 1269 | } | 1338 | } |
| 1270 | } | 1339 | } |
| 1271 | 1340 |