mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
Print the eh_frame section in MachoDump.
This is the start of work to dump the contents of the eh_frame section. It currently emits CIE entries. FDE entries will come later. It also needs improved error checking which will follow soon. http://reviews.llvm.org/D15502 Reviewed by Kevin Enderby and Lang Hames. llvm-svn: 255546
This commit is contained in:
parent
0ea913c715
commit
91dbcd5e25
BIN
test/tools/llvm-objdump/Inputs/eh_frame.macho-arm64
Normal file
BIN
test/tools/llvm-objdump/Inputs/eh_frame.macho-arm64
Normal file
Binary file not shown.
18
test/tools/llvm-objdump/eh_frame-arm64.test
Normal file
18
test/tools/llvm-objdump/eh_frame-arm64.test
Normal file
@ -0,0 +1,18 @@
|
||||
# RUN: llvm-objdump -unwind-info %p/Inputs/eh_frame.macho-arm64 2>/dev/null | FileCheck %s
|
||||
|
||||
# CHECK: Contents of __eh_frame section:
|
||||
# CHECK: CIE:
|
||||
# CHECK: Length: 16
|
||||
# CHECK: CIE ID: 0
|
||||
# CHECK: Version: 1
|
||||
# CHECK: Augmentation String: zR
|
||||
# CHECK: Code Alignment Factor: 1
|
||||
# CHECK: Data Alignment Factor: -8
|
||||
# CHECK: Return Address Register: 30
|
||||
# CHECK: Augmentation Data Length: 1
|
||||
# CHECK: FDE Address Pointer Encoding: 16
|
||||
# CHECK: Instructions:
|
||||
# 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
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include "llvm-objdump.h"
|
||||
#include "llvm-c/Disassembler.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
@ -6750,6 +6751,184 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned getSizeForEncoding(bool is64Bit,
|
||||
unsigned symbolEncoding) {
|
||||
unsigned format = symbolEncoding & 0x0f;
|
||||
switch (format) {
|
||||
default: llvm_unreachable("Unknown Encoding");
|
||||
case dwarf::DW_EH_PE_absptr:
|
||||
case dwarf::DW_EH_PE_signed:
|
||||
return is64Bit ? 8 : 4;
|
||||
case dwarf::DW_EH_PE_udata2:
|
||||
case dwarf::DW_EH_PE_sdata2:
|
||||
return 2;
|
||||
case dwarf::DW_EH_PE_udata4:
|
||||
case dwarf::DW_EH_PE_sdata4:
|
||||
return 4;
|
||||
case dwarf::DW_EH_PE_udata8:
|
||||
case dwarf::DW_EH_PE_sdata8:
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void printMachOEHFrameSection(const MachOObjectFile *Obj,
|
||||
std::map<uint64_t, SymbolRef> &Symbols,
|
||||
const SectionRef &EHFrame) {
|
||||
if (!Obj->isLittleEndian()) {
|
||||
outs() << "warning: cannot handle big endian __eh_frame section\n";
|
||||
return;
|
||||
}
|
||||
|
||||
bool is64Bit = Obj->is64Bit();
|
||||
|
||||
outs() << "Contents of __eh_frame section:\n";
|
||||
|
||||
StringRef Contents;
|
||||
EHFrame.getContents(Contents);
|
||||
|
||||
|
||||
//===----------------------------------
|
||||
// Entry header
|
||||
//===----------------------------------
|
||||
|
||||
for (const char *Pos = Contents.data(), *End = Contents.end(); Pos != End; ) {
|
||||
|
||||
uint64_t Length = readNext<uint32_t>(Pos);
|
||||
if (Length == 0xffffffff)
|
||||
Length = readNext<uint64_t>(Pos);
|
||||
|
||||
// Save the Pos so that we can check the length we encoded against what we
|
||||
// end up decoding.
|
||||
const char *PosAfterLength = Pos;
|
||||
const char *EntryEndPos = PosAfterLength + Length;
|
||||
|
||||
assert(EntryEndPos <= End &&
|
||||
"__eh_frame entry length exceeds section size");
|
||||
|
||||
uint32_t ID = readNext<uint32_t>(Pos);
|
||||
if (ID == 0) {
|
||||
// This is a CIE.
|
||||
|
||||
uint32_t Version = readNext<uint8_t>(Pos);
|
||||
|
||||
// Parse a null terminated augmentation string
|
||||
SmallString<8> AugmentationString;
|
||||
for (uint8_t Char = readNext<uint8_t>(Pos); Char;
|
||||
Char = readNext<uint8_t>(Pos))
|
||||
AugmentationString.push_back(Char);
|
||||
|
||||
// Optionally parse the EH data if the augmentation string says it's there.
|
||||
Optional<uint64_t> EHData;
|
||||
if (StringRef(AugmentationString).count("eh"))
|
||||
EHData = is64Bit ? readNext<uint64_t>(Pos) : readNext<uint32_t>(Pos);
|
||||
|
||||
unsigned ULEBByteCount;
|
||||
uint64_t CodeAlignmentFactor = decodeULEB128((const uint8_t *)Pos,
|
||||
&ULEBByteCount);
|
||||
Pos += ULEBByteCount;
|
||||
|
||||
int64_t DataAlignmentFactor = decodeSLEB128((const uint8_t *)Pos,
|
||||
&ULEBByteCount);
|
||||
Pos += ULEBByteCount;
|
||||
|
||||
uint32_t ReturnAddressRegister = readNext<uint8_t>(Pos);
|
||||
|
||||
Optional<uint64_t> AugmentationLength;
|
||||
Optional<uint32_t> LSDAPointerEncoding;
|
||||
Optional<uint32_t> PersonalityEncoding;
|
||||
Optional<uint64_t> Personality;
|
||||
Optional<uint32_t> FDEPointerEncoding;
|
||||
if (!AugmentationString.empty() && AugmentationString.front() == 'z') {
|
||||
AugmentationLength = decodeULEB128((const uint8_t *)Pos,
|
||||
&ULEBByteCount);
|
||||
Pos += ULEBByteCount;
|
||||
|
||||
// Walk the augmentation string to get all the augmentation data.
|
||||
for (unsigned i = 1, e = AugmentationString.size(); i != e; ++i) {
|
||||
char Char = AugmentationString[i];
|
||||
switch (Char) {
|
||||
case 'e':
|
||||
assert((i + 1) != e && AugmentationString[i + 1] == 'h' &&
|
||||
"Expected 'eh' in augmentation string");
|
||||
break;
|
||||
case 'L':
|
||||
assert(!LSDAPointerEncoding && "Duplicate LSDA encoding");
|
||||
LSDAPointerEncoding = readNext<uint8_t>(Pos);
|
||||
break;
|
||||
case 'P': {
|
||||
assert(!Personality && "Duplicate personality");
|
||||
PersonalityEncoding = readNext<uint8_t>(Pos);
|
||||
switch (getSizeForEncoding(is64Bit, *PersonalityEncoding)) {
|
||||
case 2:
|
||||
Personality = readNext<uint16_t>(Pos);
|
||||
break;
|
||||
case 4:
|
||||
Personality = readNext<uint32_t>(Pos);
|
||||
break;
|
||||
case 8:
|
||||
Personality = readNext<uint64_t>(Pos);
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Illegal data size");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'R':
|
||||
assert(!FDEPointerEncoding && "Duplicate FDE encoding");
|
||||
FDEPointerEncoding = readNext<uint8_t>(Pos);
|
||||
break;
|
||||
case 'z':
|
||||
llvm_unreachable("'z' must be first in the augmentation string");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outs() << "CIE:\n";
|
||||
outs() << " Length: " << Length << "\n";
|
||||
outs() << " CIE ID: " << ID << "\n";
|
||||
outs() << " Version: " << Version << "\n";
|
||||
outs() << " Augmentation String: " << AugmentationString << "\n";
|
||||
if (EHData)
|
||||
outs() << " EHData: " << *EHData << "\n";
|
||||
outs() << " Code Alignment Factor: " << CodeAlignmentFactor << "\n";
|
||||
outs() << " Data Alignment Factor: " << DataAlignmentFactor << "\n";
|
||||
outs() << " Return Address Register: " << ReturnAddressRegister << "\n";
|
||||
if (AugmentationLength) {
|
||||
outs() << " Augmentation Data Length: " << *AugmentationLength << "\n";
|
||||
if (LSDAPointerEncoding) {
|
||||
outs() << " FDE LSDA Pointer Encoding: "
|
||||
<< *LSDAPointerEncoding << "\n";
|
||||
}
|
||||
if (Personality) {
|
||||
outs() << " Personality Encoding: " << *PersonalityEncoding << "\n";
|
||||
outs() << " Personality: " << *Personality << "\n";
|
||||
}
|
||||
if (FDEPointerEncoding) {
|
||||
outs() << " FDE Address Pointer Encoding: "
|
||||
<< *FDEPointerEncoding << "\n";
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
continue;
|
||||
}
|
||||
// This is an FDE.
|
||||
outs() << "FDE:\n";
|
||||
outs() << " Length: " << Length << "\n";
|
||||
outs() << " ";
|
||||
dumpBytes(makeArrayRef((const uint8_t*)Pos, (const uint8_t*)EntryEndPos),
|
||||
outs());
|
||||
outs() << "\n";
|
||||
Pos = EntryEndPos;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) {
|
||||
std::map<uint64_t, SymbolRef> Symbols;
|
||||
for (const SymbolRef &SymRef : Obj->symbols()) {
|
||||
@ -6771,7 +6950,7 @@ void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) {
|
||||
else if (SectName == "__unwind_info")
|
||||
printMachOUnwindInfoSection(Obj, Symbols, Section);
|
||||
else if (SectName == "__eh_frame")
|
||||
outs() << "llvm-objdump: warning: unhandled __eh_frame section\n";
|
||||
printMachOEHFrameSection(Obj, Symbols, Section);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user