util/llvmdisassembler: map registers by names
Internal LLVM register IDs can and did change between LLVM versions. These magic integers are replaced by iterating over all LLVM registers and mapping them to FAIL* registers by name. As this iteration requires a LLVM object created from a binary, a static convenience function is added to LLVMtoFailTranslator which creates a translator given the binary filename. Building this functionality inside libfail-llvmdisassembler prevents experiments from needing to add LLVM includes and library definitions. Change-Id: I27927f40d5cb6d9a22bb2caf21ca2450f6bcb0b8
This commit is contained in:
@ -12,10 +12,10 @@ LLVMtoFailTranslator & LLVMDisassembler::getTranslator() {
|
||||
switch ( llvm::Triple::ArchType(object->getArch()) ) {
|
||||
case llvm::Triple::x86:
|
||||
case llvm::Triple::x86_64:
|
||||
ltofail = new LLVMtoFailBochs;
|
||||
ltofail = new LLVMtoFailBochs(this);
|
||||
break;
|
||||
case llvm::Triple::arm:
|
||||
ltofail = new LLVMtoFailGem5;
|
||||
ltofail = new LLVMtoFailGem5(this);
|
||||
break;
|
||||
default:
|
||||
std::cout << " not supported :(";
|
||||
|
||||
@ -1,48 +1,68 @@
|
||||
#include "LLVMDisassembler.hpp"
|
||||
#include "LLVMtoFailBochs.hpp"
|
||||
#include "sal/x86/X86Architecture.hpp"
|
||||
|
||||
using namespace fail;
|
||||
|
||||
LLVMtoFailBochs::LLVMtoFailBochs() {
|
||||
/* These magic numbers are taken from the llvm compiler (MC), they
|
||||
do not appear in any header. They hopefully will never
|
||||
change */
|
||||
llvm_to_fail_map[1] = reginfo_t(RID_CAX, 8, 8) ; // AH
|
||||
llvm_to_fail_map[2] = reginfo_t(RID_CAX, 8, 0); // AL
|
||||
llvm_to_fail_map[3] = reginfo_t(RID_CAX, 16, 0); // AX
|
||||
llvm_to_fail_map[43] = reginfo_t(RID_CAX, 32, 0); // EAX
|
||||
LLVMtoFailBochs::LLVMtoFailBochs(LLVMDisassembler *disas) {
|
||||
std::map<std::string, struct reginfo_t> reg_name_map;
|
||||
|
||||
llvm_to_fail_map[4] = reginfo_t(RID_CBX, 8, 8); // BH
|
||||
llvm_to_fail_map[5] = reginfo_t(RID_CBX, 8, 0); // BL
|
||||
llvm_to_fail_map[8] = reginfo_t(RID_CBX, 16, 0); // BX
|
||||
llvm_to_fail_map[45] = reginfo_t(RID_CBX, 32, 0); // EBX
|
||||
reg_name_map["AH"] = reginfo_t(RID_CAX, 8, 8);
|
||||
reg_name_map["AL"] = reginfo_t(RID_CAX, 8, 0);
|
||||
reg_name_map["AX"] = reginfo_t(RID_CAX, 16, 0);
|
||||
reg_name_map["EAX"] = reginfo_t(RID_CAX, 32, 0);
|
||||
|
||||
llvm_to_fail_map[9] = reginfo_t(RID_CCX, 8, 8); // CH
|
||||
llvm_to_fail_map[10] = reginfo_t(RID_CCX, 8, 0); // CL
|
||||
llvm_to_fail_map[28] = reginfo_t(RID_CCX, 16, 0); // CX
|
||||
llvm_to_fail_map[46] = reginfo_t(RID_CCX); // ECX
|
||||
reg_name_map["BH"] = reginfo_t(RID_CBX, 8, 8);
|
||||
reg_name_map["BL"] = reginfo_t(RID_CBX, 8, 0);
|
||||
reg_name_map["BX"] = reginfo_t(RID_CBX, 16, 0);
|
||||
reg_name_map["EBX"] = reginfo_t(RID_CBX, 32, 0);
|
||||
|
||||
llvm_to_fail_map[29] = reginfo_t(RID_CDX, 8, 8); // DH
|
||||
llvm_to_fail_map[32] = reginfo_t(RID_CDX, 8, 0); // DL
|
||||
llvm_to_fail_map[42] = reginfo_t(RID_CDX, 16, 0); // DX
|
||||
llvm_to_fail_map[48] = reginfo_t(RID_CDX); // EDX
|
||||
reg_name_map["CH"] = reginfo_t(RID_CCX, 8, 8);
|
||||
reg_name_map["CL"] = reginfo_t(RID_CCX, 8, 0);
|
||||
reg_name_map["CX"] = reginfo_t(RID_CCX, 16, 0);
|
||||
reg_name_map["ECX"] = reginfo_t(RID_CCX);
|
||||
|
||||
llvm_to_fail_map[30] = reginfo_t(RID_CDI, 16, 0); // DI
|
||||
llvm_to_fail_map[31] = reginfo_t(RID_CDI, 8, 0); // DIL
|
||||
llvm_to_fail_map[47] = reginfo_t(RID_CDI); // EDI
|
||||
reg_name_map["DH"] = reginfo_t(RID_CDX, 8, 8);
|
||||
reg_name_map["DL"] = reginfo_t(RID_CDX, 8, 0);
|
||||
reg_name_map["DX"] = reginfo_t(RID_CDX, 16, 0);
|
||||
reg_name_map["EDX"] = reginfo_t(RID_CDX);
|
||||
|
||||
llvm_to_fail_map[6] = reginfo_t(RID_CBP, 16, 0); // BP
|
||||
llvm_to_fail_map[7] = reginfo_t(RID_CBP, 8, 0); // BPL
|
||||
llvm_to_fail_map[44] = reginfo_t(RID_CBP); // EBP
|
||||
reg_name_map["DI"] = reginfo_t(RID_CDI, 16, 0);
|
||||
reg_name_map["DIL"] = reginfo_t(RID_CDI, 8, 0);
|
||||
reg_name_map["EDI"] = reginfo_t(RID_CDI);
|
||||
|
||||
llvm_to_fail_map[49] = reginfo_t(RID_FLAGS); // EFLAGS
|
||||
reg_name_map["BP"] = reginfo_t(RID_CBP, 16, 0);
|
||||
reg_name_map["BPL"] = reginfo_t(RID_CBP, 8, 0);
|
||||
reg_name_map["EBP"] = reginfo_t(RID_CBP);
|
||||
|
||||
llvm_to_fail_map[50] = reginfo_t(RID_PC); // EIP
|
||||
reg_name_map["EFLAGS"] = reginfo_t(RID_FLAGS);
|
||||
|
||||
llvm_to_fail_map[115] = reginfo_t(RID_CSI, 16, 0); // SI
|
||||
llvm_to_fail_map[53] = reginfo_t(RID_CSI); // ESI
|
||||
reg_name_map["EIP"] = reginfo_t(RID_PC);
|
||||
|
||||
llvm_to_fail_map[54] = reginfo_t(RID_CSP); // ESP
|
||||
llvm_to_fail_map[117] = reginfo_t(RID_CSP, 16, 0); // SP
|
||||
llvm_to_fail_map[118] = reginfo_t(RID_CSP, 8, 0); // SPL
|
||||
reg_name_map["SI"] = reginfo_t(RID_CSI, 16, 0);
|
||||
reg_name_map["ESI"] = reginfo_t(RID_CSI);
|
||||
|
||||
reg_name_map["ESP"] = reginfo_t(RID_CSP);
|
||||
reg_name_map["SP"] = reginfo_t(RID_CSP, 16, 0);
|
||||
reg_name_map["SPL"] = reginfo_t(RID_CSP, 8, 0);
|
||||
|
||||
reg_name_map["CR0"] = reginfo_t(RID_CR0);
|
||||
reg_name_map["CR2"] = reginfo_t(RID_CR2);
|
||||
reg_name_map["CR3"] = reginfo_t(RID_CR3);
|
||||
reg_name_map["CR4"] = reginfo_t(RID_CR4);
|
||||
|
||||
reg_name_map["CS"] = reginfo_t(RID_CS, 16, 0);
|
||||
reg_name_map["DS"] = reginfo_t(RID_DS, 16, 0);
|
||||
reg_name_map["ES"] = reginfo_t(RID_ES, 16, 0);
|
||||
reg_name_map["FS"] = reginfo_t(RID_FS, 16, 0);
|
||||
reg_name_map["GS"] = reginfo_t(RID_GS, 16, 0);
|
||||
reg_name_map["SS"] = reginfo_t(RID_SS, 16, 0);
|
||||
|
||||
const llvm::MCRegisterInfo ®_info = disas->getRegisterInfo();
|
||||
for (unsigned int i = 0; i < reg_info.getNumRegs(); ++i){
|
||||
std::string name = reg_info.getName(i);
|
||||
if (reg_name_map.count(name) > 0) {
|
||||
llvm_to_fail_map[i] = reg_name_map[name];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,11 +7,13 @@
|
||||
|
||||
namespace fail {
|
||||
|
||||
class LLVMDisassembler;
|
||||
|
||||
class LLVMtoFailBochs : public LLVMtoFailTranslator {
|
||||
|
||||
public:
|
||||
|
||||
LLVMtoFailBochs();
|
||||
LLVMtoFailBochs(LLVMDisassembler *disas);
|
||||
|
||||
};
|
||||
} // end of namespace
|
||||
|
||||
@ -1,26 +1,34 @@
|
||||
#include "LLVMDisassembler.hpp"
|
||||
#include "LLVMtoFailGem5.hpp"
|
||||
#include "sal/arm/ArmArchitecture.hpp"
|
||||
|
||||
using namespace fail;
|
||||
|
||||
LLVMtoFailGem5::LLVMtoFailGem5() {
|
||||
/* These magic numbers are taken from the machine descriptions of
|
||||
LLVM they (hopefully) will not change, since they are not exported
|
||||
via a header */
|
||||
llvm_to_fail_map[60] = reginfo_t(RI_R0);
|
||||
llvm_to_fail_map[61] = reginfo_t(RI_R1);
|
||||
llvm_to_fail_map[62] = reginfo_t(RI_R2);
|
||||
llvm_to_fail_map[63] = reginfo_t(RI_R3);
|
||||
llvm_to_fail_map[64] = reginfo_t(RI_R4);
|
||||
llvm_to_fail_map[65] = reginfo_t(RI_R5);
|
||||
llvm_to_fail_map[66] = reginfo_t(RI_R6);
|
||||
llvm_to_fail_map[67] = reginfo_t(RI_R7);
|
||||
llvm_to_fail_map[68] = reginfo_t(RI_R8);
|
||||
llvm_to_fail_map[69] = reginfo_t(RI_R9);
|
||||
llvm_to_fail_map[70] = reginfo_t(RI_R10);
|
||||
llvm_to_fail_map[71] = reginfo_t(RI_R11);
|
||||
llvm_to_fail_map[72] = reginfo_t(RI_R12);
|
||||
llvm_to_fail_map[105] = reginfo_t(RI_SP);
|
||||
llvm_to_fail_map[40] = reginfo_t(RI_LR);
|
||||
llvm_to_fail_map[43] = reginfo_t(RI_IP);
|
||||
LLVMtoFailGem5::LLVMtoFailGem5(LLVMDisassembler *disas) {
|
||||
std::map<std::string, struct reginfo_t> reg_name_map;
|
||||
|
||||
reg_name_map["R0"] = reginfo_t(RI_R0);
|
||||
reg_name_map["R1"] = reginfo_t(RI_R1);
|
||||
reg_name_map["R2"] = reginfo_t(RI_R2);
|
||||
reg_name_map["R3"] = reginfo_t(RI_R3);
|
||||
reg_name_map["R4"] = reginfo_t(RI_R4);
|
||||
reg_name_map["R5"] = reginfo_t(RI_R5);
|
||||
reg_name_map["R6"] = reginfo_t(RI_R6);
|
||||
reg_name_map["R7"] = reginfo_t(RI_R7);
|
||||
reg_name_map["R8"] = reginfo_t(RI_R8);
|
||||
reg_name_map["R9"] = reginfo_t(RI_R9);
|
||||
reg_name_map["R10"] = reginfo_t(RI_R10);
|
||||
reg_name_map["R11"] = reginfo_t(RI_R11);
|
||||
reg_name_map["R12"] = reginfo_t(RI_R12);
|
||||
reg_name_map["SP"] = reginfo_t(RI_SP);
|
||||
reg_name_map["LR"] = reginfo_t(RI_LR);
|
||||
reg_name_map["PC"] = reginfo_t(RI_IP);
|
||||
|
||||
const llvm::MCRegisterInfo ®_info = disas->getRegisterInfo();
|
||||
for (unsigned int i = 0; i < reg_info.getNumRegs(); ++i){
|
||||
std::string name = reg_info.getName(i);
|
||||
if (reg_name_map.count(name) > 0) {
|
||||
llvm_to_fail_map[i] = reg_name_map[name];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,11 +7,13 @@
|
||||
|
||||
namespace fail {
|
||||
|
||||
class LLVMDisassembler;
|
||||
|
||||
class LLVMtoFailGem5 : public LLVMtoFailTranslator {
|
||||
|
||||
public:
|
||||
|
||||
LLVMtoFailGem5();
|
||||
LLVMtoFailGem5(LLVMDisassembler *disas);
|
||||
|
||||
};
|
||||
} // end of namespace
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
#include "LLVMDisassembler.hpp"
|
||||
#include "LLVMtoFailTranslator.hpp"
|
||||
#include "sal/SALInst.hpp"
|
||||
|
||||
using namespace fail;
|
||||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
|
||||
const LLVMtoFailTranslator::reginfo_t & LLVMtoFailTranslator::getFailRegisterID(unsigned int regid) {
|
||||
ltof_map_t::iterator it = llvm_to_fail_map.find(regid);
|
||||
@ -38,3 +41,20 @@ void LLVMtoFailTranslator::setRegisterContent(ConcreteCPU & cpu, const reginfo_t
|
||||
|
||||
cpu.setRegisterContent( reg, value ); // write back register content
|
||||
}
|
||||
|
||||
LLVMtoFailTranslator* LLVMtoFailTranslator::createFromBinary(const std::string elf_path) {
|
||||
llvm_shutdown_obj Y;
|
||||
llvm::InitializeAllTargetInfos();
|
||||
llvm::InitializeAllTargetMCs();
|
||||
llvm::InitializeAllDisassemblers();
|
||||
|
||||
OwningPtr<Binary> binary;
|
||||
assert(createBinary(elf_path, binary) == 0);
|
||||
|
||||
#ifndef __puma
|
||||
LLVMDisassembler disas(dyn_cast<ObjectFile>(binary.get()));
|
||||
return &disas.getTranslator();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
@ -68,6 +68,8 @@ public:
|
||||
int getFailRegisterId(unsigned int regid) { return this->getFailRegisterID(regid).id; };
|
||||
|
||||
reginfo_t notfound;
|
||||
|
||||
static LLVMtoFailTranslator* createFromBinary(const std::string elf_path);
|
||||
};
|
||||
|
||||
} // end of namespace
|
||||
|
||||
Reference in New Issue
Block a user