示例#1
0
文件: Lift.cpp 项目: kumarak/mcsema
static void CreateInstrBreakpoint(llvm::BasicBlock *B, VA pc) {
  auto F = B->getParent();
  auto M = F->getParent();

  std::stringstream ss;
  ss << "breakpoint_" << std::hex << pc;
  auto instr_func_name = ss.str();

  auto IFT = M->getFunction(instr_func_name);
  if (!IFT) {

    IFT = llvm::Function::Create(
        LiftedFunctionType(), llvm::GlobalValue::ExternalLinkage,
        instr_func_name, M);

    IFT->addFnAttr(llvm::Attribute::OptimizeNone);
    IFT->addFnAttr(llvm::Attribute::NoInline);

    auto &C = M->getContext();
    llvm::IRBuilder<> ir(llvm::BasicBlock::Create(C, "", IFT));
    ir.CreateRetVoid();
  }

  auto state_ptr = &*F->arg_begin();
  llvm::CallInst::Create(IFT, {state_ptr}, "", B);
}
示例#2
0
文件: Arch.cpp 项目: kumarak/mcsema
// Add a function that can be used to transition from native code into lifted
// code.
// isCallback defaults to false
llvm::Function *ArchAddEntryPointDriver(llvm::Module *M,
                                        const std::string &name, VA entry,
                                        bool isCallback) {
  //convert the VA into a string name of a function, try and look it up
  std::stringstream ss;
  ss << "sub_" << std::hex << entry;

  auto s = ss.str();
  llvm::Function *F = M->getFunction(s);
  if (!F) {
    llvm::errs() << "Could not find lifted function " << s
                 << " for entry point " << name;
    return nullptr;
  }

  auto &C = F->getContext();
  auto W = M->getFunction(name);
  if (W) {
    return W;
  }

  auto VoidTy = llvm::Type::getVoidTy(C);
  auto WTy = llvm::FunctionType::get(VoidTy, false);
  W = llvm::Function::Create(
      WTy, llvm::GlobalValue::ExternalLinkage, name, M);

  W->addFnAttr(llvm::Attribute::NoInline);
  W->addFnAttr(llvm::Attribute::Naked);

  const auto Arch = SystemArch(M);
  const auto OS = SystemOS(M);

  if (llvm::Triple::Linux == OS) {
    if (_X86_64_ == Arch) {
      LinuxAddPushJumpStub(M, F, W, "__mcsema_attach_call");
    } else {
      LinuxAddPushJumpStub(M, F, W, "__mcsema_attach_call_cdecl");
    }
  } else if (llvm::Triple::Win32 == OS) {
    // if we are creating and entry point for a callback
    // then we need to decorate the function. 

    // if we are creating an entry point specified via -entrypoint
    // then the name is pre-decorated, and we don't decorate twice
    if (_X86_64_ == Arch) {
      WindowsAddPushJumpStub(isCallback, M, F, W, "__mcsema_attach_call");
    } else {
      WindowsAddPushJumpStub(isCallback, M, F, W, "__mcsema_attach_call_cdecl");
    }
  } else {
    TASSERT(false, "Unsupported OS for entry point driver.");
  }

  F->setLinkage(llvm::GlobalValue::ExternalLinkage);
  if (F->doesNotReturn()) {
    W->setDoesNotReturn();
  }

  return W;
}
示例#3
0
文件: Arch.cpp 项目: kumarak/mcsema
static void InitADFeatures(llvm::Module *M, const char *name,
                          llvm::FunctionType *EPTy) {
  auto FC = M->getOrInsertFunction(name, EPTy);
  auto F = llvm::dyn_cast<llvm::Function>(FC);
  F->setLinkage(llvm::GlobalValue::ExternalLinkage);
  F->addFnAttr(llvm::Attribute::Naked);
}
		llvm::Function* createTranslationStubFunction(Module& module,
		                                              llvm::Function* function,
		                                              const ArgInfo& translatedArgInfo) {
			const auto functionName = module.getCString("translateStub_") + function->getName();
			const auto linkage = llvm::Function::InternalLinkage;
			const auto llvmFunction = createLLVMFunction(module, translatedArgInfo, linkage, functionName);
			
			// Always inline if possible.
			llvmFunction->addFnAttr(llvm::Attribute::AlwaysInline);
			
			return llvmFunction;
		}
示例#5
0
文件: Lift.cpp 项目: kumarak/mcsema
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;
  }

  
}
示例#6
0
文件: Arch.cpp 项目: kumarak/mcsema
// Wrap `F` in a function that will transition from lifted code into native
// code, where `F` is an external reference to a native function.
llvm::Function *ArchAddExitPointDriver(llvm::Function *F) {
  std::stringstream ss;
  auto M = F->getParent();
  const auto OS = SystemOS(M);

  if(llvm::Triple::Win32 == OS) {
      ss << "mcsema_" << F->getName().str();
  } else {
      ss << "_" << F->getName().str();
  }
  auto &C = M->getContext();
  auto name = ss.str();
  auto W = M->getFunction(name);
  if (W) {
    return W;
  }

  W = llvm::Function::Create(F->getFunctionType(),
                             F->getLinkage(), name, M);
  W->setCallingConv(F->getCallingConv());
  W->addFnAttr(llvm::Attribute::NoInline);
  W->addFnAttr(llvm::Attribute::Naked);

  const auto Arch = SystemArch(M);

  if (llvm::Triple::Linux == OS) {
    if (_X86_64_ == Arch) {
      LinuxAddPushJumpStub(M, F, W, "__mcsema_detach_call");
    } else {
      switch (F->getCallingConv()) {
        case llvm::CallingConv::C:
          LinuxAddPushJumpStub(M, F, W, "__mcsema_detach_call_cdecl");
          break;
        case llvm::CallingConv::X86_StdCall:
          LinuxAddPushJumpStub(M, F, W, "__mcsema_detach_call_stdcall");
          break;
        case llvm::CallingConv::X86_FastCall:
          LinuxAddPushJumpStub(M, F, W, "__mcsema_detach_call_fastcall");
          break;
        default:
          TASSERT(false, "Unsupported Calling Convention for 32-bit Linux");
          break;
      }
    }
  } else if (llvm::Triple::Win32 == OS) {

    if (_X86_64_ == Arch) {
        WindowsAddPushJumpStub(true, M, F, W, "__mcsema_detach_call");
    } else {
      switch (F->getCallingConv()) {
        case llvm::CallingConv::C:
          WindowsAddPushJumpStub(true, M, F, W, "__mcsema_detach_call_cdecl");
          break;
        case llvm::CallingConv::X86_StdCall:
          WindowsAddPushJumpStub(true, M, F, W, "__mcsema_detach_call_stdcall");
          break;
        case llvm::CallingConv::X86_FastCall:
          WindowsAddPushJumpStub(true, M, F, W, "__mcsema_detach_call_fastcall");
          break;
        default:
          TASSERT(false, "Unsupported Calling Convention for 32-bit Windows");
          break;
      }
    }
  } else {
    TASSERT(false, "Unsupported OS for exit point driver.");
  }

  if (F->doesNotReturn()) {
    W->setDoesNotReturn();
  }
  return W;
}