| author | |
| committer | |
| log | 366ec2105249050fe88e5fa9f241e14f708db891 |
| tree | 9b01747e24d6a1b28be90af333c53dc8567ddfa6 |
| parent | 4ca9b4c44a4fbe2b64b11d2c8a951c2c3e961619 |
11 files changed, 436 insertions(+), 518 deletions(-)
src/arch/aarch64/Emit.zig+12-11| ... | ... | @@ -386,18 +386,19 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void { |
| 386 | 386 | const delta_line = @intCast(i32, line) - @intCast(i32, self.prev_di_line); |
| 387 | 387 | const delta_pc: usize = self.code.items.len - self.prev_di_pc; |
| 388 | 388 | switch (self.debug_output) { |
| 389 | .dwarf => |dbg_out| { | |
| 389 | .dwarf => |dw| { | |
| 390 | 390 | // TODO Look into using the DWARF special opcodes to compress this data. |
| 391 | 391 | // It lets you emit single-byte opcodes that add different numbers to |
| 392 | 392 | // both the PC and the line number at the same time. |
| 393 | try dbg_out.dbg_line.ensureUnusedCapacity(11); | |
| 394 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_pc); | |
| 395 | leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable; | |
| 393 | const dbg_line = dw.getDeclDebugLineBuffer(); | |
| 394 | try dbg_line.ensureUnusedCapacity(11); | |
| 395 | dbg_line.appendAssumeCapacity(DW.LNS.advance_pc); | |
| 396 | leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable; | |
| 396 | 397 | if (delta_line != 0) { |
| 397 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_line); | |
| 398 | leb128.writeILEB128(dbg_out.dbg_line.writer(), delta_line) catch unreachable; | |
| 398 | dbg_line.appendAssumeCapacity(DW.LNS.advance_line); | |
| 399 | leb128.writeILEB128(dbg_line.writer(), delta_line) catch unreachable; | |
| 399 | 400 | } |
| 400 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.copy); | |
| 401 | dbg_line.appendAssumeCapacity(DW.LNS.copy); | |
| 401 | 402 | self.prev_di_pc = self.code.items.len; |
| 402 | 403 | self.prev_di_line = line; |
| 403 | 404 | self.prev_di_column = column; |
| ... | ... | @@ -586,8 +587,8 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 586 | 587 | |
| 587 | 588 | fn mirDebugPrologueEnd(self: *Emit) !void { |
| 588 | 589 | switch (self.debug_output) { |
| 589 | .dwarf => |dbg_out| { | |
| 590 | try dbg_out.dbg_line.append(DW.LNS.set_prologue_end); | |
| 590 | .dwarf => |dw| { | |
| 591 | try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end); | |
| 591 | 592 | try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column); |
| 592 | 593 | }, |
| 593 | 594 | .plan9 => {}, |
| ... | ... | @@ -597,8 +598,8 @@ fn mirDebugPrologueEnd(self: *Emit) !void { |
| 597 | 598 | |
| 598 | 599 | fn mirDebugEpilogueBegin(self: *Emit) !void { |
| 599 | 600 | switch (self.debug_output) { |
| 600 | .dwarf => |dbg_out| { | |
| 601 | try dbg_out.dbg_line.append(DW.LNS.set_epilogue_begin); | |
| 601 | .dwarf => |dw| { | |
| 602 | try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin); | |
| 602 | 603 | try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column); |
| 603 | 604 | }, |
| 604 | 605 | .plan9 => {}, |
src/arch/arm/Emit.zig+37-36| ... | ... | @@ -328,18 +328,19 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void { |
| 328 | 328 | const delta_line = @intCast(i32, line) - @intCast(i32, self.prev_di_line); |
| 329 | 329 | const delta_pc: usize = self.code.items.len - self.prev_di_pc; |
| 330 | 330 | switch (self.debug_output) { |
| 331 | .dwarf => |dbg_out| { | |
| 331 | .dwarf => |dw| { | |
| 332 | 332 | // TODO Look into using the DWARF special opcodes to compress this data. |
| 333 | 333 | // It lets you emit single-byte opcodes that add different numbers to |
| 334 | 334 | // both the PC and the line number at the same time. |
| 335 | try dbg_out.dbg_line.ensureUnusedCapacity(11); | |
| 336 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_pc); | |
| 337 | leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable; | |
| 335 | const dbg_line = dw.getDeclDebugLineBuffer(); | |
| 336 | try dbg_line.ensureUnusedCapacity(11); | |
| 337 | dbg_line.appendAssumeCapacity(DW.LNS.advance_pc); | |
| 338 | leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable; | |
| 338 | 339 | if (delta_line != 0) { |
| 339 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_line); | |
| 340 | leb128.writeILEB128(dbg_out.dbg_line.writer(), delta_line) catch unreachable; | |
| 340 | dbg_line.appendAssumeCapacity(DW.LNS.advance_line); | |
| 341 | leb128.writeILEB128(dbg_line.writer(), delta_line) catch unreachable; | |
| 341 | 342 | } |
| 342 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.copy); | |
| 343 | dbg_line.appendAssumeCapacity(DW.LNS.copy); | |
| 343 | 344 | self.prev_di_pc = self.code.items.len; |
| 344 | 345 | self.prev_di_line = line; |
| 345 | 346 | self.prev_di_column = column; |
| ... | ... | @@ -379,19 +380,17 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void { |
| 379 | 380 | /// after codegen for this symbol is done. |
| 380 | 381 | fn addDbgInfoTypeReloc(self: *Emit, ty: Type) !void { |
| 381 | 382 | switch (self.debug_output) { |
| 382 | .dwarf => |dbg_out| { | |
| 383 | .dwarf => |dw| { | |
| 383 | 384 | assert(ty.hasRuntimeBits()); |
| 384 | const index = dbg_out.dbg_info.items.len; | |
| 385 | try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 | |
| 386 | ||
| 387 | const gop = try dbg_out.dbg_info_type_relocs.getOrPutContext(self.bin_file.allocator, ty, .{ .target = self.target.* }); | |
| 388 | if (!gop.found_existing) { | |
| 389 | gop.value_ptr.* = .{ | |
| 390 | .off = undefined, | |
| 391 | .relocs = .{}, | |
| 392 | }; | |
| 393 | } | |
| 394 | try gop.value_ptr.relocs.append(self.bin_file.allocator, @intCast(u32, index)); | |
| 385 | const dbg_info = dw.getDeclDebugInfoBuffer(); | |
| 386 | const index = dbg_info.items.len; | |
| 387 | try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 | |
| 388 | const atom = switch (self.bin_file.tag) { | |
| 389 | .elf => &self.function.mod_fn.owner_decl.link.elf.dbg_info_atom, | |
| 390 | .macho => unreachable, | |
| 391 | else => unreachable, | |
| 392 | }; | |
| 393 | try dw.addTypeReloc(atom, ty, @intCast(u32, index), null); | |
| 395 | 394 | }, |
| 396 | 395 | .plan9 => {}, |
| 397 | 396 | .none => {}, |
| ... | ... | @@ -409,16 +408,17 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void { |
| 409 | 408 | switch (mcv) { |
| 410 | 409 | .register => |reg| { |
| 411 | 410 | switch (self.debug_output) { |
| 412 | .dwarf => |dbg_out| { | |
| 413 | try dbg_out.dbg_info.ensureUnusedCapacity(3); | |
| 414 | dbg_out.dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter); | |
| 415 | dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | |
| 411 | .dwarf => |dw| { | |
| 412 | const dbg_info = dw.getDeclDebugInfoBuffer(); | |
| 413 | try dbg_info.ensureUnusedCapacity(3); | |
| 414 | dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter); | |
| 415 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | |
| 416 | 416 | 1, // ULEB128 dwarf expression length |
| 417 | 417 | reg.dwarfLocOp(), |
| 418 | 418 | }); |
| 419 | try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 419 | try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 420 | 420 | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 |
| 421 | dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 421 | dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 422 | 422 | }, |
| 423 | 423 | .plan9 => {}, |
| 424 | 424 | .none => {}, |
| ... | ... | @@ -428,7 +428,7 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void { |
| 428 | 428 | .stack_argument_offset, |
| 429 | 429 | => { |
| 430 | 430 | switch (self.debug_output) { |
| 431 | .dwarf => |dbg_out| { | |
| 431 | .dwarf => |dw| { | |
| 432 | 432 | const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch { |
| 433 | 433 | return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(target)}); |
| 434 | 434 | }; |
| ... | ... | @@ -442,7 +442,8 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void { |
| 442 | 442 | else => unreachable, |
| 443 | 443 | }; |
| 444 | 444 | |
| 445 | try dbg_out.dbg_info.append(link.File.Dwarf.abbrev_parameter); | |
| 445 | const dbg_info = dw.getDeclDebugInfoBuffer(); | |
| 446 | try dbg_info.append(link.File.Dwarf.abbrev_parameter); | |
| 446 | 447 | |
| 447 | 448 | // Get length of the LEB128 stack offset |
| 448 | 449 | var counting_writer = std.io.countingWriter(std.io.null_writer); |
| ... | ... | @@ -450,13 +451,13 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void { |
| 450 | 451 | |
| 451 | 452 | // DW.AT.location, DW.FORM.exprloc |
| 452 | 453 | // ULEB128 dwarf expression length |
| 453 | try leb128.writeULEB128(dbg_out.dbg_info.writer(), counting_writer.bytes_written + 1); | |
| 454 | try dbg_out.dbg_info.append(DW.OP.breg11); | |
| 455 | try leb128.writeILEB128(dbg_out.dbg_info.writer(), adjusted_stack_offset); | |
| 454 | try leb128.writeULEB128(dbg_info.writer(), counting_writer.bytes_written + 1); | |
| 455 | try dbg_info.append(DW.OP.breg11); | |
| 456 | try leb128.writeILEB128(dbg_info.writer(), adjusted_stack_offset); | |
| 456 | 457 | |
| 457 | try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 458 | try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 458 | 459 | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 |
| 459 | dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 460 | dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 460 | 461 | }, |
| 461 | 462 | .plan9 => {}, |
| 462 | 463 | .none => {}, |
| ... | ... | @@ -558,8 +559,8 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 558 | 559 | |
| 559 | 560 | fn mirDebugPrologueEnd(emit: *Emit) !void { |
| 560 | 561 | switch (emit.debug_output) { |
| 561 | .dwarf => |dbg_out| { | |
| 562 | try dbg_out.dbg_line.append(DW.LNS.set_prologue_end); | |
| 562 | .dwarf => |dw| { | |
| 563 | try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end); | |
| 563 | 564 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); |
| 564 | 565 | }, |
| 565 | 566 | .plan9 => {}, |
| ... | ... | @@ -569,8 +570,8 @@ fn mirDebugPrologueEnd(emit: *Emit) !void { |
| 569 | 570 | |
| 570 | 571 | fn mirDebugEpilogueBegin(emit: *Emit) !void { |
| 571 | 572 | switch (emit.debug_output) { |
| 572 | .dwarf => |dbg_out| { | |
| 573 | try dbg_out.dbg_line.append(DW.LNS.set_epilogue_begin); | |
| 573 | .dwarf => |dw| { | |
| 574 | try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin); | |
| 574 | 575 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); |
| 575 | 576 | }, |
| 576 | 577 | .plan9 => {}, |
src/arch/riscv64/CodeGen.zig+17-20| ... | ... | @@ -745,21 +745,17 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void { |
| 745 | 745 | /// after codegen for this symbol is done. |
| 746 | 746 | fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void { |
| 747 | 747 | switch (self.debug_output) { |
| 748 | .dwarf => |dbg_out| { | |
| 748 | .dwarf => |dw| { | |
| 749 | 749 | assert(ty.hasRuntimeBits()); |
| 750 | const index = dbg_out.dbg_info.items.len; | |
| 751 | try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 | |
| 752 | ||
| 753 | const gop = try dbg_out.dbg_info_type_relocs.getOrPutContext(self.gpa, ty, .{ | |
| 754 | .target = self.target.*, | |
| 755 | }); | |
| 756 | if (!gop.found_existing) { | |
| 757 | gop.value_ptr.* = .{ | |
| 758 | .off = undefined, | |
| 759 | .relocs = .{}, | |
| 760 | }; | |
| 761 | } | |
| 762 | try gop.value_ptr.relocs.append(self.gpa, @intCast(u32, index)); | |
| 750 | const dbg_info = dw.getDeclDebugInfoBuffer(); | |
| 751 | const index = dbg_info.items.len; | |
| 752 | try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 | |
| 753 | const atom = switch (self.bin_file.tag) { | |
| 754 | .elf => &self.mod_fn.owner_decl.link.elf.dbg_info_atom, | |
| 755 | .macho => unreachable, | |
| 756 | else => unreachable, | |
| 757 | }; | |
| 758 | try dw.addTypeReloc(atom, ty, @intCast(u32, index), null); | |
| 763 | 759 | }, |
| 764 | 760 | .plan9 => {}, |
| 765 | 761 | .none => {}, |
| ... | ... | @@ -1573,16 +1569,17 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32 |
| 1573 | 1569 | switch (mcv) { |
| 1574 | 1570 | .register => |reg| { |
| 1575 | 1571 | switch (self.debug_output) { |
| 1576 | .dwarf => |dbg_out| { | |
| 1577 | try dbg_out.dbg_info.ensureUnusedCapacity(3); | |
| 1578 | dbg_out.dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter); | |
| 1579 | dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | |
| 1572 | .dwarf => |dw| { | |
| 1573 | const dbg_info = dw.getDeclDebugInfoBuffer(); | |
| 1574 | try dbg_info.ensureUnusedCapacity(3); | |
| 1575 | dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter); | |
| 1576 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | |
| 1580 | 1577 | 1, // ULEB128 dwarf expression length |
| 1581 | 1578 | reg.dwarfLocOp(), |
| 1582 | 1579 | }); |
| 1583 | try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 1580 | try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 1584 | 1581 | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 |
| 1585 | dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 1582 | dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 1586 | 1583 | }, |
| 1587 | 1584 | .plan9 => {}, |
| 1588 | 1585 | .none => {}, |
src/arch/riscv64/Emit.zig+12-11| ... | ... | @@ -89,18 +89,19 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void { |
| 89 | 89 | const delta_line = @intCast(i32, line) - @intCast(i32, self.prev_di_line); |
| 90 | 90 | const delta_pc: usize = self.code.items.len - self.prev_di_pc; |
| 91 | 91 | switch (self.debug_output) { |
| 92 | .dwarf => |dbg_out| { | |
| 92 | .dwarf => |dw| { | |
| 93 | 93 | // TODO Look into using the DWARF special opcodes to compress this data. |
| 94 | 94 | // It lets you emit single-byte opcodes that add different numbers to |
| 95 | 95 | // both the PC and the line number at the same time. |
| 96 | try dbg_out.dbg_line.ensureUnusedCapacity(11); | |
| 97 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_pc); | |
| 98 | leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable; | |
| 96 | const dbg_line = dw.getDeclDebugLineBuffer(); | |
| 97 | try dbg_line.ensureUnusedCapacity(11); | |
| 98 | dbg_line.appendAssumeCapacity(DW.LNS.advance_pc); | |
| 99 | leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable; | |
| 99 | 100 | if (delta_line != 0) { |
| 100 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_line); | |
| 101 | leb128.writeILEB128(dbg_out.dbg_line.writer(), delta_line) catch unreachable; | |
| 101 | dbg_line.appendAssumeCapacity(DW.LNS.advance_line); | |
| 102 | leb128.writeILEB128(dbg_line.writer(), delta_line) catch unreachable; | |
| 102 | 103 | } |
| 103 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.copy); | |
| 104 | dbg_line.appendAssumeCapacity(DW.LNS.copy); | |
| 104 | 105 | self.prev_di_pc = self.code.items.len; |
| 105 | 106 | self.prev_di_line = line; |
| 106 | 107 | self.prev_di_column = column; |
| ... | ... | @@ -182,8 +183,8 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 182 | 183 | |
| 183 | 184 | fn mirDebugPrologueEnd(self: *Emit) !void { |
| 184 | 185 | switch (self.debug_output) { |
| 185 | .dwarf => |dbg_out| { | |
| 186 | try dbg_out.dbg_line.append(DW.LNS.set_prologue_end); | |
| 186 | .dwarf => |dw| { | |
| 187 | try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end); | |
| 187 | 188 | try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column); |
| 188 | 189 | }, |
| 189 | 190 | .plan9 => {}, |
| ... | ... | @@ -193,8 +194,8 @@ fn mirDebugPrologueEnd(self: *Emit) !void { |
| 193 | 194 | |
| 194 | 195 | fn mirDebugEpilogueBegin(self: *Emit) !void { |
| 195 | 196 | switch (self.debug_output) { |
| 196 | .dwarf => |dbg_out| { | |
| 197 | try dbg_out.dbg_line.append(DW.LNS.set_epilogue_begin); | |
| 197 | .dwarf => |dw| { | |
| 198 | try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin); | |
| 198 | 199 | try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column); |
| 199 | 200 | }, |
| 200 | 201 | .plan9 => {}, |
src/arch/x86_64/CodeGen.zig+1| ... | ... | @@ -350,6 +350,7 @@ pub fn generate( |
| 350 | 350 | var emit = Emit{ |
| 351 | 351 | .mir = mir, |
| 352 | 352 | .bin_file = bin_file, |
| 353 | .function = &function, | |
| 353 | 354 | .debug_output = debug_output, |
| 354 | 355 | .target = &bin_file.options.target, |
| 355 | 356 | .src_loc = src_loc, |
src/arch/x86_64/Emit.zig+41-40| ... | ... | @@ -16,6 +16,7 @@ const testing = std.testing; |
| 16 | 16 | |
| 17 | 17 | const Air = @import("../../Air.zig"); |
| 18 | 18 | const Allocator = mem.Allocator; |
| 19 | const CodeGen = @import("CodeGen.zig"); | |
| 19 | 20 | const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput; |
| 20 | 21 | const DW = std.dwarf; |
| 21 | 22 | const Encoder = bits.Encoder; |
| ... | ... | @@ -29,6 +30,7 @@ const Type = @import("../../type.zig").Type; |
| 29 | 30 | |
| 30 | 31 | mir: Mir, |
| 31 | 32 | bin_file: *link.File, |
| 33 | function: *const CodeGen, | |
| 32 | 34 | debug_output: DebugInfoOutput, |
| 33 | 35 | target: *const std.Target, |
| 34 | 36 | err_msg: ?*ErrorMsg = null, |
| ... | ... | @@ -963,18 +965,19 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void { |
| 963 | 965 | const delta_pc: usize = emit.code.items.len - emit.prev_di_pc; |
| 964 | 966 | log.debug(" (advance pc={d} and line={d})", .{ delta_line, delta_pc }); |
| 965 | 967 | switch (emit.debug_output) { |
| 966 | .dwarf => |dbg_out| { | |
| 968 | .dwarf => |dw| { | |
| 967 | 969 | // TODO Look into using the DWARF special opcodes to compress this data. |
| 968 | 970 | // It lets you emit single-byte opcodes that add different numbers to |
| 969 | 971 | // both the PC and the line number at the same time. |
| 970 | try dbg_out.dbg_line.ensureUnusedCapacity(11); | |
| 971 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_pc); | |
| 972 | leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable; | |
| 972 | const dbg_line = dw.getDeclDebugLineBuffer(); | |
| 973 | try dbg_line.ensureUnusedCapacity(11); | |
| 974 | dbg_line.appendAssumeCapacity(DW.LNS.advance_pc); | |
| 975 | leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable; | |
| 973 | 976 | if (delta_line != 0) { |
| 974 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_line); | |
| 975 | leb128.writeILEB128(dbg_out.dbg_line.writer(), delta_line) catch unreachable; | |
| 977 | dbg_line.appendAssumeCapacity(DW.LNS.advance_line); | |
| 978 | leb128.writeILEB128(dbg_line.writer(), delta_line) catch unreachable; | |
| 976 | 979 | } |
| 977 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.copy); | |
| 980 | dbg_line.appendAssumeCapacity(DW.LNS.copy); | |
| 978 | 981 | emit.prev_di_line = line; |
| 979 | 982 | emit.prev_di_column = column; |
| 980 | 983 | emit.prev_di_pc = emit.code.items.len; |
| ... | ... | @@ -1022,8 +1025,8 @@ fn mirDbgPrologueEnd(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { |
| 1022 | 1025 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| 1023 | 1026 | assert(tag == .dbg_prologue_end); |
| 1024 | 1027 | switch (emit.debug_output) { |
| 1025 | .dwarf => |dbg_out| { | |
| 1026 | try dbg_out.dbg_line.append(DW.LNS.set_prologue_end); | |
| 1028 | .dwarf => |dw| { | |
| 1029 | try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end); | |
| 1027 | 1030 | log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{ emit.prev_di_line, emit.prev_di_column }); |
| 1028 | 1031 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); |
| 1029 | 1032 | }, |
| ... | ... | @@ -1036,8 +1039,8 @@ fn mirDbgEpilogueBegin(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { |
| 1036 | 1039 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| 1037 | 1040 | assert(tag == .dbg_epilogue_begin); |
| 1038 | 1041 | switch (emit.debug_output) { |
| 1039 | .dwarf => |dbg_out| { | |
| 1040 | try dbg_out.dbg_line.append(DW.LNS.set_epilogue_begin); | |
| 1042 | .dwarf => |dw| { | |
| 1043 | try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin); | |
| 1041 | 1044 | log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{ emit.prev_di_line, emit.prev_di_column }); |
| 1042 | 1045 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); |
| 1043 | 1046 | }, |
| ... | ... | @@ -1063,16 +1066,17 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32 |
| 1063 | 1066 | switch (mcv) { |
| 1064 | 1067 | .register => |reg| { |
| 1065 | 1068 | switch (emit.debug_output) { |
| 1066 | .dwarf => |dbg_out| { | |
| 1067 | try dbg_out.dbg_info.ensureUnusedCapacity(3); | |
| 1068 | dbg_out.dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter); | |
| 1069 | dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | |
| 1069 | .dwarf => |dw| { | |
| 1070 | const dbg_info = dw.getDeclDebugInfoBuffer(); | |
| 1071 | try dbg_info.ensureUnusedCapacity(3); | |
| 1072 | dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter); | |
| 1073 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | |
| 1070 | 1074 | 1, // ULEB128 dwarf expression length |
| 1071 | 1075 | reg.dwarfLocOp(), |
| 1072 | 1076 | }); |
| 1073 | try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 1077 | try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 1074 | 1078 | try emit.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 |
| 1075 | dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 1079 | dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 1076 | 1080 | }, |
| 1077 | 1081 | .plan9 => {}, |
| 1078 | 1082 | .none => {}, |
| ... | ... | @@ -1080,25 +1084,26 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32 |
| 1080 | 1084 | }, |
| 1081 | 1085 | .stack_offset => |off| { |
| 1082 | 1086 | switch (emit.debug_output) { |
| 1083 | .dwarf => |dbg_out| { | |
| 1087 | .dwarf => |dw| { | |
| 1084 | 1088 | // we add here +16 like we do in airArg in CodeGen since we refer directly to |
| 1085 | 1089 | // rbp as the start of function frame minus 8 bytes for caller's rbp preserved in the |
| 1086 | 1090 | // prologue, and 8 bytes for return address. |
| 1087 | 1091 | // TODO we need to make this more generic if we don't use rbp as the frame pointer |
| 1088 | 1092 | // for example when -fomit-frame-pointer is set. |
| 1089 | 1093 | const disp = @intCast(i32, max_stack) - off + 16; |
| 1090 | try dbg_out.dbg_info.ensureUnusedCapacity(8); | |
| 1091 | dbg_out.dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter); | |
| 1092 | const fixup = dbg_out.dbg_info.items.len; | |
| 1093 | dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | |
| 1094 | const dbg_info = dw.getDeclDebugInfoBuffer(); | |
| 1095 | try dbg_info.ensureUnusedCapacity(8); | |
| 1096 | dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter); | |
| 1097 | const fixup = dbg_info.items.len; | |
| 1098 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | |
| 1094 | 1099 | 1, // we will backpatch it after we encode the displacement in LEB128 |
| 1095 | 1100 | DW.OP.breg6, // .rbp TODO handle -fomit-frame-pointer |
| 1096 | 1101 | }); |
| 1097 | leb128.writeILEB128(dbg_out.dbg_info.writer(), disp) catch unreachable; | |
| 1098 | dbg_out.dbg_info.items[fixup] += @intCast(u8, dbg_out.dbg_info.items.len - fixup - 2); | |
| 1099 | try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 1102 | leb128.writeILEB128(dbg_info.writer(), disp) catch unreachable; | |
| 1103 | dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); | |
| 1104 | try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 1100 | 1105 | try emit.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 |
| 1101 | dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 1106 | dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 1102 | 1107 | |
| 1103 | 1108 | }, |
| 1104 | 1109 | .plan9 => {}, |
| ... | ... | @@ -1113,21 +1118,17 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32 |
| 1113 | 1118 | /// after codegen for this symbol is done. |
| 1114 | 1119 | fn addDbgInfoTypeReloc(emit: *Emit, ty: Type) !void { |
| 1115 | 1120 | switch (emit.debug_output) { |
| 1116 | .dwarf => |dbg_out| { | |
| 1121 | .dwarf => |dw| { | |
| 1117 | 1122 | assert(ty.hasRuntimeBits()); |
| 1118 | const index = dbg_out.dbg_info.items.len; | |
| 1119 | try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 | |
| 1120 | ||
| 1121 | const gop = try dbg_out.dbg_info_type_relocs.getOrPutContext(emit.bin_file.allocator, ty, .{ | |
| 1122 | .target = emit.target.*, | |
| 1123 | }); | |
| 1124 | if (!gop.found_existing) { | |
| 1125 | gop.value_ptr.* = .{ | |
| 1126 | .off = undefined, | |
| 1127 | .relocs = .{}, | |
| 1128 | }; | |
| 1129 | } | |
| 1130 | try gop.value_ptr.relocs.append(emit.bin_file.allocator, @intCast(u32, index)); | |
| 1123 | const dbg_info = dw.getDeclDebugInfoBuffer(); | |
| 1124 | const index = dbg_info.items.len; | |
| 1125 | try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 | |
| 1126 | const atom = switch (emit.bin_file.tag) { | |
| 1127 | .elf => &emit.function.mod_fn.owner_decl.link.elf.dbg_info_atom, | |
| 1128 | .macho => &emit.function.mod_fn.owner_decl.link.macho.dbg_info_atom, | |
| 1129 | else => unreachable, | |
| 1130 | }; | |
| 1131 | try dw.addTypeReloc(atom, ty, @intCast(u32, index), null); | |
| 1131 | 1132 | }, |
| 1132 | 1133 | .plan9 => {}, |
| 1133 | 1134 | .none => {}, |
src/codegen.zig+1-5| ... | ... | @@ -42,11 +42,7 @@ pub const GenerateSymbolError = error{ |
| 42 | 42 | }; |
| 43 | 43 | |
| 44 | 44 | pub const DebugInfoOutput = union(enum) { |
| 45 | dwarf: struct { | |
| 46 | dbg_line: *std.ArrayList(u8), | |
| 47 | dbg_info: *std.ArrayList(u8), | |
| 48 | dbg_info_type_relocs: *link.File.Dwarf.DbgInfoTypeRelocsTable, | |
| 49 | }, | |
| 45 | dwarf: *link.File.Dwarf, | |
| 50 | 46 | /// the plan9 debuginfo output is a bytecode with 4 opcodes |
| 51 | 47 | /// assume all numbers/variables are bytes |
| 52 | 48 | /// 0 w x y z -> interpret w x y z as a big-endian i32, and add it to the line offset |
src/link/Dwarf.zig+276-272| ... | ... | @@ -39,16 +39,22 @@ atom_last: ?*Atom = null, |
| 39 | 39 | |
| 40 | 40 | abbrev_table_offset: ?u64 = null, |
| 41 | 41 | |
| 42 | /// TODO replace with InternArena | |
| 42 | 43 | /// Table of debug symbol names. |
| 43 | 44 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 44 | 45 | |
| 45 | deferred_error_sets_relocs: std.ArrayListUnmanaged(u32) = .{}, | |
| 46 | /// Lives only as long as the analysed Decl. | |
| 47 | /// Allocated with `initDeclState`. | |
| 48 | /// Freed with `commitDeclState`. | |
| 49 | decl_state: ?DeclState = null, | |
| 46 | 50 | |
| 47 | 51 | /// List of atoms that are owned directly by the DWARF module. |
| 48 | 52 | /// TODO convert links in DebugInfoAtom into indices and make |
| 49 | 53 | /// sure every atom is owned by this module. |
| 50 | 54 | managed_atoms: std.ArrayListUnmanaged(*Atom) = .{}, |
| 51 | 55 | |
| 56 | global_abbrev_relocs: std.ArrayListUnmanaged(AbbrevRelocation) = .{}, | |
| 57 | ||
| 52 | 58 | pub const Atom = struct { |
| 53 | 59 | /// Previous/next linked list pointers. |
| 54 | 60 | /// This is the linked list node for this Decl's corresponding .debug_info tag. |
| ... | ... | @@ -60,6 +66,54 @@ pub const Atom = struct { |
| 60 | 66 | len: u32, |
| 61 | 67 | }; |
| 62 | 68 | |
| 69 | /// Represents state of the analysed Decl. | |
| 70 | /// Includes Decl's abbrev table of type Types, matching arena | |
| 71 | /// and a set of relocations that will be resolved once this | |
| 72 | /// Decl's inner Atom is assigned an offset within the DWARF section. | |
| 73 | pub const DeclState = struct { | |
| 74 | dbg_line: std.ArrayList(u8), | |
| 75 | dbg_info: std.ArrayList(u8), | |
| 76 | abbrev_type_arena: std.heap.ArenaAllocator, | |
| 77 | abbrev_table: std.ArrayListUnmanaged(AbbrevEntry) = .{}, | |
| 78 | abbrev_resolver: std.HashMapUnmanaged( | |
| 79 | Type, | |
| 80 | u32, | |
| 81 | Type.HashContext64, | |
| 82 | std.hash_map.default_max_load_percentage, | |
| 83 | ) = .{}, | |
| 84 | abbrev_relocs: std.ArrayListUnmanaged(AbbrevRelocation) = .{}, | |
| 85 | ||
| 86 | fn init(gpa: Allocator) DeclState { | |
| 87 | return .{ | |
| 88 | .dbg_line = std.ArrayList(u8).init(gpa), | |
| 89 | .dbg_info = std.ArrayList(u8).init(gpa), | |
| 90 | .abbrev_type_arena = std.heap.ArenaAllocator.init(gpa), | |
| 91 | }; | |
| 92 | } | |
| 93 | ||
| 94 | fn deinit(self: *DeclState, gpa: Allocator) void { | |
| 95 | self.dbg_line.deinit(); | |
| 96 | self.dbg_info.deinit(); | |
| 97 | self.abbrev_type_arena.deinit(); | |
| 98 | self.abbrev_table.deinit(gpa); | |
| 99 | self.abbrev_resolver.deinit(gpa); | |
| 100 | self.abbrev_relocs.deinit(gpa); | |
| 101 | } | |
| 102 | }; | |
| 103 | ||
| 104 | pub const AbbrevEntry = struct { | |
| 105 | atom: *const Atom, | |
| 106 | @"type": Type, | |
| 107 | offset: u32, | |
| 108 | }; | |
| 109 | ||
| 110 | pub const AbbrevRelocation = struct { | |
| 111 | target: u32, | |
| 112 | atom: *const Atom, | |
| 113 | offset: u32, | |
| 114 | addend: u32, | |
| 115 | }; | |
| 116 | ||
| 63 | 117 | pub const SrcFn = struct { |
| 64 | 118 | /// Offset from the beginning of the Debug Line Program header that contains this function. |
| 65 | 119 | off: u32, |
| ... | ... | @@ -82,22 +136,6 @@ pub const SrcFn = struct { |
| 82 | 136 | |
| 83 | 137 | pub const PtrWidth = enum { p32, p64 }; |
| 84 | 138 | |
| 85 | pub const DbgInfoTypeRelocsTable = std.ArrayHashMapUnmanaged( | |
| 86 | Type, | |
| 87 | DbgInfoTypeReloc, | |
| 88 | Type.HashContext32, | |
| 89 | true, | |
| 90 | ); | |
| 91 | ||
| 92 | pub const DbgInfoTypeReloc = struct { | |
| 93 | /// Offset from `TextBlock.dbg_info_off` (the buffer that is local to a Decl). | |
| 94 | /// This is where the .debug_info tag for the type is. | |
| 95 | off: u32, | |
| 96 | /// Offset from `TextBlock.dbg_info_off` (the buffer that is local to a Decl). | |
| 97 | /// List of DW.AT.type / DW.FORM.ref4 that points to the type. | |
| 98 | relocs: std.ArrayListUnmanaged(u32), | |
| 99 | }; | |
| 100 | ||
| 101 | 139 | pub const abbrev_compile_unit = 1; |
| 102 | 140 | pub const abbrev_subprogram = 2; |
| 103 | 141 | pub const abbrev_subprogram_retvoid = 3; |
| ... | ... | @@ -143,7 +181,7 @@ pub fn deinit(self: *Dwarf) void { |
| 143 | 181 | self.dbg_line_fn_free_list.deinit(gpa); |
| 144 | 182 | self.atom_free_list.deinit(gpa); |
| 145 | 183 | self.strtab.deinit(gpa); |
| 146 | self.deferred_error_sets_relocs.deinit(gpa); | |
| 184 | self.global_abbrev_relocs.deinit(gpa); | |
| 147 | 185 | |
| 148 | 186 | for (self.managed_atoms.items) |atom| { |
| 149 | 187 | gpa.destroy(atom); |
| ... | ... | @@ -151,25 +189,22 @@ pub fn deinit(self: *Dwarf) void { |
| 151 | 189 | self.managed_atoms.deinit(gpa); |
| 152 | 190 | } |
| 153 | 191 | |
| 154 | pub const DeclDebugBuffers = struct { | |
| 155 | dbg_line_buffer: std.ArrayList(u8), | |
| 156 | dbg_info_buffer: std.ArrayList(u8), | |
| 157 | dbg_info_type_relocs: DbgInfoTypeRelocsTable, | |
| 158 | }; | |
| 159 | ||
| 160 | pub fn initDeclDebugInfo(self: *Dwarf, decl: *Module.Decl) !DeclDebugBuffers { | |
| 192 | /// Initializes Decl's state and its matching output buffers. | |
| 193 | /// Call this before `commitDeclState`. | |
| 194 | pub fn initDeclState(self: *Dwarf, decl: *Module.Decl) !void { | |
| 161 | 195 | const tracy = trace(@src()); |
| 162 | 196 | defer tracy.end(); |
| 163 | 197 | |
| 164 | 198 | const decl_name = try decl.getFullyQualifiedName(self.allocator); |
| 165 | 199 | defer self.allocator.free(decl_name); |
| 166 | 200 | |
| 167 | log.debug("initDeclDebugInfo {s}{*}", .{ decl_name, decl }); | |
| 201 | log.debug("initDeclState {s}{*}", .{ decl_name, decl }); | |
| 168 | 202 | |
| 169 | 203 | const gpa = self.allocator; |
| 170 | var dbg_line_buffer = std.ArrayList(u8).init(gpa); | |
| 171 | var dbg_info_buffer = std.ArrayList(u8).init(gpa); | |
| 172 | var dbg_info_type_relocs: DbgInfoTypeRelocsTable = .{}; | |
| 204 | assert(self.decl_state == null); | |
| 205 | self.decl_state = DeclState.init(gpa); | |
| 206 | const dbg_line_buffer = &self.decl_state.?.dbg_line; | |
| 207 | const dbg_info_buffer = &self.decl_state.?.dbg_info; | |
| 173 | 208 | |
| 174 | 209 | assert(decl.has_tv); |
| 175 | 210 | |
| ... | ... | @@ -232,19 +267,17 @@ pub fn initDeclDebugInfo(self: *Dwarf, decl: *Module.Decl) !DeclDebugBuffers { |
| 232 | 267 | dbg_info_buffer.items.len += ptr_width_bytes; // DW.AT.low_pc, DW.FORM.addr |
| 233 | 268 | assert(self.getRelocDbgInfoSubprogramHighPC() == dbg_info_buffer.items.len); |
| 234 | 269 | dbg_info_buffer.items.len += 4; // DW.AT.high_pc, DW.FORM.data4 |
| 270 | // | |
| 235 | 271 | if (fn_ret_has_bits) { |
| 236 | const gop = try dbg_info_type_relocs.getOrPutContext(gpa, fn_ret_type, .{ | |
| 237 | .target = self.target, | |
| 238 | }); | |
| 239 | if (!gop.found_existing) { | |
| 240 | gop.value_ptr.* = .{ | |
| 241 | .off = undefined, | |
| 242 | .relocs = .{}, | |
| 243 | }; | |
| 244 | } | |
| 245 | try gop.value_ptr.relocs.append(gpa, @intCast(u32, dbg_info_buffer.items.len)); | |
| 272 | const atom = switch (self.tag) { | |
| 273 | .elf => &decl.link.elf.dbg_info_atom, | |
| 274 | .macho => &decl.link.macho.dbg_info_atom, | |
| 275 | else => unreachable, | |
| 276 | }; | |
| 277 | try self.addTypeReloc(atom, fn_ret_type, @intCast(u32, dbg_info_buffer.items.len), null); | |
| 246 | 278 | dbg_info_buffer.items.len += 4; // DW.AT.type, DW.FORM.ref4 |
| 247 | 279 | } |
| 280 | ||
| 248 | 281 | dbg_info_buffer.appendSliceAssumeCapacity(decl_name_with_null); // DW.AT.name, DW.FORM.string |
| 249 | 282 | |
| 250 | 283 | }, |
| ... | ... | @@ -252,30 +285,28 @@ pub fn initDeclDebugInfo(self: *Dwarf, decl: *Module.Decl) !DeclDebugBuffers { |
| 252 | 285 | // TODO implement .debug_info for global variables |
| 253 | 286 | }, |
| 254 | 287 | } |
| 255 | ||
| 256 | return DeclDebugBuffers{ | |
| 257 | .dbg_info_buffer = dbg_info_buffer, | |
| 258 | .dbg_line_buffer = dbg_line_buffer, | |
| 259 | .dbg_info_type_relocs = dbg_info_type_relocs, | |
| 260 | }; | |
| 261 | 288 | } |
| 262 | 289 | |
| 263 | pub fn commitDeclDebugInfo( | |
| 290 | pub fn commitDeclState( | |
| 264 | 291 | self: *Dwarf, |
| 265 | 292 | file: *File, |
| 266 | 293 | module: *Module, |
| 267 | 294 | decl: *Module.Decl, |
| 268 | 295 | sym_addr: u64, |
| 269 | 296 | sym_size: u64, |
| 270 | debug_buffers: *DeclDebugBuffers, | |
| 271 | 297 | ) !void { |
| 272 | 298 | const tracy = trace(@src()); |
| 273 | 299 | defer tracy.end(); |
| 274 | 300 | |
| 301 | assert(self.decl_state != null); // Caller forgot to call `initDeclState` | |
| 302 | defer { | |
| 303 | self.decl_state.?.deinit(self.allocator); | |
| 304 | self.decl_state = null; | |
| 305 | } | |
| 306 | ||
| 275 | 307 | const gpa = self.allocator; |
| 276 | var dbg_line_buffer = &debug_buffers.dbg_line_buffer; | |
| 277 | var dbg_info_buffer = &debug_buffers.dbg_info_buffer; | |
| 278 | var dbg_info_type_relocs = &debug_buffers.dbg_info_type_relocs; | |
| 308 | var dbg_line_buffer = &self.decl_state.?.dbg_line; | |
| 309 | var dbg_info_buffer = &self.decl_state.?.dbg_info; | |
| 279 | 310 | |
| 280 | 311 | const target_endian = self.target.cpu.arch.endian(); |
| 281 | 312 | |
| ... | ... | @@ -473,25 +504,21 @@ pub fn commitDeclDebugInfo( |
| 473 | 504 | if (dbg_info_buffer.items.len == 0) |
| 474 | 505 | return; |
| 475 | 506 | |
| 476 | // We need this for the duration of this function only so that for composite | |
| 477 | // types such as []const u32, if the type *u32 is non-existent, we create | |
| 478 | // it synthetically and store the backing bytes in this arena. After we are | |
| 479 | // done with the relocations, we can safely deinit the entire memory slab. | |
| 480 | // TODO currently, we do not store the relocations for future use, however, | |
| 481 | // if that is the case, we should move memory management to a higher scope, | |
| 482 | // such as linker scope, or whatnot. | |
| 483 | var dbg_type_arena = std.heap.ArenaAllocator.init(gpa); | |
| 484 | defer dbg_type_arena.deinit(); | |
| 485 | ||
| 486 | var nested_ref4_relocs = std.ArrayList(u32).init(gpa); | |
| 487 | defer nested_ref4_relocs.deinit(); | |
| 507 | const atom = switch (self.tag) { | |
| 508 | .elf => &decl.link.elf.dbg_info_atom, | |
| 509 | .macho => &decl.link.macho.dbg_info_atom, | |
| 510 | else => unreachable, | |
| 511 | }; | |
| 512 | const decl_state = &self.decl_state.?; | |
| 513 | ||
| 488 | 514 | { |
| 489 | 515 | // Now we emit the .debug_info types of the Decl. These will count towards the size of |
| 490 | 516 | // the buffer, so we have to do it before computing the offset, and we can't perform the actual |
| 491 | 517 | // relocations yet. |
| 492 | var it: usize = 0; | |
| 493 | while (it < dbg_info_type_relocs.count()) : (it += 1) { | |
| 494 | const ty = dbg_info_type_relocs.keys()[it]; | |
| 518 | var sym_index: usize = 0; | |
| 519 | while (sym_index < decl_state.abbrev_table.items.len) : (sym_index += 1) { | |
| 520 | const symbol = &decl_state.abbrev_table.items[sym_index]; | |
| 521 | const ty = symbol.@"type"; | |
| 495 | 522 | const deferred: bool = blk: { |
| 496 | 523 | if (ty.isAnyError()) break :blk true; |
| 497 | 524 | switch (ty.tag()) { |
| ... | ... | @@ -504,68 +531,38 @@ pub fn commitDeclDebugInfo( |
| 504 | 531 | }; |
| 505 | 532 | if (deferred) continue; |
| 506 | 533 | |
| 507 | const value_ptr = dbg_info_type_relocs.getPtrContext(ty, .{ | |
| 508 | .target = self.target, | |
| 509 | }).?; | |
| 510 | value_ptr.off = @intCast(u32, dbg_info_buffer.items.len); | |
| 511 | try self.addDbgInfoType( | |
| 512 | dbg_type_arena.allocator(), | |
| 513 | module, | |
| 514 | ty, | |
| 515 | dbg_info_buffer, | |
| 516 | dbg_info_type_relocs, | |
| 517 | &nested_ref4_relocs, | |
| 518 | ); | |
| 534 | symbol.offset = @intCast(u32, dbg_info_buffer.items.len); | |
| 535 | try self.addDbgInfoType(decl_state.abbrev_type_arena.allocator(), module, atom, ty, dbg_info_buffer); | |
| 519 | 536 | } |
| 520 | 537 | } |
| 521 | 538 | |
| 522 | const atom = switch (self.tag) { | |
| 523 | .elf => &decl.link.elf.dbg_info_atom, | |
| 524 | .macho => &decl.link.macho.dbg_info_atom, | |
| 525 | else => unreachable, | |
| 526 | }; | |
| 527 | 539 | try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len)); |
| 528 | 540 | |
| 529 | { | |
| 530 | // Now that we have the offset assigned we can finally perform type relocations. | |
| 531 | for (dbg_info_type_relocs.keys()) |ty| { | |
| 532 | const value = dbg_info_type_relocs.getContext(ty, .{ | |
| 533 | .target = self.target, | |
| 534 | }).?; | |
| 535 | for (value.relocs.items) |off| { | |
| 536 | const deferred: bool = blk: { | |
| 537 | if (ty.isAnyError()) break :blk true; | |
| 538 | switch (ty.tag()) { | |
| 539 | .error_set_inferred => { | |
| 540 | if (!ty.castTag(.error_set_inferred).?.data.is_resolved) break :blk true; | |
| 541 | }, | |
| 542 | else => {}, | |
| 543 | } | |
| 544 | break :blk false; | |
| 545 | }; | |
| 546 | if (deferred) { | |
| 547 | // Defer until later | |
| 548 | try self.deferred_error_sets_relocs.append(self.allocator, atom.off + off); | |
| 549 | } else { | |
| 550 | mem.writeInt( | |
| 551 | u32, | |
| 552 | dbg_info_buffer.items[off..][0..4], | |
| 553 | atom.off + value.off, | |
| 554 | target_endian, | |
| 555 | ); | |
| 556 | } | |
| 541 | while (decl_state.abbrev_relocs.popOrNull()) |reloc| { | |
| 542 | const symbol = decl_state.abbrev_table.items[reloc.target]; | |
| 543 | const ty = symbol.@"type"; | |
| 544 | const deferred: bool = blk: { | |
| 545 | if (ty.isAnyError()) break :blk true; | |
| 546 | switch (ty.tag()) { | |
| 547 | .error_set_inferred => { | |
| 548 | if (!ty.castTag(.error_set_inferred).?.data.is_resolved) break :blk true; | |
| 549 | }, | |
| 550 | else => {}, | |
| 557 | 551 | } |
| 558 | } | |
| 559 | // Offsets to positions with known a priori relative displacement values. | |
| 560 | // Here, we just need to add the offset of the atom to the read value in the | |
| 561 | // relocated cell. | |
| 562 | // TODO Should probably generalise this with type relocs. | |
| 563 | for (nested_ref4_relocs.items) |off| { | |
| 564 | const addend = mem.readInt(u32, dbg_info_buffer.items[off..][0..4], target_endian); | |
| 552 | break :blk false; | |
| 553 | }; | |
| 554 | if (deferred) { | |
| 555 | try self.global_abbrev_relocs.append(gpa, .{ | |
| 556 | .target = undefined, | |
| 557 | .offset = reloc.offset, | |
| 558 | .atom = reloc.atom, | |
| 559 | .addend = reloc.addend, | |
| 560 | }); | |
| 561 | } else { | |
| 565 | 562 | mem.writeInt( |
| 566 | 563 | u32, |
| 567 | dbg_info_buffer.items[off..][0..4], | |
| 568 | atom.off + addend, | |
| 564 | dbg_info_buffer.items[reloc.offset..][0..@sizeOf(u32)], | |
| 565 | symbol.atom.off + symbol.offset + reloc.addend, | |
| 569 | 566 | target_endian, |
| 570 | 567 | ); |
| 571 | 568 | } |
| ... | ... | @@ -574,77 +571,6 @@ pub fn commitDeclDebugInfo( |
| 574 | 571 | try self.writeDeclDebugInfo(file, atom, dbg_info_buffer.items); |
| 575 | 572 | } |
| 576 | 573 | |
| 577 | pub fn commitErrorSetDebugInfo(self: *Dwarf, file: *File, module: *Module) !void { | |
| 578 | if (self.deferred_error_sets_relocs.items.len == 0) return; // Nothing to do | |
| 579 | ||
| 580 | const gpa = self.allocator; | |
| 581 | var arena_alloc = std.heap.ArenaAllocator.init(gpa); | |
| 582 | defer arena_alloc.deinit(); | |
| 583 | const arena = arena_alloc.allocator(); | |
| 584 | ||
| 585 | const error_set = try arena.create(Module.ErrorSet); | |
| 586 | const ty = try Type.Tag.error_set.create(arena, error_set); | |
| 587 | var names = Module.ErrorSet.NameMap{}; | |
| 588 | try names.ensureUnusedCapacity(arena, module.global_error_set.count()); | |
| 589 | var it = module.global_error_set.keyIterator(); | |
| 590 | while (it.next()) |key| { | |
| 591 | names.putAssumeCapacityNoClobber(key.*, {}); | |
| 592 | } | |
| 593 | error_set.names = names; | |
| 594 | ||
| 595 | var dbg_info_buffer = std.ArrayList(u8).init(arena); | |
| 596 | try self.addDbgInfoErrorSet(arena, module, ty, &dbg_info_buffer); | |
| 597 | ||
| 598 | const atom = try gpa.create(Atom); | |
| 599 | errdefer gpa.destroy(atom); | |
| 600 | atom.* = .{ | |
| 601 | .prev = null, | |
| 602 | .next = null, | |
| 603 | .off = 0, | |
| 604 | .len = 0, | |
| 605 | }; | |
| 606 | try self.managed_atoms.append(gpa, atom); | |
| 607 | try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len)); | |
| 608 | try self.writeDeclDebugInfo(file, atom, dbg_info_buffer.items); | |
| 609 | ||
| 610 | const file_pos = blk: { | |
| 611 | switch (self.tag) { | |
| 612 | .elf => { | |
| 613 | const elf_file = file.cast(File.Elf).?; | |
| 614 | const debug_info_sect = &elf_file.sections.items[elf_file.debug_info_section_index.?]; | |
| 615 | break :blk debug_info_sect.sh_offset; | |
| 616 | }, | |
| 617 | .macho => { | |
| 618 | const macho_file = file.cast(File.MachO).?; | |
| 619 | const d_sym = &macho_file.d_sym.?; | |
| 620 | const dwarf_segment = &d_sym.load_commands.items[d_sym.dwarf_segment_cmd_index.?].segment; | |
| 621 | const debug_info_sect = &dwarf_segment.sections.items[d_sym.debug_info_section_index.?]; | |
| 622 | break :blk debug_info_sect.offset; | |
| 623 | }, | |
| 624 | else => unreachable, | |
| 625 | } | |
| 626 | }; | |
| 627 | ||
| 628 | const target_endian = self.target.cpu.arch.endian(); | |
| 629 | var buf: [@sizeOf(u32)]u8 = undefined; | |
| 630 | while (self.deferred_error_sets_relocs.popOrNull()) |reloc| { | |
| 631 | mem.writeInt(u32, &buf, atom.off, target_endian); | |
| 632 | ||
| 633 | switch (self.tag) { | |
| 634 | .elf => { | |
| 635 | const elf_file = file.cast(File.Elf).?; | |
| 636 | try elf_file.base.file.?.pwriteAll(&buf, file_pos + reloc); | |
| 637 | }, | |
| 638 | .macho => { | |
| 639 | const macho_file = file.cast(File.MachO).?; | |
| 640 | const d_sym = &macho_file.d_sym.?; | |
| 641 | try d_sym.file.pwriteAll(&buf, file_pos + reloc); | |
| 642 | }, | |
| 643 | else => unreachable, | |
| 644 | } | |
| 645 | } | |
| 646 | } | |
| 647 | ||
| 648 | 574 | fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u32) !void { |
| 649 | 575 | const tracy = trace(@src()); |
| 650 | 576 | defer tracy.end(); |
| ... | ... | @@ -904,14 +830,12 @@ fn addDbgInfoType( |
| 904 | 830 | self: *Dwarf, |
| 905 | 831 | arena: Allocator, |
| 906 | 832 | module: *Module, |
| 833 | atom: *Atom, | |
| 907 | 834 | ty: Type, |
| 908 | 835 | dbg_info_buffer: *std.ArrayList(u8), |
| 909 | dbg_info_type_relocs: *DbgInfoTypeRelocsTable, | |
| 910 | nested_ref4_relocs: *std.ArrayList(u32), | |
| 911 | 836 | ) error{OutOfMemory}!void { |
| 912 | 837 | const target = self.target; |
| 913 | 838 | const target_endian = self.target.cpu.arch.endian(); |
| 914 | var relocs = std.ArrayList(struct { ty: Type, reloc: u32 }).init(arena); | |
| 915 | 839 | |
| 916 | 840 | switch (ty.zigTypeTag()) { |
| 917 | 841 | .NoReturn => unreachable, |
| ... | ... | @@ -970,7 +894,7 @@ fn addDbgInfoType( |
| 970 | 894 | // DW.AT.type, DW.FORM.ref4 |
| 971 | 895 | var index = dbg_info_buffer.items.len; |
| 972 | 896 | try dbg_info_buffer.resize(index + 4); |
| 973 | try relocs.append(.{ .ty = Type.bool, .reloc = @intCast(u32, index) }); | |
| 897 | try self.addTypeReloc(atom, Type.bool, @intCast(u32, index), null); | |
| 974 | 898 | // DW.AT.data_member_location, DW.FORM.sdata |
| 975 | 899 | try dbg_info_buffer.ensureUnusedCapacity(6); |
| 976 | 900 | dbg_info_buffer.appendAssumeCapacity(0); |
| ... | ... | @@ -982,7 +906,7 @@ fn addDbgInfoType( |
| 982 | 906 | // DW.AT.type, DW.FORM.ref4 |
| 983 | 907 | index = dbg_info_buffer.items.len; |
| 984 | 908 | try dbg_info_buffer.resize(index + 4); |
| 985 | try relocs.append(.{ .ty = payload_ty, .reloc = @intCast(u32, index) }); | |
| 909 | try self.addTypeReloc(atom, payload_ty, @intCast(u32, index), null); | |
| 986 | 910 | // DW.AT.data_member_location, DW.FORM.sdata |
| 987 | 911 | const offset = abi_size - payload_ty.abiSize(target); |
| 988 | 912 | try leb128.writeULEB128(dbg_info_buffer.writer(), offset); |
| ... | ... | @@ -1011,7 +935,7 @@ fn addDbgInfoType( |
| 1011 | 935 | try dbg_info_buffer.resize(index + 4); |
| 1012 | 936 | var buf = try arena.create(Type.SlicePtrFieldTypeBuffer); |
| 1013 | 937 | const ptr_ty = ty.slicePtrFieldType(buf); |
| 1014 | try relocs.append(.{ .ty = ptr_ty, .reloc = @intCast(u32, index) }); | |
| 938 | try self.addTypeReloc(atom, ptr_ty, @intCast(u32, index), null); | |
| 1015 | 939 | // DW.AT.data_member_location, DW.FORM.sdata |
| 1016 | 940 | try dbg_info_buffer.ensureUnusedCapacity(6); |
| 1017 | 941 | dbg_info_buffer.appendAssumeCapacity(0); |
| ... | ... | @@ -1023,7 +947,7 @@ fn addDbgInfoType( |
| 1023 | 947 | // DW.AT.type, DW.FORM.ref4 |
| 1024 | 948 | index = dbg_info_buffer.items.len; |
| 1025 | 949 | try dbg_info_buffer.resize(index + 4); |
| 1026 | try relocs.append(.{ .ty = Type.initTag(.usize), .reloc = @intCast(u32, index) }); | |
| 950 | try self.addTypeReloc(atom, Type.usize, @intCast(u32, index), null); | |
| 1027 | 951 | // DW.AT.data_member_location, DW.FORM.sdata |
| 1028 | 952 | try dbg_info_buffer.ensureUnusedCapacity(2); |
| 1029 | 953 | dbg_info_buffer.appendAssumeCapacity(@sizeOf(usize)); |
| ... | ... | @@ -1035,7 +959,7 @@ fn addDbgInfoType( |
| 1035 | 959 | // DW.AT.type, DW.FORM.ref4 |
| 1036 | 960 | const index = dbg_info_buffer.items.len; |
| 1037 | 961 | try dbg_info_buffer.resize(index + 4); |
| 1038 | try relocs.append(.{ .ty = ty.childType(), .reloc = @intCast(u32, index) }); | |
| 962 | try self.addTypeReloc(atom, ty.childType(), @intCast(u32, index), null); | |
| 1039 | 963 | } |
| 1040 | 964 | }, |
| 1041 | 965 | .Struct => blk: { |
| ... | ... | @@ -1059,7 +983,7 @@ fn addDbgInfoType( |
| 1059 | 983 | // DW.AT.type, DW.FORM.ref4 |
| 1060 | 984 | var index = dbg_info_buffer.items.len; |
| 1061 | 985 | try dbg_info_buffer.resize(index + 4); |
| 1062 | try relocs.append(.{ .ty = field, .reloc = @intCast(u32, index) }); | |
| 986 | try self.addTypeReloc(atom, field, @intCast(u32, index), null); | |
| 1063 | 987 | // DW.AT.data_member_location, DW.FORM.sdata |
| 1064 | 988 | const field_off = ty.structFieldOffset(field_index, target); |
| 1065 | 989 | try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); |
| ... | ... | @@ -1090,7 +1014,7 @@ fn addDbgInfoType( |
| 1090 | 1014 | // DW.AT.type, DW.FORM.ref4 |
| 1091 | 1015 | var index = dbg_info_buffer.items.len; |
| 1092 | 1016 | try dbg_info_buffer.resize(index + 4); |
| 1093 | try relocs.append(.{ .ty = field.ty, .reloc = @intCast(u32, index) }); | |
| 1017 | try self.addTypeReloc(atom, field.ty, @intCast(u32, index), null); | |
| 1094 | 1018 | // DW.AT.data_member_location, DW.FORM.sdata |
| 1095 | 1019 | const field_off = ty.structFieldOffset(field_index, target); |
| 1096 | 1020 | try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); |
| ... | ... | @@ -1169,14 +1093,8 @@ fn addDbgInfoType( |
| 1169 | 1093 | dbg_info_buffer.appendAssumeCapacity(0); |
| 1170 | 1094 | // DW.AT.type, DW.FORM.ref4 |
| 1171 | 1095 | const inner_union_index = dbg_info_buffer.items.len; |
| 1172 | try dbg_info_buffer.ensureUnusedCapacity(4); | |
| 1173 | mem.writeInt( | |
| 1174 | u32, | |
| 1175 | dbg_info_buffer.addManyAsArrayAssumeCapacity(4), | |
| 1176 | @intCast(u32, inner_union_index + 5), | |
| 1177 | target_endian, | |
| 1178 | ); | |
| 1179 | try nested_ref4_relocs.append(@intCast(u32, inner_union_index)); | |
| 1096 | try dbg_info_buffer.resize(inner_union_index + 4); | |
| 1097 | try self.addTypeReloc(atom, ty, @intCast(u32, inner_union_index), 5); | |
| 1180 | 1098 | // DW.AT.data_member_location, DW.FORM.sdata |
| 1181 | 1099 | try leb128.writeULEB128(dbg_info_buffer.writer(), payload_offset); |
| 1182 | 1100 | } |
| ... | ... | @@ -1203,7 +1121,7 @@ fn addDbgInfoType( |
| 1203 | 1121 | // DW.AT.type, DW.FORM.ref4 |
| 1204 | 1122 | const index = dbg_info_buffer.items.len; |
| 1205 | 1123 | try dbg_info_buffer.resize(index + 4); |
| 1206 | try relocs.append(.{ .ty = field.ty, .reloc = @intCast(u32, index) }); | |
| 1124 | try self.addTypeReloc(atom, field.ty, @intCast(u32, index), null); | |
| 1207 | 1125 | // DW.AT.data_member_location, DW.FORM.sdata |
| 1208 | 1126 | try dbg_info_buffer.append(0); |
| 1209 | 1127 | } |
| ... | ... | @@ -1220,7 +1138,7 @@ fn addDbgInfoType( |
| 1220 | 1138 | // DW.AT.type, DW.FORM.ref4 |
| 1221 | 1139 | const index = dbg_info_buffer.items.len; |
| 1222 | 1140 | try dbg_info_buffer.resize(index + 4); |
| 1223 | try relocs.append(.{ .ty = union_obj.tag_ty, .reloc = @intCast(u32, index) }); | |
| 1141 | try self.addTypeReloc(atom, union_obj.tag_ty, @intCast(u32, index), null); | |
| 1224 | 1142 | // DW.AT.data_member_location, DW.FORM.sdata |
| 1225 | 1143 | try leb128.writeULEB128(dbg_info_buffer.writer(), tag_offset); |
| 1226 | 1144 | |
| ... | ... | @@ -1229,7 +1147,40 @@ fn addDbgInfoType( |
| 1229 | 1147 | } |
| 1230 | 1148 | }, |
| 1231 | 1149 | .ErrorSet => { |
| 1232 | try self.addDbgInfoErrorSet(arena, module, ty, dbg_info_buffer); | |
| 1150 | // DW.AT.enumeration_type | |
| 1151 | try dbg_info_buffer.append(abbrev_enum_type); | |
| 1152 | // DW.AT.byte_size, DW.FORM.sdata | |
| 1153 | const abi_size = ty.abiSize(target); | |
| 1154 | try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); | |
| 1155 | // DW.AT.name, DW.FORM.string | |
| 1156 | const name = try ty.nameAllocArena(arena, target); | |
| 1157 | try dbg_info_buffer.writer().print("{s}\x00", .{name}); | |
| 1158 | ||
| 1159 | // DW.AT.enumerator | |
| 1160 | const no_error = "(no error)"; | |
| 1161 | try dbg_info_buffer.ensureUnusedCapacity(no_error.len + 2 + @sizeOf(u64)); | |
| 1162 | dbg_info_buffer.appendAssumeCapacity(abbrev_enum_variant); | |
| 1163 | // DW.AT.name, DW.FORM.string | |
| 1164 | dbg_info_buffer.appendSliceAssumeCapacity(no_error); | |
| 1165 | dbg_info_buffer.appendAssumeCapacity(0); | |
| 1166 | // DW.AT.const_value, DW.FORM.data8 | |
| 1167 | mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian); | |
| 1168 | ||
| 1169 | const error_names = ty.errorSetNames(); | |
| 1170 | for (error_names) |error_name| { | |
| 1171 | const kv = module.getErrorValue(error_name) catch unreachable; | |
| 1172 | // DW.AT.enumerator | |
| 1173 | try dbg_info_buffer.ensureUnusedCapacity(error_name.len + 2 + @sizeOf(u64)); | |
| 1174 | dbg_info_buffer.appendAssumeCapacity(abbrev_enum_variant); | |
| 1175 | // DW.AT.name, DW.FORM.string | |
| 1176 | dbg_info_buffer.appendSliceAssumeCapacity(error_name); | |
| 1177 | dbg_info_buffer.appendAssumeCapacity(0); | |
| 1178 | // DW.AT.const_value, DW.FORM.data8 | |
| 1179 | mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), kv.value, target_endian); | |
| 1180 | } | |
| 1181 | ||
| 1182 | // DW.AT.enumeration_type delimit children | |
| 1183 | try dbg_info_buffer.append(0); | |
| 1233 | 1184 | }, |
| 1234 | 1185 | .ErrorUnion => { |
| 1235 | 1186 | const error_ty = ty.errorUnionSet(); |
| ... | ... | @@ -1255,7 +1206,7 @@ fn addDbgInfoType( |
| 1255 | 1206 | // DW.AT.type, DW.FORM.ref4 |
| 1256 | 1207 | var index = dbg_info_buffer.items.len; |
| 1257 | 1208 | try dbg_info_buffer.resize(index + 4); |
| 1258 | try relocs.append(.{ .ty = payload_ty, .reloc = @intCast(u32, index) }); | |
| 1209 | try self.addTypeReloc(atom, payload_ty, @intCast(u32, index), null); | |
| 1259 | 1210 | // DW.AT.data_member_location, DW.FORM.sdata |
| 1260 | 1211 | try leb128.writeULEB128(dbg_info_buffer.writer(), payload_off); |
| 1261 | 1212 | |
| ... | ... | @@ -1268,7 +1219,7 @@ fn addDbgInfoType( |
| 1268 | 1219 | // DW.AT.type, DW.FORM.ref4 |
| 1269 | 1220 | index = dbg_info_buffer.items.len; |
| 1270 | 1221 | try dbg_info_buffer.resize(index + 4); |
| 1271 | try relocs.append(.{ .ty = error_ty, .reloc = @intCast(u32, index) }); | |
| 1222 | try self.addTypeReloc(atom, error_ty, @intCast(u32, index), null); | |
| 1272 | 1223 | // DW.AT.data_member_location, DW.FORM.sdata |
| 1273 | 1224 | try dbg_info_buffer.append(0); |
| 1274 | 1225 | |
| ... | ... | @@ -1280,65 +1231,6 @@ fn addDbgInfoType( |
| 1280 | 1231 | try dbg_info_buffer.append(abbrev_pad1); |
| 1281 | 1232 | }, |
| 1282 | 1233 | } |
| 1283 | ||
| 1284 | for (relocs.items) |rel| { | |
| 1285 | const gop = try dbg_info_type_relocs.getOrPutContext(self.allocator, rel.ty, .{ | |
| 1286 | .target = self.target, | |
| 1287 | }); | |
| 1288 | if (!gop.found_existing) { | |
| 1289 | gop.value_ptr.* = .{ | |
| 1290 | .off = undefined, | |
| 1291 | .relocs = .{}, | |
| 1292 | }; | |
| 1293 | } | |
| 1294 | try gop.value_ptr.relocs.append(self.allocator, rel.reloc); | |
| 1295 | } | |
| 1296 | } | |
| 1297 | ||
| 1298 | fn addDbgInfoErrorSet( | |
| 1299 | self: *Dwarf, | |
| 1300 | arena: Allocator, | |
| 1301 | module: *Module, | |
| 1302 | ty: Type, | |
| 1303 | dbg_info_buffer: *std.ArrayList(u8), | |
| 1304 | ) error{OutOfMemory}!void { | |
| 1305 | const target = self.target; | |
| 1306 | const target_endian = self.target.cpu.arch.endian(); | |
| 1307 | ||
| 1308 | // DW.AT.enumeration_type | |
| 1309 | try dbg_info_buffer.append(abbrev_enum_type); | |
| 1310 | // DW.AT.byte_size, DW.FORM.sdata | |
| 1311 | const abi_size = ty.abiSize(target); | |
| 1312 | try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); | |
| 1313 | // DW.AT.name, DW.FORM.string | |
| 1314 | const name = try ty.nameAllocArena(arena, target); | |
| 1315 | try dbg_info_buffer.writer().print("{s}\x00", .{name}); | |
| 1316 | ||
| 1317 | // DW.AT.enumerator | |
| 1318 | const no_error = "(no error)"; | |
| 1319 | try dbg_info_buffer.ensureUnusedCapacity(no_error.len + 2 + @sizeOf(u64)); | |
| 1320 | dbg_info_buffer.appendAssumeCapacity(abbrev_enum_variant); | |
| 1321 | // DW.AT.name, DW.FORM.string | |
| 1322 | dbg_info_buffer.appendSliceAssumeCapacity(no_error); | |
| 1323 | dbg_info_buffer.appendAssumeCapacity(0); | |
| 1324 | // DW.AT.const_value, DW.FORM.data8 | |
| 1325 | mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian); | |
| 1326 | ||
| 1327 | const error_names = ty.errorSetNames(); | |
| 1328 | for (error_names) |error_name| { | |
| 1329 | const kv = module.getErrorValue(error_name) catch unreachable; | |
| 1330 | // DW.AT.enumerator | |
| 1331 | try dbg_info_buffer.ensureUnusedCapacity(error_name.len + 2 + @sizeOf(u64)); | |
| 1332 | dbg_info_buffer.appendAssumeCapacity(abbrev_enum_variant); | |
| 1333 | // DW.AT.name, DW.FORM.string | |
| 1334 | dbg_info_buffer.appendSliceAssumeCapacity(error_name); | |
| 1335 | dbg_info_buffer.appendAssumeCapacity(0); | |
| 1336 | // DW.AT.const_value, DW.FORM.data8 | |
| 1337 | mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), kv.value, target_endian); | |
| 1338 | } | |
| 1339 | ||
| 1340 | // DW.AT.enumeration_type delimit children | |
| 1341 | try dbg_info_buffer.append(0); | |
| 1342 | 1234 | } |
| 1343 | 1235 | |
| 1344 | 1236 | pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void { |
| ... | ... | @@ -2059,3 +1951,115 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { |
| 2059 | 1951 | return std.math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch |
| 2060 | 1952 | std.math.maxInt(@TypeOf(actual_size)); |
| 2061 | 1953 | } |
| 1954 | ||
| 1955 | pub fn addTypeReloc(self: *Dwarf, atom: *const Atom, ty: Type, offset: u32, addend: ?u32) !void { | |
| 1956 | const decl_state = &self.decl_state.?; | |
| 1957 | const gpa = self.allocator; | |
| 1958 | const resolv = decl_state.abbrev_resolver.getContext(ty, .{ | |
| 1959 | .target = self.target, | |
| 1960 | }) orelse blk: { | |
| 1961 | const sym_index = @intCast(u32, decl_state.abbrev_table.items.len); | |
| 1962 | try decl_state.abbrev_table.append(gpa, .{ | |
| 1963 | .atom = atom, | |
| 1964 | .@"type" = ty, | |
| 1965 | .offset = undefined, | |
| 1966 | }); | |
| 1967 | log.debug("@{d}: {}", .{ sym_index, ty.fmtDebug() }); | |
| 1968 | try decl_state.abbrev_resolver.putNoClobberContext(gpa, ty, sym_index, .{ | |
| 1969 | .target = self.target, | |
| 1970 | }); | |
| 1971 | break :blk decl_state.abbrev_resolver.getContext(ty, .{ | |
| 1972 | .target = self.target, | |
| 1973 | }).?; | |
| 1974 | }; | |
| 1975 | const add: u32 = addend orelse 0; | |
| 1976 | ||
| 1977 | log.debug("{x}: @{d} + {x}", .{ offset, resolv, add }); | |
| 1978 | try decl_state.abbrev_relocs.append(gpa, .{ | |
| 1979 | .target = resolv, | |
| 1980 | .atom = atom, | |
| 1981 | .offset = offset, | |
| 1982 | .addend = add, | |
| 1983 | }); | |
| 1984 | } | |
| 1985 | ||
| 1986 | pub fn getDeclDebugLineBuffer(self: *Dwarf) *std.ArrayList(u8) { | |
| 1987 | return &self.decl_state.?.dbg_line; | |
| 1988 | } | |
| 1989 | ||
| 1990 | pub fn getDeclDebugInfoBuffer(self: *Dwarf) *std.ArrayList(u8) { | |
| 1991 | return &self.decl_state.?.dbg_info; | |
| 1992 | } | |
| 1993 | ||
| 1994 | pub fn flushModule(self: *Dwarf, file: *File, module: *Module) !void { | |
| 1995 | if (self.global_abbrev_relocs.items.len > 0) { | |
| 1996 | const gpa = self.allocator; | |
| 1997 | var arena_alloc = std.heap.ArenaAllocator.init(gpa); | |
| 1998 | defer arena_alloc.deinit(); | |
| 1999 | const arena = arena_alloc.allocator(); | |
| 2000 | ||
| 2001 | const error_set = try arena.create(Module.ErrorSet); | |
| 2002 | const error_ty = try Type.Tag.error_set.create(arena, error_set); | |
| 2003 | var names = Module.ErrorSet.NameMap{}; | |
| 2004 | try names.ensureUnusedCapacity(arena, module.global_error_set.count()); | |
| 2005 | var it = module.global_error_set.keyIterator(); | |
| 2006 | while (it.next()) |key| { | |
| 2007 | names.putAssumeCapacityNoClobber(key.*, {}); | |
| 2008 | } | |
| 2009 | error_set.names = names; | |
| 2010 | ||
| 2011 | const atom = try gpa.create(Atom); | |
| 2012 | errdefer gpa.destroy(atom); | |
| 2013 | atom.* = .{ | |
| 2014 | .prev = null, | |
| 2015 | .next = null, | |
| 2016 | .off = 0, | |
| 2017 | .len = 0, | |
| 2018 | }; | |
| 2019 | ||
| 2020 | var dbg_info_buffer = std.ArrayList(u8).init(arena); | |
| 2021 | try self.addDbgInfoType(arena, module, atom, error_ty, &dbg_info_buffer); | |
| 2022 | ||
| 2023 | try self.managed_atoms.append(gpa, atom); | |
| 2024 | try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len)); | |
| 2025 | try self.writeDeclDebugInfo(file, atom, dbg_info_buffer.items); | |
| 2026 | ||
| 2027 | const file_pos = blk: { | |
| 2028 | switch (self.tag) { | |
| 2029 | .elf => { | |
| 2030 | const elf_file = file.cast(File.Elf).?; | |
| 2031 | const debug_info_sect = &elf_file.sections.items[elf_file.debug_info_section_index.?]; | |
| 2032 | break :blk debug_info_sect.sh_offset; | |
| 2033 | }, | |
| 2034 | .macho => { | |
| 2035 | const macho_file = file.cast(File.MachO).?; | |
| 2036 | const d_sym = &macho_file.d_sym.?; | |
| 2037 | const dwarf_segment = &d_sym.load_commands.items[d_sym.dwarf_segment_cmd_index.?].segment; | |
| 2038 | const debug_info_sect = &dwarf_segment.sections.items[d_sym.debug_info_section_index.?]; | |
| 2039 | break :blk debug_info_sect.offset; | |
| 2040 | }, | |
| 2041 | else => unreachable, | |
| 2042 | } | |
| 2043 | }; | |
| 2044 | ||
| 2045 | var buf: [@sizeOf(u32)]u8 = undefined; | |
| 2046 | mem.writeInt(u32, &buf, atom.off, self.target.cpu.arch.endian()); | |
| 2047 | ||
| 2048 | while (self.global_abbrev_relocs.popOrNull()) |reloc| { | |
| 2049 | switch (self.tag) { | |
| 2050 | .elf => { | |
| 2051 | const elf_file = file.cast(File.Elf).?; | |
| 2052 | try elf_file.base.file.?.pwriteAll(&buf, file_pos + reloc.atom.off + reloc.offset); | |
| 2053 | }, | |
| 2054 | .macho => { | |
| 2055 | const macho_file = file.cast(File.MachO).?; | |
| 2056 | const d_sym = &macho_file.d_sym.?; | |
| 2057 | try d_sym.file.pwriteAll(&buf, file_pos + reloc.atom.off + reloc.offset); | |
| 2058 | }, | |
| 2059 | else => unreachable, | |
| 2060 | } | |
| 2061 | } | |
| 2062 | } | |
| 2063 | ||
| 2064 | assert(self.decl_state == null); | |
| 2065 | } |
src/link/Elf.zig+14-54| ... | ... | @@ -958,8 +958,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { |
| 958 | 958 | const target_endian = self.base.options.target.cpu.arch.endian(); |
| 959 | 959 | const foreign_endian = target_endian != builtin.cpu.arch.endian(); |
| 960 | 960 | |
| 961 | if (self.dwarf) |*dwarf| { | |
| 962 | try dwarf.commitErrorSetDebugInfo(&self.base, module); | |
| 961 | if (self.dwarf) |*dw| { | |
| 962 | try dw.flushModule(&self.base, module); | |
| 963 | 963 | } |
| 964 | 964 | |
| 965 | 965 | { |
| ... | ... | @@ -2232,13 +2232,6 @@ pub fn freeDecl(self: *Elf, decl: *Module.Decl) void { |
| 2232 | 2232 | } |
| 2233 | 2233 | } |
| 2234 | 2234 | |
| 2235 | fn deinitRelocs(gpa: Allocator, table: *link.File.Dwarf.DbgInfoTypeRelocsTable) void { | |
| 2236 | for (table.values()) |*value| { | |
| 2237 | value.relocs.deinit(gpa); | |
| 2238 | } | |
| 2239 | table.deinit(gpa); | |
| 2240 | } | |
| 2241 | ||
| 2242 | 2235 | fn getDeclPhdrIndex(self: *Elf, decl: *Module.Decl) !u16 { |
| 2243 | 2236 | const ty = decl.ty; |
| 2244 | 2237 | const zig_ty = ty.zigTypeTag(); |
| ... | ... | @@ -2346,26 +2339,13 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven |
| 2346 | 2339 | const decl = func.owner_decl; |
| 2347 | 2340 | self.freeUnnamedConsts(decl); |
| 2348 | 2341 | |
| 2349 | var debug_buffers_buf: Dwarf.DeclDebugBuffers = undefined; | |
| 2350 | const debug_buffers = if (self.dwarf) |*dw| blk: { | |
| 2351 | debug_buffers_buf = try dw.initDeclDebugInfo(decl); | |
| 2352 | break :blk &debug_buffers_buf; | |
| 2353 | } else null; | |
| 2354 | defer { | |
| 2355 | if (debug_buffers) |dbg| { | |
| 2356 | dbg.dbg_line_buffer.deinit(); | |
| 2357 | dbg.dbg_info_buffer.deinit(); | |
| 2358 | deinitRelocs(self.base.allocator, &dbg.dbg_info_type_relocs); | |
| 2359 | } | |
| 2342 | if (self.dwarf) |*dw| { | |
| 2343 | try dw.initDeclState(decl); | |
| 2360 | 2344 | } |
| 2361 | 2345 | |
| 2362 | const res = if (debug_buffers) |dbg| | |
| 2346 | const res = if (self.dwarf) |*dw| | |
| 2363 | 2347 | try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{ |
| 2364 | .dwarf = .{ | |
| 2365 | .dbg_line = &dbg.dbg_line_buffer, | |
| 2366 | .dbg_info = &dbg.dbg_info_buffer, | |
| 2367 | .dbg_info_type_relocs = &dbg.dbg_info_type_relocs, | |
| 2368 | }, | |
| 2348 | .dwarf = dw, | |
| 2369 | 2349 | }) |
| 2370 | 2350 | else |
| 2371 | 2351 | try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none); |
| ... | ... | @@ -2379,15 +2359,8 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven |
| 2379 | 2359 | }, |
| 2380 | 2360 | }; |
| 2381 | 2361 | const local_sym = try self.updateDeclCode(decl, code, elf.STT_FUNC); |
| 2382 | if (debug_buffers) |dbg| { | |
| 2383 | try self.dwarf.?.commitDeclDebugInfo( | |
| 2384 | &self.base, | |
| 2385 | module, | |
| 2386 | decl, | |
| 2387 | local_sym.st_value, | |
| 2388 | local_sym.st_size, | |
| 2389 | dbg, | |
| 2390 | ); | |
| 2362 | if (self.dwarf) |*dw| { | |
| 2363 | try dw.commitDeclState(&self.base, module, decl, local_sym.st_value, local_sym.st_size); | |
| 2391 | 2364 | } |
| 2392 | 2365 | |
| 2393 | 2366 | // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated. |
| ... | ... | @@ -2421,31 +2394,18 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { |
| 2421 | 2394 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 2422 | 2395 | defer code_buffer.deinit(); |
| 2423 | 2396 | |
| 2424 | var debug_buffers_buf: Dwarf.DeclDebugBuffers = undefined; | |
| 2425 | const debug_buffers = if (self.dwarf) |*dw| blk: { | |
| 2426 | debug_buffers_buf = try dw.initDeclDebugInfo(decl); | |
| 2427 | break :blk &debug_buffers_buf; | |
| 2428 | } else null; | |
| 2429 | defer { | |
| 2430 | if (debug_buffers) |dbg| { | |
| 2431 | dbg.dbg_line_buffer.deinit(); | |
| 2432 | dbg.dbg_info_buffer.deinit(); | |
| 2433 | deinitRelocs(self.base.allocator, &dbg.dbg_info_type_relocs); | |
| 2434 | } | |
| 2397 | if (self.dwarf) |*dw| { | |
| 2398 | try dw.initDeclState(decl); | |
| 2435 | 2399 | } |
| 2436 | 2400 | |
| 2437 | 2401 | // TODO implement .debug_info for global variables |
| 2438 | 2402 | const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val; |
| 2439 | const res = if (debug_buffers) |dbg| | |
| 2403 | const res = if (self.dwarf) |*dw| | |
| 2440 | 2404 | try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ |
| 2441 | 2405 | .ty = decl.ty, |
| 2442 | 2406 | .val = decl_val, |
| 2443 | 2407 | }, &code_buffer, .{ |
| 2444 | .dwarf = .{ | |
| 2445 | .dbg_line = &dbg.dbg_line_buffer, | |
| 2446 | .dbg_info = &dbg.dbg_info_buffer, | |
| 2447 | .dbg_info_type_relocs = &dbg.dbg_info_type_relocs, | |
| 2448 | }, | |
| 2408 | .dwarf = dw, | |
| 2449 | 2409 | }, .{ |
| 2450 | 2410 | .parent_atom_index = decl.link.elf.local_sym_index, |
| 2451 | 2411 | }) |
| ... | ... | @@ -2468,8 +2428,8 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { |
| 2468 | 2428 | }; |
| 2469 | 2429 | |
| 2470 | 2430 | const local_sym = try self.updateDeclCode(decl, code, elf.STT_OBJECT); |
| 2471 | if (debug_buffers) |dbg| { | |
| 2472 | try self.dwarf.?.commitDeclDebugInfo(&self.base, module, decl, local_sym.st_value, local_sym.st_size, dbg); | |
| 2431 | if (self.dwarf) |*dw| { | |
| 2432 | try dw.commitDeclState(&self.base, module, decl, local_sym.st_value, local_sym.st_size); | |
| 2473 | 2433 | } |
| 2474 | 2434 | |
| 2475 | 2435 | // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated. |
src/link/MachO.zig+25-47| ... | ... | @@ -453,6 +453,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 453 | 453 | const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type. |
| 454 | 454 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); |
| 455 | 455 | |
| 456 | if (self.d_sym) |*d_sym| { | |
| 457 | if (self.base.options.module) |module| { | |
| 458 | try d_sym.dwarf.flushModule(&self.base, module); | |
| 459 | } | |
| 460 | } | |
| 461 | ||
| 456 | 462 | // If there is no Zig code to compile, then we should skip flushing the output file because it |
| 457 | 463 | // will not be part of the linker line anyway. |
| 458 | 464 | const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: { |
| ... | ... | @@ -3670,32 +3676,17 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv |
| 3670 | 3676 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 3671 | 3677 | defer code_buffer.deinit(); |
| 3672 | 3678 | |
| 3673 | var debug_buffers_buf: link.File.Dwarf.DeclDebugBuffers = undefined; | |
| 3674 | const debug_buffers = if (self.d_sym) |*d_sym| blk: { | |
| 3675 | debug_buffers_buf = try d_sym.initDeclDebugInfo(module, decl); | |
| 3676 | break :blk &debug_buffers_buf; | |
| 3677 | } else null; | |
| 3678 | defer { | |
| 3679 | if (debug_buffers) |dbg| { | |
| 3680 | dbg.dbg_line_buffer.deinit(); | |
| 3681 | dbg.dbg_info_buffer.deinit(); | |
| 3682 | for (dbg.dbg_info_type_relocs.values()) |*value| { | |
| 3683 | value.relocs.deinit(self.base.allocator); | |
| 3684 | } | |
| 3685 | dbg.dbg_info_type_relocs.deinit(self.base.allocator); | |
| 3686 | } | |
| 3679 | if (self.d_sym) |*d_sym| { | |
| 3680 | try d_sym.dwarf.initDeclState(decl); | |
| 3687 | 3681 | } |
| 3688 | 3682 | |
| 3689 | const res = if (debug_buffers) |dbg| | |
| 3683 | const res = if (self.d_sym) |*d_sym| | |
| 3690 | 3684 | try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{ |
| 3691 | .dwarf = .{ | |
| 3692 | .dbg_line = &dbg.dbg_line_buffer, | |
| 3693 | .dbg_info = &dbg.dbg_info_buffer, | |
| 3694 | .dbg_info_type_relocs = &dbg.dbg_info_type_relocs, | |
| 3695 | }, | |
| 3685 | .dwarf = &d_sym.dwarf, | |
| 3696 | 3686 | }) |
| 3697 | 3687 | else |
| 3698 | 3688 | try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none); |
| 3689 | ||
| 3699 | 3690 | switch (res) { |
| 3700 | 3691 | .appended => { |
| 3701 | 3692 | try decl.link.macho.code.appendSlice(self.base.allocator, code_buffer.items); |
| ... | ... | @@ -3707,12 +3698,10 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv |
| 3707 | 3698 | }, |
| 3708 | 3699 | } |
| 3709 | 3700 | |
| 3710 | _ = try self.placeDecl(decl, decl.link.macho.code.items.len); | |
| 3701 | const symbol = try self.placeDecl(decl, decl.link.macho.code.items.len); | |
| 3711 | 3702 | |
| 3712 | if (debug_buffers) |db| { | |
| 3713 | if (self.d_sym) |*d_sym| { | |
| 3714 | try d_sym.commitDeclDebugInfo(module, decl, db); | |
| 3715 | } | |
| 3703 | if (self.d_sym) |*d_sym| { | |
| 3704 | try d_sym.dwarf.commitDeclState(&self.base, module, decl, symbol.n_value, decl.link.macho.size); | |
| 3716 | 3705 | } |
| 3717 | 3706 | |
| 3718 | 3707 | // Since we updated the vaddr and the size, each corresponding export symbol also |
| ... | ... | @@ -3812,33 +3801,17 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 3812 | 3801 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 3813 | 3802 | defer code_buffer.deinit(); |
| 3814 | 3803 | |
| 3815 | var debug_buffers_buf: link.File.Dwarf.DeclDebugBuffers = undefined; | |
| 3816 | const debug_buffers = if (self.d_sym) |*d_sym| blk: { | |
| 3817 | debug_buffers_buf = try d_sym.initDeclDebugInfo(module, decl); | |
| 3818 | break :blk &debug_buffers_buf; | |
| 3819 | } else null; | |
| 3820 | defer { | |
| 3821 | if (debug_buffers) |dbg| { | |
| 3822 | dbg.dbg_line_buffer.deinit(); | |
| 3823 | dbg.dbg_info_buffer.deinit(); | |
| 3824 | for (dbg.dbg_info_type_relocs.values()) |*value| { | |
| 3825 | value.relocs.deinit(self.base.allocator); | |
| 3826 | } | |
| 3827 | dbg.dbg_info_type_relocs.deinit(self.base.allocator); | |
| 3828 | } | |
| 3804 | if (self.d_sym) |*d_sym| { | |
| 3805 | try d_sym.dwarf.initDeclState(decl); | |
| 3829 | 3806 | } |
| 3830 | 3807 | |
| 3831 | 3808 | const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val; |
| 3832 | const res = if (debug_buffers) |dbg| | |
| 3809 | const res = if (self.d_sym) |*d_sym| | |
| 3833 | 3810 | try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ |
| 3834 | 3811 | .ty = decl.ty, |
| 3835 | 3812 | .val = decl_val, |
| 3836 | 3813 | }, &code_buffer, .{ |
| 3837 | .dwarf = .{ | |
| 3838 | .dbg_line = &dbg.dbg_line_buffer, | |
| 3839 | .dbg_info = &dbg.dbg_info_buffer, | |
| 3840 | .dbg_info_type_relocs = &dbg.dbg_info_type_relocs, | |
| 3841 | }, | |
| 3814 | .dwarf = &d_sym.dwarf, | |
| 3842 | 3815 | }, .{ |
| 3843 | 3816 | .parent_atom_index = decl.link.macho.local_sym_index, |
| 3844 | 3817 | }) |
| ... | ... | @@ -3870,7 +3843,11 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 3870 | 3843 | }, |
| 3871 | 3844 | } |
| 3872 | 3845 | }; |
| 3873 | _ = try self.placeDecl(decl, code.len); | |
| 3846 | const symbol = try self.placeDecl(decl, code.len); | |
| 3847 | ||
| 3848 | if (self.d_sym) |*d_sym| { | |
| 3849 | try d_sym.dwarf.commitDeclState(&self.base, module, decl, symbol.n_value, decl.link.macho.size); | |
| 3850 | } | |
| 3874 | 3851 | |
| 3875 | 3852 | // Since we updated the vaddr and the size, each corresponding export symbol also |
| 3876 | 3853 | // needs to be updated. |
| ... | ... | @@ -4084,8 +4061,9 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 |
| 4084 | 4061 | } |
| 4085 | 4062 | |
| 4086 | 4063 | pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.Decl) !void { |
| 4064 | _ = module; | |
| 4087 | 4065 | if (self.d_sym) |*d_sym| { |
| 4088 | try d_sym.updateDeclLineNumber(module, decl); | |
| 4066 | try d_sym.dwarf.updateDeclLineNumber(&self.base, decl); | |
| 4089 | 4067 | } |
| 4090 | 4068 | } |
| 4091 | 4069 |
src/link/MachO/DebugSymbols.zig-22| ... | ... | @@ -645,25 +645,3 @@ fn writeStringTable(self: *DebugSymbols) !void { |
| 645 | 645 | |
| 646 | 646 | self.load_commands_dirty = true; |
| 647 | 647 | } |
| 648 | ||
| 649 | pub fn updateDeclLineNumber(self: *DebugSymbols, module: *Module, decl: *const Module.Decl) !void { | |
| 650 | _ = module; | |
| 651 | return self.dwarf.updateDeclLineNumber(&self.base.base, decl); | |
| 652 | } | |
| 653 | ||
| 654 | /// Caller owns the returned memory. | |
| 655 | pub fn initDeclDebugInfo(self: *DebugSymbols, module: *Module, decl: *Module.Decl) !Dwarf.DeclDebugBuffers { | |
| 656 | _ = module; | |
| 657 | return self.dwarf.initDeclDebugInfo(decl); | |
| 658 | } | |
| 659 | ||
| 660 | pub fn commitDeclDebugInfo( | |
| 661 | self: *DebugSymbols, | |
| 662 | module: *Module, | |
| 663 | decl: *Module.Decl, | |
| 664 | debug_buffers: *Dwarf.DeclDebugBuffers, | |
| 665 | ) !void { | |
| 666 | const symbol = self.base.locals.items[decl.link.macho.local_sym_index]; | |
| 667 | const atom = &decl.link.macho; | |
| 668 | return self.dwarf.commitDeclDebugInfo(&self.base.base, module, decl, symbol.n_value, atom.size, debug_buffers); | |
| 669 | } |