]> git.siccegge.de Git - frida/frida.git/blobdiff - src/disassembler/llvm/LLVMDisassembler.cxx
Reoganize Function/BasicBlock creation
[frida/frida.git] / src / disassembler / llvm / LLVMDisassembler.cxx
index 18cfe8065eefc0fb5e409d7978408e50dd47a1b2..773a5189a27a33d35085da9f698864970b3ac9ec 100644 (file)
@@ -1,9 +1,11 @@
 #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>
+#include <cassert>
 
 using namespace llvm;
 using namespace llvm::object;
@@ -156,22 +158,15 @@ 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;
-                     });
-}
+LLVMDisassembler<ELFT>::~LLVMDisassembler() {}
 
 template <typename ELFT>
 Function* LLVMDisassembler<ELFT>::disassembleFunctionAt(uint64_t address, const std::string& name) {
+       Function * function;
        SectionRef text_section = sections[".text"];
        uint64_t base_address, size;
        text_section.getAddress(base_address);
@@ -182,28 +177,32 @@ Function* LLVMDisassembler<ELFT>::disassembleFunctionAt(uint64_t address, const
                return NULL;
        }
 
-       if (functions.find(address) != functions.end()) {
-               return functions[address];
-       }
+       if (NULL == (function = manager->getFunction(address))) {
 
-       LLVMFunction * function;
-       if (name == "") {
-               std::stringstream s;
-               s << "<Unnamed 0x" << std::hex << address << ">";
-               function = new LLVMFunction(s.str(), address);
-       } else {
-               function = new LLVMFunction(name, address);
+               if (name == "") {
+                       std::stringstream s;
+                       s << "<Unnamed 0x" << std::hex << address << ">";
+                       function = manager->newFunction(address);
+                       function->setName(s.str());
+               } else {
+                       function = manager->newFunction(address);
+                       function->setName(name);
+               }
+               disassembleFunction(function);
+               manager->finishFunction(function);
        }
-       functions.insert(std::make_pair(address, function));
-
-       disassembleFunction(function);
 
        return function;
 }
 
 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;
+       /* TODO:
+        * Do all blocks get added properly? We should take care to remove
+        * the other ones at the end of the function!
+        */
+       std::map<uint64_t, BasicBlock*> new_blocks;
        SectionRef text_section = sections[".text"];
        StringRef bytes;
        text_section.getContents(bytes);
@@ -211,16 +210,17 @@ void LLVMDisassembler<ELFT>::disassembleFunction(LLVMFunction* function) {
 
        LOG4CXX_DEBUG(logger, "Handling function " << function->getName());
 
-       LLVMBasicBlock * block = new LLVMBasicBlock(function->getStartAddress(), this);
+       BasicBlock * block = manager->newBasicBlock(function->getStartAddress());
        remaining_blocks.push(block);
-       blocks.insert(std::make_pair(block->getStartAddress(), block));
+       new_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());
+               LOG4CXX_DEBUG(logger, "Handling Block starting at " << std::hex
+                             << current_block->getStartAddress());
 
                uint64_t inst_size;
                uint64_t base_address;
@@ -239,31 +239,34 @@ void LLVMDisassembler<ELFT>::disassembleFunction(LLVMFunction* function) {
                                        jmptarget += base_address;
                                        if (!MIA->isIndirectBranch(inst)) {
                                                if (MIA->isCall(inst)) {
-                                                       if (functions.find(jmptarget) == functions.end()) {
+                                                       if (NULL == manager->getFunction(jmptarget))
                                                                disassembleFunctionAt(jmptarget);
-                                                       }
                                                } else {
                                                        current_block->setNextBlock(0, jmptarget);
-                                                       if (blocks.find(jmptarget) == blocks.end()) {
-                                                               LLVMBasicBlock * block = new LLVMBasicBlock(jmptarget, this);
-                                                               blocks.insert(std::make_pair(block->getStartAddress(), block));
+                                                       if (new_blocks.find(jmptarget) == new_blocks.end()) {
+                                                               BasicBlock * block = manager->newBasicBlock(jmptarget);
+                                                               assert(block);
+                                                               new_blocks.insert(std::make_pair(block->getStartAddress(), block));
                                                                function->addBasicBlock(block);
                                                                remaining_blocks.push(block);
                                                        } else {
-                                                               LOG4CXX_DEBUG(logger, "Reusing Block starting at " << std::hex << current_block->getStartAddress());
-                                                               function->addBasicBlock(blocks.find(jmptarget)->second);
+                                                               LOG4CXX_DEBUG(logger, "Reusing Block starting at " << std::hex
+                                                                             << current_block->getStartAddress());
+                                                               function->addBasicBlock(new_blocks.find(jmptarget)->second);
                                                        }
                                                        if (MIA->isConditionalBranch(inst)) {
                                                                jmptarget = base_address + current_address + inst_size;
                                                                current_block->setNextBlock(1, jmptarget);
-                                                               if (blocks.find(jmptarget) == blocks.end()) {
-                                                                       LLVMBasicBlock * block = new LLVMBasicBlock(jmptarget, this);
-                                                                       blocks.insert(std::make_pair(block->getStartAddress(), block));
+                                                               if (new_blocks.find(jmptarget) == new_blocks.end()) {
+                                                                       BasicBlock * block = manager->newBasicBlock(jmptarget);
+                                                                       assert(block);
+                                                                       new_blocks.insert(std::make_pair(block->getStartAddress(), block));
                                                                        function->addBasicBlock(block);
                                                                        remaining_blocks.push(block);
                                                                } else {
-                                                                       LOG4CXX_DEBUG(logger, "Reusing Block starting at " << std::hex << current_block->getStartAddress());
-                                                                       function->addBasicBlock(blocks.find(jmptarget)->second);
+                                                                       LOG4CXX_DEBUG(logger, "Reusing Block starting at " << std::hex
+                                                                                     << current_block->getStartAddress());
+                                                                       function->addBasicBlock(new_blocks.find(jmptarget)->second);
                                                                }
                                                        }
                                                }
@@ -291,7 +294,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) {
@@ -308,19 +311,19 @@ void LLVMDisassembler<ELFT>::disassemble() {
                        continue;
 
                if (!x->second.getAddress(result)) {
-                       LLVMFunction * fun = new LLVMFunction(x->first, result);
+                       Function * fun = manager->newFunction(result);
+                       fun->setName(x->first);
                        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);
+               manager->finishFunction(function);
        }
 
        if (binary->isELF()) {
-               typedef ELFFile<ELFT> ELFO;
                const ELFO * elffile = o->getELFFile();
                const typename ELFO::Elf_Ehdr * header = elffile->getHeader();
 
@@ -332,16 +335,14 @@ void LLVMDisassembler<ELFT>::disassemble() {
                disassembleFunctionAt(_entryAddress, s.str());
        }
 
-       if (functions.empty()) {
-               uint64_t text_entry;
-               text_section.getAddress(text_entry);
-               LOG4CXX_INFO(logger, "No Symbols found, starting at the beginning of the text segment");
-               disassembleFunctionAt(text_entry);
-       }
+       uint64_t text_entry;
+       text_section.getAddress(text_entry);
+       LOG4CXX_INFO(logger, "No Symbols found, starting at the beginning of the text segment");
+       disassembleFunctionAt(text_entry);
 }
 
 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);
@@ -364,20 +365,22 @@ void LLVMDisassembler<ELFT>::splitBlocks(LLVMFunction* function) {
                        if(llvm::MCDisassembler::Success ==
                           DisAsm->getInstruction(inst, inst_size, ref, current_address, nulls(), nulls())) {
                                // See if some other block starts here
-                               auto other = blocks.find(current_address + inst_size + base_address);
+                               BasicBlock* other = manager->getBasicBlock(current_address
+                                                                          + inst_size
+                                                                          + base_address);
 
                                // Special case, other block starts here but we are at the end anyway
-                               if (other != blocks.end()) {
+                               if (other != NULL) {
                                        uint64_t endaddress = current_address + inst_size + base_address;
                                        if (endaddress != current_block->getEndAddress()) {
                                                LOG4CXX_DEBUG(logger, "Shortening block starting at "
                                                              << std::hex
                                                              << current_block->getStartAddress()
                                                              << " now ending at "
-                                                             << other->first);
-                                               function->addBasicBlock(other->second);
+                                                             << other->getStartAddress());
+                                               function->addBasicBlock(other);
                                                current_block->setEndAddress(endaddress);
-                                               current_block->setNextBlock(0, other->first);
+                                               current_block->setNextBlock(0, other->getStartAddress());
                                                current_block->setNextBlock(1, 0);
                                        }
                                }
@@ -389,6 +392,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;
@@ -420,13 +442,13 @@ 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) {
-                             callback(x.first, x.second);
-                     });
-}
+// 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, Function*> x) {
+//     //                    callback(x.first, x.second);
+//     //               });
+// }
 
 template <typename ELFT>
 void LLVMDisassembler<ELFT>::printEachInstruction(uint64_t start, uint64_t end,