From: Christoph Egger Date: Wed, 25 Mar 2015 17:13:20 +0000 (+0100) Subject: Preliminary LLVM-3.6 support X-Git-Tag: v0.1~12 X-Git-Url: https://git.siccegge.de//index.cgi?p=frida%2Ffrida.git;a=commitdiff_plain;h=1a19eafdb36507230a6f421defbc49162d5246e6 Preliminary LLVM-3.6 support Allows llvm-3.6 in cmake and does compile with 3.6. However it does *not* work! It will segfault right away. One of the suspects is different base for addresses used in llvm's getInstruction() and family. --- diff --git a/CMakeLists.txt b/CMakeLists.txt index cbc597f..c54380d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,7 +96,7 @@ qt5_use_modules(frida Widgets) TARGET_LINK_LIBRARIES(frida ${QT_LIBRARIES} ${LLVM_LDFLAGS} - -lLLVM-3.5 + ${LLVM_DYNAMIC_LIB} ${LLVM_SYSTEM_LIBS} ${LOG4CXX_LDFLAGS} ${QUAZIP_LIBRARIES}) @@ -140,7 +140,16 @@ qt5_use_modules(fridatest Widgets) ADD_SUBDIRECTORY(/usr/src/gmock gmock) enable_testing() add_test(NAME fridatest COMMAND fridatest ${CMAKE_SOURCE_DIR}/testdata) -target_link_libraries(fridatest gmock gtest ${QT_LIBRARIES} ${LLVM_LDFLAGS} -lLLVM-3.5 ${LLVM_SYSTEM_LIBS} ${LOG4CXX_LDFLAGS} ${GUILE_LDFLAGS} ${QUAZIP_LIBRARIES}) +target_link_libraries(fridatest + gmock + gtest + ${QT_LIBRARIES} + ${LLVM_LDFLAGS} + ${LLVM_DYNAMIC_LIB} + ${LLVM_SYSTEM_LIBS} + ${LOG4CXX_LDFLAGS} + ${GUILE_LDFLAGS} + ${QUAZIP_LIBRARIES}) target_compile_options(fridatest PRIVATE -DCONFIG_TEST) set_property(TEST fridatest APPEND PROPERTY ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_CURRENT_BINARY_DIR}) diff --git a/cmake/Modules/FindLLVM.cmake b/cmake/Modules/FindLLVM.cmake index ba2dd15..6cf5e71 100644 --- a/cmake/Modules/FindLLVM.cmake +++ b/cmake/Modules/FindLLVM.cmake @@ -1,10 +1,10 @@ -find_program(LLVM_CONFIG NAMES llvm-config-3.5 llvm-config) +find_program(LLVM_CONFIG NAMES llvm-config-3.5 llvm-config llvm-config-3.6) if(LLVM_CONFIG) execute_process(COMMAND ${LLVM_CONFIG} --version OUTPUT_VARIABLE LLVM_VERSION) - if(((${LLVM_VERSION} VERSION_LESS 3.6.0) + if(((${LLVM_VERSION} VERSION_LESS 3.7.0) AND (${LLVM_VERSION} VERSION_GREATER 3.5)) OR (${LLVM_VERSION} VERSION_EQUAL 3.5)) @@ -24,6 +24,15 @@ if(LLVM_CONFIG) string(REPLACE -I "-isystem" LLVM_CFLAGS ${LLVM_CFLAGS}) separate_arguments(LLVM_CFLAGS) + + if(${LLVM_VERSION} VERSION_LESS 3.6) + set(LLVM_CFLAGS ${LLVM_CFLAGS} -DLLVM_35) + set(LLVM_DYNAMIC_LIB -lLLVM-3.5) + else() + set(LLVM_CFLAGS ${LLVM_CFLAGS} -DLLVM_36) + set(LLVM_DYNAMIC_LIB -lLLVM-3.6) + message(WARNING "LLVM 3.6 support is highly experimental and may be broken in interesting ways") + endif() endif() endif() diff --git a/src/disassembler/llvm/LLVMDisassembler.cxx b/src/disassembler/llvm/LLVMDisassembler.cxx index 45cd04e..e673c37 100644 --- a/src/disassembler/llvm/LLVMDisassembler.cxx +++ b/src/disassembler/llvm/LLVMDisassembler.cxx @@ -36,13 +36,16 @@ Disassembler * createLLVMDisassembler(const std::string& filename, InformationMa LOG4CXX_ERROR(logger, ec.message()); return NULL; } - +#if defined(LLVM_35) Binary * op = retval.get(); - - if (!op) { - LOG4CXX_ERROR(logger, "Could not open " << filename); - return NULL; - } +#elif defined(LLVM_36) + OwningBinary ob; + ob = std::move(retval.get()); + Binary* op = ob.getBinary(); + auto foo = ob.takeBinary(); + foo.first.release(); + foo.second.release(); +#endif // ELFType if (ELF32LEObjectFile * object = dyn_cast(op)) { @@ -93,7 +96,15 @@ LLVMDisassembler::LLVMDisassembler(const std::string& filename, return; } +#if defined(LLVM_35) binary.reset(result.get()); +#elif defined(LLVM_36) + OwningBinary ob; + ob = std::move(result.get()); + Binary* op = ob.getBinary(); + + binary.reset(op); +#endif o = dyn_cast(binary.get()); } else { @@ -176,8 +187,8 @@ LLVMDisassembler::LLVMDisassembler(const std::string& filename, IP->setPrintImmHex(llvm::HexStyle::C); IP->setPrintImmHex(true); - std::unique_ptr OD( - new MCObjectDisassembler(*o, *DisAsm, *MIA)); +// std::unique_ptr OD( +// new MCObjectDisassembler(*o, *DisAsm, *MIA)); //Mod.reset(OD->buildModule(false)); readSections(); @@ -198,9 +209,13 @@ Function* LLVMDisassembler::disassembleFunctionAt(uint64_t address, const Function * function; SectionRef text_section = getTextSection(); uint64_t base_address, size; +#if defined(LLVM_35) text_section.getAddress(base_address); text_section.getSize(size); - +#elif defined(LLVM_36) + base_address = text_section.getAddress(); + size = text_section.getSize(); +#endif if (address < base_address || address >= base_address + size) { return NULL; @@ -235,7 +250,14 @@ void LLVMDisassembler::disassembleFunction(Function* function) { SectionRef text_section = getTextSection(); StringRef bytes; text_section.getContents(bytes); +#if defined(LLVM_35) StringRefMemoryObject ref(bytes); +#elif defined(LLVM_36) + ArrayRef bytearray(reinterpret_cast(bytes.data()), + bytes.size()); +#else +#error LLVM != 3.5 | 3.6 not supported +#endif LOG4CXX_DEBUG(logger, "Handling function " << function->getName()); @@ -245,8 +267,13 @@ void LLVMDisassembler::disassembleFunction(Function* function) { function->addBasicBlock(block); uint64_t base_address, size; +#if defined(LLVM_35) text_section.getAddress(base_address); text_section.getSize(size); +#elif defined(LLVM_36) + base_address = text_section.getAddress(); + size = text_section.getSize(); +#endif LOG4CXX_DEBUG(logger, "Text section at " << std::hex << base_address << " with size " << size); while (remaining_blocks.size()) { @@ -264,7 +291,14 @@ void LLVMDisassembler::disassembleFunction(Function* function) { llvm::raw_string_ostream s(buf); if(llvm::MCDisassembler::Success == +#if defined(LLVM_35) DisAsm->getInstruction(inst, inst_size, ref, current_address, nulls(), nulls())) { +#elif defined(LLVM_36) + DisAsm->getInstruction(inst, inst_size, + bytearray.slice(current_address), + base_address + current_address, + nulls(), nulls())) { +#endif uint64_t jmptarget; if (MIA->evaluateBranch(inst, current_address, inst_size, jmptarget)) { @@ -336,8 +370,11 @@ void LLVMDisassembler::disassemble() { bool contains; SymbolRef::Type symbol_type; - +#if defined(LLVM_35) if (text_section.containsSymbol(x->second, contains) || !contains) +#elif defined(LLVM_36) + if (text_section.containsSymbol(x->second)) +#endif continue; if (x->second.getType(symbol_type) @@ -373,7 +410,11 @@ void LLVMDisassembler::disassemble() { if (!manager->hasFunctions()) { uint64_t text_entry; +#if defined(LLVM_35) text_section.getAddress(text_entry); +#elif defined(LLVM_36) + text_entry = text_section.getAddress(); +#endif LOG4CXX_INFO(logger, "No Symbols found, starting at the beginning of the text segment"); disassembleFunctionAt(text_entry); } @@ -414,7 +455,13 @@ void LLVMDisassembler::splitBlocks(Function* function) { SectionRef text_section = getTextSection(); StringRef bytes; text_section.getContents(bytes); +#if defined(LLVM_35) StringRefMemoryObject ref(bytes); +#elif defined(LLVM_36) + ArrayRef bytearray(reinterpret_cast(bytes.data()), + bytes.size()); +#endif + LOG4CXX_DEBUG(logger, "Splitting Blocks in Function " << function->getName()); // Split blocks where jumps are going inside the block @@ -428,7 +475,11 @@ void LLVMDisassembler::splitBlocks(Function* function) { } uint64_t inst_size; uint64_t base_address; +#if defined(LLVM_35) text_section.getAddress(base_address); +#elif defined(LLVM_36) + base_address = text_section.getAddress(); +#endif uint64_t current_address = current_block->getStartAddress() - base_address; while(current_block->getEndAddress() - base_address > current_address) { MCInst inst; @@ -436,7 +487,15 @@ void LLVMDisassembler::splitBlocks(Function* function) { llvm::raw_string_ostream s(buf); if(llvm::MCDisassembler::Success == +#if defined(LLVM_35) DisAsm->getInstruction(inst, inst_size, ref, current_address, nulls(), nulls())) { +#elif defined(LLVM_36) + DisAsm->getInstruction(inst, inst_size, + bytearray.slice(current_address), + base_address + current_address, + nulls(), nulls())) { +#endif + // See if some other block starts here BasicBlock* other = manager->getBasicBlock(current_address + inst_size @@ -541,13 +600,24 @@ std::vector LLVMDisassembler::getInstructions(const BasicBloc std::vector result; SectionRef text_section = getTextSection(); uint64_t base_address; +#if defined(LLVM_35) text_section.getAddress(base_address); +#elif defined(LLVM_36) + base_address = text_section.getAddress(); +#endif + uint64_t current_address = block->getStartAddress() - base_address; uint64_t end_position = block->getEndAddress() - base_address; StringRef bytes; text_section.getContents(bytes); +#if defined(LLVM_35) StringRefMemoryObject ref(bytes); +#elif defined(LLVM_36) + ArrayRef bytearray(reinterpret_cast(bytes.data()), + bytes.size()); +#endif + while (current_address < end_position) { uint64_t inst_size; @@ -556,10 +626,24 @@ std::vector LLVMDisassembler::getInstructions(const BasicBloc llvm::raw_string_ostream s(buf); if(llvm::MCDisassembler::Success == - DisAsm->getInstruction(inst, inst_size, ref, current_address, nulls(), nulls())) { +#if defined(LLVM_35) + DisAsm->getInstruction(inst, inst_size, ref, current_address, nulls(), nulls())) { +#elif defined(LLVM_36) + DisAsm->getInstruction(inst, inst_size, + bytearray.slice(current_address), + base_address + current_address, + nulls(), nulls())) { +#endif uint8_t bytes[inst_size+2]; +#if defined(LLVM_35) ref.readBytes(current_address, inst_size, bytes); +#elif defined(LLVM_36) + size_t bytesindex(0); + for (uint8_t byte : bytearray.slice(current_address, inst_size)) { + bytes[bytesindex++] = byte; + } +#endif uint64_t jmptarget; std::string ref(""); @@ -579,7 +663,11 @@ std::vector LLVMDisassembler::getInstructions(const BasicBloc } else { LOG4CXX_WARN(logger, "Invalid byte at" << std::hex << current_address + base_address); uint8_t bytes[1]; +#if defined(LLVM_35) ref.readBytes(current_address, 1, bytes); +#elif defined(LLVM_36) + bytes[0] = bytearray[current_address]; +#endif result.push_back(Instruction(current_address + base_address, "Invalid Instruction", std::vector(bytes, bytes+1), "")); inst_size = 1; @@ -597,12 +685,23 @@ void LLVMDisassembler::printEachInstruction(uint64_t start, uint64_t end, const std::string&)> fun) { SectionRef text_section = getTextSection(); uint64_t base_address; +#if defined(LLVM_35) text_section.getAddress(base_address); +#elif defined(LLVM_36) + base_address = text_section.getAddress(); +#endif + uint64_t current_address = start - base_address; StringRef bytes; text_section.getContents(bytes); +#if defined(LLVM_35) StringRefMemoryObject ref(bytes); +#elif defined(LLVM_36) + ArrayRef bytearray(reinterpret_cast(bytes.data()), + bytes.size()); +#endif + while (current_address < end - base_address) { uint64_t inst_size; @@ -611,10 +710,24 @@ void LLVMDisassembler::printEachInstruction(uint64_t start, uint64_t end, llvm::raw_string_ostream s(buf); if(llvm::MCDisassembler::Success == - DisAsm->getInstruction(inst, inst_size, ref, current_address, nulls(), nulls())) { +#if defined(LLVM_35) + DisAsm->getInstruction(inst, inst_size, ref, current_address, nulls(), nulls())) { +#elif defined(LLVM_36) + DisAsm->getInstruction(inst, inst_size, + bytearray.slice(current_address), + base_address + current_address, + nulls(), nulls())) { +#endif uint8_t bytes[inst_size+2]; +#if defined(LLVM_35) ref.readBytes(current_address, inst_size, bytes); +#elif defined(LLVM_36) + size_t bytesindex(0); + for (uint8_t byte : bytearray.slice(current_address, inst_size)) { + bytes[bytesindex++] = byte; + } +#endif uint64_t jmptarget; std::string ref(""); diff --git a/src/disassembler/llvm/LLVMDisassembler.hxx b/src/disassembler/llvm/LLVMDisassembler.hxx index df01c9a..d8d4056 100644 --- a/src/disassembler/llvm/LLVMDisassembler.hxx +++ b/src/disassembler/llvm/LLVMDisassembler.hxx @@ -54,7 +54,7 @@ private: std::unique_ptr MRI; std::unique_ptr AsmInfo; - std::unique_ptr Mod; +// std::unique_ptr Mod; std::unique_ptr IP; std::unique_ptr DisAsm; std::unique_ptr MOFI; diff --git a/src/disassembler/llvm/include_llvm.hxx b/src/disassembler/llvm/include_llvm.hxx index 46028f5..2f73af4 100644 --- a/src/disassembler/llvm/include_llvm.hxx +++ b/src/disassembler/llvm/include_llvm.hxx @@ -13,24 +13,27 @@ #include #include #include -#include #include #include -#include #include #include #include #include -#include -#include #include -#include #include #include #include #include #include -#include #include +#ifndef LLVM_36 +#include +#include +#include +#include +#include +#include +#endif + #endif