Esempio n. 1
0
Instruction *AddressSanitizer::generateCrashCode(
    IRBuilder<> &IRB, Value *Addr, bool IsWrite, uint32_t TypeSize) {
  // IsWrite and TypeSize are encoded in the function name.
  std::string FunctionName = std::string(kAsanReportErrorTemplate) +
      (IsWrite ? "store" : "load") + itostr(TypeSize / 8);
  Value *ReportWarningFunc = CurrentModule->getOrInsertFunction(
      FunctionName, IRB.getVoidTy(), IntptrTy, NULL);
  CallInst *Call = IRB.CreateCall(ReportWarningFunc, Addr);
  Call->setDoesNotReturn();
  return Call;
}
static InstTransResult doCallPC(InstPtr ip, BasicBlock *&b, VA tgtAddr) {
	Module		*M = b->getParent()->getParent();
	Function	*ourF = b->getParent();
    //insert a call to the call function

	//this function will be a translated function that we emit, so we should
	//be able to look it up in our module.

    std::string			fname = "sub_"+to_string<VA>(tgtAddr, std::hex);
    Function        *F = M->getFunction(fname);

    TASSERT( F != NULL, "Could not find function: " + fname );

    writeFakeReturnAddr(b);

	//we need to wrap up our current context
	writeLocalsToContext(b, 32, ABICallStore);

	//make the call, the only argument should be our parents arguments
	TASSERT(ourF->arg_size() == 1, "");

    std::vector<Value*>	subArgs;

	subArgs.push_back(ourF->arg_begin());


	CallInst *c = CallInst::Create(F, subArgs, "", b);
	c->setCallingConv(F->getCallingConv());

    if ( ip->has_local_noreturn() ) {
        // noreturn functions just hit unreachable
        std::cout << __FUNCTION__ << ": Adding Unreachable Instruction to local noreturn" << std::endl;
        c->setDoesNotReturn();
        c->setTailCall();
        Value *unreachable = new UnreachableInst(b->getContext(), b);
        return EndBlock;
    }

	//spill our context back
	writeContextToLocals(b, 32, ABIRetSpill);

	//and we can continue to run the old code

    return ContinueBlock;
}
Esempio n. 3
0
/// getTrapBB - create a basic block that traps. All overflowing conditions
/// branch to this block. There's only one trap block per function.
BasicBlock *BoundsChecking::getTrapBB() {
  if (TrapBB && SingleTrapBB)
    return TrapBB;

  Function *Fn = Inst->getParent()->getParent();
  BasicBlock::iterator PrevInsertPoint = Builder->GetInsertPoint();
  TrapBB = BasicBlock::Create(Fn->getContext(), "trap", Fn);
  Builder->SetInsertPoint(TrapBB);

  llvm::Value *F = Intrinsic::getDeclaration(Fn->getParent(), Intrinsic::trap);
  CallInst *TrapCall = Builder->CreateCall(F);
  TrapCall->setDoesNotReturn();
  TrapCall->setDoesNotThrow();
  TrapCall->setDebugLoc(Inst->getDebugLoc());
  Builder->CreateUnreachable();

  Builder->SetInsertPoint(PrevInsertPoint);
  return TrapBB;
}
static bool addBoundsChecking(Function &F, TargetLibraryInfo &TLI,
                              ScalarEvolution &SE) {
  const DataLayout &DL = F.getParent()->getDataLayout();
  ObjectSizeOffsetEvaluator ObjSizeEval(DL, &TLI, F.getContext(),
                                           /*RoundToAlign=*/true);

  // check HANDLE_MEMORY_INST in include/llvm/Instruction.def for memory
  // touching instructions
  SmallVector<std::pair<Instruction *, Value *>, 4> TrapInfo;
  for (Instruction &I : instructions(F)) {
    Value *Or = nullptr;
    BuilderTy IRB(I.getParent(), BasicBlock::iterator(&I), TargetFolder(DL));
    if (LoadInst *LI = dyn_cast<LoadInst>(&I)) {
      Or = getBoundsCheckCond(LI->getPointerOperand(), LI, DL, TLI,
                              ObjSizeEval, IRB, SE);
    } else if (StoreInst *SI = dyn_cast<StoreInst>(&I)) {
      Or = getBoundsCheckCond(SI->getPointerOperand(), SI->getValueOperand(),
                              DL, TLI, ObjSizeEval, IRB, SE);
    } else if (AtomicCmpXchgInst *AI = dyn_cast<AtomicCmpXchgInst>(&I)) {
      Or = getBoundsCheckCond(AI->getPointerOperand(), AI->getCompareOperand(),
                              DL, TLI, ObjSizeEval, IRB, SE);
    } else if (AtomicRMWInst *AI = dyn_cast<AtomicRMWInst>(&I)) {
      Or = getBoundsCheckCond(AI->getPointerOperand(), AI->getValOperand(), DL,
                              TLI, ObjSizeEval, IRB, SE);
    }
    if (Or)
      TrapInfo.push_back(std::make_pair(&I, Or));
  }

  // Create a trapping basic block on demand using a callback. Depending on
  // flags, this will either create a single block for the entire function or
  // will create a fresh block every time it is called.
  BasicBlock *TrapBB = nullptr;
  auto GetTrapBB = [&TrapBB](BuilderTy &IRB) {
    if (TrapBB && SingleTrapBB)
      return TrapBB;

    Function *Fn = IRB.GetInsertBlock()->getParent();
    // FIXME: This debug location doesn't make a lot of sense in the
    // `SingleTrapBB` case.
    auto DebugLoc = IRB.getCurrentDebugLocation();
    IRBuilder<>::InsertPointGuard Guard(IRB);
    TrapBB = BasicBlock::Create(Fn->getContext(), "trap", Fn);
    IRB.SetInsertPoint(TrapBB);

    auto *F = Intrinsic::getDeclaration(Fn->getParent(), Intrinsic::trap);
    CallInst *TrapCall = IRB.CreateCall(F, {});
    TrapCall->setDoesNotReturn();
    TrapCall->setDoesNotThrow();
    TrapCall->setDebugLoc(DebugLoc);
    IRB.CreateUnreachable();

    return TrapBB;
  };

  // Add the checks.
  for (const auto &Entry : TrapInfo) {
    Instruction *Inst = Entry.first;
    BuilderTy IRB(Inst->getParent(), BasicBlock::iterator(Inst), TargetFolder(DL));
    insertBoundsCheck(Entry.second, IRB, GetTrapBB);
  }

  return !TrapInfo.empty();
}
static InstTransResult doCallPCExtern(BasicBlock *&b, std::string target, bool esp_adjust = false) {
    Module      *M = b->getParent()->getParent();
    
    //write it into the location pointer to by ESP-4
    Value   *espOld = R_READ<32>(b, X86::ESP);
    //Value   *espSub = 
    //    BinaryOperator::CreateSub(espOld, CONST_V<32>(b, 4), "", b);
    //M_WRITE_0<32>(b, espSub, CONST_V<32>(b, 0));
    //R_WRITE<32>(b, X86::ESP, espSub);

    //write the local values into the context register
    //for now, we will stop doing this because we are not calling a wrapper
    //that meaningfully understands the context structure
    //writeLocalsToContext(b, 32);

    //lookup the function in the module
    Function    *externFunction = M->getFunction(target);
    TASSERT(externFunction != NULL, "Coult not find external function: "+target);
    FunctionType    *externFunctionTy = externFunction->getFunctionType();
    Type            *rType = externFunction->getReturnType();
    int        paramCount = externFunctionTy->getNumParams();

    //now we need to do a series of reads off the stack, essentially
    //a series of POPs but without writing anything back to ESP
    Value   *baseEspVal=NULL;
    std::vector<Value *> arguments;

    // in fastcall, the first two params are passed via register
    // only need to adjust stack if there are more than two args

    if( externFunction->getCallingConv() == CallingConv::X86_FastCall)
    {
        

        Function::ArgumentListType::iterator  it =
                        externFunction->getArgumentList().begin();
        Function::ArgumentListType::iterator  end =
                        externFunction->getArgumentList().end();
        AttrBuilder B;
        B.addAttribute(Attribute::InReg);

        if(paramCount && it != end) {
            Value *r_ecx = R_READ<32>(b, X86::ECX);
            arguments.push_back(r_ecx);
            --paramCount;
            // set argument 1's attribute: make it in a register
            it->addAttr(AttributeSet::get(it->getContext(), 1,  B));
            ++it;
        }

        if(paramCount && it != end) {
            Value *r_edx = R_READ<32>(b, X86::EDX);
            arguments.push_back(r_edx);
            --paramCount;
            // set argument 2's attribute: make it in a register
            it->addAttr(AttributeSet::get(it->getContext(), 2, B));
            ++it;
        }
    }



    if( paramCount ) {
        baseEspVal = R_READ<32>(b, X86::ESP);
        if(esp_adjust) {
            baseEspVal = 
                BinaryOperator::CreateAdd(baseEspVal, CONST_V<32>(b, 4), "", b);
        }
    }

    for( int i = 0; i < paramCount; i++ ) {
        Value   *vFromStack = M_READ_0<32>(b, baseEspVal);

        arguments.push_back(vFromStack);

        if( i+1 != paramCount ) {
            baseEspVal = 
                BinaryOperator::CreateAdd(baseEspVal, CONST_V<32>(b, 4), "", b);
        }
    }

    CallInst    *callR = CallInst::Create(externFunction, arguments, "", b);
    callR->setCallingConv(externFunction->getCallingConv());
   
    noAliasMCSemaScope(callR); 

    if ( externFunction->doesNotReturn() ) {
        // noreturn functions just hit unreachable
        std::cout << __FUNCTION__ << ": Adding Unreachable Instruction" << std::endl;
        callR->setDoesNotReturn();
        callR->setTailCall();
        Value *unreachable = new UnreachableInst(b->getContext(), b);
        return EndBlock;
    }
    
    //then, put the registers back into the locals
    //see above
    //writeContextToLocals(b, 32);
    
    
    // we returned from an extern: assume it cleared the direction flag
    // which is standard for MS calling conventions
    //
    F_CLEAR(b, DF);
   
    //if our convention says to keep the call result alive then do it
    //really, we could always keep the call result alive...
    if( rType == Type::getInt32Ty(M->getContext()) ) {
        R_WRITE<32>(b, X86::EAX, callR);
    }


    // stdcall and fastcall: callee changed ESP; adjust
    // REG_ESP accordingly
    if( externFunction->getCallingConv() == CallingConv::X86_StdCall ||
        externFunction->getCallingConv() == CallingConv::X86_FastCall)
    {
        Value *ESP_adjust = CONST_V<32>(b, 4*paramCount);
        Value *espFix =
            BinaryOperator::CreateAdd(espOld, ESP_adjust, "", b);

        R_WRITE<32>(b, X86::ESP, espFix);
    }

    return ContinueBlock;
}
Esempio n. 6
0
    virtual bool runOnFunction(Function &F) {
      DEBUG(errs() << "Running on " << F.getName() << "\n");
      DEBUG(F.dump());
      Changed = false;
      BaseMap.clear();
      BoundsMap.clear();
      AbrtBB = 0;
      valid = true;

      if (!rootNode) {
        rootNode = getAnalysis<CallGraph>().getRoot();
        // No recursive functions for now.
        // In the future we may insert runtime checks for stack depth.
        for (scc_iterator<CallGraphNode*> SCCI = scc_begin(rootNode),
             E = scc_end(rootNode); SCCI != E; ++SCCI) {
          const std::vector<CallGraphNode*> &nextSCC = *SCCI;
          if (nextSCC.size() > 1 || SCCI.hasLoop()) {
            errs() << "INVALID: Recursion detected, callgraph SCC components: ";
            for (std::vector<CallGraphNode*>::const_iterator I = nextSCC.begin(),
                 E = nextSCC.end(); I != E; ++I) {
              Function *FF = (*I)->getFunction();
              if (FF) {
                errs() << FF->getName() << ", ";
                badFunctions.insert(FF);
              }
            }
            if (SCCI.hasLoop())
              errs() << "(self-loop)";
            errs() << "\n";
          }
          // we could also have recursion via function pointers, but we don't
          // allow calls to unknown functions, see runOnFunction() below
        }
      }

      BasicBlock::iterator It = F.getEntryBlock().begin();
      while (isa<AllocaInst>(It) || isa<PHINode>(It)) ++It;
      EP = &*It;

      TD = &getAnalysis<TargetData>();
      SE = &getAnalysis<ScalarEvolution>();
      PT = &getAnalysis<PointerTracking>();
      DT = &getAnalysis<DominatorTree>();

      std::vector<Instruction*> insns;

      BasicBlock *LastBB = 0;
      bool skip = false;
      for (inst_iterator I=inst_begin(F),E=inst_end(F); I != E;++I) {
        Instruction *II = &*I;
	if (II->getParent() != LastBB) {
	    LastBB = II->getParent();
	    skip = DT->getNode(LastBB) == 0;
	}
	if (skip)
	    continue;
        if (isa<LoadInst>(II) || isa<StoreInst>(II) || isa<MemIntrinsic>(II))
          insns.push_back(II);
        if (CallInst *CI = dyn_cast<CallInst>(II)) {
          Value *V = CI->getCalledValue()->stripPointerCasts();
          Function *F = dyn_cast<Function>(V);
          if (!F) {
            printLocation(CI, true);
            errs() << "Could not determine call target\n";
            valid = 0;
            continue;
          }
          if (!F->isDeclaration())
            continue;
          insns.push_back(CI);
        }
      }
      while (!insns.empty()) {
        Instruction *II = insns.back();
        insns.pop_back();
        DEBUG(dbgs() << "checking " << *II << "\n");
        if (LoadInst *LI = dyn_cast<LoadInst>(II)) {
          const Type *Ty = LI->getType();
          valid &= validateAccess(LI->getPointerOperand(),
                                  TD->getTypeAllocSize(Ty), LI);
        } else if (StoreInst *SI = dyn_cast<StoreInst>(II)) {
          const Type *Ty = SI->getOperand(0)->getType();
          valid &= validateAccess(SI->getPointerOperand(),
                                  TD->getTypeAllocSize(Ty), SI);
        } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(II)) {
          valid &= validateAccess(MI->getDest(), MI->getLength(), MI);
          if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(MI)) {
            valid &= validateAccess(MTI->getSource(), MI->getLength(), MI);
          }
        } else if (CallInst *CI = dyn_cast<CallInst>(II)) {
          Value *V = CI->getCalledValue()->stripPointerCasts();
          Function *F = cast<Function>(V);
          const FunctionType *FTy = F->getFunctionType();
	  CallSite CS(CI);

          if (F->getName().equals("memcmp") && FTy->getNumParams() == 3) {
            valid &= validateAccess(CS.getArgument(0), CS.getArgument(2), CI);
            valid &= validateAccess(CS.getArgument(1), CS.getArgument(2), CI);
            continue;
          }
	  unsigned i;
#ifdef CLAMBC_COMPILER
	  i = 0;
#else
	  i = 1;// skip hidden ctx*
#endif
          for (;i<FTy->getNumParams();i++) {
            if (isa<PointerType>(FTy->getParamType(i))) {
              Value *Ptr = CS.getArgument(i);
              if (i+1 >= FTy->getNumParams()) {
                printLocation(CI, false);
                errs() << "Call to external function with pointer parameter last cannot be analyzed\n";
                errs() << *CI << "\n";
                valid = 0;
                break;
              }
              Value *Size = CS.getArgument(i+1);
              if (!Size->getType()->isIntegerTy()) {
                printLocation(CI, false);
                errs() << "Pointer argument must be followed by integer argument representing its size\n";
                errs() << *CI << "\n";
                valid = 0;
                break;
              }
              valid &= validateAccess(Ptr, Size, CI);
            }
          }
        }
      }
      if (badFunctions.count(&F))
        valid = 0;

      if (!valid) {
	DEBUG(F.dump());
        ClamBCModule::stop("Verification found errors!", &F);
	// replace function with call to abort
        std::vector<const Type*>args;
        FunctionType* abrtTy = FunctionType::get(
          Type::getVoidTy(F.getContext()),args,false);
        Constant *func_abort =
          F.getParent()->getOrInsertFunction("abort", abrtTy);

	BasicBlock *BB = &F.getEntryBlock();
	Instruction *I = &*BB->begin();
	Instruction *UI = new UnreachableInst(F.getContext(), I);
	CallInst *AbrtC = CallInst::Create(func_abort, "", UI);
        AbrtC->setCallingConv(CallingConv::C);
        AbrtC->setTailCall(true);
        AbrtC->setDoesNotReturn(true);
        AbrtC->setDoesNotThrow(true);
	// remove all instructions from entry
	BasicBlock::iterator BBI = I, BBE=BB->end();
	while (BBI != BBE) {
	    if (!BBI->use_empty())
		BBI->replaceAllUsesWith(UndefValue::get(BBI->getType()));
	    BB->getInstList().erase(BBI++);
	}
      }
      return Changed;
    }