| 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,18 +386,19 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void { |
| 386 | const delta_line = @intCast(i32, line) - @intCast(i32, self.prev_di_line); | 386 | const delta_line = @intCast(i32, line) - @intCast(i32, self.prev_di_line); |
| 387 | const delta_pc: usize = self.code.items.len - self.prev_di_pc; | 387 | const delta_pc: usize = self.code.items.len - self.prev_di_pc; |
| 388 | switch (self.debug_output) { | 388 | switch (self.debug_output) { |
| 389 | .dwarf => |dbg_out| { | 389 | .dwarf => |dw| { |
| 390 | // TODO Look into using the DWARF special opcodes to compress this data. | 390 | // TODO Look into using the DWARF special opcodes to compress this data. |
| 391 | // It lets you emit single-byte opcodes that add different numbers to | 391 | // It lets you emit single-byte opcodes that add different numbers to |
| 392 | // both the PC and the line number at the same time. | 392 | // both the PC and the line number at the same time. |
| 393 | try dbg_out.dbg_line.ensureUnusedCapacity(11); | 393 | const dbg_line = dw.getDeclDebugLineBuffer(); |
| 394 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_pc); | 394 | try dbg_line.ensureUnusedCapacity(11); |
| 395 | leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable; | 395 | dbg_line.appendAssumeCapacity(DW.LNS.advance_pc); |
| 396 | leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable; | ||
| 396 | if (delta_line != 0) { | 397 | if (delta_line != 0) { |
| 397 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_line); | 398 | dbg_line.appendAssumeCapacity(DW.LNS.advance_line); |
| 398 | leb128.writeILEB128(dbg_out.dbg_line.writer(), delta_line) catch unreachable; | 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 | self.prev_di_pc = self.code.items.len; | 402 | self.prev_di_pc = self.code.items.len; |
| 402 | self.prev_di_line = line; | 403 | self.prev_di_line = line; |
| 403 | self.prev_di_column = column; | 404 | self.prev_di_column = column; |
| ... | @@ -586,8 +587,8 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -586,8 +587,8 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 586 | 587 | ||
| 587 | fn mirDebugPrologueEnd(self: *Emit) !void { | 588 | fn mirDebugPrologueEnd(self: *Emit) !void { |
| 588 | switch (self.debug_output) { | 589 | switch (self.debug_output) { |
| 589 | .dwarf => |dbg_out| { | 590 | .dwarf => |dw| { |
| 590 | try dbg_out.dbg_line.append(DW.LNS.set_prologue_end); | 591 | try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end); |
| 591 | try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column); | 592 | try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column); |
| 592 | }, | 593 | }, |
| 593 | .plan9 => {}, | 594 | .plan9 => {}, |
| ... | @@ -597,8 +598,8 @@ fn mirDebugPrologueEnd(self: *Emit) !void { | ... | @@ -597,8 +598,8 @@ fn mirDebugPrologueEnd(self: *Emit) !void { |
| 597 | 598 | ||
| 598 | fn mirDebugEpilogueBegin(self: *Emit) !void { | 599 | fn mirDebugEpilogueBegin(self: *Emit) !void { |
| 599 | switch (self.debug_output) { | 600 | switch (self.debug_output) { |
| 600 | .dwarf => |dbg_out| { | 601 | .dwarf => |dw| { |
| 601 | try dbg_out.dbg_line.append(DW.LNS.set_epilogue_begin); | 602 | try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin); |
| 602 | try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column); | 603 | try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column); |
| 603 | }, | 604 | }, |
| 604 | .plan9 => {}, | 605 | .plan9 => {}, |
src/arch/arm/Emit.zig+37-36| ... | @@ -328,18 +328,19 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void { | ... | @@ -328,18 +328,19 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void { |
| 328 | const delta_line = @intCast(i32, line) - @intCast(i32, self.prev_di_line); | 328 | const delta_line = @intCast(i32, line) - @intCast(i32, self.prev_di_line); |
| 329 | const delta_pc: usize = self.code.items.len - self.prev_di_pc; | 329 | const delta_pc: usize = self.code.items.len - self.prev_di_pc; |
| 330 | switch (self.debug_output) { | 330 | switch (self.debug_output) { |
| 331 | .dwarf => |dbg_out| { | 331 | .dwarf => |dw| { |
| 332 | // TODO Look into using the DWARF special opcodes to compress this data. | 332 | // TODO Look into using the DWARF special opcodes to compress this data. |
| 333 | // It lets you emit single-byte opcodes that add different numbers to | 333 | // It lets you emit single-byte opcodes that add different numbers to |
| 334 | // both the PC and the line number at the same time. | 334 | // both the PC and the line number at the same time. |
| 335 | try dbg_out.dbg_line.ensureUnusedCapacity(11); | 335 | const dbg_line = dw.getDeclDebugLineBuffer(); |
| 336 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_pc); | 336 | try dbg_line.ensureUnusedCapacity(11); |
| 337 | leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable; | 337 | dbg_line.appendAssumeCapacity(DW.LNS.advance_pc); |
| 338 | leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable; | ||
| 338 | if (delta_line != 0) { | 339 | if (delta_line != 0) { |
| 339 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_line); | 340 | dbg_line.appendAssumeCapacity(DW.LNS.advance_line); |
| 340 | leb128.writeILEB128(dbg_out.dbg_line.writer(), delta_line) catch unreachable; | 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 | self.prev_di_pc = self.code.items.len; | 344 | self.prev_di_pc = self.code.items.len; |
| 344 | self.prev_di_line = line; | 345 | self.prev_di_line = line; |
| 345 | self.prev_di_column = column; | 346 | self.prev_di_column = column; |
| ... | @@ -379,19 +380,17 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void { | ... | @@ -379,19 +380,17 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void { |
| 379 | /// after codegen for this symbol is done. | 380 | /// after codegen for this symbol is done. |
| 380 | fn addDbgInfoTypeReloc(self: *Emit, ty: Type) !void { | 381 | fn addDbgInfoTypeReloc(self: *Emit, ty: Type) !void { |
| 381 | switch (self.debug_output) { | 382 | switch (self.debug_output) { |
| 382 | .dwarf => |dbg_out| { | 383 | .dwarf => |dw| { |
| 383 | assert(ty.hasRuntimeBits()); | 384 | assert(ty.hasRuntimeBits()); |
| 384 | const index = dbg_out.dbg_info.items.len; | 385 | const dbg_info = dw.getDeclDebugInfoBuffer(); |
| 385 | try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 | 386 | const index = dbg_info.items.len; |
| 386 | 387 | try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 | |
| 387 | const gop = try dbg_out.dbg_info_type_relocs.getOrPutContext(self.bin_file.allocator, ty, .{ .target = self.target.* }); | 388 | const atom = switch (self.bin_file.tag) { |
| 388 | if (!gop.found_existing) { | 389 | .elf => &self.function.mod_fn.owner_decl.link.elf.dbg_info_atom, |
| 389 | gop.value_ptr.* = .{ | 390 | .macho => unreachable, |
| 390 | .off = undefined, | 391 | else => unreachable, |
| 391 | .relocs = .{}, | 392 | }; |
| 392 | }; | 393 | try dw.addTypeReloc(atom, ty, @intCast(u32, index), null); |
| 393 | } | ||
| 394 | try gop.value_ptr.relocs.append(self.bin_file.allocator, @intCast(u32, index)); | ||
| 395 | }, | 394 | }, |
| 396 | .plan9 => {}, | 395 | .plan9 => {}, |
| 397 | .none => {}, | 396 | .none => {}, |
| ... | @@ -409,16 +408,17 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void { | ... | @@ -409,16 +408,17 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void { |
| 409 | switch (mcv) { | 408 | switch (mcv) { |
| 410 | .register => |reg| { | 409 | .register => |reg| { |
| 411 | switch (self.debug_output) { | 410 | switch (self.debug_output) { |
| 412 | .dwarf => |dbg_out| { | 411 | .dwarf => |dw| { |
| 413 | try dbg_out.dbg_info.ensureUnusedCapacity(3); | 412 | const dbg_info = dw.getDeclDebugInfoBuffer(); |
| 414 | dbg_out.dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter); | 413 | try dbg_info.ensureUnusedCapacity(3); |
| 415 | dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | 414 | dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter); |
| 415 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | ||
| 416 | 1, // ULEB128 dwarf expression length | 416 | 1, // ULEB128 dwarf expression length |
| 417 | reg.dwarfLocOp(), | 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 | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 | 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 | .plan9 => {}, | 423 | .plan9 => {}, |
| 424 | .none => {}, | 424 | .none => {}, |
| ... | @@ -428,7 +428,7 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void { | ... | @@ -428,7 +428,7 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void { |
| 428 | .stack_argument_offset, | 428 | .stack_argument_offset, |
| 429 | => { | 429 | => { |
| 430 | switch (self.debug_output) { | 430 | switch (self.debug_output) { |
| 431 | .dwarf => |dbg_out| { | 431 | .dwarf => |dw| { |
| 432 | const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch { | 432 | const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch { |
| 433 | return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(target)}); | 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,7 +442,8 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void { |
| 442 | else => unreachable, | 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 | // Get length of the LEB128 stack offset | 448 | // Get length of the LEB128 stack offset |
| 448 | var counting_writer = std.io.countingWriter(std.io.null_writer); | 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,13 +451,13 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void { |
| 450 | 451 | ||
| 451 | // DW.AT.location, DW.FORM.exprloc | 452 | // DW.AT.location, DW.FORM.exprloc |
| 452 | // ULEB128 dwarf expression length | 453 | // ULEB128 dwarf expression length |
| 453 | try leb128.writeULEB128(dbg_out.dbg_info.writer(), counting_writer.bytes_written + 1); | 454 | try leb128.writeULEB128(dbg_info.writer(), counting_writer.bytes_written + 1); |
| 454 | try dbg_out.dbg_info.append(DW.OP.breg11); | 455 | try dbg_info.append(DW.OP.breg11); |
| 455 | try leb128.writeILEB128(dbg_out.dbg_info.writer(), adjusted_stack_offset); | 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 | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 | 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 | .plan9 => {}, | 462 | .plan9 => {}, |
| 462 | .none => {}, | 463 | .none => {}, |
| ... | @@ -558,8 +559,8 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -558,8 +559,8 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 558 | 559 | ||
| 559 | fn mirDebugPrologueEnd(emit: *Emit) !void { | 560 | fn mirDebugPrologueEnd(emit: *Emit) !void { |
| 560 | switch (emit.debug_output) { | 561 | switch (emit.debug_output) { |
| 561 | .dwarf => |dbg_out| { | 562 | .dwarf => |dw| { |
| 562 | try dbg_out.dbg_line.append(DW.LNS.set_prologue_end); | 563 | try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end); |
| 563 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); | 564 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); |
| 564 | }, | 565 | }, |
| 565 | .plan9 => {}, | 566 | .plan9 => {}, |
| ... | @@ -569,8 +570,8 @@ fn mirDebugPrologueEnd(emit: *Emit) !void { | ... | @@ -569,8 +570,8 @@ fn mirDebugPrologueEnd(emit: *Emit) !void { |
| 569 | 570 | ||
| 570 | fn mirDebugEpilogueBegin(emit: *Emit) !void { | 571 | fn mirDebugEpilogueBegin(emit: *Emit) !void { |
| 571 | switch (emit.debug_output) { | 572 | switch (emit.debug_output) { |
| 572 | .dwarf => |dbg_out| { | 573 | .dwarf => |dw| { |
| 573 | try dbg_out.dbg_line.append(DW.LNS.set_epilogue_begin); | 574 | try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin); |
| 574 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); | 575 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); |
| 575 | }, | 576 | }, |
| 576 | .plan9 => {}, | 577 | .plan9 => {}, |
src/arch/riscv64/CodeGen.zig+17-20| ... | @@ -745,21 +745,17 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void { | ... | @@ -745,21 +745,17 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void { |
| 745 | /// after codegen for this symbol is done. | 745 | /// after codegen for this symbol is done. |
| 746 | fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void { | 746 | fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void { |
| 747 | switch (self.debug_output) { | 747 | switch (self.debug_output) { |
| 748 | .dwarf => |dbg_out| { | 748 | .dwarf => |dw| { |
| 749 | assert(ty.hasRuntimeBits()); | 749 | assert(ty.hasRuntimeBits()); |
| 750 | const index = dbg_out.dbg_info.items.len; | 750 | const dbg_info = dw.getDeclDebugInfoBuffer(); |
| 751 | try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 | 751 | const index = dbg_info.items.len; |
| 752 | 752 | try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 | |
| 753 | const gop = try dbg_out.dbg_info_type_relocs.getOrPutContext(self.gpa, ty, .{ | 753 | const atom = switch (self.bin_file.tag) { |
| 754 | .target = self.target.*, | 754 | .elf => &self.mod_fn.owner_decl.link.elf.dbg_info_atom, |
| 755 | }); | 755 | .macho => unreachable, |
| 756 | if (!gop.found_existing) { | 756 | else => unreachable, |
| 757 | gop.value_ptr.* = .{ | 757 | }; |
| 758 | .off = undefined, | 758 | try dw.addTypeReloc(atom, ty, @intCast(u32, index), null); |
| 759 | .relocs = .{}, | ||
| 760 | }; | ||
| 761 | } | ||
| 762 | try gop.value_ptr.relocs.append(self.gpa, @intCast(u32, index)); | ||
| 763 | }, | 759 | }, |
| 764 | .plan9 => {}, | 760 | .plan9 => {}, |
| 765 | .none => {}, | 761 | .none => {}, |
| ... | @@ -1573,16 +1569,17 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32 | ... | @@ -1573,16 +1569,17 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32 |
| 1573 | switch (mcv) { | 1569 | switch (mcv) { |
| 1574 | .register => |reg| { | 1570 | .register => |reg| { |
| 1575 | switch (self.debug_output) { | 1571 | switch (self.debug_output) { |
| 1576 | .dwarf => |dbg_out| { | 1572 | .dwarf => |dw| { |
| 1577 | try dbg_out.dbg_info.ensureUnusedCapacity(3); | 1573 | const dbg_info = dw.getDeclDebugInfoBuffer(); |
| 1578 | dbg_out.dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter); | 1574 | try dbg_info.ensureUnusedCapacity(3); |
| 1579 | dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | 1575 | dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter); |
| 1576 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | ||
| 1580 | 1, // ULEB128 dwarf expression length | 1577 | 1, // ULEB128 dwarf expression length |
| 1581 | reg.dwarfLocOp(), | 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 | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 | 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 | .plan9 => {}, | 1584 | .plan9 => {}, |
| 1588 | .none => {}, | 1585 | .none => {}, |
src/arch/riscv64/Emit.zig+12-11| ... | @@ -89,18 +89,19 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void { | ... | @@ -89,18 +89,19 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void { |
| 89 | const delta_line = @intCast(i32, line) - @intCast(i32, self.prev_di_line); | 89 | const delta_line = @intCast(i32, line) - @intCast(i32, self.prev_di_line); |
| 90 | const delta_pc: usize = self.code.items.len - self.prev_di_pc; | 90 | const delta_pc: usize = self.code.items.len - self.prev_di_pc; |
| 91 | switch (self.debug_output) { | 91 | switch (self.debug_output) { |
| 92 | .dwarf => |dbg_out| { | 92 | .dwarf => |dw| { |
| 93 | // TODO Look into using the DWARF special opcodes to compress this data. | 93 | // TODO Look into using the DWARF special opcodes to compress this data. |
| 94 | // It lets you emit single-byte opcodes that add different numbers to | 94 | // It lets you emit single-byte opcodes that add different numbers to |
| 95 | // both the PC and the line number at the same time. | 95 | // both the PC and the line number at the same time. |
| 96 | try dbg_out.dbg_line.ensureUnusedCapacity(11); | 96 | const dbg_line = dw.getDeclDebugLineBuffer(); |
| 97 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_pc); | 97 | try dbg_line.ensureUnusedCapacity(11); |
| 98 | leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable; | 98 | dbg_line.appendAssumeCapacity(DW.LNS.advance_pc); |
| 99 | leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable; | ||
| 99 | if (delta_line != 0) { | 100 | if (delta_line != 0) { |
| 100 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_line); | 101 | dbg_line.appendAssumeCapacity(DW.LNS.advance_line); |
| 101 | leb128.writeILEB128(dbg_out.dbg_line.writer(), delta_line) catch unreachable; | 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 | self.prev_di_pc = self.code.items.len; | 105 | self.prev_di_pc = self.code.items.len; |
| 105 | self.prev_di_line = line; | 106 | self.prev_di_line = line; |
| 106 | self.prev_di_column = column; | 107 | self.prev_di_column = column; |
| ... | @@ -182,8 +183,8 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -182,8 +183,8 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 182 | 183 | ||
| 183 | fn mirDebugPrologueEnd(self: *Emit) !void { | 184 | fn mirDebugPrologueEnd(self: *Emit) !void { |
| 184 | switch (self.debug_output) { | 185 | switch (self.debug_output) { |
| 185 | .dwarf => |dbg_out| { | 186 | .dwarf => |dw| { |
| 186 | try dbg_out.dbg_line.append(DW.LNS.set_prologue_end); | 187 | try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end); |
| 187 | try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column); | 188 | try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column); |
| 188 | }, | 189 | }, |
| 189 | .plan9 => {}, | 190 | .plan9 => {}, |
| ... | @@ -193,8 +194,8 @@ fn mirDebugPrologueEnd(self: *Emit) !void { | ... | @@ -193,8 +194,8 @@ fn mirDebugPrologueEnd(self: *Emit) !void { |
| 193 | 194 | ||
| 194 | fn mirDebugEpilogueBegin(self: *Emit) !void { | 195 | fn mirDebugEpilogueBegin(self: *Emit) !void { |
| 195 | switch (self.debug_output) { | 196 | switch (self.debug_output) { |
| 196 | .dwarf => |dbg_out| { | 197 | .dwarf => |dw| { |
| 197 | try dbg_out.dbg_line.append(DW.LNS.set_epilogue_begin); | 198 | try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin); |
| 198 | try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column); | 199 | try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column); |
| 199 | }, | 200 | }, |
| 200 | .plan9 => {}, | 201 | .plan9 => {}, |
src/arch/x86_64/CodeGen.zig+1| ... | @@ -350,6 +350,7 @@ pub fn generate( | ... | @@ -350,6 +350,7 @@ pub fn generate( |
| 350 | var emit = Emit{ | 350 | var emit = Emit{ |
| 351 | .mir = mir, | 351 | .mir = mir, |
| 352 | .bin_file = bin_file, | 352 | .bin_file = bin_file, |
| 353 | .function = &function, | ||
| 353 | .debug_output = debug_output, | 354 | .debug_output = debug_output, |
| 354 | .target = &bin_file.options.target, | 355 | .target = &bin_file.options.target, |
| 355 | .src_loc = src_loc, | 356 | .src_loc = src_loc, |
src/arch/x86_64/Emit.zig+41-40| ... | @@ -16,6 +16,7 @@ const testing = std.testing; | ... | @@ -16,6 +16,7 @@ const testing = std.testing; |
| 16 | 16 | ||
| 17 | const Air = @import("../../Air.zig"); | 17 | const Air = @import("../../Air.zig"); |
| 18 | const Allocator = mem.Allocator; | 18 | const Allocator = mem.Allocator; |
| 19 | const CodeGen = @import("CodeGen.zig"); | ||
| 19 | const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput; | 20 | const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput; |
| 20 | const DW = std.dwarf; | 21 | const DW = std.dwarf; |
| 21 | const Encoder = bits.Encoder; | 22 | const Encoder = bits.Encoder; |
| ... | @@ -29,6 +30,7 @@ const Type = @import("../../type.zig").Type; | ... | @@ -29,6 +30,7 @@ const Type = @import("../../type.zig").Type; |
| 29 | 30 | ||
| 30 | mir: Mir, | 31 | mir: Mir, |
| 31 | bin_file: *link.File, | 32 | bin_file: *link.File, |
| 33 | function: *const CodeGen, | ||
| 32 | debug_output: DebugInfoOutput, | 34 | debug_output: DebugInfoOutput, |
| 33 | target: *const std.Target, | 35 | target: *const std.Target, |
| 34 | err_msg: ?*ErrorMsg = null, | 36 | err_msg: ?*ErrorMsg = null, |
| ... | @@ -963,18 +965,19 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void { | ... | @@ -963,18 +965,19 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void { |
| 963 | const delta_pc: usize = emit.code.items.len - emit.prev_di_pc; | 965 | const delta_pc: usize = emit.code.items.len - emit.prev_di_pc; |
| 964 | log.debug(" (advance pc={d} and line={d})", .{ delta_line, delta_pc }); | 966 | log.debug(" (advance pc={d} and line={d})", .{ delta_line, delta_pc }); |
| 965 | switch (emit.debug_output) { | 967 | switch (emit.debug_output) { |
| 966 | .dwarf => |dbg_out| { | 968 | .dwarf => |dw| { |
| 967 | // TODO Look into using the DWARF special opcodes to compress this data. | 969 | // TODO Look into using the DWARF special opcodes to compress this data. |
| 968 | // It lets you emit single-byte opcodes that add different numbers to | 970 | // It lets you emit single-byte opcodes that add different numbers to |
| 969 | // both the PC and the line number at the same time. | 971 | // both the PC and the line number at the same time. |
| 970 | try dbg_out.dbg_line.ensureUnusedCapacity(11); | 972 | const dbg_line = dw.getDeclDebugLineBuffer(); |
| 971 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_pc); | 973 | try dbg_line.ensureUnusedCapacity(11); |
| 972 | leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable; | 974 | dbg_line.appendAssumeCapacity(DW.LNS.advance_pc); |
| 975 | leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable; | ||
| 973 | if (delta_line != 0) { | 976 | if (delta_line != 0) { |
| 974 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_line); | 977 | dbg_line.appendAssumeCapacity(DW.LNS.advance_line); |
| 975 | leb128.writeILEB128(dbg_out.dbg_line.writer(), delta_line) catch unreachable; | 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 | emit.prev_di_line = line; | 981 | emit.prev_di_line = line; |
| 979 | emit.prev_di_column = column; | 982 | emit.prev_di_column = column; |
| 980 | emit.prev_di_pc = emit.code.items.len; | 983 | emit.prev_di_pc = emit.code.items.len; |
| ... | @@ -1022,8 +1025,8 @@ fn mirDbgPrologueEnd(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | ... | @@ -1022,8 +1025,8 @@ fn mirDbgPrologueEnd(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { |
| 1022 | const tag = emit.mir.instructions.items(.tag)[inst]; | 1025 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| 1023 | assert(tag == .dbg_prologue_end); | 1026 | assert(tag == .dbg_prologue_end); |
| 1024 | switch (emit.debug_output) { | 1027 | switch (emit.debug_output) { |
| 1025 | .dwarf => |dbg_out| { | 1028 | .dwarf => |dw| { |
| 1026 | try dbg_out.dbg_line.append(DW.LNS.set_prologue_end); | 1029 | try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end); |
| 1027 | log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{ emit.prev_di_line, emit.prev_di_column }); | 1030 | log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{ emit.prev_di_line, emit.prev_di_column }); |
| 1028 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); | 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,8 +1039,8 @@ fn mirDbgEpilogueBegin(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { |
| 1036 | const tag = emit.mir.instructions.items(.tag)[inst]; | 1039 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| 1037 | assert(tag == .dbg_epilogue_begin); | 1040 | assert(tag == .dbg_epilogue_begin); |
| 1038 | switch (emit.debug_output) { | 1041 | switch (emit.debug_output) { |
| 1039 | .dwarf => |dbg_out| { | 1042 | .dwarf => |dw| { |
| 1040 | try dbg_out.dbg_line.append(DW.LNS.set_epilogue_begin); | 1043 | try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin); |
| 1041 | log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{ emit.prev_di_line, emit.prev_di_column }); | 1044 | log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{ emit.prev_di_line, emit.prev_di_column }); |
| 1042 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); | 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,16 +1066,17 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32 |
| 1063 | switch (mcv) { | 1066 | switch (mcv) { |
| 1064 | .register => |reg| { | 1067 | .register => |reg| { |
| 1065 | switch (emit.debug_output) { | 1068 | switch (emit.debug_output) { |
| 1066 | .dwarf => |dbg_out| { | 1069 | .dwarf => |dw| { |
| 1067 | try dbg_out.dbg_info.ensureUnusedCapacity(3); | 1070 | const dbg_info = dw.getDeclDebugInfoBuffer(); |
| 1068 | dbg_out.dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter); | 1071 | try dbg_info.ensureUnusedCapacity(3); |
| 1069 | dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | 1072 | dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter); |
| 1073 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | ||
| 1070 | 1, // ULEB128 dwarf expression length | 1074 | 1, // ULEB128 dwarf expression length |
| 1071 | reg.dwarfLocOp(), | 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 | try emit.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 | 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 | .plan9 => {}, | 1081 | .plan9 => {}, |
| 1078 | .none => {}, | 1082 | .none => {}, |
| ... | @@ -1080,25 +1084,26 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32 | ... | @@ -1080,25 +1084,26 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32 |
| 1080 | }, | 1084 | }, |
| 1081 | .stack_offset => |off| { | 1085 | .stack_offset => |off| { |
| 1082 | switch (emit.debug_output) { | 1086 | switch (emit.debug_output) { |
| 1083 | .dwarf => |dbg_out| { | 1087 | .dwarf => |dw| { |
| 1084 | // we add here +16 like we do in airArg in CodeGen since we refer directly to | 1088 | // we add here +16 like we do in airArg in CodeGen since we refer directly to |
| 1085 | // rbp as the start of function frame minus 8 bytes for caller's rbp preserved in the | 1089 | // rbp as the start of function frame minus 8 bytes for caller's rbp preserved in the |
| 1086 | // prologue, and 8 bytes for return address. | 1090 | // prologue, and 8 bytes for return address. |
| 1087 | // TODO we need to make this more generic if we don't use rbp as the frame pointer | 1091 | // TODO we need to make this more generic if we don't use rbp as the frame pointer |
| 1088 | // for example when -fomit-frame-pointer is set. | 1092 | // for example when -fomit-frame-pointer is set. |
| 1089 | const disp = @intCast(i32, max_stack) - off + 16; | 1093 | const disp = @intCast(i32, max_stack) - off + 16; |
| 1090 | try dbg_out.dbg_info.ensureUnusedCapacity(8); | 1094 | const dbg_info = dw.getDeclDebugInfoBuffer(); |
| 1091 | dbg_out.dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter); | 1095 | try dbg_info.ensureUnusedCapacity(8); |
| 1092 | const fixup = dbg_out.dbg_info.items.len; | 1096 | dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter); |
| 1093 | dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | 1097 | const fixup = dbg_info.items.len; |
| 1098 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | ||
| 1094 | 1, // we will backpatch it after we encode the displacement in LEB128 | 1099 | 1, // we will backpatch it after we encode the displacement in LEB128 |
| 1095 | DW.OP.breg6, // .rbp TODO handle -fomit-frame-pointer | 1100 | DW.OP.breg6, // .rbp TODO handle -fomit-frame-pointer |
| 1096 | }); | 1101 | }); |
| 1097 | leb128.writeILEB128(dbg_out.dbg_info.writer(), disp) catch unreachable; | 1102 | leb128.writeILEB128(dbg_info.writer(), disp) catch unreachable; |
| 1098 | dbg_out.dbg_info.items[fixup] += @intCast(u8, dbg_out.dbg_info.items.len - fixup - 2); | 1103 | dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); |
| 1099 | try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | 1104 | try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); |
| 1100 | try emit.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 | 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 | .plan9 => {}, | 1109 | .plan9 => {}, |
| ... | @@ -1113,21 +1118,17 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32 | ... | @@ -1113,21 +1118,17 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32 |
| 1113 | /// after codegen for this symbol is done. | 1118 | /// after codegen for this symbol is done. |
| 1114 | fn addDbgInfoTypeReloc(emit: *Emit, ty: Type) !void { | 1119 | fn addDbgInfoTypeReloc(emit: *Emit, ty: Type) !void { |
| 1115 | switch (emit.debug_output) { | 1120 | switch (emit.debug_output) { |
| 1116 | .dwarf => |dbg_out| { | 1121 | .dwarf => |dw| { |
| 1117 | assert(ty.hasRuntimeBits()); | 1122 | assert(ty.hasRuntimeBits()); |
| 1118 | const index = dbg_out.dbg_info.items.len; | 1123 | const dbg_info = dw.getDeclDebugInfoBuffer(); |
| 1119 | try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 | 1124 | const index = dbg_info.items.len; |
| 1120 | 1125 | try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 | |
| 1121 | const gop = try dbg_out.dbg_info_type_relocs.getOrPutContext(emit.bin_file.allocator, ty, .{ | 1126 | const atom = switch (emit.bin_file.tag) { |
| 1122 | .target = emit.target.*, | 1127 | .elf => &emit.function.mod_fn.owner_decl.link.elf.dbg_info_atom, |
| 1123 | }); | 1128 | .macho => &emit.function.mod_fn.owner_decl.link.macho.dbg_info_atom, |
| 1124 | if (!gop.found_existing) { | 1129 | else => unreachable, |
| 1125 | gop.value_ptr.* = .{ | 1130 | }; |
| 1126 | .off = undefined, | 1131 | try dw.addTypeReloc(atom, ty, @intCast(u32, index), null); |
| 1127 | .relocs = .{}, | ||
| 1128 | }; | ||
| 1129 | } | ||
| 1130 | try gop.value_ptr.relocs.append(emit.bin_file.allocator, @intCast(u32, index)); | ||
| 1131 | }, | 1132 | }, |
| 1132 | .plan9 => {}, | 1133 | .plan9 => {}, |
| 1133 | .none => {}, | 1134 | .none => {}, |
src/codegen.zig+1-5| ... | @@ -42,11 +42,7 @@ pub const GenerateSymbolError = error{ | ... | @@ -42,11 +42,7 @@ pub const GenerateSymbolError = error{ |
| 42 | }; | 42 | }; |
| 43 | 43 | ||
| 44 | pub const DebugInfoOutput = union(enum) { | 44 | pub const DebugInfoOutput = union(enum) { |
| 45 | dwarf: struct { | 45 | dwarf: *link.File.Dwarf, |
| 46 | dbg_line: *std.ArrayList(u8), | ||
| 47 | dbg_info: *std.ArrayList(u8), | ||
| 48 | dbg_info_type_relocs: *link.File.Dwarf.DbgInfoTypeRelocsTable, | ||
| 49 | }, | ||
| 50 | /// the plan9 debuginfo output is a bytecode with 4 opcodes | 46 | /// the plan9 debuginfo output is a bytecode with 4 opcodes |
| 51 | /// assume all numbers/variables are bytes | 47 | /// assume all numbers/variables are bytes |
| 52 | /// 0 w x y z -> interpret w x y z as a big-endian i32, and add it to the line offset | 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,16 +39,22 @@ atom_last: ?*Atom = null, |
| 39 | 39 | ||
| 40 | abbrev_table_offset: ?u64 = null, | 40 | abbrev_table_offset: ?u64 = null, |
| 41 | 41 | ||
| 42 | /// TODO replace with InternArena | ||
| 42 | /// Table of debug symbol names. | 43 | /// Table of debug symbol names. |
| 43 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 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 | /// List of atoms that are owned directly by the DWARF module. | 51 | /// List of atoms that are owned directly by the DWARF module. |
| 48 | /// TODO convert links in DebugInfoAtom into indices and make | 52 | /// TODO convert links in DebugInfoAtom into indices and make |
| 49 | /// sure every atom is owned by this module. | 53 | /// sure every atom is owned by this module. |
| 50 | managed_atoms: std.ArrayListUnmanaged(*Atom) = .{}, | 54 | managed_atoms: std.ArrayListUnmanaged(*Atom) = .{}, |
| 51 | 55 | ||
| 56 | global_abbrev_relocs: std.ArrayListUnmanaged(AbbrevRelocation) = .{}, | ||
| 57 | |||
| 52 | pub const Atom = struct { | 58 | pub const Atom = struct { |
| 53 | /// Previous/next linked list pointers. | 59 | /// Previous/next linked list pointers. |
| 54 | /// This is the linked list node for this Decl's corresponding .debug_info tag. | 60 | /// This is the linked list node for this Decl's corresponding .debug_info tag. |
| ... | @@ -60,6 +66,54 @@ pub const Atom = struct { | ... | @@ -60,6 +66,54 @@ pub const Atom = struct { |
| 60 | len: u32, | 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 | pub const SrcFn = struct { | 117 | pub const SrcFn = struct { |
| 64 | /// Offset from the beginning of the Debug Line Program header that contains this function. | 118 | /// Offset from the beginning of the Debug Line Program header that contains this function. |
| 65 | off: u32, | 119 | off: u32, |
| ... | @@ -82,22 +136,6 @@ pub const SrcFn = struct { | ... | @@ -82,22 +136,6 @@ pub const SrcFn = struct { |
| 82 | 136 | ||
| 83 | pub const PtrWidth = enum { p32, p64 }; | 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 | pub const abbrev_compile_unit = 1; | 139 | pub const abbrev_compile_unit = 1; |
| 102 | pub const abbrev_subprogram = 2; | 140 | pub const abbrev_subprogram = 2; |
| 103 | pub const abbrev_subprogram_retvoid = 3; | 141 | pub const abbrev_subprogram_retvoid = 3; |
| ... | @@ -143,7 +181,7 @@ pub fn deinit(self: *Dwarf) void { | ... | @@ -143,7 +181,7 @@ pub fn deinit(self: *Dwarf) void { |
| 143 | self.dbg_line_fn_free_list.deinit(gpa); | 181 | self.dbg_line_fn_free_list.deinit(gpa); |
| 144 | self.atom_free_list.deinit(gpa); | 182 | self.atom_free_list.deinit(gpa); |
| 145 | self.strtab.deinit(gpa); | 183 | self.strtab.deinit(gpa); |
| 146 | self.deferred_error_sets_relocs.deinit(gpa); | 184 | self.global_abbrev_relocs.deinit(gpa); |
| 147 | 185 | ||
| 148 | for (self.managed_atoms.items) |atom| { | 186 | for (self.managed_atoms.items) |atom| { |
| 149 | gpa.destroy(atom); | 187 | gpa.destroy(atom); |
| ... | @@ -151,25 +189,22 @@ pub fn deinit(self: *Dwarf) void { | ... | @@ -151,25 +189,22 @@ pub fn deinit(self: *Dwarf) void { |
| 151 | self.managed_atoms.deinit(gpa); | 189 | self.managed_atoms.deinit(gpa); |
| 152 | } | 190 | } |
| 153 | 191 | ||
| 154 | pub const DeclDebugBuffers = struct { | 192 | /// Initializes Decl's state and its matching output buffers. |
| 155 | dbg_line_buffer: std.ArrayList(u8), | 193 | /// Call this before `commitDeclState`. |
| 156 | dbg_info_buffer: std.ArrayList(u8), | 194 | pub fn initDeclState(self: *Dwarf, decl: *Module.Decl) !void { |
| 157 | dbg_info_type_relocs: DbgInfoTypeRelocsTable, | ||
| 158 | }; | ||
| 159 | |||
| 160 | pub fn initDeclDebugInfo(self: *Dwarf, decl: *Module.Decl) !DeclDebugBuffers { | ||
| 161 | const tracy = trace(@src()); | 195 | const tracy = trace(@src()); |
| 162 | defer tracy.end(); | 196 | defer tracy.end(); |
| 163 | 197 | ||
| 164 | const decl_name = try decl.getFullyQualifiedName(self.allocator); | 198 | const decl_name = try decl.getFullyQualifiedName(self.allocator); |
| 165 | defer self.allocator.free(decl_name); | 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 | const gpa = self.allocator; | 203 | const gpa = self.allocator; |
| 170 | var dbg_line_buffer = std.ArrayList(u8).init(gpa); | 204 | assert(self.decl_state == null); |
| 171 | var dbg_info_buffer = std.ArrayList(u8).init(gpa); | 205 | self.decl_state = DeclState.init(gpa); |
| 172 | var dbg_info_type_relocs: DbgInfoTypeRelocsTable = .{}; | 206 | const dbg_line_buffer = &self.decl_state.?.dbg_line; |
| 207 | const dbg_info_buffer = &self.decl_state.?.dbg_info; | ||
| 173 | 208 | ||
| 174 | assert(decl.has_tv); | 209 | assert(decl.has_tv); |
| 175 | 210 | ||
| ... | @@ -232,19 +267,17 @@ pub fn initDeclDebugInfo(self: *Dwarf, decl: *Module.Decl) !DeclDebugBuffers { | ... | @@ -232,19 +267,17 @@ pub fn initDeclDebugInfo(self: *Dwarf, decl: *Module.Decl) !DeclDebugBuffers { |
| 232 | dbg_info_buffer.items.len += ptr_width_bytes; // DW.AT.low_pc, DW.FORM.addr | 267 | dbg_info_buffer.items.len += ptr_width_bytes; // DW.AT.low_pc, DW.FORM.addr |
| 233 | assert(self.getRelocDbgInfoSubprogramHighPC() == dbg_info_buffer.items.len); | 268 | assert(self.getRelocDbgInfoSubprogramHighPC() == dbg_info_buffer.items.len); |
| 234 | dbg_info_buffer.items.len += 4; // DW.AT.high_pc, DW.FORM.data4 | 269 | dbg_info_buffer.items.len += 4; // DW.AT.high_pc, DW.FORM.data4 |
| 270 | // | ||
| 235 | if (fn_ret_has_bits) { | 271 | if (fn_ret_has_bits) { |
| 236 | const gop = try dbg_info_type_relocs.getOrPutContext(gpa, fn_ret_type, .{ | 272 | const atom = switch (self.tag) { |
| 237 | .target = self.target, | 273 | .elf => &decl.link.elf.dbg_info_atom, |
| 238 | }); | 274 | .macho => &decl.link.macho.dbg_info_atom, |
| 239 | if (!gop.found_existing) { | 275 | else => unreachable, |
| 240 | gop.value_ptr.* = .{ | 276 | }; |
| 241 | .off = undefined, | 277 | try self.addTypeReloc(atom, fn_ret_type, @intCast(u32, dbg_info_buffer.items.len), null); |
| 242 | .relocs = .{}, | ||
| 243 | }; | ||
| 244 | } | ||
| 245 | try gop.value_ptr.relocs.append(gpa, @intCast(u32, dbg_info_buffer.items.len)); | ||
| 246 | dbg_info_buffer.items.len += 4; // DW.AT.type, DW.FORM.ref4 | 278 | dbg_info_buffer.items.len += 4; // DW.AT.type, DW.FORM.ref4 |
| 247 | } | 279 | } |
| 280 | |||
| 248 | dbg_info_buffer.appendSliceAssumeCapacity(decl_name_with_null); // DW.AT.name, DW.FORM.string | 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,30 +285,28 @@ pub fn initDeclDebugInfo(self: *Dwarf, decl: *Module.Decl) !DeclDebugBuffers { |
| 252 | // TODO implement .debug_info for global variables | 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 | self: *Dwarf, | 291 | self: *Dwarf, |
| 265 | file: *File, | 292 | file: *File, |
| 266 | module: *Module, | 293 | module: *Module, |
| 267 | decl: *Module.Decl, | 294 | decl: *Module.Decl, |
| 268 | sym_addr: u64, | 295 | sym_addr: u64, |
| 269 | sym_size: u64, | 296 | sym_size: u64, |
| 270 | debug_buffers: *DeclDebugBuffers, | ||
| 271 | ) !void { | 297 | ) !void { |
| 272 | const tracy = trace(@src()); | 298 | const tracy = trace(@src()); |
| 273 | defer tracy.end(); | 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 | const gpa = self.allocator; | 307 | const gpa = self.allocator; |
| 276 | var dbg_line_buffer = &debug_buffers.dbg_line_buffer; | 308 | var dbg_line_buffer = &self.decl_state.?.dbg_line; |
| 277 | var dbg_info_buffer = &debug_buffers.dbg_info_buffer; | 309 | var dbg_info_buffer = &self.decl_state.?.dbg_info; |
| 278 | var dbg_info_type_relocs = &debug_buffers.dbg_info_type_relocs; | ||
| 279 | 310 | ||
| 280 | const target_endian = self.target.cpu.arch.endian(); | 311 | const target_endian = self.target.cpu.arch.endian(); |
| 281 | 312 | ||
| ... | @@ -473,25 +504,21 @@ pub fn commitDeclDebugInfo( | ... | @@ -473,25 +504,21 @@ pub fn commitDeclDebugInfo( |
| 473 | if (dbg_info_buffer.items.len == 0) | 504 | if (dbg_info_buffer.items.len == 0) |
| 474 | return; | 505 | return; |
| 475 | 506 | ||
| 476 | // We need this for the duration of this function only so that for composite | 507 | const atom = switch (self.tag) { |
| 477 | // types such as []const u32, if the type *u32 is non-existent, we create | 508 | .elf => &decl.link.elf.dbg_info_atom, |
| 478 | // it synthetically and store the backing bytes in this arena. After we are | 509 | .macho => &decl.link.macho.dbg_info_atom, |
| 479 | // done with the relocations, we can safely deinit the entire memory slab. | 510 | else => unreachable, |
| 480 | // TODO currently, we do not store the relocations for future use, however, | 511 | }; |
| 481 | // if that is the case, we should move memory management to a higher scope, | 512 | const decl_state = &self.decl_state.?; |
| 482 | // such as linker scope, or whatnot. | 513 | |
| 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(); | ||
| 488 | { | 514 | { |
| 489 | // Now we emit the .debug_info types of the Decl. These will count towards the size of | 515 | // Now we emit the .debug_info types of the Decl. These will count towards the size of |
| 490 | // the buffer, so we have to do it before computing the offset, and we can't perform the actual | 516 | // the buffer, so we have to do it before computing the offset, and we can't perform the actual |
| 491 | // relocations yet. | 517 | // relocations yet. |
| 492 | var it: usize = 0; | 518 | var sym_index: usize = 0; |
| 493 | while (it < dbg_info_type_relocs.count()) : (it += 1) { | 519 | while (sym_index < decl_state.abbrev_table.items.len) : (sym_index += 1) { |
| 494 | const ty = dbg_info_type_relocs.keys()[it]; | 520 | const symbol = &decl_state.abbrev_table.items[sym_index]; |
| 521 | const ty = symbol.@"type"; | ||
| 495 | const deferred: bool = blk: { | 522 | const deferred: bool = blk: { |
| 496 | if (ty.isAnyError()) break :blk true; | 523 | if (ty.isAnyError()) break :blk true; |
| 497 | switch (ty.tag()) { | 524 | switch (ty.tag()) { |
| ... | @@ -504,68 +531,38 @@ pub fn commitDeclDebugInfo( | ... | @@ -504,68 +531,38 @@ pub fn commitDeclDebugInfo( |
| 504 | }; | 531 | }; |
| 505 | if (deferred) continue; | 532 | if (deferred) continue; |
| 506 | 533 | ||
| 507 | const value_ptr = dbg_info_type_relocs.getPtrContext(ty, .{ | 534 | symbol.offset = @intCast(u32, dbg_info_buffer.items.len); |
| 508 | .target = self.target, | 535 | try self.addDbgInfoType(decl_state.abbrev_type_arena.allocator(), module, atom, ty, dbg_info_buffer); |
| 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 | ); | ||
| 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 | try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len)); | 539 | try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len)); |
| 528 | 540 | ||
| 529 | { | 541 | while (decl_state.abbrev_relocs.popOrNull()) |reloc| { |
| 530 | // Now that we have the offset assigned we can finally perform type relocations. | 542 | const symbol = decl_state.abbrev_table.items[reloc.target]; |
| 531 | for (dbg_info_type_relocs.keys()) |ty| { | 543 | const ty = symbol.@"type"; |
| 532 | const value = dbg_info_type_relocs.getContext(ty, .{ | 544 | const deferred: bool = blk: { |
| 533 | .target = self.target, | 545 | if (ty.isAnyError()) break :blk true; |
| 534 | }).?; | 546 | switch (ty.tag()) { |
| 535 | for (value.relocs.items) |off| { | 547 | .error_set_inferred => { |
| 536 | const deferred: bool = blk: { | 548 | if (!ty.castTag(.error_set_inferred).?.data.is_resolved) break :blk true; |
| 537 | if (ty.isAnyError()) break :blk true; | 549 | }, |
| 538 | switch (ty.tag()) { | 550 | else => {}, |
| 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 | } | ||
| 557 | } | 551 | } |
| 558 | } | 552 | break :blk false; |
| 559 | // Offsets to positions with known a priori relative displacement values. | 553 | }; |
| 560 | // Here, we just need to add the offset of the atom to the read value in the | 554 | if (deferred) { |
| 561 | // relocated cell. | 555 | try self.global_abbrev_relocs.append(gpa, .{ |
| 562 | // TODO Should probably generalise this with type relocs. | 556 | .target = undefined, |
| 563 | for (nested_ref4_relocs.items) |off| { | 557 | .offset = reloc.offset, |
| 564 | const addend = mem.readInt(u32, dbg_info_buffer.items[off..][0..4], target_endian); | 558 | .atom = reloc.atom, |
| 559 | .addend = reloc.addend, | ||
| 560 | }); | ||
| 561 | } else { | ||
| 565 | mem.writeInt( | 562 | mem.writeInt( |
| 566 | u32, | 563 | u32, |
| 567 | dbg_info_buffer.items[off..][0..4], | 564 | dbg_info_buffer.items[reloc.offset..][0..@sizeOf(u32)], |
| 568 | atom.off + addend, | 565 | symbol.atom.off + symbol.offset + reloc.addend, |
| 569 | target_endian, | 566 | target_endian, |
| 570 | ); | 567 | ); |
| 571 | } | 568 | } |
| ... | @@ -574,77 +571,6 @@ pub fn commitDeclDebugInfo( | ... | @@ -574,77 +571,6 @@ pub fn commitDeclDebugInfo( |
| 574 | try self.writeDeclDebugInfo(file, atom, dbg_info_buffer.items); | 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 | fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u32) !void { | 574 | fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u32) !void { |
| 649 | const tracy = trace(@src()); | 575 | const tracy = trace(@src()); |
| 650 | defer tracy.end(); | 576 | defer tracy.end(); |
| ... | @@ -904,14 +830,12 @@ fn addDbgInfoType( | ... | @@ -904,14 +830,12 @@ fn addDbgInfoType( |
| 904 | self: *Dwarf, | 830 | self: *Dwarf, |
| 905 | arena: Allocator, | 831 | arena: Allocator, |
| 906 | module: *Module, | 832 | module: *Module, |
| 833 | atom: *Atom, | ||
| 907 | ty: Type, | 834 | ty: Type, |
| 908 | dbg_info_buffer: *std.ArrayList(u8), | 835 | dbg_info_buffer: *std.ArrayList(u8), |
| 909 | dbg_info_type_relocs: *DbgInfoTypeRelocsTable, | ||
| 910 | nested_ref4_relocs: *std.ArrayList(u32), | ||
| 911 | ) error{OutOfMemory}!void { | 836 | ) error{OutOfMemory}!void { |
| 912 | const target = self.target; | 837 | const target = self.target; |
| 913 | const target_endian = self.target.cpu.arch.endian(); | 838 | const target_endian = self.target.cpu.arch.endian(); |
| 914 | var relocs = std.ArrayList(struct { ty: Type, reloc: u32 }).init(arena); | ||
| 915 | 839 | ||
| 916 | switch (ty.zigTypeTag()) { | 840 | switch (ty.zigTypeTag()) { |
| 917 | .NoReturn => unreachable, | 841 | .NoReturn => unreachable, |
| ... | @@ -970,7 +894,7 @@ fn addDbgInfoType( | ... | @@ -970,7 +894,7 @@ fn addDbgInfoType( |
| 970 | // DW.AT.type, DW.FORM.ref4 | 894 | // DW.AT.type, DW.FORM.ref4 |
| 971 | var index = dbg_info_buffer.items.len; | 895 | var index = dbg_info_buffer.items.len; |
| 972 | try dbg_info_buffer.resize(index + 4); | 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 | // DW.AT.data_member_location, DW.FORM.sdata | 898 | // DW.AT.data_member_location, DW.FORM.sdata |
| 975 | try dbg_info_buffer.ensureUnusedCapacity(6); | 899 | try dbg_info_buffer.ensureUnusedCapacity(6); |
| 976 | dbg_info_buffer.appendAssumeCapacity(0); | 900 | dbg_info_buffer.appendAssumeCapacity(0); |
| ... | @@ -982,7 +906,7 @@ fn addDbgInfoType( | ... | @@ -982,7 +906,7 @@ fn addDbgInfoType( |
| 982 | // DW.AT.type, DW.FORM.ref4 | 906 | // DW.AT.type, DW.FORM.ref4 |
| 983 | index = dbg_info_buffer.items.len; | 907 | index = dbg_info_buffer.items.len; |
| 984 | try dbg_info_buffer.resize(index + 4); | 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 | // DW.AT.data_member_location, DW.FORM.sdata | 910 | // DW.AT.data_member_location, DW.FORM.sdata |
| 987 | const offset = abi_size - payload_ty.abiSize(target); | 911 | const offset = abi_size - payload_ty.abiSize(target); |
| 988 | try leb128.writeULEB128(dbg_info_buffer.writer(), offset); | 912 | try leb128.writeULEB128(dbg_info_buffer.writer(), offset); |
| ... | @@ -1011,7 +935,7 @@ fn addDbgInfoType( | ... | @@ -1011,7 +935,7 @@ fn addDbgInfoType( |
| 1011 | try dbg_info_buffer.resize(index + 4); | 935 | try dbg_info_buffer.resize(index + 4); |
| 1012 | var buf = try arena.create(Type.SlicePtrFieldTypeBuffer); | 936 | var buf = try arena.create(Type.SlicePtrFieldTypeBuffer); |
| 1013 | const ptr_ty = ty.slicePtrFieldType(buf); | 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 | // DW.AT.data_member_location, DW.FORM.sdata | 939 | // DW.AT.data_member_location, DW.FORM.sdata |
| 1016 | try dbg_info_buffer.ensureUnusedCapacity(6); | 940 | try dbg_info_buffer.ensureUnusedCapacity(6); |
| 1017 | dbg_info_buffer.appendAssumeCapacity(0); | 941 | dbg_info_buffer.appendAssumeCapacity(0); |
| ... | @@ -1023,7 +947,7 @@ fn addDbgInfoType( | ... | @@ -1023,7 +947,7 @@ fn addDbgInfoType( |
| 1023 | // DW.AT.type, DW.FORM.ref4 | 947 | // DW.AT.type, DW.FORM.ref4 |
| 1024 | index = dbg_info_buffer.items.len; | 948 | index = dbg_info_buffer.items.len; |
| 1025 | try dbg_info_buffer.resize(index + 4); | 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 | // DW.AT.data_member_location, DW.FORM.sdata | 951 | // DW.AT.data_member_location, DW.FORM.sdata |
| 1028 | try dbg_info_buffer.ensureUnusedCapacity(2); | 952 | try dbg_info_buffer.ensureUnusedCapacity(2); |
| 1029 | dbg_info_buffer.appendAssumeCapacity(@sizeOf(usize)); | 953 | dbg_info_buffer.appendAssumeCapacity(@sizeOf(usize)); |
| ... | @@ -1035,7 +959,7 @@ fn addDbgInfoType( | ... | @@ -1035,7 +959,7 @@ fn addDbgInfoType( |
| 1035 | // DW.AT.type, DW.FORM.ref4 | 959 | // DW.AT.type, DW.FORM.ref4 |
| 1036 | const index = dbg_info_buffer.items.len; | 960 | const index = dbg_info_buffer.items.len; |
| 1037 | try dbg_info_buffer.resize(index + 4); | 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 | .Struct => blk: { | 965 | .Struct => blk: { |
| ... | @@ -1059,7 +983,7 @@ fn addDbgInfoType( | ... | @@ -1059,7 +983,7 @@ fn addDbgInfoType( |
| 1059 | // DW.AT.type, DW.FORM.ref4 | 983 | // DW.AT.type, DW.FORM.ref4 |
| 1060 | var index = dbg_info_buffer.items.len; | 984 | var index = dbg_info_buffer.items.len; |
| 1061 | try dbg_info_buffer.resize(index + 4); | 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 | // DW.AT.data_member_location, DW.FORM.sdata | 987 | // DW.AT.data_member_location, DW.FORM.sdata |
| 1064 | const field_off = ty.structFieldOffset(field_index, target); | 988 | const field_off = ty.structFieldOffset(field_index, target); |
| 1065 | try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); | 989 | try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); |
| ... | @@ -1090,7 +1014,7 @@ fn addDbgInfoType( | ... | @@ -1090,7 +1014,7 @@ fn addDbgInfoType( |
| 1090 | // DW.AT.type, DW.FORM.ref4 | 1014 | // DW.AT.type, DW.FORM.ref4 |
| 1091 | var index = dbg_info_buffer.items.len; | 1015 | var index = dbg_info_buffer.items.len; |
| 1092 | try dbg_info_buffer.resize(index + 4); | 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 | // DW.AT.data_member_location, DW.FORM.sdata | 1018 | // DW.AT.data_member_location, DW.FORM.sdata |
| 1095 | const field_off = ty.structFieldOffset(field_index, target); | 1019 | const field_off = ty.structFieldOffset(field_index, target); |
| 1096 | try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); | 1020 | try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); |
| ... | @@ -1169,14 +1093,8 @@ fn addDbgInfoType( | ... | @@ -1169,14 +1093,8 @@ fn addDbgInfoType( |
| 1169 | dbg_info_buffer.appendAssumeCapacity(0); | 1093 | dbg_info_buffer.appendAssumeCapacity(0); |
| 1170 | // DW.AT.type, DW.FORM.ref4 | 1094 | // DW.AT.type, DW.FORM.ref4 |
| 1171 | const inner_union_index = dbg_info_buffer.items.len; | 1095 | const inner_union_index = dbg_info_buffer.items.len; |
| 1172 | try dbg_info_buffer.ensureUnusedCapacity(4); | 1096 | try dbg_info_buffer.resize(inner_union_index + 4); |
| 1173 | mem.writeInt( | 1097 | try self.addTypeReloc(atom, ty, @intCast(u32, inner_union_index), 5); |
| 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)); | ||
| 1180 | // DW.AT.data_member_location, DW.FORM.sdata | 1098 | // DW.AT.data_member_location, DW.FORM.sdata |
| 1181 | try leb128.writeULEB128(dbg_info_buffer.writer(), payload_offset); | 1099 | try leb128.writeULEB128(dbg_info_buffer.writer(), payload_offset); |
| 1182 | } | 1100 | } |
| ... | @@ -1203,7 +1121,7 @@ fn addDbgInfoType( | ... | @@ -1203,7 +1121,7 @@ fn addDbgInfoType( |
| 1203 | // DW.AT.type, DW.FORM.ref4 | 1121 | // DW.AT.type, DW.FORM.ref4 |
| 1204 | const index = dbg_info_buffer.items.len; | 1122 | const index = dbg_info_buffer.items.len; |
| 1205 | try dbg_info_buffer.resize(index + 4); | 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 | // DW.AT.data_member_location, DW.FORM.sdata | 1125 | // DW.AT.data_member_location, DW.FORM.sdata |
| 1208 | try dbg_info_buffer.append(0); | 1126 | try dbg_info_buffer.append(0); |
| 1209 | } | 1127 | } |
| ... | @@ -1220,7 +1138,7 @@ fn addDbgInfoType( | ... | @@ -1220,7 +1138,7 @@ fn addDbgInfoType( |
| 1220 | // DW.AT.type, DW.FORM.ref4 | 1138 | // DW.AT.type, DW.FORM.ref4 |
| 1221 | const index = dbg_info_buffer.items.len; | 1139 | const index = dbg_info_buffer.items.len; |
| 1222 | try dbg_info_buffer.resize(index + 4); | 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 | // DW.AT.data_member_location, DW.FORM.sdata | 1142 | // DW.AT.data_member_location, DW.FORM.sdata |
| 1225 | try leb128.writeULEB128(dbg_info_buffer.writer(), tag_offset); | 1143 | try leb128.writeULEB128(dbg_info_buffer.writer(), tag_offset); |
| 1226 | 1144 | ||
| ... | @@ -1229,7 +1147,40 @@ fn addDbgInfoType( | ... | @@ -1229,7 +1147,40 @@ fn addDbgInfoType( |
| 1229 | } | 1147 | } |
| 1230 | }, | 1148 | }, |
| 1231 | .ErrorSet => { | 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 | .ErrorUnion => { | 1185 | .ErrorUnion => { |
| 1235 | const error_ty = ty.errorUnionSet(); | 1186 | const error_ty = ty.errorUnionSet(); |
| ... | @@ -1255,7 +1206,7 @@ fn addDbgInfoType( | ... | @@ -1255,7 +1206,7 @@ fn addDbgInfoType( |
| 1255 | // DW.AT.type, DW.FORM.ref4 | 1206 | // DW.AT.type, DW.FORM.ref4 |
| 1256 | var index = dbg_info_buffer.items.len; | 1207 | var index = dbg_info_buffer.items.len; |
| 1257 | try dbg_info_buffer.resize(index + 4); | 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 | // DW.AT.data_member_location, DW.FORM.sdata | 1210 | // DW.AT.data_member_location, DW.FORM.sdata |
| 1260 | try leb128.writeULEB128(dbg_info_buffer.writer(), payload_off); | 1211 | try leb128.writeULEB128(dbg_info_buffer.writer(), payload_off); |
| 1261 | 1212 | ||
| ... | @@ -1268,7 +1219,7 @@ fn addDbgInfoType( | ... | @@ -1268,7 +1219,7 @@ fn addDbgInfoType( |
| 1268 | // DW.AT.type, DW.FORM.ref4 | 1219 | // DW.AT.type, DW.FORM.ref4 |
| 1269 | index = dbg_info_buffer.items.len; | 1220 | index = dbg_info_buffer.items.len; |
| 1270 | try dbg_info_buffer.resize(index + 4); | 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 | // DW.AT.data_member_location, DW.FORM.sdata | 1223 | // DW.AT.data_member_location, DW.FORM.sdata |
| 1273 | try dbg_info_buffer.append(0); | 1224 | try dbg_info_buffer.append(0); |
| 1274 | 1225 | ||
| ... | @@ -1280,65 +1231,6 @@ fn addDbgInfoType( | ... | @@ -1280,65 +1231,6 @@ fn addDbgInfoType( |
| 1280 | try dbg_info_buffer.append(abbrev_pad1); | 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 | pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void { | 1236 | pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void { |
| ... | @@ -2059,3 +1951,115 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { | ... | @@ -2059,3 +1951,115 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { |
| 2059 | return std.math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch | 1951 | return std.math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch |
| 2060 | std.math.maxInt(@TypeOf(actual_size)); | 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,8 +958,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { |
| 958 | const target_endian = self.base.options.target.cpu.arch.endian(); | 958 | const target_endian = self.base.options.target.cpu.arch.endian(); |
| 959 | const foreign_endian = target_endian != builtin.cpu.arch.endian(); | 959 | const foreign_endian = target_endian != builtin.cpu.arch.endian(); |
| 960 | 960 | ||
| 961 | if (self.dwarf) |*dwarf| { | 961 | if (self.dwarf) |*dw| { |
| 962 | try dwarf.commitErrorSetDebugInfo(&self.base, module); | 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,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 | fn getDeclPhdrIndex(self: *Elf, decl: *Module.Decl) !u16 { | 2235 | fn getDeclPhdrIndex(self: *Elf, decl: *Module.Decl) !u16 { |
| 2243 | const ty = decl.ty; | 2236 | const ty = decl.ty; |
| 2244 | const zig_ty = ty.zigTypeTag(); | 2237 | const zig_ty = ty.zigTypeTag(); |
| ... | @@ -2346,26 +2339,13 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven | ... | @@ -2346,26 +2339,13 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven |
| 2346 | const decl = func.owner_decl; | 2339 | const decl = func.owner_decl; |
| 2347 | self.freeUnnamedConsts(decl); | 2340 | self.freeUnnamedConsts(decl); |
| 2348 | 2341 | ||
| 2349 | var debug_buffers_buf: Dwarf.DeclDebugBuffers = undefined; | 2342 | if (self.dwarf) |*dw| { |
| 2350 | const debug_buffers = if (self.dwarf) |*dw| blk: { | 2343 | try dw.initDeclState(decl); |
| 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 | } | ||
| 2360 | } | 2344 | } |
| 2361 | 2345 | ||
| 2362 | const res = if (debug_buffers) |dbg| | 2346 | const res = if (self.dwarf) |*dw| |
| 2363 | try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{ | 2347 | try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{ |
| 2364 | .dwarf = .{ | 2348 | .dwarf = dw, |
| 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 | }, | ||
| 2369 | }) | 2349 | }) |
| 2370 | else | 2350 | else |
| 2371 | try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none); | 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,15 +2359,8 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven |
| 2379 | }, | 2359 | }, |
| 2380 | }; | 2360 | }; |
| 2381 | const local_sym = try self.updateDeclCode(decl, code, elf.STT_FUNC); | 2361 | const local_sym = try self.updateDeclCode(decl, code, elf.STT_FUNC); |
| 2382 | if (debug_buffers) |dbg| { | 2362 | if (self.dwarf) |*dw| { |
| 2383 | try self.dwarf.?.commitDeclDebugInfo( | 2363 | try dw.commitDeclState(&self.base, module, decl, local_sym.st_value, local_sym.st_size); |
| 2384 | &self.base, | ||
| 2385 | module, | ||
| 2386 | decl, | ||
| 2387 | local_sym.st_value, | ||
| 2388 | local_sym.st_size, | ||
| 2389 | dbg, | ||
| 2390 | ); | ||
| 2391 | } | 2364 | } |
| 2392 | 2365 | ||
| 2393 | // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated. | 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,31 +2394,18 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { |
| 2421 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | 2394 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 2422 | defer code_buffer.deinit(); | 2395 | defer code_buffer.deinit(); |
| 2423 | 2396 | ||
| 2424 | var debug_buffers_buf: Dwarf.DeclDebugBuffers = undefined; | 2397 | if (self.dwarf) |*dw| { |
| 2425 | const debug_buffers = if (self.dwarf) |*dw| blk: { | 2398 | try dw.initDeclState(decl); |
| 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 | } | ||
| 2435 | } | 2399 | } |
| 2436 | 2400 | ||
| 2437 | // TODO implement .debug_info for global variables | 2401 | // TODO implement .debug_info for global variables |
| 2438 | const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val; | 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 | try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ | 2404 | try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ |
| 2441 | .ty = decl.ty, | 2405 | .ty = decl.ty, |
| 2442 | .val = decl_val, | 2406 | .val = decl_val, |
| 2443 | }, &code_buffer, .{ | 2407 | }, &code_buffer, .{ |
| 2444 | .dwarf = .{ | 2408 | .dwarf = dw, |
| 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 | }, | ||
| 2449 | }, .{ | 2409 | }, .{ |
| 2450 | .parent_atom_index = decl.link.elf.local_sym_index, | 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,8 +2428,8 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { |
| 2468 | }; | 2428 | }; |
| 2469 | 2429 | ||
| 2470 | const local_sym = try self.updateDeclCode(decl, code, elf.STT_OBJECT); | 2430 | const local_sym = try self.updateDeclCode(decl, code, elf.STT_OBJECT); |
| 2471 | if (debug_buffers) |dbg| { | 2431 | if (self.dwarf) |*dw| { |
| 2472 | try self.dwarf.?.commitDeclDebugInfo(&self.base, module, decl, local_sym.st_value, local_sym.st_size, dbg); | 2432 | try dw.commitDeclState(&self.base, module, decl, local_sym.st_value, local_sym.st_size); |
| 2473 | } | 2433 | } |
| 2474 | 2434 | ||
| 2475 | // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated. | 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,6 +453,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 453 | const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type. | 453 | const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type. |
| 454 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); | 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 | // If there is no Zig code to compile, then we should skip flushing the output file because it | 462 | // If there is no Zig code to compile, then we should skip flushing the output file because it |
| 457 | // will not be part of the linker line anyway. | 463 | // will not be part of the linker line anyway. |
| 458 | const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: { | 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,32 +3676,17 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv |
| 3670 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | 3676 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 3671 | defer code_buffer.deinit(); | 3677 | defer code_buffer.deinit(); |
| 3672 | 3678 | ||
| 3673 | var debug_buffers_buf: link.File.Dwarf.DeclDebugBuffers = undefined; | 3679 | if (self.d_sym) |*d_sym| { |
| 3674 | const debug_buffers = if (self.d_sym) |*d_sym| blk: { | 3680 | try d_sym.dwarf.initDeclState(decl); |
| 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 | } | ||
| 3687 | } | 3681 | } |
| 3688 | 3682 | ||
| 3689 | const res = if (debug_buffers) |dbg| | 3683 | const res = if (self.d_sym) |*d_sym| |
| 3690 | try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{ | 3684 | try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{ |
| 3691 | .dwarf = .{ | 3685 | .dwarf = &d_sym.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 | }, | ||
| 3696 | }) | 3686 | }) |
| 3697 | else | 3687 | else |
| 3698 | try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none); | 3688 | try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none); |
| 3689 | |||
| 3699 | switch (res) { | 3690 | switch (res) { |
| 3700 | .appended => { | 3691 | .appended => { |
| 3701 | try decl.link.macho.code.appendSlice(self.base.allocator, code_buffer.items); | 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,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| { | 3703 | if (self.d_sym) |*d_sym| { |
| 3713 | if (self.d_sym) |*d_sym| { | 3704 | try d_sym.dwarf.commitDeclState(&self.base, module, decl, symbol.n_value, decl.link.macho.size); |
| 3714 | try d_sym.commitDeclDebugInfo(module, decl, db); | ||
| 3715 | } | ||
| 3716 | } | 3705 | } |
| 3717 | 3706 | ||
| 3718 | // Since we updated the vaddr and the size, each corresponding export symbol also | 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,33 +3801,17 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 3812 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | 3801 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 3813 | defer code_buffer.deinit(); | 3802 | defer code_buffer.deinit(); |
| 3814 | 3803 | ||
| 3815 | var debug_buffers_buf: link.File.Dwarf.DeclDebugBuffers = undefined; | 3804 | if (self.d_sym) |*d_sym| { |
| 3816 | const debug_buffers = if (self.d_sym) |*d_sym| blk: { | 3805 | try d_sym.dwarf.initDeclState(decl); |
| 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 | } | ||
| 3829 | } | 3806 | } |
| 3830 | 3807 | ||
| 3831 | const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val; | 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 | try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ | 3810 | try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ |
| 3834 | .ty = decl.ty, | 3811 | .ty = decl.ty, |
| 3835 | .val = decl_val, | 3812 | .val = decl_val, |
| 3836 | }, &code_buffer, .{ | 3813 | }, &code_buffer, .{ |
| 3837 | .dwarf = .{ | 3814 | .dwarf = &d_sym.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 | }, | ||
| 3842 | }, .{ | 3815 | }, .{ |
| 3843 | .parent_atom_index = decl.link.macho.local_sym_index, | 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,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 | // Since we updated the vaddr and the size, each corresponding export symbol also | 3852 | // Since we updated the vaddr and the size, each corresponding export symbol also |
| 3876 | // needs to be updated. | 3853 | // needs to be updated. |
| ... | @@ -4084,8 +4061,9 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 | ... | @@ -4084,8 +4061,9 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 |
| 4084 | } | 4061 | } |
| 4085 | 4062 | ||
| 4086 | pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.Decl) !void { | 4063 | pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.Decl) !void { |
| 4064 | _ = module; | ||
| 4087 | if (self.d_sym) |*d_sym| { | 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,25 +645,3 @@ fn writeStringTable(self: *DebugSymbols) !void { |
| 645 | 645 | ||
| 646 | self.load_commands_dirty = true; | 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 | } |