Beispiel #1
0
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;
}
Beispiel #2
0
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);
}
Beispiel #3
0
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;
  }

  
}