diff --git a/CMakeLists.txt b/CMakeLists.txt index 06b46f71..9016c0ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,7 @@ if("${CMAKE_VERSION}" VERSION_GREATER 2.8.3) # (makes cmake 2.8.4 and newer) cmake_policy(SET CMP0017 NEW) endif("${CMAKE_VERSION}" VERSION_GREATER 2.8.3) +ENABLE_TESTING() PROJECT(Fail*) @@ -19,6 +20,12 @@ SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin) ## (The autoconf'd Bochs instance is placed in the auto-configured path, ## as we still just call Bochs' Makefile's make install) +# where will executable tests be written ? +IF (EXECUTABLE_OUTPUT_PATH) + SET (CXX_TEST_PATH ${EXECUTABLE_OUTPUT_PATH}) +ELSE (EXECUTABLE_OUTPUT_PATH) + SET (CXX_TEST_PATH .) +ENDIF (EXECUTABLE_OUTPUT_PATH) #### Setup search path for custom cmake scipts #### SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) diff --git a/cmake/FindLLVM.cmake b/cmake/FindLLVM.cmake new file mode 100644 index 00000000..9e9a8b89 --- /dev/null +++ b/cmake/FindLLVM.cmake @@ -0,0 +1,34 @@ +find_program(LLVMCONFIG NAMES llvm-config llvm-config-3.1) + +if( NOT LLVMCONFIG ) + message(FATAL_ERROR "llvm-config not found, try installing llvm-dev llvm") +else() + message(STATUS "[Fail*] LLVM Disassembler: Found llvm-config @ ${LLVMCONFIG}") +endif() + +# examine LLVM include directory +execute_process( COMMAND ${LLVMCONFIG} --includedir + OUTPUT_VARIABLE LLVM_INCLUDE_DIRS + OUTPUT_STRIP_TRAILING_WHITESPACE ) +include_directories( ${LLVM_INCLUDE_DIRS} ) + +# Library path +execute_process( COMMAND ${LLVMCONFIG} --libdir + OUTPUT_VARIABLE LLVM_LIBRARY_DIRS + OUTPUT_STRIP_TRAILING_WHITESPACE ) +link_directories( ${LLVM_LIBRARY_DIRS} ) + +# necessary CPP flags. +execute_process( COMMAND ${LLVMCONFIG} --cxxflags + OUTPUT_VARIABLE LLVM_CXX_FLAGS + OUTPUT_STRIP_TRAILING_WHITESPACE ) + +# and additional libs (this is -ldl and -lpthread in llvm 3.1) +execute_process( COMMAND ${LLVMCONFIG} --ldflags + OUTPUT_VARIABLE LLVM_LDFLAGS + OUTPUT_STRIP_TRAILING_WHITESPACE ) + +## FIXME? Here we add *all* libraries to the link step (although we need only a handful..) +execute_process( COMMAND ${LLVMCONFIG} --libs all + OUTPUT_VARIABLE LLVM_LIBS + OUTPUT_STRIP_TRAILING_WHITESPACE ) diff --git a/src/core/config/VariantConfig.hpp.in b/src/core/config/VariantConfig.hpp.in index 607d5b29..45f7cefe 100644 --- a/src/core/config/VariantConfig.hpp.in +++ b/src/core/config/VariantConfig.hpp.in @@ -10,6 +10,8 @@ #cmakedefine BUILD_X86 #cmakedefine BUILD_ARM +#cmakedefine BUILD_LLVM_DISASSEMBLER + #define ARCH_TOOL_PREFIX "@ARCH_TOOL_PREFIX@" #endif // __VARIANT_CONFIG_HPP__ diff --git a/src/core/util/CMakeLists.txt b/src/core/util/CMakeLists.txt index a2bec4a3..6b31e80e 100644 --- a/src/core/util/CMakeLists.txt +++ b/src/core/util/CMakeLists.txt @@ -62,3 +62,9 @@ mark_as_advanced(FAIL_OBJDUMP) add_library(fail-util ${SRCS}) add_dependencies(fail-util fail-comm) target_link_libraries(fail-util ${PROTOBUF_LIBRARY} ${Boost_LIBRARIES} ${LIB_IBERTY} ) + +option(BUILD_LLVM_DISASSEMBLER "Build the llvm based disassembler (exactly llvm 3.1 required)" OFF) +if (BUILD_LLVM_DISASSEMBLER) + add_subdirectory(llvmdisassembler) +endif (BUILD_LLVM_DISASSEMBLER) + diff --git a/src/core/util/llvmdisassembler/CMakeLists.txt b/src/core/util/llvmdisassembler/CMakeLists.txt new file mode 100644 index 00000000..62df6d76 --- /dev/null +++ b/src/core/util/llvmdisassembler/CMakeLists.txt @@ -0,0 +1,27 @@ +set(SRCS + LLVMDisassembler.cpp + LLVMDisassembler.hpp + LLVMtoFailBochs.cpp + LLVMtoFailBochs.hpp + LLVMtoFailGem5.hpp + LLVMtoFailGem5.cpp + LLVMtoFailTranslator.cpp + LLVMtoFailTranslator.hpp +) + +include(FindLLVM) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LLVM_CXX_FLAGS}" ) + +add_library(fail-llvmdisassembler ${SRCS}) +add_dependencies(fail-llvmdisassembler fail-sal) +target_link_libraries(fail-llvmdisassembler ${LLVM_LIBS} ${LLVM_LDFLAGS} ) + +### Tests +add_executable(llvmDisTest testing/llvmDisTest.cc) +target_link_libraries(llvmDisTest fail-llvmdisassembler fail-sal) + +add_test(NAME llvmDisx86Test COMMAND llvmDisTest ${CMAKE_CURRENT_SOURCE_DIR}/testing/x86 ) +add_test(NAME llvmDisx86_64Test COMMAND llvmDisTest ${CMAKE_CURRENT_SOURCE_DIR}/testing/x86_64 ) +add_test(NAME llvmDisARMM3Test COMMAND llvmDisTest ${CMAKE_CURRENT_SOURCE_DIR}/testing/armm3 ) +add_test(NAME llvmDisARM9Test COMMAND llvmDisTest ${CMAKE_CURRENT_SOURCE_DIR}/testing/arm9 ) diff --git a/src/core/util/llvmdisassembler/LLVMDisassembler.cpp b/src/core/util/llvmdisassembler/LLVMDisassembler.cpp new file mode 100644 index 00000000..356a2612 --- /dev/null +++ b/src/core/util/llvmdisassembler/LLVMDisassembler.cpp @@ -0,0 +1,151 @@ +#ifndef __puma +#include "LLVMDisassembler.hpp" + +using namespace fail; +using namespace llvm; +using namespace llvm::object; + + +LLVMtoFailTranslator & LLVMDisassembler::getTranslator() { + if ( ltofail == 0 ){ + std::cout << "ArchType: " << llvm::Triple::getArchTypeName( llvm::Triple::ArchType(object->getArch()) ) << std::endl; + + switch ( llvm::Triple::ArchType(object->getArch()) ) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + ltofail = new LLVMtoFailBochs; + break; + case llvm::Triple::arm: + ltofail = new LLVMtoFailGem5; + break; + default: + std::cout << " not supported :("; + exit(1); + } + } + return *ltofail; +} + +void LLVMDisassembler::disassemble() +{ + error_code ec; + for (section_iterator i = object->begin_sections(), + e = object->end_sections(); + i != e; i.increment(ec)) { + if (error(ec)) break; + bool text; + if (error(i->isText(text))) break; + if (!text) continue; + + uint64_t SectionAddr; + if (error(i->getAddress(SectionAddr))) break; + + uint64_t SectionLength; + if (error(i->getSize(SectionLength))) break; + + // Make a list of all the symbols in this section. + std::vector > Symbols; + for (symbol_iterator si = object->begin_symbols(), + se = object->end_symbols(); + si != se; si.increment(ec)) { + bool contains; + StringRef Name; + + if (!error(i->containsSymbol(*si, contains)) && contains) { + uint64_t Address; + if (error(si->getAddress(Address))) break; + Address -= SectionAddr; + + if (error(si->getName(Name))) break; + Symbols.push_back(std::make_pair(Address, Name)); + } + } + + // Sort the symbols by address, just in case they didn't come in that way. + array_pod_sort(Symbols.begin(), Symbols.end()); + + StringRef name; + if (error(i->getName(name))) break; + + // If the section has no symbols just insert a dummy one and disassemble + // the whole section. + if (Symbols.empty()) + Symbols.push_back(std::make_pair(0, name)); + + StringRef Bytes; + if (error(i->getContents(Bytes))) break; + StringRefMemoryObject memoryObject(Bytes); + uint64_t Size; + uint64_t Index; + uint64_t SectSize; + if (error(i->getSize(SectSize))) break; + + // Disassemble symbol by symbol. + for (unsigned si = 0, se = Symbols.size(); si != se; ++si) { + uint64_t Start = Symbols[si].first; + uint64_t End; + // The end is either the size of the section or the beginning of the next + // symbol. + if (si == se - 1) + End = SectSize; + // Make sure this symbol takes up space. + else if (Symbols[si + 1].first != Start) + End = Symbols[si + 1].first - 1; + else + // This symbol has the same address as the next symbol. Skip it. + continue; + + for (Index = Start; Index < End; Index += Size) { + MCInst Inst; + + if (disas->getInstruction(Inst, Size, memoryObject, Index, + nulls(), nulls())) { + const MCInstrDesc &desc = this->instr_info->get(Inst.getOpcode()); + // Inst.dump(); + Instr instr_info; + instr_info.opcode = Inst.getOpcode(); + instr_info.length = Size; + instr_info.address = SectionAddr + Index; + + unsigned int pos = 0; + for (MCInst::iterator it = Inst.begin(); it != Inst.end(); ++it) { + + if (it->isValid() && it->isReg() + && it->getReg() != 0 /* NOREG */) { + // Distinguish between input and + // output register operands + if (pos < desc.getNumDefs()) + instr_info.reg_defs.push_back(it->getReg()); + else + instr_info.reg_uses.push_back(it->getReg()); + } + pos ++; + } + const uint16_t *ptr = desc.getImplicitUses(); + for (unsigned int i = 0; i < desc.getNumImplicitUses(); i++) { + if (ptr[i] == 0) // NOREG + continue; + instr_info.reg_uses.push_back(ptr[i]); + } + ptr = desc.getImplicitDefs(); + for (unsigned int i = 0; i < desc.getNumImplicitDefs(); i++) { + if (ptr[i] == 0) // NOREG + continue; + instr_info.reg_defs.push_back(ptr[i]); + } + + // Insert the instruction info into the instr map + (*instrs)[instr_info.address] = instr_info; + } else { + if (Size == 0) + Size = 1; // skip illegible bytes + } + } + } + } + +} + +void LLVMDisassembler::StringRefMemoryObject::anchor() {} + +#endif diff --git a/src/core/util/llvmdisassembler/LLVMDisassembler.hpp b/src/core/util/llvmdisassembler/LLVMDisassembler.hpp new file mode 100644 index 00000000..7a0a4fe9 --- /dev/null +++ b/src/core/util/llvmdisassembler/LLVMDisassembler.hpp @@ -0,0 +1,141 @@ +#ifndef __LLVMDISASSEMBLER_HPP__ +#define __LLVMDISASSEMBLER_HPP__ + +#ifndef __puma + +#include +#include +#include +#include + +#include "llvm/Object/ObjectFile.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/MemoryObject.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/ADT/StringExtras.h" + +#include "llvm/Support/Casting.h" + +#include "llvm/ADT/OwningPtr.h" + +#include "LLVMtoFailTranslator.hpp" +#include "LLVMtoFailBochs.hpp" +#include "LLVMtoFailGem5.hpp" + +namespace fail { + +class LLVMDisassembler { + +public: + typedef uint16_t register_t; + typedef unsigned int address_t; + struct Instr { + unsigned int opcode; + unsigned int address; + unsigned char length; + std::vector reg_uses; + std::vector reg_defs; + }; + + typedef std::map InstrMap; + +private: + const llvm::object::ObjectFile *object; + const llvm::Target *target; + std::string triple; + std::string MCPU; + std::string FeaturesStr; + llvm::OwningPtr subtargetinfo; + llvm::OwningPtr disas; + llvm::OwningPtr instr_info; + llvm::OwningPtr register_info; + llvm::OwningPtr instrs; + + fail::LLVMtoFailTranslator * ltofail; + + + static std::string GetTriple(const llvm::object::ObjectFile *Obj) { + llvm::Triple TT("unknown-unknown-unknown"); + TT.setArch(llvm::Triple::ArchType(Obj->getArch())); + std::string TripleName = TT.str(); + return TripleName; + } + + + static const llvm::Target *GetTarget(const std::string &TripleName) { + // Get the target specific parser. + std::string Error; + const llvm::Target *TheTarget = llvm::TargetRegistry::lookupTarget(TripleName, Error); + if (TheTarget) + return TheTarget; + + std::cerr << "error: unable to get target for '" << TripleName + << std::endl; + return 0; + } + + static bool error(llvm::error_code ec) { + if (!ec) return false; + + std::cerr << "DIS" << ": error reading file: " << ec.message() << ".\n"; + return true; + } + + class StringRefMemoryObject : public llvm::MemoryObject { + virtual void anchor(); + llvm::StringRef Bytes; + public: + StringRefMemoryObject(llvm::StringRef bytes) : Bytes(bytes) {} + + uint64_t getBase() const { return 0; } + uint64_t getExtent() const { return Bytes.size(); } + + int readByte(uint64_t Addr, uint8_t *Byte) const { + if (Addr >= getExtent()) + return -1; + *Byte = Bytes[Addr]; + return 0; + } + }; + + + +public: + LLVMDisassembler(const llvm::object::ObjectFile *object) : ltofail(0) { + this->object = object; + this->triple = GetTriple(object); + this->target = GetTarget(triple); + this->subtargetinfo.reset(target->createMCSubtargetInfo(triple, MCPU, FeaturesStr)); + this->disas.reset(target->createMCDisassembler(*subtargetinfo)); + this->instr_info.reset(target->createMCInstrInfo()); + this->register_info.reset(target->createMCRegInfo(triple)); + + this->instrs.reset(new InstrMap()); + } + + ~LLVMDisassembler() { delete ltofail; }; + + InstrMap &getInstrMap() { return *instrs; }; + const llvm::MCRegisterInfo &getRegisterInfo() { return *register_info;} + fail::LLVMtoFailTranslator & getTranslator() ; + + const std::string & GetTriple() const { return triple; }; + + void disassemble(); +}; + + +} +#endif // puma +#endif // __LLVMDISASSEMBLER_HPP__ diff --git a/src/core/util/llvmdisassembler/LLVMtoFailBochs.cpp b/src/core/util/llvmdisassembler/LLVMtoFailBochs.cpp new file mode 100644 index 00000000..f1b47325 --- /dev/null +++ b/src/core/util/llvmdisassembler/LLVMtoFailBochs.cpp @@ -0,0 +1,50 @@ +#include "LLVMtoFailBochs.hpp" +#include "sal/x86/X86Architecture.hpp" + +using namespace fail; + +LLVMtoFailBochs::LLVMtoFailBochs() { +#ifndef __puma + /* 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 + + 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 + + llvm_to_fail_map[9] = reginfo_t(RID_CCX, 8, 8); // CH + llvm_to_fail_map[10] = reginfo_t(RID_CCX, 0xff); // CL + llvm_to_fail_map[28] = reginfo_t(RID_CCX, 16, 0); // CX + llvm_to_fail_map[46] = reginfo_t(RID_CCX); // ECX + + llvm_to_fail_map[29] = reginfo_t(RID_CDX, 8, 8); // DH + llvm_to_fail_map[32] = reginfo_t(RID_CDX, 0xff); // DL + llvm_to_fail_map[42] = reginfo_t(RID_CDX, 16, 0); // DX + llvm_to_fail_map[48] = reginfo_t(RID_CDX); // EDX + + 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 + + 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 + + llvm_to_fail_map[49] = reginfo_t(RID_FLAGS); // EFLAGS + + llvm_to_fail_map[50] = reginfo_t(RID_PC); // EIP + + llvm_to_fail_map[115] = reginfo_t(RID_CSI, 16, 0); // SI + llvm_to_fail_map[53] = reginfo_t(RID_CSI); // ESI + + 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 +#endif +} diff --git a/src/core/util/llvmdisassembler/LLVMtoFailBochs.hpp b/src/core/util/llvmdisassembler/LLVMtoFailBochs.hpp new file mode 100644 index 00000000..25161afa --- /dev/null +++ b/src/core/util/llvmdisassembler/LLVMtoFailBochs.hpp @@ -0,0 +1,19 @@ +#ifndef __LLVMTOFAILBOCHS_HPP_ +#define __LLVMTOFAILBOCHS_HPP_ + +#include "LLVMtoFailTranslator.hpp" +#include +#include + +namespace fail { + +class LLVMtoFailBochs : public LLVMtoFailTranslator { + +public: + + LLVMtoFailBochs(); + +}; +} // end of namespace + +#endif diff --git a/src/core/util/llvmdisassembler/LLVMtoFailGem5.cpp b/src/core/util/llvmdisassembler/LLVMtoFailGem5.cpp new file mode 100644 index 00000000..bac70b29 --- /dev/null +++ b/src/core/util/llvmdisassembler/LLVMtoFailGem5.cpp @@ -0,0 +1,28 @@ +#include "LLVMtoFailGem5.hpp" +#include "sal/arm/ArmArchitecture.hpp" + +using namespace fail; + +LLVMtoFailGem5::LLVMtoFailGem5() { +#ifndef __puma + /* 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); +#endif +} diff --git a/src/core/util/llvmdisassembler/LLVMtoFailGem5.hpp b/src/core/util/llvmdisassembler/LLVMtoFailGem5.hpp new file mode 100644 index 00000000..92e46aba --- /dev/null +++ b/src/core/util/llvmdisassembler/LLVMtoFailGem5.hpp @@ -0,0 +1,19 @@ +#ifndef __LLVMTOFAILGEM5_HPP_ +#define __LLVMTOFAILGEM5_HPP_ + +#include "LLVMtoFailTranslator.hpp" +#include +#include + +namespace fail { + +class LLVMtoFailGem5 : public LLVMtoFailTranslator { + +public: + + LLVMtoFailGem5(); + +}; +} // end of namespace + +#endif diff --git a/src/core/util/llvmdisassembler/LLVMtoFailTranslator.cpp b/src/core/util/llvmdisassembler/LLVMtoFailTranslator.cpp new file mode 100644 index 00000000..0d10e1a2 --- /dev/null +++ b/src/core/util/llvmdisassembler/LLVMtoFailTranslator.cpp @@ -0,0 +1,42 @@ +#include "LLVMtoFailTranslator.hpp" +#include "sal/SALInst.hpp" + +using namespace fail; + +const LLVMtoFailTranslator::reginfo_t & LLVMtoFailTranslator::getFailRegisterID(unsigned int regid) { +#ifndef __puma + ltof_map_t::iterator it = llvm_to_fail_map.find(regid); + if( it != llvm_to_fail_map.end() ) {// found + return (*it).second; + } else { // not found + std::cout << "Fail ID for LLVM Register id " << regid << " not found :(" << std::endl; + //exit(EXIT_FAILURE); + return notfound; + } +#endif +} + +regdata_t LLVMtoFailTranslator::getRegisterContent(ConcreteCPU& cpu, const reginfo_t ®info){ + regdata_t result; + + Register* reg = cpu.getRegister(reginfo.id); + result = cpu.getRegisterContent(reg); + + result &= reginfo.mask; + result >>= reginfo.offset; + + return result; +} + +void LLVMtoFailTranslator::setRegisterContent(ConcreteCPU & cpu, const reginfo_t ®info, regdata_t value){ + Register* reg = cpu.getRegister(reginfo.id); + + regdata_t origval = cpu.getRegisterContent(reg); // Get register Value from fail + origval &= ~(reginfo.mask); // clear bits to write + + value <<= reginfo.offset; // shift value to write up to position + value &= reginfo.mask; // mask out trailing and leading bits + value |= origval; // set bits to write + + cpu.setRegisterContent( reg, value ); // write back register content +} diff --git a/src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp b/src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp new file mode 100644 index 00000000..4e9444c2 --- /dev/null +++ b/src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp @@ -0,0 +1,67 @@ +#ifndef __LLVMTOFAILTRANSLATOR_HPP_ +#define __LLVMTOFAILTRANSLATOR_HPP_ + +#include "sal/SALConfig.hpp" +#include "sal/ConcreteCPU.hpp" +#include + +namespace fail { + +/** + * Translates LLVM disassembler ids + * to Fail* SAL representations. + */ +class LLVMtoFailTranslator { +public: + struct reginfo_t { + int id; + regwidth_t width; + regdata_t mask; + byte_t offset; + + int toDataAddress() const { + // .. 5 4 | 7 6 5 4 | 3 2 1 0 + // | | + return (id << 8) | ((width/8) << 4) | (offset / 8); + } + static reginfo_t fromDataAddress(int addr) { + int id = addr >> 8; + regwidth_t width = ((addr >> 4) & 0xf) * 8; + byte_t offset = (addr & 0xf) * 8; + return reginfo_t(id, width, offset); + } + + + reginfo_t(int id=-1, regwidth_t width = 32, byte_t offs = 0) + : id(id), width(width), mask((regwidth_t)((((long long)1 << width) - 1) << offs)), offset(offs) {}; + }; +protected: + + LLVMtoFailTranslator(){}; + +#ifndef __puma + typedef std::map ltof_map_t; + ltof_map_t llvm_to_fail_map; +#endif + + +public: + const reginfo_t & getFailRegisterID(unsigned int regid); + + regdata_t getRegisterContent(ConcreteCPU & cpu, const reginfo_t & reg); + void setRegisterContent(ConcreteCPU & cpu, const reginfo_t ®, regdata_t value); + regdata_t getRegisterContent(ConcreteCPU & cpu, unsigned int llvmid) { + return getRegisterContent(cpu, getFailRegisterID(llvmid)); + } + void setRegisterContent(ConcreteCPU & cpu, unsigned int llvmid, regdata_t value) { + setRegisterContent(cpu, getFailRegisterID(llvmid), value); + } + + int getFailRegisterId(unsigned int regid) { return this->getFailRegisterID(regid).id; }; +private: + reginfo_t notfound; +}; + +} // end of namespace + +#endif diff --git a/src/core/util/llvmdisassembler/testing/arm9 b/src/core/util/llvmdisassembler/testing/arm9 new file mode 100755 index 00000000..854f81e4 Binary files /dev/null and b/src/core/util/llvmdisassembler/testing/arm9 differ diff --git a/src/core/util/llvmdisassembler/testing/armm3 b/src/core/util/llvmdisassembler/testing/armm3 new file mode 100755 index 00000000..637f00bc Binary files /dev/null and b/src/core/util/llvmdisassembler/testing/armm3 differ diff --git a/src/core/util/llvmdisassembler/testing/armregs.txt b/src/core/util/llvmdisassembler/testing/armregs.txt new file mode 100644 index 00000000..3b6c21cb --- /dev/null +++ b/src/core/util/llvmdisassembler/testing/armregs.txt @@ -0,0 +1,281 @@ +Triple: arm-unknown-unknown + +Number of Registers: 278 +0 - NOREG +1 - APSR +2 - CPSR +3 - D0 +4 - D1 +5 - D2 +6 - D3 +7 - D4 +8 - D5 +9 - D6 +10 - D7 +11 - D8 +12 - D9 +13 - D10 +14 - D11 +15 - D12 +16 - D13 +17 - D14 +18 - D15 +19 - D16 +20 - D17 +21 - D18 +22 - D19 +23 - D20 +24 - D21 +25 - D22 +26 - D23 +27 - D24 +28 - D25 +29 - D26 +30 - D27 +31 - D28 +32 - D29 +33 - D30 +34 - D31 +35 - FPEXC +36 - FPSCR +37 - FPSCR_NZCV +38 - FPSID +39 - ITSTATE +40 - LR +41 - MVFR0 +42 - MVFR1 +43 - PC +44 - Q0 +45 - Q1 +46 - Q2 +47 - Q3 +48 - Q4 +49 - Q5 +50 - Q6 +51 - Q7 +52 - Q8 +53 - Q9 +54 - Q10 +55 - Q11 +56 - Q12 +57 - Q13 +58 - Q14 +59 - Q15 +60 - R0 +61 - R1 +62 - R2 +63 - R3 +64 - R4 +65 - R5 +66 - R6 +67 - R7 +68 - R8 +69 - R9 +70 - R10 +71 - R11 +72 - R12 +73 - S0 +74 - S1 +75 - S2 +76 - S3 +77 - S4 +78 - S5 +79 - S6 +80 - S7 +81 - S8 +82 - S9 +83 - S10 +84 - S11 +85 - S12 +86 - S13 +87 - S14 +88 - S15 +89 - S16 +90 - S17 +91 - S18 +92 - S19 +93 - S20 +94 - S21 +95 - S22 +96 - S23 +97 - S24 +98 - S25 +99 - S26 +100 - S27 +101 - S28 +102 - S29 +103 - S30 +104 - S31 +105 - SP +106 - SPSR +107 - D0_D2 +108 - D1_D3 +109 - D2_D4 +110 - D3_D5 +111 - D4_D6 +112 - D5_D7 +113 - D6_D8 +114 - D7_D9 +115 - D8_D10 +116 - D9_D11 +117 - D10_D12 +118 - D11_D13 +119 - D12_D14 +120 - D13_D15 +121 - D14_D16 +122 - D15_D17 +123 - D16_D18 +124 - D17_D19 +125 - D18_D20 +126 - D19_D21 +127 - D20_D22 +128 - D21_D23 +129 - D22_D24 +130 - D23_D25 +131 - D24_D26 +132 - D25_D27 +133 - D26_D28 +134 - D27_D29 +135 - D28_D30 +136 - D29_D31 +137 - Q0_Q1 +138 - Q1_Q2 +139 - Q2_Q3 +140 - Q3_Q4 +141 - Q4_Q5 +142 - Q5_Q6 +143 - Q6_Q7 +144 - Q7_Q8 +145 - Q8_Q9 +146 - Q9_Q10 +147 - Q10_Q11 +148 - Q11_Q12 +149 - Q12_Q13 +150 - Q13_Q14 +151 - Q14_Q15 +152 - Q0_Q1_Q2_Q3 +153 - Q1_Q2_Q3_Q4 +154 - Q2_Q3_Q4_Q5 +155 - Q3_Q4_Q5_Q6 +156 - Q4_Q5_Q6_Q7 +157 - Q5_Q6_Q7_Q8 +158 - Q6_Q7_Q8_Q9 +159 - Q7_Q8_Q9_Q10 +160 - Q8_Q9_Q10_Q11 +161 - Q9_Q10_Q11_Q12 +162 - Q10_Q11_Q12_Q13 +163 - Q11_Q12_Q13_Q14 +164 - Q12_Q13_Q14_Q15 +165 - D0_D1_D2 +166 - D1_D2_D3 +167 - D2_D3_D4 +168 - D3_D4_D5 +169 - D4_D5_D6 +170 - D5_D6_D7 +171 - D6_D7_D8 +172 - D7_D8_D9 +173 - D8_D9_D10 +174 - D9_D10_D11 +175 - D10_D11_D12 +176 - D11_D12_D13 +177 - D12_D13_D14 +178 - D13_D14_D15 +179 - D14_D15_D16 +180 - D15_D16_D17 +181 - D16_D17_D18 +182 - D17_D18_D19 +183 - D18_D19_D20 +184 - D19_D20_D21 +185 - D20_D21_D22 +186 - D21_D22_D23 +187 - D22_D23_D24 +188 - D23_D24_D25 +189 - D24_D25_D26 +190 - D25_D26_D27 +191 - D26_D27_D28 +192 - D27_D28_D29 +193 - D28_D29_D30 +194 - D29_D30_D31 +195 - D0_D2_D4 +196 - D1_D3_D5 +197 - D2_D4_D6 +198 - D3_D5_D7 +199 - D4_D6_D8 +200 - D5_D7_D9 +201 - D6_D8_D10 +202 - D7_D9_D11 +203 - D8_D10_D12 +204 - D9_D11_D13 +205 - D10_D12_D14 +206 - D11_D13_D15 +207 - D12_D14_D16 +208 - D13_D15_D17 +209 - D14_D16_D18 +210 - D15_D17_D19 +211 - D16_D18_D20 +212 - D17_D19_D21 +213 - D18_D20_D22 +214 - D19_D21_D23 +215 - D20_D22_D24 +216 - D21_D23_D25 +217 - D22_D24_D26 +218 - D23_D25_D27 +219 - D24_D26_D28 +220 - D25_D27_D29 +221 - D26_D28_D30 +222 - D27_D29_D31 +223 - D0_D2_D4_D6 +224 - D1_D3_D5_D7 +225 - D2_D4_D6_D8 +226 - D3_D5_D7_D9 +227 - D4_D6_D8_D10 +228 - D5_D7_D9_D11 +229 - D6_D8_D10_D12 +230 - D7_D9_D11_D13 +231 - D8_D10_D12_D14 +232 - D9_D11_D13_D15 +233 - D10_D12_D14_D16 +234 - D11_D13_D15_D17 +235 - D12_D14_D16_D18 +236 - D13_D15_D17_D19 +237 - D14_D16_D18_D20 +238 - D15_D17_D19_D21 +239 - D16_D18_D20_D22 +240 - D17_D19_D21_D23 +241 - D18_D20_D22_D24 +242 - D19_D21_D23_D25 +243 - D20_D22_D24_D26 +244 - D21_D23_D25_D27 +245 - D22_D24_D26_D28 +246 - D23_D25_D27_D29 +247 - D24_D26_D28_D30 +248 - D25_D27_D29_D31 +249 - D1_D2 +250 - D3_D4 +251 - D5_D6 +252 - D7_D8 +253 - D9_D10 +254 - D11_D12 +255 - D13_D14 +256 - D15_D16 +257 - D17_D18 +258 - D19_D20 +259 - D21_D22 +260 - D23_D24 +261 - D25_D26 +262 - D27_D28 +263 - D29_D30 +264 - D1_D2_D3_D4 +265 - D3_D4_D5_D6 +266 - D5_D6_D7_D8 +267 - D7_D8_D9_D10 +268 - D9_D10_D11_D12 +269 - D11_D12_D13_D14 +270 - D13_D14_D15_D16 +271 - D15_D16_D17_D18 +272 - D17_D18_D19_D20 +273 - D19_D20_D21_D22 +274 - D21_D22_D23_D24 +275 - D23_D24_D25_D26 +276 - D25_D26_D27_D28 +277 - D27_D28_D29_D30 diff --git a/src/core/util/llvmdisassembler/testing/bubble.cc b/src/core/util/llvmdisassembler/testing/bubble.cc new file mode 100644 index 00000000..c9685e33 --- /dev/null +++ b/src/core/util/llvmdisassembler/testing/bubble.cc @@ -0,0 +1,71 @@ +#include + +class random_generator_t +{ +private: + unsigned int a; // (sqrt(5)-1)/2 = 0.61803398875 + unsigned int b; + unsigned int last_val; + unsigned int sd; +public: + void forth() { + last_val = a*last_val + b; + } + + + random_generator_t(unsigned int seed = 1) + : a(2654435769), b(seed), last_val(1), sd(seed){ + forth(); + } + + unsigned int item() const { + return last_val; + } + + void reset() { + last_val = 1; + b = sd; + forth(); + } +}; + + + + +void sort(int len, int arr[] ) +{ + int tmp; + int again; + int i; + + for(again=1; again; ) + for( again=0, i=0; i < (len-1); ++i){ + assert(0<=i && i+1 arr[i+1] ){ + tmp = arr[i]; + arr[i] = arr[i+1]; + arr[i+1] = tmp; + again = 1; + } + } +} + + + + +int main() +{ + const unsigned int arr_size = 10000; //50000; + + int arr[arr_size]; + int i; + random_generator_t rand; + + for(i=0; i!=arr_size; ++i){ + arr[i] = rand.item(); + rand.forth(); + } + + sort(arr_size, arr); +} + diff --git a/src/core/util/llvmdisassembler/testing/howtobuild.txt b/src/core/util/llvmdisassembler/testing/howtobuild.txt new file mode 100644 index 00000000..5b678fd1 --- /dev/null +++ b/src/core/util/llvmdisassembler/testing/howtobuild.txt @@ -0,0 +1,4 @@ +g++ -m32 bubble.cc -o x86 +g++ -m64 bubble.cc -o x86_64 +arm-none-eabi-g++ -mcpu=cortex-m3 bubble.cc -o armm3 +arm-none-eabi-g++ -mcpu=arm9 bubble.cc -o arm9 diff --git a/src/core/util/llvmdisassembler/testing/llvmDisTest.cc b/src/core/util/llvmdisassembler/testing/llvmDisTest.cc new file mode 100644 index 00000000..4ada92ee --- /dev/null +++ b/src/core/util/llvmdisassembler/testing/llvmDisTest.cc @@ -0,0 +1,68 @@ +#ifndef __puma +#include "../LLVMDisassembler.hpp" + +using namespace llvm; +using namespace llvm::object; +using namespace fail; + +int main(int argc, char* argv[]) { + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + // Initialize targets and assembly printers/parsers. + llvm::InitializeAllTargetInfos(); + llvm::InitializeAllTargetMCs(); + // llvm::InitializeAllAsmParsers(); + llvm::InitializeAllDisassemblers(); + + std::string file; + + if(argc > 1){ + std::cout << "Trying to disassemble: " << argv[1] << std::endl; + file = argv[1]; + } else { + std::cerr << "No file to disassemble :(" << std::endl; + return -1; + } + + OwningPtr binary; + if (error_code ec = createBinary(file, binary)) { + std::cerr << "Dis" << ": '" << file << "': " << ec.message() << ".\n"; + return -1; + } + + ObjectFile *obj = dyn_cast(binary.get()); + + LLVMDisassembler disas(obj); + disas.disassemble(); + + LLVMDisassembler::InstrMap &instr_map = disas.getInstrMap(); + std::cout << "Map Size: " << instr_map.size() << "\nTriple: " << disas.GetTriple() << std::endl; + + LLVMDisassembler::InstrMap::const_iterator itr; + const MCRegisterInfo ®_info = disas.getRegisterInfo(); + + std::cout << std::endl << "Number of Registers: " << reg_info.getNumRegs() << std::endl; + // for(unsigned int i = 0; i < reg_info.getNumRegs(); ++i){ + // std::cout << i << " - " << reg_info.getName(i) << std::endl; + // } + fail::LLVMtoFailTranslator & ltof = disas.getTranslator() ; + + for(itr = instr_map.begin(); itr != instr_map.end(); ++itr){ + const LLVMDisassembler::Instr &instr = (*itr).second; + std::cout << std::hex << (*itr).first << " | " << instr.opcode << std::endl; + std::cout << std::dec << "USES: "; + for (std::vector::const_iterator it = instr.reg_uses.begin(); + it != instr.reg_uses.end(); ++it) { + std::cout << reg_info.getName(*it) <<"(" << *it << ") "; + std::cout << "Fail: " << ltof.getFailRegisterId(*it) << " "; + } + std::cout << std::endl; + + std::cout << "DEFS: "; + for (std::vector::const_iterator it = instr.reg_defs.begin(); + it != instr.reg_defs.end(); ++it) { + std::cout << reg_info.getName(*it) << "(" << *it << ") "; + } + std::cout << std::endl; + } +} +#endif diff --git a/src/core/util/llvmdisassembler/testing/x86 b/src/core/util/llvmdisassembler/testing/x86 new file mode 100755 index 00000000..3dac5193 Binary files /dev/null and b/src/core/util/llvmdisassembler/testing/x86 differ diff --git a/src/core/util/llvmdisassembler/testing/x86_64 b/src/core/util/llvmdisassembler/testing/x86_64 new file mode 100755 index 00000000..513f3211 Binary files /dev/null and b/src/core/util/llvmdisassembler/testing/x86_64 differ diff --git a/src/core/util/llvmdisassembler/testing/x86regs.txt b/src/core/util/llvmdisassembler/testing/x86regs.txt new file mode 100644 index 00000000..bc01c6c5 --- /dev/null +++ b/src/core/util/llvmdisassembler/testing/x86regs.txt @@ -0,0 +1,163 @@ +Triple: x86_64-unknown-unknown + +Number of Registers: 160 +0 - NOREG +1 - AH +2 - AL +3 - AX +4 - BH +5 - BL +6 - BP +7 - BPL +8 - BX +9 - CH +10 - CL +11 - CR0 +12 - CR1 +13 - CR2 +14 - CR3 +15 - CR4 +16 - CR5 +17 - CR6 +18 - CR7 +19 - CR8 +20 - CR9 +21 - CR10 +22 - CR11 +23 - CR12 +24 - CR13 +25 - CR14 +26 - CR15 +27 - CS +28 - CX +29 - DH +30 - DI +31 - DIL +32 - DL +33 - DR0 +34 - DR1 +35 - DR2 +36 - DR3 +37 - DR4 +38 - DR5 +39 - DR6 +40 - DR7 +41 - DS +42 - DX +43 - EAX +44 - EBP +45 - EBX +46 - ECX +47 - EDI +48 - EDX +49 - EFLAGS +50 - EIP +51 - EIZ +52 - ES +53 - ESI +54 - ESP +55 - FP0 +56 - FP1 +57 - FP2 +58 - FP3 +59 - FP4 +60 - FP5 +61 - FP6 +62 - FS +63 - GS +64 - IP +65 - MM0 +66 - MM1 +67 - MM2 +68 - MM3 +69 - MM4 +70 - MM5 +71 - MM6 +72 - MM7 +73 - R8 +74 - R8B +75 - R8D +76 - R8W +77 - R9 +78 - R9B +79 - R9D +80 - R9W +81 - R10 +82 - R10B +83 - R10D +84 - R10W +85 - R11 +86 - R11B +87 - R11D +88 - R11W +89 - R12 +90 - R12B +91 - R12D +92 - R12W +93 - R13 +94 - R13B +95 - R13D +96 - R13W +97 - R14 +98 - R14B +99 - R14D +100 - R14W +101 - R15 +102 - R15B +103 - R15D +104 - R15W +105 - RAX +106 - RBP +107 - RBX +108 - RCX +109 - RDI +110 - RDX +111 - RIP +112 - RIZ +113 - RSI +114 - RSP +115 - SI +116 - SIL +117 - SP +118 - SPL +119 - SS +120 - ST0 +121 - ST1 +122 - ST2 +123 - ST3 +124 - ST4 +125 - ST5 +126 - ST6 +127 - ST7 +128 - XMM0 +129 - XMM1 +130 - XMM2 +131 - XMM3 +132 - XMM4 +133 - XMM5 +134 - XMM6 +135 - XMM7 +136 - XMM8 +137 - XMM9 +138 - XMM10 +139 - XMM11 +140 - XMM12 +141 - XMM13 +142 - XMM14 +143 - XMM15 +144 - YMM0 +145 - YMM1 +146 - YMM2 +147 - YMM3 +148 - YMM4 +149 - YMM5 +150 - YMM6 +151 - YMM7 +152 - YMM8 +153 - YMM9 +154 - YMM10 +155 - YMM11 +156 - YMM12 +157 - YMM13 +158 - YMM14 +159 - YMM15