void GraphBuilder::visitPtrToIntInst(PtrToIntInst& I) { DSNode* N = getValueDest(I.getOperand(0)).getNode(); if(I.hasOneUse()) { if(isa<ICmpInst>(*(I.use_begin()))) { NumBoringIntToPtr++; return; } } if(I.hasOneUse()) { Value *V = dyn_cast<Value>(*(I.use_begin())); DenseSet<Value *> Seen; while(V && V->hasOneUse() && Seen.insert(V).second) { if(isa<LoadInst>(V)) break; if(isa<StoreInst>(V)) break; if(isa<CallInst>(V)) break; V = dyn_cast<Value>(*(V->use_begin())); } if(isa<BranchInst>(V)){ NumBoringIntToPtr++; return; } } if(N) N->setPtrToIntMarker(); }
bool CallAnalyzer::visitPtrToInt(PtrToIntInst &I) { // Propagate constants through ptrtoint. if (Constant *COp = dyn_cast<Constant>(I.getOperand(0))) if (Constant *C = ConstantExpr::getPtrToInt(COp, I.getType())) { SimplifiedValues[&I] = C; return true; } // Track base/offset pairs when converted to a plain integer provided the // integer is large enough to represent the pointer. unsigned IntegerSize = I.getType()->getScalarSizeInBits(); if (TD && IntegerSize >= TD->getPointerSizeInBits()) { std::pair<Value *, APInt> BaseAndOffset = ConstantOffsetPtrs.lookup(I.getOperand(0)); if (BaseAndOffset.first) ConstantOffsetPtrs[&I] = BaseAndOffset; } // This is really weird. Technically, ptrtoint will disable SROA. However, // unless that ptrtoint is *used* somewhere in the live basic blocks after // inlining, it will be nuked, and SROA should proceed. All of the uses which // would block SROA would also block SROA if applied directly to a pointer, // and so we can just add the integer in here. The only places where SROA is // preserved either cannot fire on an integer, or won't in-and-of themselves // disable SROA (ext) w/o some later use that we would see and disable. Value *SROAArg; DenseMap<Value *, int>::iterator CostIt; if (lookupSROAArgAndCost(I.getOperand(0), SROAArg, CostIt)) SROAArgValues[&I] = SROAArg; return isInstructionFree(&I, TD); }
void PandaInstrumentVisitor::visitMemSetInst(MemSetInst &I){ Function *F = mod->getFunction("log_dynval"); if (!F) { printf("Instrumentation function not found\n"); assert(1==0); } int bytes = 0; Value *length = I.getLength(); if (ConstantInt* CI = dyn_cast<ConstantInt>(length)) { if (CI->getBitWidth() <= 64) { bytes = CI->getSExtValue(); } } if (bytes > 100) { //This mostly happens in cpu state reset printf("Note: dyn log ignoring memset greater than 100 bytes\n"); return; } PtrToIntInst *PTII; CallInst *CI; std::vector<Value*> argValues; PTII = static_cast<PtrToIntInst*>(IRB.CreatePtrToInt( I.getOperand(0), wordType)); argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, ADDRENTRY)); argValues.push_back(ConstantInt::get(intType, STORE)); argValues.push_back(static_cast<Value*>(PTII)); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); PTII->insertBefore(static_cast<Instruction*>(CI)); }
void GCInvariantVerifier::visitPtrToIntInst(PtrToIntInst &PII) { Check(!isSpecialAS(PII.getPointerAddressSpace()), "Illegal inttoptr", &PII); }
// // Method: addBitMasking() // // Description: // Add code before the specified instruction to perform the appropriate // bit-masking of the specified pointer. // Value * Iago::addBitMasking (Value * Pointer, Instruction & I) { // // Create the integer values used for bit-masking. // TargetData & TD = getAnalysis<TargetData>(); Type * IntPtrTy = TD.getIntPtrType(I.getContext()); Value * CheckMask = ConstantInt::get (IntPtrTy, checkMask); Value * SetMask = ConstantInt::get (IntPtrTy, setMask); Value * Zero = ConstantInt::get (IntPtrTy, 0u); Value * ThirtyTwo = ConstantInt::get (IntPtrTy, 32u); // // Convert the pointer into an integer and then shift the higher order bits // into the lower-half of the integer. Bit-masking operations can use // constant operands, reducing register pressure, if the operands are 32-bits // or smaller. // PtrToIntInst * CastedPointer = new PtrToIntInst(Pointer, IntPtrTy, "ptr", &I); Value * PtrHighBits = BinaryOperator::Create (Instruction::LShr, CastedPointer, ThirtyTwo, "highbits", &I); #if 1 #if 1 // // Create an instruction to mask off the proper bits to see if the pointer // is within the secure memory range. // Value * CheckMasked = BinaryOperator::Create (Instruction::And, PtrHighBits, CheckMask, "checkMask", &I); #endif // // Compare the masked pointer to the mask. If they're the same, we need to // set that bit. // #if 1 Value * Cmp = new ICmpInst (&I, CmpInst::ICMP_EQ, CheckMasked, CheckMask, "cmp"); #else Value * Cmp = new ICmpInst (&I, CmpInst::ICMP_ULE, CheckMask, CastedPointer, "cmp"); #endif // // Create the select instruction that, at run-time, will determine if we use // the bit-masked pointer or the original pointer value. // Value * MaskValue = SelectInst::Create (Cmp, SetMask, Zero, "ptr", &I); // // Create instructions that create a version of the pointer with the proper // bit set. // Value * Masked = BinaryOperator::Create (Instruction::Or, CastedPointer, MaskValue, "setMask", &I); // // Now replace all uses of the original instruction with this one. Be sure // to fixup instructions we created that need to use the old value. // Masked = new IntToPtrInst (Masked, Pointer->getType(), "masked", &I); Pointer->replaceAllUsesWith (Masked); CastedPointer->replaceUsesOfWith (Masked, Pointer); return (Masked); #else Module * M = I.getParent()->getParent()->getParent(); Function * CheckFunction = cast<Function>(M->getFunction ("sva_checkptr")); assert (CheckFunction && "CheckFunction not found!\n"); CallInst::Create (CheckFunction, CastedPointer, "", &I); return Pointer; #endif }
/* * Call the logging function, logging the address of the load. If it's loading * the root of a global value (likely CPUState), then we can ignore it. */ void PandaInstrumentVisitor::visitLoadInst(LoadInst &I){ Function *F = mod->getFunction("log_dynval"); if (!F) { printf("Instrumentation function not found\n"); assert(1==0); } // We used to ignore global values, but I think we will keep it now since // global QEMU values may be referenced in helper functions //if (!(isa<GlobalValue>(I.getPointerOperand()))){ if (isa<GetElementPtrInst>(I.getPointerOperand())){ // Result from a getelementptr instruction CallInst *CI; PtrToIntInst *PTII; std::vector<Value*> argValues; PTII = static_cast<PtrToIntInst*>( IRB.CreatePtrToInt(I.getPointerOperand(), ptrType)); argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, ADDRENTRY)); argValues.push_back(ConstantInt::get(intType, LOAD)); argValues.push_back(static_cast<Value*>(PTII)); //argValues.push_back(static_cast<Value*>(I.getPointerOperand())); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); PTII->insertBefore(static_cast<Instruction*>(CI)); } else if ( // GetElementPtr ConstantExpr (isa<ConstantExpr>(I.getPointerOperand()) && static_cast<ConstantExpr*>(I.getPointerOperand())->getOpcode() == Instruction::GetElementPtr) // IntToPtr ConstantExpr || (isa<ConstantExpr>(I.getPointerOperand()) && static_cast<ConstantExpr*>(I.getPointerOperand())->getOpcode() == Instruction::IntToPtr) // env, or some other global variable || (isa<GlobalVariable>(I.getPointerOperand())) ){ CallInst *CI; PtrToIntInst *PTII; std::vector<Value*> argValues; PTII = static_cast<PtrToIntInst*>( IRB.CreatePtrToInt(I.getPointerOperand(), ptrType)); argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, ADDRENTRY)); argValues.push_back(ConstantInt::get(intType, LOAD)); argValues.push_back(static_cast<Value*>(PTII)); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); } else { PtrToIntInst *PTII; CallInst *CI; std::vector<Value*> argValues; PTII = static_cast<PtrToIntInst*>(IRB.CreatePtrToInt( I.getPointerOperand(), wordType)); argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, ADDRENTRY)); argValues.push_back(ConstantInt::get(intType, LOAD)); argValues.push_back(static_cast<Value*>(PTII)); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); PTII->insertBefore(static_cast<Instruction*>(CI)); } //} }
// Call the logging function, logging the address of the store void PandaInstrumentVisitor::visitStoreInst(StoreInst &I){ Function *F = mod->getFunction("log_dynval"); if (!F) { printf("Instrumentation function not found\n"); assert(1==0); } if (I.isVolatile()){ // Stores to LLVM runtime that we don't care about return; } else if (isa<ConstantExpr>(I.getPointerOperand()) && isa<Constant>(static_cast<Instruction*>( I.getPointerOperand())->getOperand(0))){ /* * Storing to a constant looks something like this: * store i32 %29, i32* inttoptr (i64 135186980 to i32*), * sort of like an inttoptr instruction as an operand. This is how we * deal with logging that weirdness. */ CallInst *CI; std::vector<Value*> argValues; uint64_t constaddr = static_cast<ConstantInt*>( static_cast<Instruction*>( I.getPointerOperand())->getOperand(0))->getZExtValue(); argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, ADDRENTRY)); argValues.push_back(ConstantInt::get(intType, STORE)); argValues.push_back(ConstantInt::get(wordType, constaddr)); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); } else if (isa<GlobalVariable>(I.getPointerOperand())){ //else if (isa<GlobalValue>(I.getPointerOperand())){ // env, or some other global variable CallInst *CI; PtrToIntInst *PTII; std::vector<Value*> argValues; PTII = static_cast<PtrToIntInst*>( IRB.CreatePtrToInt(I.getPointerOperand(), ptrType)); argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, ADDRENTRY)); argValues.push_back(ConstantInt::get(intType, STORE)); argValues.push_back(static_cast<Value*>(PTII)); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); } else { PtrToIntInst *PTII; CallInst *CI; std::vector<Value*> argValues; PTII = static_cast<PtrToIntInst*>(IRB.CreatePtrToInt( I.getPointerOperand(), wordType)); argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, ADDRENTRY)); argValues.push_back(ConstantInt::get(intType, STORE)); argValues.push_back(static_cast<Value*>(PTII)); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); PTII->insertBefore(static_cast<Instruction*>(CI)); } }