]> git.siccegge.de Git - frida/frida.git/blobdiff - src/disassembler/llvm/LLVMDisassembler.cxx
Get entry address from llvm
[frida/frida.git] / src / disassembler / llvm / LLVMDisassembler.cxx
index 6a25e9abad87e756a9d77c77876f72be90aa96fc..18cfe8065eefc0fb5e409d7978408e50dd47a1b2 100644 (file)
@@ -9,31 +9,67 @@ using namespace llvm;
 using namespace llvm::object;
 using std::error_code;
 
+/*
+ *
+ */
+Disassembler * createLLVMDisassembler(const std::string& filename, InformationManager* manager) {
+       if (filename == "")
+               return NULL;
+
+       std::unique_ptr<Binary> o;
+       o.reset(createBinary(filename).get());
+       Binary * op = o.release();
+
+       // ELFType<endian, maxalign, 64bit>
+       if (ELF32LEObjectFile * object = dyn_cast<ELF32LEObjectFile>(op)) {
+               return new LLVMDisassembler<ELFType<support::little, 2, false>>(filename, manager, object);
+       }
+       if (ELF64LEObjectFile * object = dyn_cast<ELF64LEObjectFile>(op)) {
+               return new LLVMDisassembler<ELFType<support::little, 2, true>>(filename, manager, object);
+       }
+       if (ELF32BEObjectFile * object = dyn_cast<ELF32BEObjectFile>(op)) {
+               return new LLVMDisassembler<ELFType<support::big, 2, false>>(filename, manager, object);
+       }
+       if (ELF64BEObjectFile * object = dyn_cast<ELF64BEObjectFile>(op)) {
+               return new LLVMDisassembler<ELFType<support::big, 2, true>>(filename, manager, object);
+       }
+
+       return NULL;
+}
+
 /*
  * TODO: fallback code falls die Datei kein ELF/PE/COFF/MacO/.. binary
  * ist sondern z.B. einfach nur Instruktionen oder ein Bootsektor oder
  * foo
  */
-LLVMDisassembler::LLVMDisassembler(const std::string& filename,
-                                   InformationManager* manager)
+template <typename ELFT>
+LLVMDisassembler<ELFT>::LLVMDisassembler(const std::string& filename,
+                                         InformationManager* manager,
+                                         ELFObjectFile<ELFT>* file)
        : Disassembler(filename, manager)
        , logger(log4cxx::Logger::getLogger("LLVMDisassembler"))
        , triple("unknown-unknown-unknown")
        , manager(manager)
 {
        LOG4CXX_DEBUG(logger, "Handling file" << filename);
-       auto result = createBinary(filename);
 
-       error_code ec;
-       if ((ec = result.getError())) {
-               LOG4CXX_ERROR(logger, "Failed to load Binary" << ec.message());
-               binary = NULL;
-               return;
-       }
+       if (!file) {
+               auto result = createBinary(filename);
+
+               error_code ec;
+               if ((ec = result.getError())) {
+                       LOG4CXX_ERROR(logger, "Failed to load Binary" << ec.message());
+                       binary = NULL;
+                       return;
+               }
 
-       binary.reset(result.get());
+               binary.reset(result.get());
 
-       o = dyn_cast<ObjectFile>(binary.get());
+               o = dyn_cast<ELFObjectFile<ELFT>>(binary.get());
+       } else {
+               o = file;
+               binary.reset(file);
+       }
 
        triple.setArch(Triple::ArchType(o->getArch()));
        std::string tripleName(triple.getTriple());
@@ -115,13 +151,15 @@ LLVMDisassembler::LLVMDisassembler(const std::string& filename,
        Mod.reset(OD->buildModule(false));
 }
 
-void LLVMDisassembler::start() {
+template <typename ELFT>
+void LLVMDisassembler<ELFT>::start() {
        readSymbols();
        readSections();
        disassemble();
 }
 
-LLVMDisassembler::~LLVMDisassembler() {
+template <typename ELFT>
+LLVMDisassembler<ELFT>::~LLVMDisassembler() {
        std::for_each(functions.begin(), functions.end(),
                      [](std::pair<uint64_t,LLVMFunction*> it) {
                              delete it.second;
@@ -132,7 +170,8 @@ LLVMDisassembler::~LLVMDisassembler() {
                      });
 }
 
-Function* LLVMDisassembler::disassembleFunctionAt(uint64_t address, const std::string& name) {
+template <typename ELFT>
+Function* LLVMDisassembler<ELFT>::disassembleFunctionAt(uint64_t address, const std::string& name) {
        SectionRef text_section = sections[".text"];
        uint64_t base_address, size;
        text_section.getAddress(base_address);
@@ -162,7 +201,8 @@ Function* LLVMDisassembler::disassembleFunctionAt(uint64_t address, const std::s
        return function;
 }
 
-void LLVMDisassembler::disassembleFunction(LLVMFunction* function) {
+template <typename ELFT>
+void LLVMDisassembler<ELFT>::disassembleFunction(LLVMFunction* function) {
        std::stack<LLVMBasicBlock*> remaining_blocks;
        SectionRef text_section = sections[".text"];
        StringRef bytes;
@@ -248,7 +288,8 @@ void LLVMDisassembler::disassembleFunction(LLVMFunction* function) {
        manager->signal_new_function(function);
 }
 
-void LLVMDisassembler::disassemble() {
+template <typename ELFT>
+void LLVMDisassembler<ELFT>::disassemble() {
        SectionRef text_section = sections[".text"];
        std::vector<LLVMFunction*> remaining_functions;
 
@@ -279,22 +320,16 @@ void LLVMDisassembler::disassemble() {
        }
 
        if (binary->isELF()) {
-               bool is64bit = (binary->getData()[4] == 0x02);
+               typedef ELFFile<ELFT> ELFO;
+               const ELFO * elffile = o->getELFFile();
+               const typename ELFO::Elf_Ehdr * header = elffile->getHeader();
 
-               uint64_t entry(0);
-               for (int i(0); i < (is64bit? 8 : 4); ++i) {
-                       if (binary->isLittleEndian()) {
-                               entry |= (unsigned int)((unsigned char)binary->getData()[0x18 + i]) << 8*i;
-                       } else {
-                               entry = entry << 8;
-                               entry |= (unsigned char)binary->getData()[0x18 + i];
-                       }
-               }
-               LOG4CXX_DEBUG(logger, "Adding entry at: " << std::hex << entry);
+               _entryAddress = header->e_entry;
+               LOG4CXX_DEBUG(logger, "Adding entryAddress at: " << std::hex << _entryAddress);
                std::stringstream s;
-               s << "<_start 0x" << std::hex << entry << ">";
+               s << "<_start 0x" << std::hex << _entryAddress << ">";
 
-               disassembleFunctionAt(entry, s.str());
+               disassembleFunctionAt(_entryAddress, s.str());
        }
 
        if (functions.empty()) {
@@ -305,7 +340,8 @@ void LLVMDisassembler::disassemble() {
        }
 }
 
-void LLVMDisassembler::splitBlocks(LLVMFunction* function) {
+template <typename ELFT>
+void LLVMDisassembler<ELFT>::splitBlocks(LLVMFunction* function) {
        SectionRef text_section = sections[".text"];
        StringRef bytes;
        text_section.getContents(bytes);
@@ -353,7 +389,8 @@ void LLVMDisassembler::splitBlocks(LLVMFunction* function) {
        }
 }
 
-void LLVMDisassembler::readSymbols() {
+template <typename ELFT>
+void LLVMDisassembler<ELFT>::readSymbols() {
        error_code ec;
        symbol_iterator si(o->symbol_begin()), se(o->symbol_end());
        for (; si != se; ++si) {
@@ -367,7 +404,8 @@ void LLVMDisassembler::readSymbols() {
        }
 }
 
-void LLVMDisassembler::readSections() {
+template <typename ELFT>
+void LLVMDisassembler<ELFT>::readSections() {
        error_code ec;
        section_iterator i(o->section_begin()), e(o->section_end());
        for (; i != e; ++i) {
@@ -382,16 +420,19 @@ void LLVMDisassembler::readSections() {
 
 }
 
-void LLVMDisassembler::forEachFunction(std::function<void (uint64_t, Function*)> callback) {
+template <typename ELFT>
+void LLVMDisassembler<ELFT>::forEachFunction(std::function<void (uint64_t, Function*)> callback) {
        std::for_each(functions.begin(), functions.end(),
                      [&](std::pair<uint64_t, LLVMFunction*> x) {
                              callback(x.first, x.second);
                      });
 }
 
-void LLVMDisassembler::printEachInstruction(uint64_t start, uint64_t end,
-                                            std::function<void (uint8_t*, size_t,
-                                                                const std::string&)> fun) {
+template <typename ELFT>
+void LLVMDisassembler<ELFT>::printEachInstruction(uint64_t start, uint64_t end,
+                                                  std::function<void (uint8_t*, size_t,
+                                                                         const std::string&,
+                                                                         const std::string&)> fun) {
        SectionRef text_section = sections[".text"];
        uint64_t base_address;
        text_section.getAddress(base_address);
@@ -414,17 +455,24 @@ void LLVMDisassembler::printEachInstruction(uint64_t start, uint64_t end,
                        ref.readBytes(current_address, inst_size, bytes);
 
                        uint64_t jmptarget;
+                       std::string ref("");
+                       IP->printInst(&inst, s, "");
                        if (MIA->evaluateBranch(inst, current_address, inst_size, jmptarget)) {
                                std::stringstream stream;
+                               if (MIA->isCall(inst))
+                                       stream << "function:";
+                               else
+                                       stream << "block:";
+
                                stream << std::hex << (base_address + jmptarget);
-                               IP->printInst(&inst, s, stream.str());
-                       } else
-                               IP->printInst(&inst, s, "");
+                               ref = stream.str();
+                       }
+
 
-                       fun(bytes, inst_size, s.str());
+                       fun(bytes, inst_size, s.str(), ref);
                } else {
                        LOG4CXX_WARN(logger, "Invalid byte at" << std::hex << current_address + base_address);
-                       fun(NULL, 0, "Invalid Byte");
+                       fun(NULL, 0, "Invalid Byte", "");
                        inst_size = 1;
                }