mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 11:02:59 +02:00
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. llvm-svn: 255550
This commit is contained in:
parent
91dbcd5e25
commit
9826aaba7a
@ -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
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user