Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Conversation

igorkudrin
Copy link
Collaborator

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.

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.
@llvmbot
Copy link
Collaborator

llvmbot commented Mar 7, 2024

@llvm/pr-subscribers-llvm-binary-utilities

@llvm/pr-subscribers-debuginfo

Author: Igor Kudrin (igorkudrin)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/84274.diff

5 Files Affected:

  • (modified) llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h (+3-3)
  • (modified) llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp (+13-6)
  • (modified) llvm/test/DebugInfo/dwarfdump-debug-frame-simple.test (+3-3)
  • (modified) llvm/test/tools/llvm-readobj/ELF/unwind.test (+17-17)
  • (modified) llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h (+5-2)
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";

Copy link
Collaborator

@jh7370 jh7370 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems good to me.

@igorkudrin igorkudrin merged commit fe84764 into llvm:main Mar 8, 2024
9 checks passed
@igorkudrin igorkudrin deleted the ikudrin/dump-new-address-for-DW_CFA_advance_loc branch March 8, 2024 00:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants