diff options
author | Pete Cooper <peter_cooper@apple.com> | 2015-12-14 21:49:49 +0000 |
---|---|---|
committer | Pete Cooper <peter_cooper@apple.com> | 2015-12-14 21:49:49 +0000 |
commit | 2d6ab4db1cefe78251a21cb1f3727be3cb2039d8 (patch) | |
tree | 5bf77c475cb255eaf1f8d2c722707bc39d95b7d8 /tools | |
parent | 832d1103af38a870d0baf9b59194e9a6f482647d (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@255550 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools')
-rw-r--r-- | tools/llvm-objdump/MachODump.cpp | 112 |
1 files changed, 107 insertions, 5 deletions
diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index a3356c785d6..2fd0751dd8c 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -6786,13 +6786,22 @@ static void printMachOEHFrameSection(const MachOObjectFile *Obj, 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(const MachOObjectFile *Obj, 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; - } } |