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); }
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; } }