[llvm] r255550 - Start implementing FDE dumping when printing the eh_frame.

Pete Cooper via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 14 13:49:49 PST 2015


Author: pete
Date: Mon Dec 14 15:49:49 2015
New Revision: 255550

URL: http://llvm.org/viewvc/llvm-project?rev=255550&view=rev
Log:
Start implementing FDE dumping when printing the eh_frame.

This code adds some simple decoding of the FDE's in an eh_frame.

There's still more to be done in terms of error handling and verification.

Also, we need to be able to decode the CFI's.

Modified:
    llvm/trunk/test/tools/llvm-objdump/eh_frame-arm64.test
    llvm/trunk/tools/llvm-objdump/MachODump.cpp

Modified: llvm/trunk/test/tools/llvm-objdump/eh_frame-arm64.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/eh_frame-arm64.test?rev=255550&r1=255549&r2=255550&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-objdump/eh_frame-arm64.test (original)
+++ llvm/trunk/test/tools/llvm-objdump/eh_frame-arm64.test Mon Dec 14 15:49:49 2015
@@ -15,4 +15,9 @@
 # CHECK:   0c 1f 00 
 # CHECK: FDE:
 # CHECK:   Length: 32
-# CHECK:   e4 ff ff ff ff ff ff ff 20 00 00 00 00 00 00 00 00 48 0e 10 9e 01 9d 02 00 00 00 00 
+# CHECK:   CIE Offset: 0
+# CHECK:   PC Begin: ffffffffffffffe4
+# CHECK:   PC Range: 0000000000000020
+# CHECK:   Augmentation Data Length: 0
+# CHECK:   Instructions:
+# CHECK:   48 0e 10 9e 01 9d 02 00 00 00 00

Modified: llvm/trunk/tools/llvm-objdump/MachODump.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/MachODump.cpp?rev=255550&r1=255549&r2=255550&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objdump/MachODump.cpp (original)
+++ llvm/trunk/tools/llvm-objdump/MachODump.cpp Mon Dec 14 15:49:49 2015
@@ -6786,13 +6786,22 @@ static void printMachOEHFrameSection(con
   StringRef Contents;
   EHFrame.getContents(Contents);
 
+  /// A few fields of the CIE are used when decoding the FDE's.  This struct
+  /// will cache those fields we need so that we don't have to decode it
+  /// repeatedly for each FDE that references it.
+  struct DecodedCIE {
+    Optional<uint32_t> FDEPointerEncoding;
+    Optional<uint32_t> LSDAPointerEncoding;
+    bool hasAugmentationLength;
+  };
 
-  //===----------------------------------
-  // Entry header
-  //===----------------------------------
+  // Map from the start offset of the CIE to the cached data for that CIE.
+  DenseMap<uint64_t, DecodedCIE> CachedCIEs;
 
   for (const char *Pos = Contents.data(), *End = Contents.end(); Pos != End; ) {
 
+    const char *EntryStartPos = Pos;
+
     uint64_t Length = readNext<uint32_t>(Pos);
     if (Length == 0xffffffff)
       Length = readNext<uint64_t>(Pos);
@@ -6915,17 +6924,110 @@ static void printMachOEHFrameSection(con
                 outs());
       outs() << "\n";
       Pos = EntryEndPos;
+
+      // Cache this entry.
+      uint64_t Offset = EntryStartPos - Contents.data();
+      CachedCIEs[Offset] = { FDEPointerEncoding, LSDAPointerEncoding,
+                             AugmentationLength.hasValue() };
       continue;
     }
+
     // This is an FDE.
+    // The CIE pointer for an FDE is the same location as the ID which we
+    // already read.
+    uint32_t CIEPointer = ID;
+
+    const char *CIEStart = PosAfterLength - CIEPointer;
+    assert(CIEStart >= Contents.data() &&
+           "FDE points to CIE before the __eh_frame start");
+
+    uint64_t CIEOffset = CIEStart - Contents.data();
+    auto CIEIt = CachedCIEs.find(CIEOffset);
+    if (CIEIt == CachedCIEs.end())
+      llvm_unreachable("Couldn't find CIE at offset in to __eh_frame section");
+
+    const DecodedCIE &CIE = CIEIt->getSecond();
+    assert(CIE.FDEPointerEncoding &&
+           "FDE references CIE which did not set pointer encoding");
+
+    uint64_t PCPointerSize = getSizeForEncoding(is64Bit,
+                                                *CIE.FDEPointerEncoding);
+
+    uint64_t PCBegin;
+    uint64_t PCRange;
+    switch (PCPointerSize) {
+      case 2:
+        PCBegin = readNext<uint16_t>(Pos);
+        PCRange = readNext<uint16_t>(Pos);
+        break;
+      case 4:
+        PCBegin = readNext<uint32_t>(Pos);
+        PCRange = readNext<uint32_t>(Pos);
+        break;
+      case 8:
+        PCBegin = readNext<uint64_t>(Pos);
+        PCRange = readNext<uint64_t>(Pos);
+        break;
+      default:
+        llvm_unreachable("Illegal data size");
+    }
+
+    Optional<uint64_t> AugmentationLength;
+    uint32_t LSDAPointerSize;
+    Optional<uint64_t> LSDAPointer;
+    if (CIE.hasAugmentationLength) {
+      unsigned ULEBByteCount;
+      AugmentationLength = decodeULEB128((const uint8_t *)Pos,
+                                         &ULEBByteCount);
+      Pos += ULEBByteCount;
+
+      // Decode the LSDA if the CIE augmentation string said we should.
+      if (CIE.LSDAPointerEncoding) {
+        LSDAPointerSize = getSizeForEncoding(is64Bit, *CIE.LSDAPointerEncoding);
+        switch (LSDAPointerSize) {
+          case 2:
+            LSDAPointer = readNext<uint16_t>(Pos);
+            break;
+          case 4:
+            LSDAPointer = readNext<uint32_t>(Pos);
+            break;
+          case 8:
+            LSDAPointer = readNext<uint64_t>(Pos);
+            break;
+          default:
+            llvm_unreachable("Illegal data size");
+        }
+      }
+    }
+
     outs() << "FDE:\n";
     outs() << "  Length: " << Length << "\n";
-    outs() << "  ";
+    outs() << "  CIE Offset: " << CIEOffset << "\n";
+
+    if (PCPointerSize == 8) {
+      outs() << format("  PC Begin: %016" PRIx64, PCBegin) << "\n";
+      outs() << format("  PC Range: %016" PRIx64, PCRange) << "\n";
+    } else {
+      outs() << format("  PC Begin: %08" PRIx64, PCBegin) << "\n";
+      outs() << format("  PC Range: %08" PRIx64, PCRange) << "\n";
+    }
+    if (AugmentationLength) {
+      outs() << "  Augmentation Data Length: " << *AugmentationLength << "\n";
+      if (LSDAPointer) {
+        if (LSDAPointerSize == 8)
+          outs() << format("  LSDA Pointer: %016\n" PRIx64, *LSDAPointer);
+        else
+          outs() << format("  LSDA Pointer: %08\n" PRIx64, *LSDAPointer);
+      }
+    }
+
+    // FIXME: Handle instructions.
+    // For now just emit some bytes
+    outs() << "  Instructions:\n  ";
     dumpBytes(makeArrayRef((const uint8_t*)Pos, (const uint8_t*)EntryEndPos),
               outs());
     outs() << "\n";
     Pos = EntryEndPos;
-
   }
 }
 




More information about the llvm-commits mailing list