[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