[DWARF] Dump an updated location for DW_CFA_advance_loc* (#84274)

When dumping FDEs, `readelf` prints new location values after
`DW_CFA_advance_loc(*)` instructions, which looks quite convenient:

```
> readelf -wf test.o
...
... FDE ... pc=0000000000000030..0000000000000064
  DW_CFA_advance_loc: 4 to 0000000000000034
  ...
  DW_CFA_advance_loc: 4 to 0000000000000038
...
```

This patch makes `llvm-dwarfdump` and `llvm-readobj` do the same.
This commit is contained in:
Igor Kudrin 2024-03-07 16:34:36 -08:00 committed by GitHub
parent 0cd7942c7f
commit fe84764724
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 41 additions and 31 deletions

View File

@ -454,8 +454,8 @@ public:
/// where a problem occurred in case an error is returned.
Error parse(DWARFDataExtractor Data, uint64_t *Offset, uint64_t EndOffset);
void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
unsigned IndentLevel = 1) const;
void dump(raw_ostream &OS, DIDumpOptions DumpOpts, unsigned IndentLevel,
std::optional<uint64_t> InitialLocation) const;
void addInstruction(const Instruction &I) { Instructions.push_back(I); }
@ -524,7 +524,7 @@ private:
/// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
void printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
const Instruction &Instr, unsigned OperandIdx,
uint64_t Operand) const;
uint64_t Operand, std::optional<uint64_t> &Address) const;
};
/// An entry in either debug_frame or eh_frame. This entry can be a CIE or an

View File

@ -860,7 +860,8 @@ CFIProgram::getOperandTypes() {
/// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
const Instruction &Instr, unsigned OperandIdx,
uint64_t Operand) const {
uint64_t Operand,
std::optional<uint64_t> &Address) const {
assert(OperandIdx < MaxOperands);
uint8_t Opcode = Instr.Opcode;
OperandType Type = getOperandTypes()[Opcode][OperandIdx];
@ -879,6 +880,7 @@ void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
break;
case OT_Address:
OS << format(" %" PRIx64, Operand);
Address = Operand;
break;
case OT_Offset:
// The offsets are all encoded in a unsigned form, but in practice
@ -890,7 +892,11 @@ void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
if (CodeAlignmentFactor)
OS << format(" %" PRId64, Operand * CodeAlignmentFactor);
else
OS << format(" %" PRId64 "*code_alignment_factor" , Operand);
OS << format(" %" PRId64 "*code_alignment_factor", Operand);
if (Address && CodeAlignmentFactor) {
*Address += Operand * CodeAlignmentFactor;
OS << format(" to 0x%" PRIx64, *Address);
}
break;
case OT_SignedFactDataOffset:
if (DataAlignmentFactor)
@ -920,13 +926,14 @@ void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
}
void CFIProgram::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
unsigned IndentLevel) const {
unsigned IndentLevel,
std::optional<uint64_t> Address) const {
for (const auto &Instr : Instructions) {
uint8_t Opcode = Instr.Opcode;
OS.indent(2 * IndentLevel);
OS << callFrameString(Opcode) << ":";
for (unsigned i = 0; i < Instr.Ops.size(); ++i)
printOperand(OS, DumpOpts, Instr, i, Instr.Ops[i]);
printOperand(OS, DumpOpts, Instr, i, Instr.Ops[i], Address);
OS << '\n';
}
}
@ -977,7 +984,7 @@ void CIE::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
OS << "\n";
}
OS << "\n";
CFIs.dump(OS, DumpOpts);
CFIs.dump(OS, DumpOpts, /*IndentLevel=*/1, /*InitialLocation=*/{});
OS << "\n";
if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))
@ -1005,7 +1012,7 @@ void FDE::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
OS << " Format: " << FormatString(IsDWARF64) << "\n";
if (LSDAAddress)
OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress);
CFIs.dump(OS, DumpOpts);
CFIs.dump(OS, DumpOpts, /*IndentLevel=*/1, InitialLocation);
OS << "\n";
if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))

View File

@ -12,15 +12,15 @@
; FRAMES-NEXT: DW_CFA_nop:
; FRAMES: 00000014 00000010 00000000 FDE cie=00000000 pc=00000000...00000022
; FRAMES: DW_CFA_advance_loc: 3
; FRAMES: DW_CFA_advance_loc: 3 to 0x3
; FRAMES-NEXT: DW_CFA_def_cfa_offset: +12
; FRAMES-NEXT: DW_CFA_nop:
; FRAMES: 00000028 00000014 00000000 FDE cie=00000000 pc=00000030...00000080
; FRAMES: DW_CFA_advance_loc: 1
; FRAMES: DW_CFA_advance_loc: 1 to 0x31
; FRAMES-NEXT: DW_CFA_def_cfa_offset: +8
; FRAMES-NEXT: DW_CFA_offset: {{reg5|EBP}} -8
; FRAMES-NEXT: DW_CFA_advance_loc: 2
; FRAMES-NEXT: DW_CFA_advance_loc: 2 to 0x33
; FRAMES-NEXT: DW_CFA_def_cfa_register: {{reg5|EBP}}
; FRAMES-NOT: CIE

View File

@ -96,9 +96,9 @@
# CHECK: Program:
# CHECK-NEXT: DW_CFA_def_cfa_offset: +16
# CHECK-NEXT: DW_CFA_advance_loc: 6
# CHECK-NEXT: DW_CFA_advance_loc: 6 to 0x4004a6
# CHECK-NEXT: DW_CFA_def_cfa_offset: +24
# CHECK-NEXT: DW_CFA_advance_loc: 10
# CHECK-NEXT: DW_CFA_advance_loc: 10 to 0x4004b0
# CHECK-NEXT: DW_CFA_def_cfa_expression: DW_OP_breg7 +8, DW_OP_breg16 +0, DW_OP_lit15, DW_OP_and, DW_OP_lit11, DW_OP_ge, DW_OP_lit3, DW_OP_shl, DW_OP_plus
# CHECK-NEXT: DW_CFA_nop:
# CHECK-NEXT: DW_CFA_nop:
@ -110,12 +110,12 @@
# CHECK-NEXT: address_range: 0x10 (end : 0x4005c6)
# CHECK: Program:
# CHECK-NEXT: DW_CFA_advance_loc: 1
# CHECK-NEXT: DW_CFA_advance_loc: 1 to 0x4005b7
# CHECK-NEXT: DW_CFA_def_cfa_offset: +16
# CHECK-NEXT: DW_CFA_offset: reg6 -16
# CHECK-NEXT: DW_CFA_advance_loc: 3
# CHECK-NEXT: DW_CFA_advance_loc: 3 to 0x4005ba
# CHECK-NEXT: DW_CFA_def_cfa_register: reg6
# CHECK-NEXT: DW_CFA_advance_loc: 11
# CHECK-NEXT: DW_CFA_advance_loc: 11 to 0x4005c5
# CHECK-NEXT: DW_CFA_def_cfa: reg7 +8
# CHECK-NEXT: DW_CFA_nop:
# CHECK-NEXT: DW_CFA_nop:
@ -126,15 +126,15 @@
# CHECK-NEXT: address_range: 0xc7f (end : 0x40124f)
# CHECK: Program:
# CHECK-NEXT: DW_CFA_advance_loc: 5
# CHECK-NEXT: DW_CFA_advance_loc: 5 to 0x4005d5
# CHECK-NEXT: DW_CFA_def_cfa: reg10 +0
# CHECK-NEXT: DW_CFA_advance_loc: 9
# CHECK-NEXT: DW_CFA_advance_loc: 9 to 0x4005de
# CHECK-NEXT: DW_CFA_expression: reg6 DW_OP_breg6 +0
# CHECK-NEXT: DW_CFA_advance_loc: 5
# CHECK-NEXT: DW_CFA_advance_loc: 5 to 0x4005e3
# CHECK-NEXT: DW_CFA_def_cfa_expression: DW_OP_breg6 -8, DW_OP_deref
# CHECK-NEXT: DW_CFA_advance_loc2: 3174
# CHECK-NEXT: DW_CFA_advance_loc2: 3174 to 0x401249
# CHECK-NEXT: DW_CFA_def_cfa: reg10 +0
# CHECK-NEXT: DW_CFA_advance_loc: 5
# CHECK-NEXT: DW_CFA_advance_loc: 5 to 0x40124e
# CHECK-NEXT: DW_CFA_def_cfa: reg7 +8
# CHECK-NEXT: DW_CFA_nop:
# CHECK-NEXT: DW_CFA_nop:
@ -146,21 +146,21 @@
# CHECK-NEXT: address_range: 0x66 (end : 0x4012b6)
# CHECK: Program:
# CHECK-NEXT: DW_CFA_advance_loc: 1
# CHECK-NEXT: DW_CFA_advance_loc: 1 to 0x401251
# CHECK-NEXT: DW_CFA_def_cfa_offset: +16
# CHECK-NEXT: DW_CFA_offset: reg6 -16
# CHECK-NEXT: DW_CFA_advance_loc: 3
# CHECK-NEXT: DW_CFA_advance_loc: 3 to 0x401254
# CHECK-NEXT: DW_CFA_def_cfa_register: reg6
# CHECK-NEXT: DW_CFA_advance_loc: 2
# CHECK-NEXT: DW_CFA_advance_loc: 2 to 0x401256
# CHECK-NEXT: DW_CFA_offset: reg15 -24
# CHECK-NEXT: DW_CFA_advance_loc: 5
# CHECK-NEXT: DW_CFA_advance_loc: 5 to 0x40125b
# CHECK-NEXT: DW_CFA_offset: reg14 -32
# CHECK-NEXT: DW_CFA_advance_loc: 7
# CHECK-NEXT: DW_CFA_advance_loc: 7 to 0x401262
# CHECK-NEXT: DW_CFA_offset: reg13 -40
# CHECK-NEXT: DW_CFA_offset: reg12 -48
# CHECK-NEXT: DW_CFA_advance_loc: 8
# CHECK-NEXT: DW_CFA_advance_loc: 8 to 0x40126a
# CHECK-NEXT: DW_CFA_offset: reg3 -56
# CHECK-NEXT: DW_CFA_advance_loc1: 75
# CHECK-NEXT: DW_CFA_advance_loc1: 75 to 0x4012b5
# CHECK-NEXT: DW_CFA_def_cfa: reg7 +8
# CHECK-NEXT: DW_CFA_nop:
# CHECK-NEXT: DW_CFA_nop:

View File

@ -196,6 +196,7 @@ void PrinterContext<ELFT>::printEHFrame(const Elf_Shdr *EHFrameShdr) const {
reportError(std::move(E), ObjF.getFileName());
for (const dwarf::FrameEntry &Entry : EHFrame) {
std::optional<uint64_t> InitialLocation;
if (const dwarf::CIE *CIE = dyn_cast<dwarf::CIE>(&Entry)) {
W.startLine() << format("[0x%" PRIx64 "] CIE length=%" PRIu64 "\n",
Address + CIE->getOffset(), CIE->getLength());
@ -214,8 +215,9 @@ void PrinterContext<ELFT>::printEHFrame(const Elf_Shdr *EHFrameShdr) const {
Address + FDE->getLinkedCIE()->getOffset());
W.indent();
InitialLocation = FDE->getInitialLocation();
W.startLine() << format("initial_location: 0x%" PRIx64 "\n",
FDE->getInitialLocation());
*InitialLocation);
W.startLine() << format(
"address_range: 0x%" PRIx64 " (end : 0x%" PRIx64 ")\n",
FDE->getAddressRange(),
@ -227,7 +229,8 @@ void PrinterContext<ELFT>::printEHFrame(const Elf_Shdr *EHFrameShdr) const {
W.indent();
auto DumpOpts = DIDumpOptions();
DumpOpts.IsEH = true;
Entry.cfis().dump(W.getOStream(), DumpOpts, W.getIndentLevel());
Entry.cfis().dump(W.getOStream(), DumpOpts, W.getIndentLevel(),
InitialLocation);
W.unindent();
W.unindent();
W.getOStream() << "\n";