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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@255546 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Pete Cooper 2015-12-14 21:39:27 +00:00
parent 839b384a80
commit 832d1103af
3 changed files with 198 additions and 1 deletions

Binary file not shown.

View 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

View File

@ -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);
}
}