]> git.siccegge.de Git - frida/frida.git/blobdiff - src/disassembler/llvm/LLVMDisassembler.cxx
Pass the InformationManager inside the BasicBlock and Function classes
[frida/frida.git] / src / disassembler / llvm / LLVMDisassembler.cxx
index 7d4da0119955da9087ea2a70a5b11c4ae0e4a485..b6f8dae75ae2d6cc33b2586bc2b45df68b899eec 100644 (file)
@@ -1,6 +1,7 @@
 #include "disassembler/llvm/LLVMDisassembler.hxx"
-#include "disassembler/llvm/LLVMBasicBlock.hxx"
-#include "disassembler/llvm/LLVMFunction.hxx"
+#include "core/InformationManager.hxx"
+#include "core/Function.hxx"
+#include "core/BasicBlock.hxx"
 
 #include <stack>
 #include <algorithm>
@@ -13,26 +14,25 @@ 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());
-       const Binary * op = o.get();
+       Binary * op = o.release();
 
        // ELFType<endian, maxalign, 64bit>
-       if (const ELF32LEObjectFile * _ = dyn_cast<ELF32LEObjectFile>(op)) {
-#pragma unused(_)
-               return new LLVMDisassembler<ELFType<support::little, 2, false>>(filename, manager);
+       if (ELF32LEObjectFile * object = dyn_cast<ELF32LEObjectFile>(op)) {
+               return new LLVMDisassembler<ELFType<support::little, 2, false>>(filename, manager, object);
        }
-       if (const ELF64LEObjectFile * _ = dyn_cast<ELF64LEObjectFile>(op)) {
-#pragma unused(_)
-               return new LLVMDisassembler<ELFType<support::little, 2, true>>(filename, manager);
+       if (ELF64LEObjectFile * object = dyn_cast<ELF64LEObjectFile>(op)) {
+               return new LLVMDisassembler<ELFType<support::little, 2, true>>(filename, manager, object);
        }
-       if (const ELF32BEObjectFile * _ = dyn_cast<ELF32BEObjectFile>(op)) {
-#pragma unused(_)
-               return new LLVMDisassembler<ELFType<support::big, 2, false>>(filename, manager);
+       if (ELF32BEObjectFile * object = dyn_cast<ELF32BEObjectFile>(op)) {
+               return new LLVMDisassembler<ELFType<support::big, 2, false>>(filename, manager, object);
        }
-       if (const ELF64BEObjectFile * _ = dyn_cast<ELF64BEObjectFile>(op)) {
-#pragma unused(_)
-               return new LLVMDisassembler<ELFType<support::big, 2, true>>(filename, manager);
+       if (ELF64BEObjectFile * object = dyn_cast<ELF64BEObjectFile>(op)) {
+               return new LLVMDisassembler<ELFType<support::big, 2, true>>(filename, manager, object);
        }
 
        return NULL;
@@ -45,25 +45,32 @@ Disassembler * createLLVMDisassembler(const std::string& filename, InformationMa
  */
 template <typename ELFT>
 LLVMDisassembler<ELFT>::LLVMDisassembler(const std::string& filename,
-                                   InformationManager* manager)
+                                         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());
@@ -150,18 +157,19 @@ void LLVMDisassembler<ELFT>::start() {
        readSymbols();
        readSections();
        disassemble();
+       readDynamicSymbols();
 }
 
 template <typename ELFT>
 LLVMDisassembler<ELFT>::~LLVMDisassembler() {
-       std::for_each(functions.begin(), functions.end(),
-                     [](std::pair<uint64_t,LLVMFunction*> it) {
-                             delete it.second;
-                     });
-       std::for_each(blocks.begin(), blocks.end(),
-                     [](std::pair<uint64_t, LLVMBasicBlock*> it) {
-                             delete it.second;
-                     });
+       // std::for_each(functions.begin(), functions.end(),
+       //               [](std::pair<uint64_t,LLVMFunction*> it) {
+       //                    delete it.second;
+       //               });
+       // std::for_each(blocks.begin(), blocks.end(),
+       //               [](std::pair<uint64_t, LLVMBasicBlock*> it) {
+       //                    delete it.second;
+       //               });
 }
 
 template <typename ELFT>
@@ -180,13 +188,13 @@ Function* LLVMDisassembler<ELFT>::disassembleFunctionAt(uint64_t address, const
                return functions[address];
        }
 
-       LLVMFunction * function;
+       Function * function;
        if (name == "") {
                std::stringstream s;
                s << "<Unnamed 0x" << std::hex << address << ">";
-               function = new LLVMFunction(s.str(), address);
+               function = new Function(s.str(), address, manager);
        } else {
-               function = new LLVMFunction(name, address);
+               function = new Function(name, address, manager);
        }
        functions.insert(std::make_pair(address, function));
 
@@ -196,8 +204,8 @@ Function* LLVMDisassembler<ELFT>::disassembleFunctionAt(uint64_t address, const
 }
 
 template <typename ELFT>
-void LLVMDisassembler<ELFT>::disassembleFunction(LLVMFunction* function) {
-       std::stack<LLVMBasicBlock*> remaining_blocks;
+void LLVMDisassembler<ELFT>::disassembleFunction(Function* function) {
+       std::stack<BasicBlock*> remaining_blocks;
        SectionRef text_section = sections[".text"];
        StringRef bytes;
        text_section.getContents(bytes);
@@ -205,13 +213,13 @@ void LLVMDisassembler<ELFT>::disassembleFunction(LLVMFunction* function) {
 
        LOG4CXX_DEBUG(logger, "Handling function " << function->getName());
 
-       LLVMBasicBlock * block = new LLVMBasicBlock(function->getStartAddress(), this);
+       BasicBlock * block = new BasicBlock(function->getStartAddress(), this, manager);
        remaining_blocks.push(block);
        blocks.insert(std::make_pair(block->getStartAddress(), block));
        function->addBasicBlock(block);
 
        while (remaining_blocks.size()) {
-               LLVMBasicBlock * current_block = remaining_blocks.top();
+               BasicBlock * current_block = remaining_blocks.top();
                remaining_blocks.pop();
 
                LOG4CXX_DEBUG(logger, "Handling Block starting at " << std::hex << current_block->getStartAddress());
@@ -239,7 +247,7 @@ void LLVMDisassembler<ELFT>::disassembleFunction(LLVMFunction* function) {
                                                } else {
                                                        current_block->setNextBlock(0, jmptarget);
                                                        if (blocks.find(jmptarget) == blocks.end()) {
-                                                               LLVMBasicBlock * block = new LLVMBasicBlock(jmptarget, this);
+                                                               BasicBlock * block = new BasicBlock(jmptarget, this, manager);
                                                                blocks.insert(std::make_pair(block->getStartAddress(), block));
                                                                function->addBasicBlock(block);
                                                                remaining_blocks.push(block);
@@ -251,7 +259,7 @@ void LLVMDisassembler<ELFT>::disassembleFunction(LLVMFunction* function) {
                                                                jmptarget = base_address + current_address + inst_size;
                                                                current_block->setNextBlock(1, jmptarget);
                                                                if (blocks.find(jmptarget) == blocks.end()) {
-                                                                       LLVMBasicBlock * block = new LLVMBasicBlock(jmptarget, this);
+                                                                       BasicBlock * block = new BasicBlock(jmptarget, this, manager);
                                                                        blocks.insert(std::make_pair(block->getStartAddress(), block));
                                                                        function->addBasicBlock(block);
                                                                        remaining_blocks.push(block);
@@ -285,7 +293,7 @@ void LLVMDisassembler<ELFT>::disassembleFunction(LLVMFunction* function) {
 template <typename ELFT>
 void LLVMDisassembler<ELFT>::disassemble() {
        SectionRef text_section = sections[".text"];
-       std::vector<LLVMFunction*> remaining_functions;
+       std::vector<Function*> remaining_functions;
 
        // Assume all function symbols actually start a real function
        for (auto x = symbols.begin(); x != symbols.end(); ++x) {
@@ -302,28 +310,22 @@ void LLVMDisassembler<ELFT>::disassemble() {
                        continue;
 
                if (!x->second.getAddress(result)) {
-                       LLVMFunction * fun = new LLVMFunction(x->first, result);
+                       Function * fun = new Function(x->first, result, manager);
                        remaining_functions.push_back(fun);
                        functions.insert(std::make_pair(result, fun));
                        LOG4CXX_DEBUG(logger, "Disasembling " << x->first);
                }
        }
 
-       for (LLVMFunction* function : remaining_functions) {
+       for (Function* function : remaining_functions) {
                disassembleFunction(function);
        }
 
        if (binary->isELF()) {
-               bool is64bit = (binary->getData()[4] == 0x02);
+               const ELFO * elffile = o->getELFFile();
+               const typename ELFO::Elf_Ehdr * header = elffile->getHeader();
 
-               for (int i(0); i < (is64bit? 8 : 4); ++i) {
-                       if (binary->isLittleEndian()) {
-                               _entryAddress |= (unsigned int)((unsigned char)binary->getData()[0x18 + i]) << 8*i;
-                       } else {
-                               _entryAddress = _entryAddress << 8;
-                               _entryAddress |= (unsigned char)binary->getData()[0x18 + i];
-                       }
-               }
+               _entryAddress = header->e_entry;
                LOG4CXX_DEBUG(logger, "Adding entryAddress at: " << std::hex << _entryAddress);
                std::stringstream s;
                s << "<_start 0x" << std::hex << _entryAddress << ">";
@@ -340,7 +342,7 @@ void LLVMDisassembler<ELFT>::disassemble() {
 }
 
 template <typename ELFT>
-void LLVMDisassembler<ELFT>::splitBlocks(LLVMFunction* function) {
+void LLVMDisassembler<ELFT>::splitBlocks(Function* function) {
        SectionRef text_section = sections[".text"];
        StringRef bytes;
        text_section.getContents(bytes);
@@ -388,6 +390,25 @@ void LLVMDisassembler<ELFT>::splitBlocks(LLVMFunction* function) {
        }
 }
 
+template <typename ELFT>
+void LLVMDisassembler<ELFT>::readDynamicSymbols() {
+       const ELFO * elffile = o->getELFFile();
+       for (typename ELFO::Elf_Sym_Iter
+                    it = elffile->begin_dynamic_symbols(),
+                    end = elffile->end_dynamic_symbols();
+            it != end;
+            ++it) {
+               if (it->getType() == 2) { // Function
+                       bool is_default;
+                       // TODO: Error handling
+                       std::string symbolname = *(elffile->getSymbolName(it));
+                       std::string symbolversion = *(elffile->getSymbolVersion(nullptr, &*it, is_default));
+                       manager->signal_new_dyn_symbol(symbolname + (is_default? "@@" : "@") + symbolversion);
+                       LOG4CXX_DEBUG(logger, "Adding dynamic Symbol " << symbolname << (is_default? "@@" : "@") << symbolversion);
+               }
+       }
+}
+
 template <typename ELFT>
 void LLVMDisassembler<ELFT>::readSymbols() {
        error_code ec;
@@ -422,15 +443,16 @@ void LLVMDisassembler<ELFT>::readSections() {
 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) {
+                     [&](std::pair<uint64_t, Function*> x) {
                              callback(x.first, x.second);
                      });
 }
 
 template <typename ELFT>
 void LLVMDisassembler<ELFT>::printEachInstruction(uint64_t start, uint64_t end,
-                                            std::function<void (uint8_t*, size_t,
-                                                                const std::string&)> fun) {
+                                                  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);
@@ -453,17 +475,24 @@ void LLVMDisassembler<ELFT>::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;
                }