authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-08 11:13:52+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-08 11:13:52+01:00
log37033a96ac2e33a56eb2e153462d1a730b426029
tree1d599e8f86942a7daed800ad0c8010855a1c0780
parent3122fd0ba0eb4cdb17616658b462a255a37f1ad7

macho: move Dwarf handle to ZigObject from DebugSymbols


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 },
13521352
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 },
15981599
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;
24402445
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 });
263265
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 );
276269
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 );
279276
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 });
284279
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)
31523144
3153pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl_index: InternPool.DeclIndex) !void {3145pub 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}
31573149
3158pub fn updateExports(3150pub fn updateExports(
src/link/MachO/DebugSymbols.zig+35-112
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1allocator: Allocator,1allocator: Allocator,
2dwarf: Dwarf,
3file: fs.File,2file: fs.File,
43
5symtab_cmd: macho.symtab_command = .{},4symtab_cmd: macho.symtab_command = .{},
...@@ -17,12 +16,6 @@ debug_str_section_index: ?u8 = null,...@@ -17,12 +16,6 @@ debug_str_section_index: ?u8 = null,
17debug_aranges_section_index: ?u8 = null,16debug_aranges_section_index: ?u8 = null,
18debug_line_section_index: ?u8 = null,17debug_line_section_index: ?u8 = null,
1918
20debug_string_table_dirty: bool = false,
21debug_abbrev_section_dirty: bool = false,
22debug_aranges_section_dirty: bool = false,
23debug_info_header_dirty: bool = false,
24debug_line_header_dirty: bool = false,
25
26relocs: std.ArrayListUnmanaged(Reloc) = .{},19relocs: std.ArrayListUnmanaged(Reloc) = .{},
2720
28/// Output synthetic sections21/// Output synthetic sections
...@@ -44,7 +37,7 @@ pub const Reloc = struct {...@@ -44,7 +37,7 @@ pub const Reloc = struct {
44pub fn initMetadata(self: *DebugSymbols, macho_file: *MachO) !void {37pub fn initMetadata(self: *DebugSymbols, macho_file: *MachO) !void {
45 try self.strtab.append(self.allocator, 0);38 try self.strtab.append(self.allocator, 0);
4639
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));
4942
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 }
6558
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,
7669 .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}
10773
108fn allocateSection(self: *DebugSymbols, sectname: []const u8, size: u64, alignment: u16) !u8 {74fn 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}
135101
136pub fn growSection(self: *DebugSymbols, sect_index: u8, needed_size: u32, requires_file_copy: bool) !void {102pub 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);
138110
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 }
163135
164 sect.size = needed_size;136 sect.size = needed_size;
165 self.markDirty(sect_index);137 self.markDirty(sect_index, macho_file);
166}138}
167139
168pub fn markDirty(self: *DebugSymbols, sect_index: u8) void {140pub 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}
181155
...@@ -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}
202176
203pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {177pub 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 }
228195
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);
269198
270 // Write load commands199 // 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}
278203
279pub fn deinit(self: *DebugSymbols) void {204pub 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;
534const trace = @import("../../tracy.zig").trace;458const trace = @import("../../tracy.zig").trace;
535459
536const Allocator = mem.Allocator;460const Allocator = mem.Allocator;
537const Dwarf = @import("../Dwarf.zig");
538const MachO = @import("../MachO.zig");461const MachO = @import("../MachO.zig");
539const StringTable = @import("../StringTable.zig");462const StringTable = @import("../StringTable.zig");
540const Type = @import("../../type.zig").Type;463const 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.
47relocs: RelocationTable = .{},47relocs: RelocationTable = .{},
4848
49dwarf: ?Dwarf = null,
50
49dynamic_relocs: MachO.DynamicRelocs = .{},51dynamic_relocs: MachO.DynamicRelocs = .{},
50output_symtab_ctx: MachO.SymtabCtx = .{},52output_symtab_ctx: MachO.SymtabCtx = .{},
51output_ar_state: Archive.ArState = .{},53output_ar_state: Archive.ArState = .{},
5254
55debug_strtab_dirty: bool = true,
56debug_abbrev_dirty: bool = true,
57debug_aranges_dirty: bool = true,
58debug_info_header_dirty: bool = true,
59debug_line_header_dirty: bool = true,
60
53pub fn init(self: *ZigObject, macho_file: *MachO) !void {61pub 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;
5664
57 try self.atoms.append(gpa, 0); // null input section65 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}
6077
61pub fn deinit(self: *ZigObject, allocator: Allocator) void {78pub 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}
105126
106fn addNlist(self: *ZigObject, allocator: Allocator) !Symbol.Index {127fn 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}
411486
412pub fn getDeclVAddr(487pub 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();
574649
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();
577652
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(
600675
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();
649724
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();
652727
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(
681756
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}
12581333
1259/// Must be called only after a successful call to `updateDecl`.1334/// Must be called only after a successful call to `updateDecl`.
1260pub fn updateDeclLineNumber(1335pub 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}
12711340