forked from OSchip/llvm-project
Teach llvm-flo how to read .eh_frame information from binaries
Summary: In order to reorder binaries with C++ exceptions, we first need to read DWARF CFI (call frame info) from binaries in a table in the .eh_frame ELF section. This table contains unwinding information we need to be aware of when reordering basic blocks, so as to avoid corrupting it. This patch also cleans up some code from Exceptions.cpp due to a refactoring where we moved some functions to the LLVM's libSupport. (cherry picked from FBD2614464)
This commit is contained in:
parent
7d592d0975
commit
2088875656
|
@ -2,6 +2,7 @@ set(LLVM_LINK_COMPONENTS
|
|||
${LLVM_TARGETS_TO_BUILD}
|
||||
CodeGen
|
||||
Core
|
||||
DebugInfoDWARF
|
||||
MC
|
||||
MCDisassembler
|
||||
MCParser
|
||||
|
|
|
@ -45,119 +45,6 @@ PrintExceptions("print-exceptions",
|
|||
|
||||
} // namespace opts
|
||||
|
||||
namespace {
|
||||
|
||||
/// Read an unsigned LEB128 value from data, advancing it past the value.
|
||||
uintptr_t readULEB128(const uint8_t *&Data) {
|
||||
uintptr_t Result = 0;
|
||||
uintptr_t Shift = 0;
|
||||
unsigned char Byte;
|
||||
|
||||
do {
|
||||
Byte = *Data++;
|
||||
Result |= (Byte & 0x7f) << Shift;
|
||||
Shift += 7;
|
||||
} while (Byte & 0x80);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// Read a signed LEB128 value from data, advancing it past the value.
|
||||
uintptr_t readSLEB128(const uint8_t *&Data) {
|
||||
uintptr_t Result = 0;
|
||||
uintptr_t Shift = 0;
|
||||
unsigned char Byte;
|
||||
|
||||
do {
|
||||
Byte = *Data++;
|
||||
Result |= (Byte & 0x7f) << Shift;
|
||||
Shift += 7;
|
||||
} while (Byte & 0x80);
|
||||
|
||||
if ((Byte & 0x40) && (Shift < (sizeof(Result) << 3))) {
|
||||
Result |= (~0 << Shift);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// Read and return a T from data, advancing it past the read item.
|
||||
template<typename T>
|
||||
T readValue(const uint8_t *&Data) {
|
||||
T Val;
|
||||
memcpy(&Val, Data, sizeof(T));
|
||||
Data += sizeof(T);
|
||||
return Val;
|
||||
}
|
||||
|
||||
/// Read an encoded DWARF value from data, advancing it past any data read. This
|
||||
/// function was adapted from the ExceptionDemo.cpp example in llvm.
|
||||
uintptr_t readEncodedPointer(const uint8_t *&Data, uint8_t Encoding) {
|
||||
uintptr_t Result = 0;
|
||||
auto const Start = Data;
|
||||
|
||||
if (Encoding == DW_EH_PE_omit)
|
||||
return Result;
|
||||
|
||||
// first get value
|
||||
switch (Encoding & 0x0F) {
|
||||
case DW_EH_PE_absptr:
|
||||
Result = readValue<uintptr_t>(Data);
|
||||
break;
|
||||
case DW_EH_PE_uleb128:
|
||||
Result = readULEB128(Data);
|
||||
break;
|
||||
case DW_EH_PE_sleb128:
|
||||
Result = readSLEB128(Data);
|
||||
break;
|
||||
case DW_EH_PE_udata2:
|
||||
Result = readValue<uint16_t>(Data);
|
||||
break;
|
||||
case DW_EH_PE_udata4:
|
||||
Result = readValue<uint32_t>(Data);
|
||||
break;
|
||||
case DW_EH_PE_udata8:
|
||||
Result = readValue<uint64_t>(Data);
|
||||
break;
|
||||
case DW_EH_PE_sdata2:
|
||||
Result = readValue<int16_t>(Data);
|
||||
break;
|
||||
case DW_EH_PE_sdata4:
|
||||
Result = readValue<int32_t>(Data);
|
||||
break;
|
||||
case DW_EH_PE_sdata8:
|
||||
Result = readValue<int64_t>(Data);
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("not implemented");
|
||||
}
|
||||
|
||||
// then add relative offset
|
||||
switch (Encoding & 0x70) {
|
||||
case DW_EH_PE_absptr:
|
||||
// do nothing
|
||||
break;
|
||||
case DW_EH_PE_pcrel:
|
||||
Result += reinterpret_cast<uintptr_t>(Start);
|
||||
break;
|
||||
case DW_EH_PE_textrel:
|
||||
case DW_EH_PE_datarel:
|
||||
case DW_EH_PE_funcrel:
|
||||
case DW_EH_PE_aligned:
|
||||
default:
|
||||
llvm_unreachable("not implemented");
|
||||
}
|
||||
|
||||
// then apply indirection
|
||||
if (Encoding & 0x80 /*DW_EH_PE_indirect*/) {
|
||||
Result = *((uintptr_t*)Result);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// readLSDA is reading and dumping the whole .gcc_exception_table section
|
||||
// at once.
|
||||
//
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "DataReader.h"
|
||||
#include "Exceptions.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
||||
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
|
||||
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
|
||||
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
|
||||
|
@ -105,6 +106,10 @@ static cl::opt<bool>
|
|||
DumpData("dump-data", cl::desc("dump parsed flo data and exit (debugging)"),
|
||||
cl::Hidden);
|
||||
|
||||
static cl::opt<bool>
|
||||
DumpEHFrame("dump-eh-frame", cl::desc("dump parsed .eh_frame (debugging)"),
|
||||
cl::Hidden);
|
||||
|
||||
static cl::opt<bool>
|
||||
PrintAll("print-all", cl::desc("print functions after each stage"),
|
||||
cl::Hidden);
|
||||
|
@ -464,6 +469,13 @@ static void OptimizeFile(ELFObjectFileBase *File, const DataReader &DR) {
|
|||
}
|
||||
}
|
||||
|
||||
// Process debug sections.
|
||||
std::unique_ptr<DWARFContext> DwCtx(new DWARFContextInMemory(*File));
|
||||
if (opts::DumpEHFrame) {
|
||||
const auto *Frames = DwCtx->getEHFrame();
|
||||
Frames->dump(outs());
|
||||
}
|
||||
|
||||
// Disassemble every function and build it's control flow graph.
|
||||
for (auto &BFI : BinaryFunctions) {
|
||||
BinaryFunction &Function = BFI.second;
|
||||
|
|
Loading…
Reference in New Issue