static bool LiftFunctionsIntoModule(NativeModulePtr natMod, llvm::Module *M) { // populate functions for (auto &func_info : natMod->get_funcs()) { NativeFunctionPtr f = func_info.second; if (!InsertFunctionIntoModule(natMod, f, M)) { std::string fname = f->get_name(); std::cerr << "Could not insert function: " << fname << " into the LLVM module" << std::endl; return false; } } return true; }
void PrintCFGFunctionList(const NativeModulePtr native_module, const std::string &architecture) noexcept { std::ios::fmtflags original_stream_flags(std::cout.flags()); int address_digit_count = (architecture == "amd64" ? 16 : 8); std::cout << "\nCFG Function List:\n"; const auto &function_map = native_module->get_funcs(); for (const auto &function_descriptor : function_map) { VA virtual_address = function_descriptor.first; const NativeFunctionPtr function = function_descriptor.second; std::cout << " " << std::hex << std::setw(address_digit_count) << std::setfill('0') << virtual_address << " "; std::cout << function->get_name() << std::endl; } std::cout.flags(original_stream_flags); }
NativeFunctionPtr getFunc(ExecutableContainer *c, LLVMByteDecoder &d, stack<VA> &funcs, ExternalFunctionMap &f, VA e, raw_ostream &out) { NativeFunctionPtr F = NativeFunctionPtr(new NativeFunction(e)); stack<VA> toVisit; set<VA> visited; toVisit.push(e); out << "getFunc: Starting at 0x" << to_string<VA>(e,hex) << "\n"; out << "getFunc: toVisit size is: " << toVisit.size() << "\n"; while(toVisit.size() > 0) { VA curBlockHeader = toVisit.top(); toVisit.pop(); if(visited.find(curBlockHeader) != visited.end()) { continue; } else { visited.insert(curBlockHeader); } // funcs is new functions to visit later // toVisit is basic blocks of *this* function to visit now NativeBlockPtr B = decodeBlock(c, f, d, toVisit, curBlockHeader, funcs, out); F->add_block(B); } out << "getFunc: Function recovery complete for "; out << " func at " << to_string<VA>(e,hex) << "\n"; F->compute_graph(); return F; }
void doPrintModule(NativeModulePtr m) { string pathBase = "./"; list<NativeFunctionPtr> mod_funcs = m->get_funcs(); list<NativeFunctionPtr>::iterator it = mod_funcs.begin(); for(; it != mod_funcs.end(); ++it) { NativeFunctionPtr f = *it; string n = pathBase+to_string<uint64_t>(f->get_start(), hex) + ".dot"; ofstream out(n.c_str()); block_label_writer bgl(f); CFG g = f->get_cfg(); write_graphviz(out, g, bgl); } return; }
static bool InsertFunctionIntoModule(NativeModulePtr mod, NativeFunctionPtr func, llvm::Module *M) { auto &C = M->getContext(); auto F = M->getFunction(func->get_name()); if (!F) { throw TErr(__LINE__, __FILE__, "Could not get func " + func->get_name()); } if (!F->empty()) { std::cout << "WARNING: Asking to re-insert function: " << func->get_name() << std::endl << "\tReturning current function instead" << std::endl; return true; } auto entryBlock = llvm::BasicBlock::Create(F->getContext(), "entry", F); ArchAllocRegisterVars(entryBlock); TranslationContext ctx; ctx.natM = mod; ctx.natF = func; ctx.natI = nullptr; ctx.M = M; ctx.F = F; // Create basic blocks for each basic block in the original function. for (auto block_info : func->get_blocks()) { ctx.va_to_bb[block_info.first] = llvm::BasicBlock::Create( C, block_info.second->get_name(), F); } // Create a branch from the end of the entry block to the first block llvm::BranchInst::Create(ctx.va_to_bb[func->get_start()], entryBlock); try { // Lift every basic block into the functions. auto error = false; for (auto block_info : func->get_blocks()) { ctx.natB = block_info.second; error = LiftBlockIntoFunction(ctx) || error; ctx.natB = nullptr; } // For ease of debugging generated code, don't allow lifted functions to // be inlined. This will make lifted and native call graphs one-to-one. F->addFnAttr(llvm::Attribute::NoInline); //we should be done, having inserted every block into the module return !error; } catch (std::exception &e) { std::cerr << "error: " << std::endl << e.what() << std::endl << "in function " << std::hex << ctx.natF->get_start() << std::endl; if (ctx.natB) { std::cerr << "in block " << std::hex << ctx.natB->get_base() << std::endl; if (ctx.natI) { std::cerr << "in inst " << std::hex << ctx.natI->get_loc() << std::endl; } } return false; } }