/// AddCatchInfo - Extract the personality and type infos from an eh.selector /// call, and add them to the specified machine basic block. void llvm::AddCatchInfo(CallInst &I, MachineModuleInfo *MMI, MachineBasicBlock *MBB) { // Inform the MachineModuleInfo of the personality for this landing pad. ConstantExpr *CE = cast<ConstantExpr>(I.getOperand(2)); assert(CE->getOpcode() == Instruction::BitCast && isa<Function>(CE->getOperand(0)) && "Personality should be a function"); MMI->addPersonality(MBB, cast<Function>(CE->getOperand(0))); // Gather all the type infos for this landing pad and pass them along to // MachineModuleInfo. std::vector<GlobalVariable *> TyInfo; unsigned N = I.getNumOperands(); for (unsigned i = N - 1; i > 2; --i) { if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(i))) { unsigned FilterLength = CI->getZExtValue(); unsigned FirstCatch = i + FilterLength + !FilterLength; assert (FirstCatch <= N && "Invalid filter length"); if (FirstCatch < N) { TyInfo.reserve(N - FirstCatch); for (unsigned j = FirstCatch; j < N; ++j) TyInfo.push_back(ExtractTypeInfo(I.getOperand(j))); MMI->addCatchTypeInfo(MBB, TyInfo); TyInfo.clear(); } if (!FilterLength) { // Cleanup. MMI->addCleanup(MBB); } else { // Filter. TyInfo.reserve(FilterLength - 1); for (unsigned j = i + 1; j < FirstCatch; ++j) TyInfo.push_back(ExtractTypeInfo(I.getOperand(j))); MMI->addFilterTypeInfo(MBB, TyInfo); TyInfo.clear(); } N = i; } } if (N > 3) { TyInfo.reserve(N - 3); for (unsigned j = 3; j < N; ++j) TyInfo.push_back(ExtractTypeInfo(I.getOperand(j))); MMI->addCatchTypeInfo(MBB, TyInfo); } }
/// IsConstantOffsetFromGlobal - If this constant is actually a constant offset /// from a global, return the global and the constant. Because of /// constantexprs, this function is recursive. static bool IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV, int64_t &Offset, const TargetData &TD) { // Trivial case, constant is the global. if ((GV = dyn_cast<GlobalValue>(C))) { Offset = 0; return true; } // Otherwise, if this isn't a constant expr, bail out. ConstantExpr *CE = dyn_cast<ConstantExpr>(C); if (!CE) return false; // Look through ptr->int and ptr->ptr casts. if (CE->getOpcode() == Instruction::PtrToInt || CE->getOpcode() == Instruction::BitCast) return IsConstantOffsetFromGlobal(CE->getOperand(0), GV, Offset, TD); // i32* getelementptr ([5 x i32]* @a, i32 0, i32 5) if (CE->getOpcode() == Instruction::GetElementPtr) { // Cannot compute this if the element type of the pointer is missing size // info. if (!cast<PointerType>(CE->getOperand(0)->getType())->getElementType()->isSized()) return false; // If the base isn't a global+constant, we aren't either. if (!IsConstantOffsetFromGlobal(CE->getOperand(0), GV, Offset, TD)) return false; // Otherwise, add any offset that our operands provide. gep_type_iterator GTI = gep_type_begin(CE); for (unsigned i = 1, e = CE->getNumOperands(); i != e; ++i, ++GTI) { ConstantInt *CI = dyn_cast<ConstantInt>(CE->getOperand(i)); if (!CI) return false; // Index isn't a simple constant? if (CI->getZExtValue() == 0) continue; // Not adding anything. if (const StructType *ST = dyn_cast<StructType>(*GTI)) { // N = N + Offset Offset += TD.getStructLayout(ST)->getElementOffset(CI->getZExtValue()); } else { const SequentialType *SQT = cast<SequentialType>(*GTI); Offset += TD.getTypeSize(SQT->getElementType())*CI->getSExtValue(); } } return true; } return false; }
void ClassHierarchyUtils::findClassHierarchy(Module& M) { // extract call hierarchy using std::type_info structures rather // than debug info. The former works even for when there are anonymous // namespaces. type_info structs can be obtained from vtable globals. // (for more info, see http://mentorembedded.github.io/cxx-abi/abi.html) for (Module::global_iterator I=M.global_begin(), E=M.global_end(); I != E; I++) { GlobalVariable* G = &*I; if (G->getName().startswith("_ZTV")) { if (G->hasInitializer()) { SDEBUG("soaap.util.classhierarchy", 3, G->dump()); ConstantArray* Ginit = cast<ConstantArray>(G->getInitializer()); // Ginit[1] is the type_info global for this vtable's type bool typeInfoFound = false; bool primaryVTable = true; for (int i=0; i<Ginit->getNumOperands(); i++) { // typeinfo will be the first global variable in the array. // It's not always at a fixed index so we have to search for it... if (GlobalVariable* TI = dyn_cast<GlobalVariable>(Ginit->getOperand(i)->stripPointerCasts())) { //TI->dump(); typeInfoToVTable[TI] = G; vTableToTypeInfo[G] = TI; processTypeInfo(TI); // process TI recursively (it contains refs to super-class TIs) typeInfoFound = true; if (primaryVTable) { primaryVTable = false; vTableToSecondaryVTableMaps[G][0] = i+1; // i+1 is also the size of the vtable header } else { // offset_to_top is at the previous index ConstantExpr* offsetValCast = cast<ConstantExpr>(Ginit->getOperand(i-1)->stripPointerCasts()); ConstantInt* offsetVal = cast<ConstantInt>(offsetValCast->getOperand(0)); int offsetToTop = offsetVal->getSExtValue(); if (offsetToTop > 0) { dbgs() << "ERROR: offsetToTop is positive!\n"; G->dump(); } else { offsetToTop *= -1; } SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "offsetToTop: " << offsetToTop << "\n"); vTableToSecondaryVTableMaps[G][offsetToTop] = i+1; } } } if (!typeInfoFound) { dbgs() << "ERROR: vtable initializer is not a global variable...\n"; dbgs() << *G << " = " << *Ginit << "\n"; } } } } SDEBUG("soaap.util.classhierarchy", 3, ppClassHierarchy(classToSubclasses)); }
void ControlFlowIntegrity::PatchDtorFunctions(void) { GlobalVariable *global_dtors = _M.getNamedGlobal("llvm.global_dtors"); // check for dtor section if (!global_dtors || !global_dtors->getOperand(0)) { return; } Constant *c = global_dtors->getInitializer(); if (!c) report_fatal_error("llvm.global_dtors without initializer!", false); ConstantArray *CA = dyn_cast<ConstantArray>(c); if (!CA) report_fatal_error("Cast to ConstantArray failed", true); for (Value *Op : ValueOpRange(*CA)) { ConstantStruct *CS = dyn_cast<ConstantStruct>(Op); if (!CS) report_fatal_error("Cast to ConstantStruct failed", true); Constant *FP = CS->getOperand(1); if (FP->isNullValue()) break; // found a NULL termintator, stop here Function *F = dyn_cast_or_null<Function>(FP); if (F == NULL) { // Strip off constant expression cast ConstantExpr *CE = dyn_cast<ConstantExpr>(FP); if (!CE) report_fatal_error("Cast to ConstantExpr failed", true); if (CE->isCast()) { FP = CE->getOperand(0); } F = dyn_cast_or_null<Function>(FP); } if (!F) report_fatal_error("Cast to Function failed", true); // set visibility to hidden (do not export), unless it is already // local (for ex. static), in which case we have to make it non-static if (F->hasLocalLinkage()) { F->setLinkage(llvm::GlobalValue::ExternalLinkage); } F->setVisibility(GlobalValue::HiddenVisibility); _FiniFunctions.insert(F->getName()); } if (global_dtors->getNumUses() > 0) report_fatal_error("llvm.global_dtors uses count is > 0!", false); global_dtors->removeFromParent(); }
/// Return true if the specified constant can be handled by the code generator. /// We don't want to generate something like: /// void *X = &X/42; /// because the code generator doesn't have a relocation that can handle that. /// /// This function should be called if C was not found (but just got inserted) /// in SimpleConstants to avoid having to rescan the same constants all the /// time. static bool isSimpleEnoughValueToCommitHelper(Constant *C, SmallPtrSetImpl<Constant *> &SimpleConstants, const DataLayout &DL) { // Simple global addresses are supported, do not allow dllimport or // thread-local globals. if (auto *GV = dyn_cast<GlobalValue>(C)) return !GV->hasDLLImportStorageClass() && !GV->isThreadLocal(); // Simple integer, undef, constant aggregate zero, etc are all supported. if (C->getNumOperands() == 0 || isa<BlockAddress>(C)) return true; // Aggregate values are safe if all their elements are. if (isa<ConstantArray>(C) || isa<ConstantStruct>(C) || isa<ConstantVector>(C)) { for (Value *Op : C->operands()) if (!isSimpleEnoughValueToCommit(cast<Constant>(Op), SimpleConstants, DL)) return false; return true; } // We don't know exactly what relocations are allowed in constant expressions, // so we allow &global+constantoffset, which is safe and uniformly supported // across targets. ConstantExpr *CE = cast<ConstantExpr>(C); switch (CE->getOpcode()) { case Instruction::BitCast: // Bitcast is fine if the casted value is fine. return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, DL); case Instruction::IntToPtr: case Instruction::PtrToInt: // int <=> ptr is fine if the int type is the same size as the // pointer type. if (DL.getTypeSizeInBits(CE->getType()) != DL.getTypeSizeInBits(CE->getOperand(0)->getType())) return false; return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, DL); // GEP is fine if it is simple + constant offset. case Instruction::GetElementPtr: for (unsigned i = 1, e = CE->getNumOperands(); i != e; ++i) if (!isa<ConstantInt>(CE->getOperand(i))) return false; return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, DL); case Instruction::Add: // We allow simple+cst. if (!isa<ConstantInt>(CE->getOperand(1))) return false; return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, DL); } return false; }
static GlobalValue *getAliaseeGV(GlobalAlias *GA) { Constant *C = GA->getAliasee(); assert(C && "Must alias something"); if (GlobalValue *GV = dyn_cast<GlobalValue>(C)) return GV; ConstantExpr *CE = cast<ConstantExpr>(C); assert((CE->getOpcode() == Instruction::BitCast || CE->getOpcode() == Instruction::AddrSpaceCast || CE->getOpcode() == Instruction::GetElementPtr) && "Unsupported aliasee"); return cast<GlobalValue>(CE->getOperand(0)); }
GlobalValue *GlobalAlias::getAliasedGlobal() { Constant *C = getAliasee(); if (C == 0) return 0; if (GlobalValue *GV = dyn_cast<GlobalValue>(C)) return GV; ConstantExpr *CE = cast<ConstantExpr>(C); assert((CE->getOpcode() == Instruction::BitCast || CE->getOpcode() == Instruction::AddrSpaceCast || CE->getOpcode() == Instruction::GetElementPtr) && "Unsupported aliasee"); return cast<GlobalValue>(CE->getOperand(0)); }
static Constant* sd_getDestructorFunction(Constant* vtblElement) { ConstantExpr* bcExpr = NULL; // if this a constant bitcast expression, this might be a vthunk if ((bcExpr = dyn_cast<ConstantExpr>(vtblElement)) && bcExpr->getOpcode() == BITCAST_OPCODE) { Constant* operand = bcExpr->getOperand(0); // this is a vthunk if (sd_isDestructorName(operand->getName())) { return operand; } } return NULL; }
static Constant* sd_isRTTI(Constant* vtblElement) { ConstantExpr* bcExpr = NULL; // if this a constant bitcast expression, this might be a vthunk if ((bcExpr = dyn_cast<ConstantExpr>(vtblElement)) && bcExpr->getOpcode() == Instruction::BitCast) { Constant* operand = bcExpr->getOperand(0); // this is a vthunk if (operand->getName().startswith("_ZTI")) { return operand; } } return NULL; }
std::string readAnnotate(Function *f) { std::string annotation = ""; // Get annotation variable GlobalVariable *glob = f->getParent()->getGlobalVariable("llvm.global.annotations"); if (glob != NULL) { // Get the array if (ConstantArray *ca = dyn_cast<ConstantArray>(glob->getInitializer())) { for (unsigned i = 0; i < ca->getNumOperands(); ++i) { // Get the struct if (ConstantStruct *structAn = dyn_cast<ConstantStruct>(ca->getOperand(i))) { if (ConstantExpr *expr = dyn_cast<ConstantExpr>(structAn->getOperand(0))) { // If it's a bitcast we can check if the annotation is concerning // the current function if (expr->getOpcode() == Instruction::BitCast && expr->getOperand(0) == f) { ConstantExpr *note = cast<ConstantExpr>(structAn->getOperand(1)); // If it's a GetElementPtr, that means we found the variable // containing the annotations if (note->getOpcode() == Instruction::GetElementPtr) { if (GlobalVariable *annoteStr = dyn_cast<GlobalVariable>(note->getOperand(0))) { if (ConstantDataSequential *data = dyn_cast<ConstantDataSequential>( annoteStr->getInitializer())) { if (data->isString()) { annotation += data->getAsString().lower() + " "; } } } } } } } } } } return annotation; }
void ControlFlowIntegrity::ParseAnnotations(void) { GlobalVariable *global_ctors = _M.getNamedGlobal("llvm.global.annotations"); // check for ctor section if (!global_ctors || !global_ctors->getOperand(0)) { return; } Constant *c = global_ctors->getInitializer(); if (!c) report_fatal_error("llvm.global.annotations without initializer!", false); ConstantArray *CA = dyn_cast<ConstantArray>(c); if (!CA) report_fatal_error("Cast to ConstantArray failed", true); for (Value *Op : ValueOpRange(*CA)) { ConstantStruct *CS = dyn_cast<ConstantStruct>(Op); if (!CS) report_fatal_error("Cast to ConstantStruct failed", true); Constant *FP = CS->getOperand(0); if (FP->isNullValue()) break; // found a NULL termintator, stop here ConstantExpr *CE; Function *F = dyn_cast_or_null<Function>(FP); if (F == NULL) { // Strip off constant expression cast CE = dyn_cast<ConstantExpr>(FP); if (!CE) report_fatal_error("Cast to ConstantExpr failed", true); if (CE->isCast()) { FP = CE->getOperand(0); F = dyn_cast_or_null<Function>(FP); } } if (!F) report_fatal_error("Cast to Function failed", true); Constant *SP = CS->getOperand(1); if (SP->isNullValue()) break; // found a NULL termintator, stop here // Strip off constant expression cast CE = dyn_cast<ConstantExpr>(SP); if (!CE) report_fatal_error("Cast to ConstantExpr failed", true); if (CE->isCast()) { SP = CE->getOperand(0); } Value *V = SP->getOperand(0); GlobalVariable *GV = dyn_cast_or_null<GlobalVariable>(V); if (!GV) report_fatal_error("Cast to GlobalVariable failed", false); assert(GV && "cast to GlobalVariable failed"); Constant *cval = GV->getInitializer(); const StringRef s = (cast<ConstantDataArray>(cval))->getAsCString(); if (s == ANNOTATION_IGNORE_BLOCK) { _IgnoredBlocksFunctions.insert(F->getName()); } } if (global_ctors->getNumUses() > 0) report_fatal_error("llvm.global.annotations uses count is > 0", false); }
// // Method: runOnModule() // // Description: // Entry point for this LLVM pass. // Search for all call sites to casted functions. // Check if they only differ in an argument type // Cast the argument, and call the original function // // Inputs: // M - A reference to the LLVM module to transform // // Outputs: // M - The transformed LLVM module. // // Return value: // true - The module was modified. // false - The module was not modified. // bool ArgCast::runOnModule(Module& M) { std::vector<CallInst*> worklist; for (Module::iterator I = M.begin(); I != M.end(); ++I) { if (I->mayBeOverridden()) continue; // Find all uses of this function for(Value::user_iterator ui = I->user_begin(), ue = I->user_end(); ui != ue; ) { // check if is ever casted to a different function type ConstantExpr *CE = dyn_cast<ConstantExpr>(*ui++); if(!CE) continue; if (CE->getOpcode() != Instruction::BitCast) continue; if(CE->getOperand(0) != I) continue; const PointerType *PTy = dyn_cast<PointerType>(CE->getType()); if (!PTy) continue; const Type *ETy = PTy->getElementType(); const FunctionType *FTy = dyn_cast<FunctionType>(ETy); if(!FTy) continue; // casting to a varargs funtion // or function with same number of arguments // possibly varying types of arguments if(FTy->getNumParams() != I->arg_size() && !FTy->isVarArg()) continue; for(Value::user_iterator uii = CE->user_begin(), uee = CE->user_end(); uii != uee; ++uii) { // Find all uses of the casted value, and check if it is // used in a Call Instruction if (CallInst* CI = dyn_cast<CallInst>(*uii)) { // Check that it is the called value, and not an argument if(CI->getCalledValue() != CE) continue; // Check that the number of arguments passed, and expected // by the function are the same. if(!I->isVarArg()) { if(CI->getNumOperands() != I->arg_size() + 1) continue; } else { if(CI->getNumOperands() < I->arg_size() + 1) continue; } // If so, add to worklist worklist.push_back(CI); } } } } // Proces the worklist of potential call sites to transform while(!worklist.empty()) { CallInst *CI = worklist.back(); worklist.pop_back(); // Get the called Function Function *F = cast<Function>(CI->getCalledValue()->stripPointerCasts()); const FunctionType *FTy = F->getFunctionType(); SmallVector<Value*, 8> Args; unsigned i =0; for(i =0; i< FTy->getNumParams(); ++i) { Type *ArgType = CI->getOperand(i+1)->getType(); Type *FormalType = FTy->getParamType(i); // If the types for this argument match, just add it to the // parameter list. No cast needs to be inserted. if(ArgType == FormalType) { Args.push_back(CI->getOperand(i+1)); } else if(ArgType->isPointerTy() && FormalType->isPointerTy()) { CastInst *CastI = CastInst::CreatePointerCast(CI->getOperand(i+1), FormalType, "", CI); Args.push_back(CastI); } else if (ArgType->isIntegerTy() && FormalType->isIntegerTy()) { unsigned SrcBits = ArgType->getScalarSizeInBits(); unsigned DstBits = FormalType->getScalarSizeInBits(); if(SrcBits > DstBits) { CastInst *CastI = CastInst::CreateIntegerCast(CI->getOperand(i+1), FormalType, true, "", CI); Args.push_back(CastI); } else { if (F->getAttributes().hasAttribute(i+1, Attribute::SExt)) { CastInst *CastI = CastInst::CreateIntegerCast(CI->getOperand(i+1), FormalType, true, "", CI); Args.push_back(CastI); } else if (F->getAttributes().hasAttribute(i+1, Attribute::ZExt)) { CastInst *CastI = CastInst::CreateIntegerCast(CI->getOperand(i+1), FormalType, false, "", CI); Args.push_back(CastI); } else { // Use ZExt in default case. // Derived from InstCombine. Also, the only reason this should happen // is mismatched prototypes. // Seen in case of integer constants which get interpreted as i32, // even if being used as i64. // TODO: is this correct? CastInst *CastI = CastInst::CreateIntegerCast(CI->getOperand(i+1), FormalType, false, "", CI); Args.push_back(CastI); } } } else { DEBUG(ArgType->dump()); DEBUG(FormalType->dump()); break; } } // If we found an argument we could not cast, try the next instruction if(i != FTy->getNumParams()) { continue; } if(FTy->isVarArg()) { for(; i< CI->getNumOperands() - 1 ;i++) { Args.push_back(CI->getOperand(i+1)); } } // else replace the call instruction CallInst *CINew = CallInst::Create(F, Args, "", CI); CINew->setCallingConv(CI->getCallingConv()); CINew->setAttributes(CI->getAttributes()); if(!CI->use_empty()) { CastInst *RetCast; if(CI->getType() != CINew->getType()) { if(CI->getType()->isPointerTy() && CINew->getType()->isPointerTy()) RetCast = CastInst::CreatePointerCast(CINew, CI->getType(), "", CI); else if(CI->getType()->isIntOrIntVectorTy() && CINew->getType()->isIntOrIntVectorTy()) RetCast = CastInst::CreateIntegerCast(CINew, CI->getType(), false, "", CI); else if(CI->getType()->isIntOrIntVectorTy() && CINew->getType()->isPointerTy()) RetCast = CastInst::CreatePointerCast(CINew, CI->getType(), "", CI); else if(CI->getType()->isPointerTy() && CINew->getType()->isIntOrIntVectorTy()) RetCast = new IntToPtrInst(CINew, CI->getType(), "", CI); else { // TODO: I'm not sure what right behavior is here, but this case should be handled. llvm_unreachable("Unexpected type conversion in call!"); abort(); } CI->replaceAllUsesWith(RetCast); } else { CI->replaceAllUsesWith(CINew); } } // Debug printing DEBUG(errs() << "ARGCAST:"); DEBUG(errs() << "ERASE:"); DEBUG(CI->dump()); DEBUG(errs() << "ARGCAST:"); DEBUG(errs() << "ADDED:"); DEBUG(CINew->dump()); CI->eraseFromParent(); numChanged++; } return true; }
virtual bool runOnFunction(Function &F) { //F.dump(); bool changed = false; for (inst_iterator inst_it = inst_begin(F), _inst_end = inst_end(F); inst_it != _inst_end; ++inst_it) { LoadInst *li = dyn_cast<LoadInst>(&*inst_it); if (!li) continue; ConstantExpr *ce = dyn_cast<ConstantExpr>(li->getOperand(0)); // Not 100% sure what the isGEPWithNoNotionalOverIndexing() means, but // at least it checks if it's a gep: if (ce && ce->isGEPWithNoNotionalOverIndexing() && ce->getOperand(0)->getType() == g.llvm_flavor_type_ptr) { changed = handleFlavor(li, ce); } GlobalVariable *gv = dyn_cast<GlobalVariable>(li->getOperand(0)); if (!gv) continue; llvm::Type* gv_t = gv->getType(); if (gv_t == g.llvm_bool_type_ptr->getPointerTo()) { changed = handleBool(li, gv) || changed; continue; } if (gv_t == g.llvm_class_type_ptr->getPointerTo()) { changed = handleCls(li, gv) || changed; continue; } } return changed; }