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

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 6 19:50:54 PST 2024


https://github.com/igorkudrin created https://github.com/llvm/llvm-project/pull/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.

>From ee022864643fa2614648fcdc26143c027b6f3fd1 Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Wed, 6 Mar 2024 19:45:15 -0800
Subject: [PATCH] [DWARF] Dump an updated location for DW_CFA_advance_loc*

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.
---
 .../llvm/DebugInfo/DWARF/DWARFDebugFrame.h    |  6 ++--
 llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp  | 19 +++++++----
 .../dwarfdump-debug-frame-simple.test         |  6 ++--
 llvm/test/tools/llvm-readobj/ELF/unwind.test  | 34 +++++++++----------
 llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h   |  7 ++--
 5 files changed, 41 insertions(+), 31 deletions(-)

diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
index bc35f2ab988ed2..c7c558850a2805 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
@@ -454,8 +454,8 @@ class CFIProgram {
   /// 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 @@ class CFIProgram {
   /// 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
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
index aae1668c1639c4..0f77d9f5f76058 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
@@ -858,7 +858,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];
@@ -877,6 +878,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
@@ -888,7 +890,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)
@@ -918,13 +924,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';
   }
 }
@@ -975,7 +982,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))
@@ -1003,7 +1010,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))
diff --git a/llvm/test/DebugInfo/dwarfdump-debug-frame-simple.test b/llvm/test/DebugInfo/dwarfdump-debug-frame-simple.test
index 6c049af43efe74..2cd281c8d0af9f 100644
--- a/llvm/test/DebugInfo/dwarfdump-debug-frame-simple.test
+++ b/llvm/test/DebugInfo/dwarfdump-debug-frame-simple.test
@@ -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
diff --git a/llvm/test/tools/llvm-readobj/ELF/unwind.test b/llvm/test/tools/llvm-readobj/ELF/unwind.test
index 2deb1a587d2438..2e51ec2a61a637 100644
--- a/llvm/test/tools/llvm-readobj/ELF/unwind.test
+++ b/llvm/test/tools/llvm-readobj/ELF/unwind.test
@@ -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:
diff --git a/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h b/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
index 687d97abd0232d..2e89463e68d519 100644
--- a/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
+++ b/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
@@ -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";



More information about the llvm-commits mailing list