void moveGlobalVariableInitializer(GlobalVariable &OrigGV, ValueToValueMapTy &VMap, ValueMaterializer *Materializer, GlobalVariable *NewGV) { assert(OrigGV.hasInitializer() && "Nothing to move"); if (!NewGV) NewGV = cast<GlobalVariable>(VMap[&OrigGV]); else assert(VMap[&OrigGV] == NewGV && "Incorrect global variable mapping in VMap."); assert(NewGV->getParent() != OrigGV.getParent() && "moveGlobalVariable should only be used to move initializers between " "modules"); NewGV->setInitializer(MapValue(OrigGV.getInitializer(), VMap, RF_None, nullptr, Materializer)); }
/// Return true if this constant is simple enough for us to understand. In /// particular, if it is a cast to anything other than from one pointer type to /// another pointer type, we punt. We basically just support direct accesses to /// globals and GEP's of globals. This should be kept up to date with /// CommitValueTo. static bool isSimpleEnoughPointerToCommit(Constant *C) { // Conservatively, avoid aggregate types. This is because we don't // want to worry about them partially overlapping other stores. if (!cast<PointerType>(C->getType())->getElementType()->isSingleValueType()) return false; if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) // Do not allow weak/*_odr/linkonce linkage or external globals. return GV->hasUniqueInitializer(); if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) { // Handle a constantexpr gep. if (CE->getOpcode() == Instruction::GetElementPtr && isa<GlobalVariable>(CE->getOperand(0)) && cast<GEPOperator>(CE)->isInBounds()) { GlobalVariable *GV = cast<GlobalVariable>(CE->getOperand(0)); // Do not allow weak/*_odr/linkonce/dllimport/dllexport linkage or // external globals. if (!GV->hasUniqueInitializer()) return false; // The first index must be zero. ConstantInt *CI = dyn_cast<ConstantInt>(*std::next(CE->op_begin())); if (!CI || !CI->isZero()) return false; // The remaining indices must be compile-time known integers within the // notional bounds of the corresponding static array types. if (!CE->isGEPWithNoNotionalOverIndexing()) return false; return ConstantFoldLoadThroughGEPConstantExpr(GV->getInitializer(), CE); // A constantexpr bitcast from a pointer to another pointer is a no-op, // and we know how to evaluate it by moving the bitcast from the pointer // operand to the value operand. } else if (CE->getOpcode() == Instruction::BitCast && isa<GlobalVariable>(CE->getOperand(0))) { // Do not allow weak/*_odr/linkonce/dllimport/dllexport linkage or // external globals. return cast<GlobalVariable>(CE->getOperand(0))->hasUniqueInitializer(); } } return false; }
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; }
// doInitialization - Initializes the vector of functions that have been // annotated with the noinline attribute. bool SimpleInliner::doInitialization(CallGraph &CG) { CA.setTargetData(getAnalysisIfAvailable<TargetData>()); Module &M = CG.getModule(); for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) if (!I->isDeclaration() && I->hasFnAttr(Attribute::NoInline)) NeverInline.insert(I); // Get llvm.noinline GlobalVariable *GV = M.getNamedGlobal("llvm.noinline"); if (GV == 0) return false; // Don't crash on invalid code if (!GV->hasDefinitiveInitializer()) return false; const ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer()); if (InitList == 0) return false; // Iterate over each element and add to the NeverInline set for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { // Get Source const Constant *Elt = InitList->getOperand(i); if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(Elt)) if (CE->getOpcode() == Instruction::BitCast) Elt = CE->getOperand(0); // Insert into set of functions to never inline if (const Function *F = dyn_cast<Function>(Elt)) NeverInline.insert(F); } return false; }
std::string ModuloScheduler::get_legup_label(BasicBlock *bb) { std::string label = ""; for (BasicBlock::iterator instr = bb->begin(), ie = bb->end(); instr != ie; ++instr) { const CallInst *ci = dyn_cast<CallInst>(instr); if (!ci) continue; Function *calledFunc = ci->getCalledFunction(); // ignore indirect function invocations if (!calledFunc) continue; if (calledFunc->getName() == "__legup_label") { // errs() << "Found label: " << *ci << "\n"; Value *str = *ci->op_begin(); // handle getelementptr if (const User *U = dyn_cast<User>(str)) { if (U->getNumOperands() > 1) { str = U->getOperand(0); } } GlobalVariable *G = dyn_cast<GlobalVariable>(str); assert(G); Constant *C = G->getInitializer(); assert(C); // TODO: LLVM 3.4 update // ConstantArray *CA = dyn_cast<ConstantArray>(C); if (ConstantArray *CA = dyn_cast<ConstantArray>(C)) { assert(CA); label = arrayToString(CA); } else if (ConstantDataArray *CA = dyn_cast<ConstantDataArray>(C)) { assert(CA); label = CA->getAsCString(); } return label; } } return label; }
void AssertionSiteInstrumenter::ParseAssertionLocation( Location *Loc, CallInst *Call) { assert(Call->getCalledFunction()->getName() == INLINE_ASSERTION); if (Call->getNumArgOperands() < 4) panic("TESLA assertion must have at least 4 arguments"); // The filename (argument 1) should be a global variable. GlobalVariable *NameVar = dyn_cast<GlobalVariable>(Call->getOperand(1)->stripPointerCasts()); ConstantDataArray *A; if (!NameVar || !(A = dyn_cast_or_null<ConstantDataArray>(NameVar->getInitializer()))) { Call->dump(); panic("unable to parse filename from TESLA assertion"); } *Loc->mutable_filename() = A->getAsString(); // The line and counter values should be constant integers. ConstantInt *Line = dyn_cast<ConstantInt>(Call->getOperand(2)); if (!Line) { Call->getOperand(2)->dump(); panic("assertion line must be a constant int"); } Loc->set_line(Line->getLimitedValue(INT_MAX)); ConstantInt *Count = dyn_cast<ConstantInt>(Call->getOperand(3)); if (!Count) { Call->getOperand(3)->dump(); panic("assertion count must be a constant int"); } Loc->set_counter(Count->getLimitedValue(INT_MAX)); }
void MemoryInstrumenter::lowerGlobalCtors(Module &M) { // Find llvm.global_ctors. GlobalVariable *GV = M.getNamedGlobal("llvm.global_ctors"); if (!GV) return; assert(!GV->isDeclaration() && !GV->hasLocalLinkage()); // Should be an array of '{ int, void ()* }' structs. The first value is // the init priority, which must be 65535 if the bitcode is generated using // clang. if (ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer())) { for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i)); assert(CS); assert(CS->getNumOperands() == 2); // Get the priority. ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0)); assert(Priority); // TODO: For now, we assume all priorities must be 65535. assert(Priority->equalsInt(65535)); // Get the constructor function. Constant *FP = CS->getOperand(1); if (FP->isNullValue()) break; // Found a null terminator, exit. // Explicitly call the constructor at the main entry. CallInst::Create(FP, "", Main->begin()->getFirstNonPHI()); } } // Clear the global_ctors array. // Use eraseFromParent() instead of removeFromParent(). GV->eraseFromParent(); }
void PerfMonitor::addToGlobalConstructors(Function *Fn) { const char *Name = "llvm.global_ctors"; GlobalVariable *GV = M->getGlobalVariable(Name); std::vector<Constant *> V; if (GV) { Constant *Array = GV->getInitializer(); for (Value *X : Array->operand_values()) V.push_back(cast<Constant>(X)); GV->eraseFromParent(); } StructType *ST = StructType::get(Builder.getInt32Ty(), Fn->getType(), Builder.getInt8PtrTy()); V.push_back( ConstantStruct::get(ST, Builder.getInt32(10), Fn, ConstantPointerNull::get(Builder.getInt8PtrTy()))); ArrayType *Ty = ArrayType::get(ST, V.size()); GV = new GlobalVariable(*M, Ty, true, GlobalValue::AppendingLinkage, ConstantArray::get(Ty, V), Name, nullptr, GlobalVariable::NotThreadLocal); }
/// Return the value that would be computed by a load from P after the stores /// reflected by 'memory' have been performed. If we can't decide, return null. Constant *Evaluator::ComputeLoadResult(Constant *P) { // If this memory location has been recently stored, use the stored value: it // is the most up-to-date. DenseMap<Constant*, Constant*>::const_iterator I = MutatedMemory.find(P); if (I != MutatedMemory.end()) return I->second; // Access it. if (GlobalVariable *GV = dyn_cast<GlobalVariable>(P)) { if (GV->hasDefinitiveInitializer()) return GV->getInitializer(); return nullptr; } // Handle a constantexpr getelementptr. if (ConstantExpr *CE = dyn_cast<ConstantExpr>(P)) if (CE->getOpcode() == Instruction::GetElementPtr && isa<GlobalVariable>(CE->getOperand(0))) { GlobalVariable *GV = cast<GlobalVariable>(CE->getOperand(0)); if (GV->hasDefinitiveInitializer()) return ConstantFoldLoadThroughGEPConstantExpr(GV->getInitializer(), CE); } return nullptr; // don't know how to evaluate. }
bool ConstantMerge::runOnModule(Module &M) { // Find all the globals that are marked "used". These cannot be merged. SmallPtrSet<const GlobalValue*, 8> UsedGlobals; FindUsedValues(M.getGlobalVariable("llvm.used"), UsedGlobals); FindUsedValues(M.getGlobalVariable("llvm.compiler.used"), UsedGlobals); // Map unique constant/section pairs to globals. We don't want to merge // globals in different sections. DenseMap<Constant*, GlobalVariable*> CMap; // Replacements - This vector contains a list of replacements to perform. SmallVector<std::pair<GlobalVariable*, GlobalVariable*>, 32> Replacements; bool MadeChange = false; // Iterate constant merging while we are still making progress. Merging two // constants together may allow us to merge other constants together if the // second level constants have initializers which point to the globals that // were just merged. while (1) { // First pass: identify all globals that can be merged together, filling in // the Replacements vector. We cannot do the replacement in this pass // because doing so may cause initializers of other globals to be rewritten, // invalidating the Constant* pointers in CMap. // for (Module::global_iterator GVI = M.global_begin(), E = M.global_end(); GVI != E; ) { GlobalVariable *GV = GVI++; // If this GV is dead, remove it. GV->removeDeadConstantUsers(); if (GV->use_empty() && GV->hasLocalLinkage()) { GV->eraseFromParent(); continue; } // Only process constants with initializers in the default addres space. if (!GV->isConstant() ||!GV->hasDefinitiveInitializer() || GV->getType()->getAddressSpace() != 0 || !GV->getSection().empty() || // Don't touch values marked with attribute(used). UsedGlobals.count(GV)) continue; Constant *Init = GV->getInitializer(); // Check to see if the initializer is already known. GlobalVariable *&Slot = CMap[Init]; if (Slot == 0) { // Nope, add it to the map. Slot = GV; } else if (GV->hasLocalLinkage()) { // Yup, this is a duplicate! // Make all uses of the duplicate constant use the canonical version. Replacements.push_back(std::make_pair(GV, Slot)); } } if (Replacements.empty()) return MadeChange; CMap.clear(); // Now that we have figured out which replacements must be made, do them all // now. This avoid invalidating the pointers in CMap, which are unneeded // now. for (unsigned i = 0, e = Replacements.size(); i != e; ++i) { // Eliminate any uses of the dead global. Replacements[i].first->replaceAllUsesWith(Replacements[i].second); // Delete the global value from the module. Replacements[i].first->eraseFromParent(); } NumMerged += Replacements.size(); Replacements.clear(); } }
SandboxVector SandboxUtils::findSandboxes(Module& M) { FunctionIntMap funcToOverhead; FunctionIntMap funcToClearances; map<Function*,string> funcToSandboxName; map<string,FunctionSet> sandboxNameToEntryPoints; StringSet ephemeralSandboxes; SandboxVector sandboxes; // function-level annotations of sandboxed code Regex *sboxPerfRegex = new Regex("perf_overhead_\\(([0-9]{1,2})\\)", true); SmallVector<StringRef, 4> matches; if (GlobalVariable* lga = M.getNamedGlobal("llvm.global.annotations")) { ConstantArray* lgaArray = dyn_cast<ConstantArray>(lga->getInitializer()->stripPointerCasts()); for (User::op_iterator i=lgaArray->op_begin(), e = lgaArray->op_end(); e!=i; i++) { ConstantStruct* lgaArrayElement = dyn_cast<ConstantStruct>(i->get()); // get the annotation value first GlobalVariable* annotationStrVar = dyn_cast<GlobalVariable>(lgaArrayElement->getOperand(1)->stripPointerCasts()); ConstantDataArray* annotationStrArray = dyn_cast<ConstantDataArray>(annotationStrVar->getInitializer()); StringRef annotationStrArrayCString = annotationStrArray->getAsCString(); GlobalValue* annotatedVal = dyn_cast<GlobalValue>(lgaArrayElement->getOperand(0)->stripPointerCasts()); if (isa<Function>(annotatedVal)) { Function* annotatedFunc = dyn_cast<Function>(annotatedVal); StringRef sandboxName; if (annotationStrArrayCString.startswith(SANDBOX_PERSISTENT) || annotationStrArrayCString.startswith(SANDBOX_EPHEMERAL)) { sandboxEntryPoints.insert(annotatedFunc); outs() << INDENT_1 << "Found sandbox entrypoint " << annotatedFunc->getName() << "\n"; outs() << INDENT_2 << "Annotation string: " << annotationStrArrayCString << "\n"; if (annotationStrArrayCString.startswith(SANDBOX_PERSISTENT)) { sandboxName = annotationStrArrayCString.substr(strlen(SANDBOX_PERSISTENT)+1); } else if (annotationStrArrayCString.startswith(SANDBOX_EPHEMERAL)) { sandboxName = annotationStrArrayCString.substr(strlen(SANDBOX_EPHEMERAL)+1); ephemeralSandboxes.insert(sandboxName); } outs() << INDENT_2 << "Sandbox name: " << sandboxName << "\n"; if (funcToSandboxName.find(annotatedFunc) != funcToSandboxName.end()) { outs() << INDENT_1 << "*** Error: Function " << annotatedFunc->getName() << " is already an entrypoint for another sandbox\n"; } else { funcToSandboxName[annotatedFunc] = sandboxName; sandboxNameToEntryPoints[sandboxName].insert(annotatedFunc); } } else if (sboxPerfRegex->match(annotationStrArrayCString, &matches)) { int overhead; outs() << INDENT_2 << "Threshold set to " << matches[1].str() << "%\n"; matches[1].getAsInteger(0, overhead); funcToOverhead[annotatedFunc] = overhead; } else if (annotationStrArrayCString.startswith(CLEARANCE)) { StringRef className = annotationStrArrayCString.substr(strlen(CLEARANCE)+1); outs() << INDENT_2 << "Sandbox has clearance for \"" << className << "\"\n"; ClassifiedUtils::assignBitIdxToClassName(className); funcToClearances[annotatedFunc] |= (1 << ClassifiedUtils::getBitIdxFromClassName(className)); } } } } // TODO: sanity check overhead and clearance annotations // Combine all annotation information for function-level sandboxes to create Sandbox instances for (pair<string,FunctionSet> p : sandboxNameToEntryPoints) { string sandboxName = p.first; FunctionSet entryPoints = p.second; int idx = assignBitIdxToSandboxName(sandboxName); int overhead = 0; int clearances = 0; bool persistent = find(ephemeralSandboxes.begin(), ephemeralSandboxes.end(), sandboxName) == ephemeralSandboxes.end(); // set overhead and clearances; any of the entry points could be annotated for (Function* entryPoint : entryPoints) { if (funcToOverhead.find(entryPoint) != funcToOverhead.end()) { overhead = funcToOverhead[entryPoint]; } if (funcToClearances.find(entryPoint) != funcToClearances.end()) { clearances = funcToClearances[entryPoint]; } } SDEBUG("soaap.util.sandbox", 3, dbgs() << INDENT_2 << "Creating new Sandbox instance for " << sandboxName << "\n"); sandboxes.push_back(new Sandbox(sandboxName, idx, entryPoints, persistent, M, overhead, clearances)); SDEBUG("soaap.util.sandbox", 3, dbgs() << INDENT_2 << "Created new Sandbox instance\n"); } /* for (map<Function*,string>::iterator I=funcToSandboxName.begin(), E=funcToSandboxName.end(); I!=E; I++) { Function* entryPoint = I->first; string sandboxName = I->second; int idx = assignBitIdxToSandboxName(sandboxName); int overhead = funcToOverhead[entryPoint]; int clearances = funcToClearances[entryPoint]; bool persistent = find(ephemeralSandboxes.begin(), ephemeralSandboxes.end(), entryPoint) == ephemeralSandboxes.end(); SDEBUG("soaap.util.sandbox", 3, dbgs() << INDENT_2 << "Creating new Sandbox instance\n"); sandboxes.push_back(new Sandbox(sandboxName, idx, entryPoint, persistent, M, overhead, clearances)); SDEBUG("soaap.util.sandbox", 3, dbgs() << INDENT_2 << "Created new Sandbox instance\n"); } */ // Handle sandboxed code regions, i.e. start_sandboxed_code(N) and end_sandboxed_code(N) blocks if (Function* SboxStart = M.getFunction("llvm.annotation.i32")) { for (User* U : SboxStart->users()) { if (IntrinsicInst* annotCall = dyn_cast<IntrinsicInst>(U)) { GlobalVariable* annotationStrVar = dyn_cast<GlobalVariable>(annotCall->getOperand(1)->stripPointerCasts()); ConstantDataArray* annotationStrValArray = dyn_cast<ConstantDataArray>(annotationStrVar->getInitializer()); StringRef annotationStrValCString = annotationStrValArray->getAsCString(); if (annotationStrValCString.startswith(SOAAP_SANDBOX_REGION_START)) { StringRef sandboxName = annotationStrValCString.substr(strlen(SOAAP_SANDBOX_REGION_START)+1); //+1 because of _ SDEBUG("soaap.util.sandbox", 3, dbgs() << INDENT_3 << "Found start of sandboxed code region: "; annotCall->dump();); InstVector sandboxedInsts; findAllSandboxedInstructions(annotCall, sandboxName, sandboxedInsts); int idx = assignBitIdxToSandboxName(sandboxName); sandboxes.push_back(new Sandbox(sandboxName, idx, sandboxedInsts, false, M)); //TODO: obtain persistent/ephemeral information in a better way (currently we obtain it from the creation point) } }
void SDBuildCHA::buildClouds(Module &M) { // this set is used for checking if a parent class is defined or not std::set<vtbl_t> build_undefinedVtables; for(auto itr = M.getNamedMDList().begin(); itr != M.getNamedMDList().end(); itr++) { NamedMDNode* md = itr; // check if this is a metadata that we've added if(! md->getName().startswith(SD_MD_CLASSINFO)) continue; //sd_print("GOT METADATA: %s\n", md->getName().data()); std::vector<nmd_t> infoVec = extractMetadata(md); for (const nmd_t& info : infoVec) { // record the old vtable array GlobalVariable* oldVtable = M.getGlobalVariable(info.className, true); //sd_print("class %s with %d subtables\n", info.className.c_str(), info.subVTables.size()); /* sd_print("oldvtables: %p, %d, class %s\n", oldVtable, oldVtable ? oldVtable->hasInitializer() : -1, info.className.c_str()); */ if (oldVtable && oldVtable->hasInitializer()) { ConstantArray* vtable = dyn_cast<ConstantArray>(oldVtable->getInitializer()); assert(vtable); oldVTables[info.className] = vtable; } else { undefinedVTables.insert(info.className); } for(unsigned ind = 0; ind < info.subVTables.size(); ind++) { const nmd_sub_t* subInfo = & info.subVTables[ind]; vtbl_t name(info.className, ind); /* sd_print("SubVtable[%d] Order: %d Parents[%d]: %s [%d-%d] AddrPt: %d\n", ind, subInfo->order, subInfo->parents.size(), "NYI", subInfo->start, subInfo->end, subInfo->addressPoint); */ if (build_undefinedVtables.find(name) != build_undefinedVtables.end()) { //sd_print("Removing %s,%d from build_udnefinedVtables\n", name.first.c_str(), name.second); build_undefinedVtables.erase(name); } if (cloudMap.find(name) == cloudMap.end()){ //sd_print("Inserting %s, %d in cloudMap\n", name.first.c_str(), name.second); cloudMap[name] = std::set<vtbl_t>(); } vtbl_set_t parents; for (auto it : subInfo->parents) { if (it.first != "") { vtbl_t &parent = it; parents.insert(parent); // if the parent class is not defined yet, add it to the // undefined vtable set if (cloudMap.find(parent) == cloudMap.end()) { //sd_print("Inserting %s, %d in cloudMap - undefined parent\n", parent.first.c_str(), parent.second); cloudMap[parent] = std::set<vtbl_t>(); build_undefinedVtables.insert(parent); } // add the current class to the parent's children set cloudMap[parent].insert(name); } else { assert(ind == 0); // make sure secondary vtables have a direct parent // add the class to the root set roots.insert(info.className); } } parentMap[info.className].push_back(parents); // record the original address points addrPtMap[info.className].push_back(subInfo->addressPoint); // record the sub-vtable ends rangeMap[info.className].push_back(range_t(subInfo->start, subInfo->end)); } } } if (build_undefinedVtables.size() != 0) { sd_print("Build Undefined vtables:\n"); for (auto n : build_undefinedVtables) { sd_print("%s,%d\n", n.first.c_str(), n.second); } } assert(build_undefinedVtables.size() == 0); for (auto rootName : roots) { vtbl_t root(rootName, 0); for (auto child : preorder(root)) { if (ancestorMap.find(child) == ancestorMap.end()) { ancestorMap[child] = rootName; } } } for (auto it : parentMap) { const vtbl_name_t &className = it.first; const std::vector<vtbl_set_t> &parentSetV = it.second; for (int ind = 0; ind < parentSetV.size(); ind++) { vtbl_name_t layoutClass = "none"; // Check that all possible parents are in the same layout cloud for (auto ptIt : parentSetV[ind]) { if (layoutClass != "none") assert(layoutClass == ancestorMap[ptIt] && "All parents of a primitive vtable should have the same root layout."); else layoutClass = ancestorMap[ptIt]; } // No parents - then our "layout class" is ourselves. if (layoutClass == "none") layoutClass = className; // record the class name of the sub-object subObjNameMap[className].push_back(layoutClass); } } }
// // Method: postOrderInline() // // Description: // This methods does a post order traversal of the call graph and performs // bottom-up inlining of the DSGraphs. // void BUDataStructures::postOrderInline (Module & M) { // Variables used for Tarjan SCC-finding algorithm. These are passed into // the recursive function used to find SCCs. std::vector<const Function*> Stack; std::map<const Function*, unsigned> ValMap; unsigned NextID = 1; // Do post order traversal on the global ctors. Use this information to update // the globals graph. const char *Name = "llvm.global_ctors"; GlobalVariable *GV = M.getNamedGlobal(Name); if (GV && !(GV->isDeclaration()) && !(GV->hasLocalLinkage())) { // Should be an array of '{ int, void ()* }' structs. The first value is // the init priority, which we ignore. ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer()); if (InitList) { for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) if (ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i))) { if (CS->getNumOperands() != 2) break; // Not array of 2-element structs. Constant *FP = CS->getOperand(1); if (FP->isNullValue()) break; // Found a null terminator, exit. if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP)) if (CE->isCast()) FP = CE->getOperand(0); Function *F = dyn_cast<Function>(FP); if (F && !F->isDeclaration() && !ValMap.count(F)) { calculateGraphs(F, Stack, NextID, ValMap); CloneAuxIntoGlobal(getDSGraph(*F)); } } GlobalsGraph->removeTriviallyDeadNodes(); GlobalsGraph->maskIncompleteMarkers(); // Mark external globals incomplete. GlobalsGraph->markIncompleteNodes(DSGraph::IgnoreGlobals); GlobalsGraph->computeExternalFlags(DSGraph::DontMarkFormalsExternal); GlobalsGraph->computeIntPtrFlags(); // // Create equivalence classes for aliasing globals so that we only need to // record one global per DSNode. // formGlobalECs(); // propogte information calculated // from the globals graph to the other graphs. for (Module::iterator F = M.begin(); F != M.end(); ++F) { if (!(F->isDeclaration())){ DSGraph *Graph = getDSGraph(*F); cloneGlobalsInto(Graph, DSGraph::DontCloneCallNodes | DSGraph::DontCloneAuxCallNodes); Graph->buildCallGraph(callgraph, GlobalFunctionList, filterCallees); Graph->maskIncompleteMarkers(); Graph->markIncompleteNodes(DSGraph::MarkFormalArgs | DSGraph::IgnoreGlobals); Graph->computeExternalFlags(DSGraph::DontMarkFormalsExternal); Graph->computeIntPtrFlags(); } } } } // // Start the post order traversal with the main() function. If there is no // main() function, don't worry; we'll have a separate traversal for inlining // graphs for functions not reachable from main(). // Function *MainFunc = M.getFunction ("main"); if (MainFunc && !MainFunc->isDeclaration()) { calculateGraphs(MainFunc, Stack, NextID, ValMap); CloneAuxIntoGlobal(getDSGraph(*MainFunc)); } // // Calculate the graphs for any functions that are unreachable from main... // for (Function &F : M) if (!F.isDeclaration() && !ValMap.count(&F)) { if (MainFunc) DEBUG(errs() << debugname << ": Function unreachable from main: " << F.getName() << "\n"); calculateGraphs(&F, Stack, NextID, ValMap); // Calculate all graphs. CloneAuxIntoGlobal(getDSGraph(F)); // Mark this graph as processed. Do this by finding all functions // in the graph that map to it, and mark them visited. // Note that this really should be handled neatly by calculateGraphs // itself, not here. However this catches the worst offenders. DSGraph *G = getDSGraph(F); for(DSGraph::retnodes_iterator RI = G->retnodes_begin(), RE = G->retnodes_end(); RI != RE; ++RI) { if (getDSGraph(*RI->first) == G) { if (!ValMap.count(RI->first)) ValMap[RI->first] = ~0U; else assert(ValMap[RI->first] == ~0U); } } } return; }
bool GenericToNVVM::runOnModule(Module &M) { // Create a clone of each global variable that has the default address space. // The clone is created with the global address space specifier, and the pair // of original global variable and its clone is placed in the GVMap for later // use. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E;) { GlobalVariable *GV = &*I++; if (GV->getType()->getAddressSpace() == llvm::ADDRESS_SPACE_GENERIC && !llvm::isTexture(*GV) && !llvm::isSurface(*GV) && !llvm::isSampler(*GV) && !GV->getName().startswith("llvm.")) { GlobalVariable *NewGV = new GlobalVariable( M, GV->getValueType(), GV->isConstant(), GV->getLinkage(), GV->hasInitializer() ? GV->getInitializer() : nullptr, "", GV, GV->getThreadLocalMode(), llvm::ADDRESS_SPACE_GLOBAL); NewGV->copyAttributesFrom(GV); GVMap[GV] = NewGV; } } // Return immediately, if every global variable has a specific address space // specifier. if (GVMap.empty()) { return false; } // Walk through the instructions in function defitinions, and replace any use // of original global variables in GVMap with a use of the corresponding // copies in GVMap. If necessary, promote constants to instructions. for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { if (I->isDeclaration()) { continue; } IRBuilder<> Builder(I->getEntryBlock().getFirstNonPHIOrDbg()); for (Function::iterator BBI = I->begin(), BBE = I->end(); BBI != BBE; ++BBI) { for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE; ++II) { for (unsigned i = 0, e = II->getNumOperands(); i < e; ++i) { Value *Operand = II->getOperand(i); if (isa<Constant>(Operand)) { II->setOperand( i, remapConstant(&M, &*I, cast<Constant>(Operand), Builder)); } } } } ConstantToValueMap.clear(); } // Copy GVMap over to a standard value map. ValueToValueMapTy VM; for (auto I = GVMap.begin(), E = GVMap.end(); I != E; ++I) VM[I->first] = I->second; // Walk through the metadata section and update the debug information // associated with the global variables in the default address space. for (NamedMDNode &I : M.named_metadata()) { remapNamedMDNode(VM, &I); } // Walk through the global variable initializers, and replace any use of // original global variables in GVMap with a use of the corresponding copies // in GVMap. The copies need to be bitcast to the original global variable // types, as we cannot use cvta in global variable initializers. for (GVMapTy::iterator I = GVMap.begin(), E = GVMap.end(); I != E;) { GlobalVariable *GV = I->first; GlobalVariable *NewGV = I->second; // Remove GV from the map so that it can be RAUWed. Note that // DenseMap::erase() won't invalidate any iterators but this one. auto Next = std::next(I); GVMap.erase(I); I = Next; Constant *BitCastNewGV = ConstantExpr::getPointerCast(NewGV, GV->getType()); // At this point, the remaining uses of GV should be found only in global // variable initializers, as other uses have been already been removed // while walking through the instructions in function definitions. GV->replaceAllUsesWith(BitCastNewGV); std::string Name = GV->getName(); GV->eraseFromParent(); NewGV->setName(Name); } assert(GVMap.empty() && "Expected it to be empty by now"); return true; }
DyckVertex* AAAnalyzer::wrapValue(Value * v) { // if the vertex of v exists, return it, otherwise create one pair < DyckVertex*, bool> retpair = dgraph->retrieveDyckVertex(v); if (retpair.second) { return retpair.first; } DyckVertex* vdv = retpair.first; // constantTy are handled as below. if (isa<ConstantExpr>(v)) { // constant expr should be handled like a assignment instruction if (isa<GEPOperator>(v)) { DyckVertex * got = handle_gep((GEPOperator*) v); makeAlias(vdv, got); } else if (((ConstantExpr*) v)->isCast()) { // errs() << *v << "\n"; DyckVertex * got = wrapValue(((ConstantExpr*) v)->getOperand(0)); makeAlias(vdv, got); } else { unsigned opcode = ((ConstantExpr*) v)->getOpcode(); switch (opcode) { case 23: // BinaryConstantExpr "and" case 24: // BinaryConstantExpr "or" { // do nothing } break; default: { errs() << "ERROR when handle the following constant expression\n"; errs() << *v << "\n"; errs() << ((ConstantExpr*) v)->getOpcode() << "\n"; errs() << ((ConstantExpr*) v)->getOpcodeName() << "\n"; errs().flush(); exit(-1); } break; } } } else if (isa<ConstantArray>(v)) { #ifndef ARRAY_SIMPLIFIED DyckVertex* ptr = addPtrTo(NULL, vdv, dgraph); DyckVertex* current = ptr; Constant * vAgg = (Constant*) v; int numElmt = vAgg->getNumOperands(); for (int i = 0; i < numElmt; i++) { Value * vi = vAgg->getOperand(i); DyckVertex* viptr = addPtrOffset(current, i * dl.getTypeAllocSize(vi->getType()), dgraph); addPtrTo(viptr, wrapValue(vi, dgraph, dl), dgraph); } #else Constant * vAgg = (Constant*) v; int numElmt = vAgg->getNumOperands(); for (int i = 0; i < numElmt; i++) { Value * vi = vAgg->getOperand(i); makeAlias(vdv, wrapValue(vi)); } #endif } else if (isa<ConstantStruct>(v)) { //DyckVertex* ptr = addPtrTo(NULL, vdv); //DyckVertex* current = ptr; Constant * vAgg = (Constant*) v; int numElmt = vAgg->getNumOperands(); for (int i = 0; i < numElmt; i++) { Value * vi = vAgg->getOperand(i); addField(vdv, -2 - i, wrapValue(vi)); } } else if (isa<GlobalValue>(v)) { if (isa<GlobalVariable>(v)) { GlobalVariable * global = (GlobalVariable *) v; if (global->hasInitializer()) { Value * initializer = global->getInitializer(); if (!isa<UndefValue>(initializer)) { DyckVertex * initVer = wrapValue(initializer); addPtrTo(vdv, initVer); } } } else if (isa<GlobalAlias>(v)) { GlobalAlias * global = (GlobalAlias *) v; Value * aliasee = global->getAliasee(); makeAlias(vdv, wrapValue(aliasee)); } else if (isa<Function>(v)) { // do nothing } // no else } else if (isa<ConstantInt>(v) || isa<ConstantFP>(v) || isa<ConstantPointerNull>(v) || isa<UndefValue>(v)) { // do nothing } else if (isa<ConstantDataArray>(v) || isa<ConstantAggregateZero>(v)) { // do nothing } else if (isa<BlockAddress>(v)) { // do nothing } else if (isa<ConstantDataVector>(v)) { errs() << "ERROR when handle the following ConstantDataSequential, ConstantDataVector\n"; errs() << *v << "\n"; errs().flush(); exit(-1); } else if (isa<ConstantVector>(v)) { errs() << "ERROR when handle the following ConstantVector\n"; errs() << *v << "\n"; errs().flush(); exit(-1); } else if (isa<Constant>(v)) { errs() << "ERROR when handle the following constant value\n"; errs() << *v << "\n"; errs().flush(); exit(-1); } return vdv; }
/// analyzeDestructor - Given the heap.metadata argument to swift_allocObject, /// take a look a the destructor and try to decide if it has side effects or any /// other bad effects that can prevent it from being optimized. static DtorKind analyzeDestructor(Value *P) { // If we have a null pointer for the metadata info, the dtor has no side // effects. Actually, the final release would crash. This is really only // useful for writing testcases. if (isa<ConstantPointerNull>(P->stripPointerCasts())) return DtorKind::NoSideEffects; // We have to have a known heap metadata value, reject dynamically computed // ones, or places GlobalVariable *GV = dyn_cast<GlobalVariable>(P->stripPointerCasts()); if (GV == 0 || GV->mayBeOverridden()) return DtorKind::Unknown; ConstantStruct *CS = dyn_cast_or_null<ConstantStruct>(GV->getInitializer()); if (CS == 0 || CS->getNumOperands() == 0) return DtorKind::Unknown; // FIXME: Would like to abstract the dtor slot (#0) out from this to somewhere // unified. enum { DTorSlotOfHeapMetadata = 0 }; Function *DtorFn =dyn_cast<Function>(CS->getOperand(DTorSlotOfHeapMetadata)); if (DtorFn == 0 || DtorFn->mayBeOverridden() || DtorFn->hasExternalLinkage()) return DtorKind::Unknown; // Okay, we have a body, and we can trust it. If the function is marked // readonly, then we know it can't have any interesting side effects, so we // don't need to analyze it at all. if (DtorFn->onlyReadsMemory()) return DtorKind::NoSideEffects; // The first argument is the object being destroyed. assert(DtorFn->arg_size() == 1 && !DtorFn->isVarArg() && "expected a single object argument to destructors"); Value *ThisObject = &*DtorFn->arg_begin(); // Scan the body of the function, looking for anything scary. for (BasicBlock &BB : *DtorFn) { for (Instruction &I : BB) { // Note that the destructor may not be in any particular canonical form. switch (classifyInstruction(I)) { // These instructions should not reach here based on the pass ordering. // i.e. LLVMARCOpt -> LLVMContractOpt. case RT_RetainN: case RT_UnknownRetainN: case RT_BridgeRetainN: case RT_ReleaseN: case RT_UnknownReleaseN: case RT_BridgeReleaseN: llvm_unreachable("These are only created by LLVMARCContract !"); case RT_NoMemoryAccessed: case RT_AllocObject: case RT_FixLifetime: case RT_CheckUnowned: // Skip over random instructions that don't touch memory in the caller. continue; case RT_RetainUnowned: case RT_BridgeRetain: // x = swift_bridgeRetain(y) case RT_Retain: { // swift_retain(obj) // Ignore retains of the "self" object, no resurrection is possible. Value *ThisRetainedObject = cast<CallInst>(I).getArgOperand(0); if (ThisRetainedObject->stripPointerCasts() == ThisObject->stripPointerCasts()) continue; // Otherwise, we may be retaining something scary. break; } case RT_Release: { // If we get to a release that is provably to this object, then we can // ignore it. Value *ThisReleasedObject = cast<CallInst>(I).getArgOperand(0); if (ThisReleasedObject->stripPointerCasts() == ThisObject->stripPointerCasts()) continue; // Otherwise, we may be retaining something scary. break; } case RT_ObjCRelease: case RT_ObjCRetain: case RT_UnknownRetain: case RT_UnknownRelease: case RT_BridgeRelease: // Objective-C retain and release can have arbitrary side effects. break; case RT_Unknown: // Ignore all instructions with no side effects. if (!I.mayHaveSideEffects()) continue; // store, memcpy, memmove *to* the object can be dropped. if (StoreInst *SI = dyn_cast<StoreInst>(&I)) { if (SI->getPointerOperand()->stripInBoundsOffsets() == ThisObject) continue; } if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(&I)) { if (MI->getDest()->stripInBoundsOffsets() == ThisObject) continue; } // Otherwise, we can't remove the deallocation completely. break; } // Okay, the function has some side effects, if it doesn't capture the // object argument, at least that is something. return DtorFn->doesNotCapture(0) ? DtorKind::NoEscape : DtorKind::Unknown; } } // If we didn't find any side effects, we win. return DtorKind::NoSideEffects; }
void ClassHierarchyUtils::processTypeInfo(GlobalVariable* TI, Module& M) { if (find(classes.begin(), classes.end(), TI) == classes.end()) { SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Adding class " << TI->getName() << "\n"); classes.push_back(TI); // First process the correspoding virtual table. We store the indexes of the primary // and secondary vtables, indexed by the corresponding subobject offset. This will allow // us to quickly jump to a particular sub-vtable. if (typeInfoToVTable.find(TI) != typeInfoToVTable.end()) { GlobalVariable* VT = typeInfoToVTable[TI]; SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Found vtable: " << VT->getName() << "\n"); ConstantStruct* VTinit = cast<ConstantStruct>(VT->getInitializer()); for (int i=0; i<VTinit->getNumOperands(); i++) { ConstantArray* VTinitElem = cast<ConstantArray>(VTinit->getOperand(i)); for (int j=0; j<VTinitElem->getNumOperands(); j++) { // Each sub-vtable is preceded by a reference to the class's type_info instance. // (See https://mentorembedded.github.io/cxx-abi/abi.html). if (TI == VTinitElem->getOperand(j)->stripPointerCasts()) { SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Found TI at index " << i << "\n"); SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Storing mapping " << VT->getName() << " <-> " << TI->getName() << "\n"); // the offset to top is the offset from the vptr pointing to this // sub-vtable, back to the top of the object. This will be negative, // but the absolute value gives us the offset from the start of the // object (i.e. first vptr), to the subobject. int offsetToTop = 0; if (ConstantExpr* offsetValCast = dyn_cast<ConstantExpr>(VTinitElem->getOperand(j-1)->stripPointerCasts())) { ConstantInt* offsetVal = cast<ConstantInt>(offsetValCast->getOperand(0)); offsetToTop = offsetVal->getSExtValue(); // will be 0 for the primary } if (offsetToTop > 0) { report_fatal_error("ERROR: offsetToTop is positive!"); } else { offsetToTop *= -1; } SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "offsetToTop: " << offsetToTop << "\n") vTableToSecondaryVTableMaps[VT][offsetToTop] = pair<int, int>(i, j+1); } } } } else { SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "No vtable found for " << TI->getName() << "\n"); } // Now process the type_info struct, extract direct base class info (what // their subobject offsets are, or if they are virtual then their // virtual-base-offset-offset) if (TI->hasInitializer()) { ConstantStruct* TIinit = cast<ConstantStruct>(TI->getInitializer()); int TInumOperands = TIinit->getNumOperands(); if (TInumOperands > 2) { // first two operands are vptr and type name // we have >= 1 base class(es). if (TInumOperands == 3) { // abi::__si_class_type_info: single, public, non-virtual base at // offset 0 SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "abi::__si_class_type_info\n"); GlobalVariable* baseTI = cast<GlobalVariable>(TIinit->getOperand(2)->stripPointerCasts()); classToSubclasses[baseTI].push_back(TI); //dbgs() << " " << *baseTI << "\n"; classToBaseOffset[TI][baseTI] = 0; processTypeInfo(baseTI, M); } else { // abi::__vmi_class_type_info: all other cases SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "abi::__vmi_class_type_info\n"); // (skip over first two additional fields, which are "flags" and "base_count") for (int i=4; i<TInumOperands; i+=2) { GlobalVariable* baseTI = cast<GlobalVariable>(TIinit->getOperand(i)->stripPointerCasts()); classToSubclasses[baseTI].push_back(TI); long offset_flags = cast<ConstantInt>(TIinit->getOperand(i+1))->getSExtValue(); SDEBUG("soaap.util.classhierarchy", 3, dbgs() << TI->getName() << " -> " << baseTI->getName() << "\n"); SDEBUG("soaap.util.classhierarchy", 3, dbgs() << " offset_flags = " << offset_flags << "\n"); ptrdiff_t offset = offset_flags >> offset_shift; SDEBUG("soaap.util.classhierarchy", 3, dbgs() << " offset = " << offset << "\n"); // If this a virtual base class, then we obtain the // vbase-offset-offset. This is the offset from the start of the // derived class's (primary) vtable to the location containing the // vbase-offset, which is the offset from the start of the object // to the virtual base's subobject. Note that virtual base // subobjects only exist once and are laid out after all other // non-virtual objects. We keep track of the vbase-offset-offset, // so that we can find the vbase offset when going down the class // hierarchy. (The vbase offset may differ every time but the // vbase-offset-offset will remain the same relative to the current // class's vtable in subclasses). if (offset_flags & virtual_mask) { // is this a virtual base class? SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "virtual base class: " << baseTI->getName() << "\n"); int vbaseOffsetOffset = offset/sizeof(long); // this should be negative SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "vbase-offset-offset: " << vbaseOffsetOffset << "\n"); classToVBaseOffsetOffset[TI][baseTI] = vbaseOffsetOffset; if (typeInfoToVTable.find(TI) != typeInfoToVTable.end()) { GlobalVariable* VT = typeInfoToVTable[TI]; int vbaseOffsetIdx = vTableToSecondaryVTableMaps[VT][0].second+vbaseOffsetOffset; SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "vbase-offset-idx: " << vbaseOffsetIdx << "\n"); } else { SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "No VTable for " << TI->getName() << "\n"); } } else { // In the non-virtual base class case, we just record the subobj // offset. This is the offset from the start of the derived // object to the base class's subobject. We use this information // together with the offset-to-top info we obtained from the // vtable to find the base class's subvtable. Note that the // relative position of the base class subobj within the current // derived object will always remain the same, even in // subclasses. classToBaseOffset[TI][baseTI] = offset; } //dbgs() << " " << *baseTI << "\n"; processTypeInfo(baseTI, M); } } } }
/// Update the initializers in the Dest module now that all globals that may be /// referenced are in Dest. void IRLinker::linkGlobalInit(GlobalVariable &Dst, GlobalVariable &Src) { // Figure out what the initializer looks like in the dest module. Dst.setInitializer(MapValue(Src.getInitializer(), ValueMap, RF_MoveDistinctMDs, &TypeMap, &GValMaterializer)); }
bool AllocateDataSegment::runOnModule(Module &M) { DataLayout DL(&M); Type *I8 = Type::getInt8Ty(M.getContext()); Type *I32 = Type::getInt32Ty(M.getContext()); Type *IntPtrType = DL.getIntPtrType(M.getContext()); // First, we do a pass over the global variables, in which we compute // the amount of required padding between them and consequently their // addresses relative to the memory base of the sandbox. References to each // global are then replaced with direct memory pointers. uint32_t VarOffset = 0; DenseMap<GlobalVariable*, uint32_t> VarPadding; for (Module::global_iterator GV = M.global_begin(), E = M.global_end(); GV != E; ++GV) { assert(GV->hasInitializer()); uint32_t Padding = getPadding(VarOffset, GV, DL); VarPadding[GV] = Padding; VarOffset += Padding; GV->replaceAllUsesWith( ConstantExpr::getIntToPtr( ConstantInt::get(IntPtrType, DataSegmentBaseAddress + VarOffset), GV->getType())); VarOffset += DL.getTypeStoreSize(GV->getType()->getPointerElementType()); } // Using the offsets computed above, we prepare the layout and the contents // of the desired data structure. After the type and initializer of each // global is copied, the global is not needed any more and it is erased. SmallVector<Type*, 10> TemplateLayout; SmallVector<Constant*, 10> TemplateData; for (Module::global_iterator It = M.global_begin(), E = M.global_end(); It != E; ) { GlobalVariable *GV = It++; uint32_t Padding = VarPadding[GV]; if (Padding > 0) { Type *PaddingType = ArrayType::get(I8, Padding); TemplateLayout.push_back(PaddingType); TemplateData.push_back(ConstantAggregateZero::get(PaddingType)); } TemplateLayout.push_back(GV->getType()->getPointerElementType()); TemplateData.push_back(GV->getInitializer()); GV->eraseFromParent(); } // Finally, we create the struct and size global variables. StructType *TemplateType = StructType::create(M.getContext(), ExternalSymName_DataSegment); TemplateType->setBody(TemplateLayout, /*isPacked=*/true); Constant *Template = ConstantStruct::get(TemplateType, TemplateData); new GlobalVariable(M, Template->getType(), /*isConstant=*/true, GlobalVariable::ExternalLinkage, Template, ExternalSymName_DataSegment); Constant *TemplateSize = ConstantInt::get(I32, DL.getTypeAllocSize(TemplateType)); new GlobalVariable(M, TemplateSize->getType(), /*isConstant=*/true, GlobalVariable::ExternalLinkage, TemplateSize, ExternalSymName_DataSegmentSize); return true; }
bool ConstantMerge::runOnModule(Module &M) { TD = getAnalysisIfAvailable<TargetData>(); // Find all the globals that are marked "used". These cannot be merged. SmallPtrSet<const GlobalValue*, 8> UsedGlobals; FindUsedValues(M.getGlobalVariable("llvm.used"), UsedGlobals); FindUsedValues(M.getGlobalVariable("llvm.compiler.used"), UsedGlobals); // Map unique <constants, has-unknown-alignment> pairs to globals. We don't // want to merge globals of unknown alignment with those of explicit // alignment. If we have TargetData, we always know the alignment. DenseMap<PointerIntPair<Constant*, 1, bool>, GlobalVariable*> CMap; // Replacements - This vector contains a list of replacements to perform. SmallVector<std::pair<GlobalVariable*, GlobalVariable*>, 32> Replacements; bool MadeChange = false; // Iterate constant merging while we are still making progress. Merging two // constants together may allow us to merge other constants together if the // second level constants have initializers which point to the globals that // were just merged. while (1) { // First: Find the canonical constants others will be merged with. for (Module::global_iterator GVI = M.global_begin(), E = M.global_end(); GVI != E; ) { GlobalVariable *GV = GVI++; // If this GV is dead, remove it. GV->removeDeadConstantUsers(); if (GV->use_empty() && GV->hasLocalLinkage()) { GV->eraseFromParent(); continue; } // Only process constants with initializers in the default address space. if (!GV->isConstant() || !GV->hasDefinitiveInitializer() || GV->getType()->getAddressSpace() != 0 || GV->hasSection() || // Don't touch values marked with attribute(used). UsedGlobals.count(GV)) continue; // This transformation is legal for weak ODR globals in the sense it // doesn't change semantics, but we really don't want to perform it // anyway; it's likely to pessimize code generation, and some tools // (like the Darwin linker in cases involving CFString) don't expect it. if (GV->isWeakForLinker()) continue; Constant *Init = GV->getInitializer(); // Check to see if the initializer is already known. PointerIntPair<Constant*, 1, bool> Pair(Init, hasKnownAlignment(GV)); GlobalVariable *&Slot = CMap[Pair]; // If this is the first constant we find or if the old one is local, // replace with the current one. If the current is externally visible // it cannot be replace, but can be the canonical constant we merge with. if (Slot == 0 || IsBetterCannonical(*GV, *Slot)) Slot = GV; } // Second: identify all globals that can be merged together, filling in // the Replacements vector. We cannot do the replacement in this pass // because doing so may cause initializers of other globals to be rewritten, // invalidating the Constant* pointers in CMap. for (Module::global_iterator GVI = M.global_begin(), E = M.global_end(); GVI != E; ) { GlobalVariable *GV = GVI++; // Only process constants with initializers in the default address space. if (!GV->isConstant() || !GV->hasDefinitiveInitializer() || GV->getType()->getAddressSpace() != 0 || GV->hasSection() || // Don't touch values marked with attribute(used). UsedGlobals.count(GV)) continue; // We can only replace constant with local linkage. if (!GV->hasLocalLinkage()) continue; Constant *Init = GV->getInitializer(); // Check to see if the initializer is already known. PointerIntPair<Constant*, 1, bool> Pair(Init, hasKnownAlignment(GV)); GlobalVariable *Slot = CMap[Pair]; if (!Slot || Slot == GV) continue; if (!Slot->hasUnnamedAddr() && !GV->hasUnnamedAddr()) continue; if (!GV->hasUnnamedAddr()) Slot->setUnnamedAddr(false); // Make all uses of the duplicate constant use the canonical version. Replacements.push_back(std::make_pair(GV, Slot)); } if (Replacements.empty()) return MadeChange; CMap.clear(); // Now that we have figured out which replacements must be made, do them all // now. This avoid invalidating the pointers in CMap, which are unneeded // now. for (unsigned i = 0, e = Replacements.size(); i != e; ++i) { // Bump the alignment if necessary. if (Replacements[i].first->getAlignment() || Replacements[i].second->getAlignment()) { Replacements[i].second->setAlignment(std::max( Replacements[i].first->getAlignment(), Replacements[i].second->getAlignment())); } // Eliminate any uses of the dead global. Replacements[i].first->replaceAllUsesWith(Replacements[i].second); // Delete the global value from the module. assert(Replacements[i].first->hasLocalLinkage() && "Refusing to delete an externally visible global variable."); Replacements[i].first->eraseFromParent(); } NumMerged += Replacements.size(); Replacements.clear(); } }
// This function replaces all global variables with new variables that have // trailing redzones. It also creates a function that poisons // redzones and inserts this function into llvm.global_ctors. bool AddressSanitizer::insertGlobalRedzones(Module &M) { SmallVector<GlobalVariable *, 16> GlobalsToChange; for (Module::GlobalListType::iterator G = M.getGlobalList().begin(), E = M.getGlobalList().end(); G != E; ++G) { Type *Ty = cast<PointerType>(G->getType())->getElementType(); DEBUG(dbgs() << "GLOBAL: " << *G); if (!Ty->isSized()) continue; if (!G->hasInitializer()) continue; // Touch only those globals that will not be defined in other modules. // Don't handle ODR type linkages since other modules may be built w/o asan. if (G->getLinkage() != GlobalVariable::ExternalLinkage && G->getLinkage() != GlobalVariable::PrivateLinkage && G->getLinkage() != GlobalVariable::InternalLinkage) continue; // Two problems with thread-locals: // - The address of the main thread's copy can't be computed at link-time. // - Need to poison all copies, not just the main thread's one. if (G->isThreadLocal()) continue; // For now, just ignore this Alloca if the alignment is large. if (G->getAlignment() > RedzoneSize) continue; // Ignore all the globals with the names starting with "\01L_OBJC_". // Many of those are put into the .cstring section. The linker compresses // that section by removing the spare \0s after the string terminator, so // our redzones get broken. if ((G->getName().find("\01L_OBJC_") == 0) || (G->getName().find("\01l_OBJC_") == 0)) { DEBUG(dbgs() << "Ignoring \\01L_OBJC_* global: " << *G); continue; } if (G->hasSection()) { StringRef Section(G->getSection()); // Ignore the globals from the __OBJC section. The ObjC runtime assumes // those conform to /usr/lib/objc/runtime.h, so we can't add redzones to // them. if ((Section.find("__OBJC,") == 0) || (Section.find("__DATA, __objc_") == 0)) { DEBUG(dbgs() << "Ignoring ObjC runtime global: " << *G); continue; } // See http://code.google.com/p/address-sanitizer/issues/detail?id=32 // Constant CFString instances are compiled in the following way: // -- the string buffer is emitted into // __TEXT,__cstring,cstring_literals // -- the constant NSConstantString structure referencing that buffer // is placed into __DATA,__cfstring // Therefore there's no point in placing redzones into __DATA,__cfstring. // Moreover, it causes the linker to crash on OS X 10.7 if (Section.find("__DATA,__cfstring") == 0) { DEBUG(dbgs() << "Ignoring CFString: " << *G); continue; } } GlobalsToChange.push_back(G); } size_t n = GlobalsToChange.size(); if (n == 0) return false; // A global is described by a structure // size_t beg; // size_t size; // size_t size_with_redzone; // const char *name; // We initialize an array of such structures and pass it to a run-time call. StructType *GlobalStructTy = StructType::get(IntptrTy, IntptrTy, IntptrTy, IntptrTy, NULL); SmallVector<Constant *, 16> Initializers(n); IRBuilder<> IRB(CtorInsertBefore); for (size_t i = 0; i < n; i++) { GlobalVariable *G = GlobalsToChange[i]; PointerType *PtrTy = cast<PointerType>(G->getType()); Type *Ty = PtrTy->getElementType(); uint64_t SizeInBytes = TD->getTypeStoreSizeInBits(Ty) / 8; uint64_t RightRedzoneSize = RedzoneSize + (RedzoneSize - (SizeInBytes % RedzoneSize)); Type *RightRedZoneTy = ArrayType::get(IRB.getInt8Ty(), RightRedzoneSize); StructType *NewTy = StructType::get(Ty, RightRedZoneTy, NULL); Constant *NewInitializer = ConstantStruct::get( NewTy, G->getInitializer(), Constant::getNullValue(RightRedZoneTy), NULL); SmallString<2048> DescriptionOfGlobal = G->getName(); DescriptionOfGlobal += " ("; DescriptionOfGlobal += M.getModuleIdentifier(); DescriptionOfGlobal += ")"; GlobalVariable *Name = createPrivateGlobalForString(M, DescriptionOfGlobal); // Create a new global variable with enough space for a redzone. GlobalVariable *NewGlobal = new GlobalVariable( M, NewTy, G->isConstant(), G->getLinkage(), NewInitializer, "", G, G->isThreadLocal()); NewGlobal->copyAttributesFrom(G); NewGlobal->setAlignment(RedzoneSize); Value *Indices2[2]; Indices2[0] = IRB.getInt32(0); Indices2[1] = IRB.getInt32(0); G->replaceAllUsesWith( ConstantExpr::getGetElementPtr(NewGlobal, Indices2, true)); NewGlobal->takeName(G); G->eraseFromParent(); Initializers[i] = ConstantStruct::get( GlobalStructTy, ConstantExpr::getPointerCast(NewGlobal, IntptrTy), ConstantInt::get(IntptrTy, SizeInBytes), ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize), ConstantExpr::getPointerCast(Name, IntptrTy), NULL); DEBUG(dbgs() << "NEW GLOBAL:\n" << *NewGlobal); } ArrayType *ArrayOfGlobalStructTy = ArrayType::get(GlobalStructTy, n); GlobalVariable *AllGlobals = new GlobalVariable( M, ArrayOfGlobalStructTy, false, GlobalVariable::PrivateLinkage, ConstantArray::get(ArrayOfGlobalStructTy, Initializers), ""); Function *AsanRegisterGlobals = cast<Function>(M.getOrInsertFunction( kAsanRegisterGlobalsName, IRB.getVoidTy(), IntptrTy, IntptrTy, NULL)); AsanRegisterGlobals->setLinkage(Function::ExternalLinkage); IRB.CreateCall2(AsanRegisterGlobals, IRB.CreatePointerCast(AllGlobals, IntptrTy), ConstantInt::get(IntptrTy, n)); // We also need to unregister globals at the end, e.g. when a shared library // gets closed. Function *AsanDtorFunction = Function::Create( FunctionType::get(Type::getVoidTy(*C), false), GlobalValue::InternalLinkage, kAsanModuleDtorName, &M); BasicBlock *AsanDtorBB = BasicBlock::Create(*C, "", AsanDtorFunction); IRBuilder<> IRB_Dtor(ReturnInst::Create(*C, AsanDtorBB)); Function *AsanUnregisterGlobals = cast<Function>(M.getOrInsertFunction( kAsanUnregisterGlobalsName, IRB.getVoidTy(), IntptrTy, IntptrTy, NULL)); AsanUnregisterGlobals->setLinkage(Function::ExternalLinkage); IRB_Dtor.CreateCall2(AsanUnregisterGlobals, IRB.CreatePointerCast(AllGlobals, IntptrTy), ConstantInt::get(IntptrTy, n)); appendToGlobalDtors(M, AsanDtorFunction, kAsanCtorAndCtorPriority); DEBUG(dbgs() << M); return true; }
void llvm::copyGVInitializer(GlobalVariable &New, const GlobalVariable &Orig, ValueToValueMapTy &VMap) { if (Orig.hasInitializer()) New.setInitializer(MapValue(Orig.getInitializer(), VMap)); }
bool SpDefUseInstrumenter::runOnModule(Module &M) { cerr << "instrument: --- Def-Use pair Spectrum ---\n"; Function *Main = M.getFunction("main"); LLVMContext &C = M.getContext(); if (Main == 0) { cerr << "WARNING: cannot insert def-use instrumentation into a module" << " with no main function!\n"; return false; // No main, no instrumentation! } // Add library function prototype Constant *SpFn = M.getOrInsertFunction("_updateSpectrum", Type::getVoidTy(C), Type::getInt32Ty(C), // spectrum index Type::getInt32Ty(C), // component index NULL); unsigned spectrumIndex = IndexManager::getSpectrumIndex(); unsigned nDefs = 0; unsigned nUses = 0; // Loop through all functions within module for (Module::iterator F = M.begin(), ME = M.end(); F != ME; ++F) { // skip function declarations if(F->isDeclaration()) continue; // skip the _registerAll function if(F->getName()=="_registerAll") continue; // Loop through all basic blocks within function for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) { //skip dead blocks //is this really safe?? BasicBlock *bb = B; if (B!=F->begin() && (pred_begin(bb)==pred_end(bb))) continue; //skip dead blocks // Loop through all instructions within basic block for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE; I++) { if(isa<DbgDeclareInst>(*I)) { // extract source file information from debug intrinsic DbgDeclareInst &DDI = cast<DbgDeclareInst>(*I); std::string file, dir; std::string name; GlobalVariable *gv = cast<GlobalVariable>(DDI.getVariable()); if(!gv->hasInitializer()) continue; ConstantStruct *cs = cast<ConstantStruct>(gv->getInitializer()); llvm::GetConstantStringInfo(cs->getOperand(2), name); unsigned int line = unsigned(cast<ConstantInt>(cs->getOperand(4))->getZExtValue()); Value *V = cast<Value>(cs->getOperand(3)); GlobalVariable *gv2 = cast<GlobalVariable>(cast<ConstantExpr>(V)->getOperand(0)); if(!gv2->hasInitializer()) continue; ConstantStruct *cs2 = cast<ConstantStruct>(gv2->getInitializer()); llvm::GetConstantStringInfo(cs2->getOperand(3), file); llvm::GetConstantStringInfo(cs2->getOperand(4), dir); // get the allocation instruction of the variable definition AllocaInst *AI; if(isa<AllocaInst>(DDI.getAddress())) { AI = cast<AllocaInst>(DDI.getAddress()); } else if (isa<BitCastInst>(DDI.getAddress())) { AI = cast<AllocaInst>(cast<BitCastInst>(DDI.getAddress())->getOperand(0)); } else { continue; } nDefs++; // add calls to lib function for each use of the variable int currUses = 0; for(AllocaInst::use_iterator U = AI->use_begin(), UE = AI->use_end(); U != UE; ++U) { if(isa<Instruction>(*U)) { User *user = *U; Instruction *insertInst = (Instruction*)user; // find most likely context location of use int useline = line; std::string usefile = file, usedir = dir; BasicBlock *parent = insertInst->getParent(); BasicBlock::iterator inst = parent->begin(); while(((Instruction *)inst) != insertInst && inst != parent->end()) { /*TODO: solve DbgStopPointInst problem*/ /*if(isa<DbgStopPointInst>(*inst)) { DbgStopPointInst &DSPI = cast<DbgStopPointInst>(*inst); llvm::GetConstantStringInfo(DSPI.getDirectory(), usedir); llvm::GetConstantStringInfo(DSPI.getFileName(), usefile); useline = DSPI.getLine(); }*/ inst++; } std::stringstream usename; usename << name << "(use_" << currUses << ")"; // add source context of this invariant to context file ContextManager::addSpectrumContext( spectrumIndex, // spectrumIndex nUses, // componentIndex usedir, // path usefile, // file useline, // line usename.str()); // name currUses++; std::vector<Value*> Args(2); Args[0] = ConstantInt::get(Type::getInt32Ty(C), spectrumIndex); Args[1] = ConstantInt::get(Type::getInt32Ty(C), nUses++); CallInst::Create(SpFn, Args.begin(), Args.end(), "", insertInst); } } } } } } // add the registration of the instrumented spectrum points in the _registerAll() function addSpectrumRegistration(M, spectrumIndex, nUses, "Def-Use_Pairs"); std::cerr << "instrument: " << nDefs << " defines with a total number of " << nUses << " uses instrumented\n"; // notify change of program return true; }
void InitializeSoftBound:: constructCheckHandlers(Module & module){ Type* void_ty = Type::getVoidTy(module.getContext()); Type* void_ptr_ty = PointerType::getUnqual(Type::getInt8Ty(module.getContext())); Type* size_ty = Type::getInt64Ty(module.getContext()); module.getOrInsertFunction("__softboundcets_spatial_load_dereference_check", void_ty, void_ptr_ty, void_ptr_ty, void_ptr_ty, size_ty, NULL); module.getOrInsertFunction("__softboundcets_spatial_store_dereference_check", void_ty, void_ptr_ty, void_ptr_ty, void_ptr_ty, size_ty, NULL); module.getOrInsertFunction("__softboundcets_temporal_load_dereference_check", void_ty, void_ptr_ty, size_ty, void_ptr_ty, void_ptr_ty, NULL); module.getOrInsertFunction("__softboundcets_temporal_store_dereference_check", void_ty, void_ptr_ty, size_ty, void_ptr_ty, void_ptr_ty, NULL); Function* global_init = (Function *) module.getOrInsertFunction("__softboundcets_global_init", void_ty, NULL); global_init->setDoesNotThrow(); global_init->setLinkage(GlobalValue::InternalLinkage); BasicBlock* BB = BasicBlock::Create(module.getContext(), "entry", global_init); Function* softboundcets_init = (Function*) module.getOrInsertFunction("__softboundcets_init", void_ty, Type::getInt32Ty(module.getContext()), NULL); SmallVector<Value*, 8> args; Constant * const_one = ConstantInt::get(Type::getInt32Ty(module.getContext()), 1); args.push_back(const_one); Instruction* ret = ReturnInst::Create(module.getContext(), BB); CallInst::Create(softboundcets_init, args, "", ret); Type * Int32Type = IntegerType::getInt32Ty(module.getContext()); std::vector<Constant *> CtorInits; CtorInits.push_back(ConstantInt::get(Int32Type, 0)); CtorInits.push_back(global_init); StructType * ST = ConstantStruct::getTypeForElements(CtorInits, false); Constant * RuntimeCtorInit = ConstantStruct::get(ST, CtorInits); // // Get the current set of static global constructors and add the new ctor // to the list. // std::vector<Constant *> CurrentCtors; GlobalVariable * GVCtor = module.getNamedGlobal ("llvm.global_ctors"); if (GVCtor) { if (Constant * C = GVCtor->getInitializer()) { for (unsigned index = 0; index < C->getNumOperands(); ++index) { CurrentCtors.push_back (dyn_cast<Constant>(C->getOperand (index))); } } } CurrentCtors.push_back(RuntimeCtorInit); // // Create a new initializer. // ArrayType * AT = ArrayType::get (RuntimeCtorInit-> getType(), CurrentCtors.size()); Constant * NewInit = ConstantArray::get (AT, CurrentCtors); // // Create the new llvm.global_ctors global variable and remove the old one // if it existed. // Value * newGVCtor = new GlobalVariable (module, NewInit->getType(), false, GlobalValue::AppendingLinkage, NewInit, "llvm.global_ctors"); if (GVCtor) { newGVCtor->takeName (GVCtor); GVCtor->eraseFromParent (); } }
/// Update the initializers in the Dest module now that all globals that may be /// referenced are in Dest. void IRLinker::linkGlobalVariable(GlobalVariable &Dst, GlobalVariable &Src) { Dst.copyMetadata(&Src, 0); // Figure out what the initializer looks like in the dest module. Mapper.scheduleMapGlobalInitializer(Dst, *Src.getInitializer()); }
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); }
// This function replaces all global variables with new variables that have // trailing redzones. It also creates a function that poisons // redzones and inserts this function into llvm.global_ctors. bool AddressSanitizer::insertGlobalRedzones(Module &M) { SmallVector<GlobalVariable *, 16> GlobalsToChange; for (Module::GlobalListType::iterator G = M.global_begin(), E = M.global_end(); G != E; ++G) { if (ShouldInstrumentGlobal(G)) GlobalsToChange.push_back(G); } size_t n = GlobalsToChange.size(); if (n == 0) return false; // A global is described by a structure // size_t beg; // size_t size; // size_t size_with_redzone; // const char *name; // size_t has_dynamic_init; // We initialize an array of such structures and pass it to a run-time call. StructType *GlobalStructTy = StructType::get(IntptrTy, IntptrTy, IntptrTy, IntptrTy, IntptrTy, NULL); SmallVector<Constant *, 16> Initializers(n), DynamicInit; IRBuilder<> IRB(CtorInsertBefore); if (ClInitializers) FindDynamicInitializers(M); // The addresses of the first and last dynamically initialized globals in // this TU. Used in initialization order checking. Value *FirstDynamic = 0, *LastDynamic = 0; for (size_t i = 0; i < n; i++) { GlobalVariable *G = GlobalsToChange[i]; PointerType *PtrTy = cast<PointerType>(G->getType()); Type *Ty = PtrTy->getElementType(); uint64_t SizeInBytes = TD->getTypeAllocSize(Ty); uint64_t RightRedzoneSize = RedzoneSize + (RedzoneSize - (SizeInBytes % RedzoneSize)); Type *RightRedZoneTy = ArrayType::get(IRB.getInt8Ty(), RightRedzoneSize); // Determine whether this global should be poisoned in initialization. bool GlobalHasDynamicInitializer = HasDynamicInitializer(G); // Don't check initialization order if this global is blacklisted. GlobalHasDynamicInitializer &= !BL->isInInit(*G); StructType *NewTy = StructType::get(Ty, RightRedZoneTy, NULL); Constant *NewInitializer = ConstantStruct::get( NewTy, G->getInitializer(), Constant::getNullValue(RightRedZoneTy), NULL); SmallString<2048> DescriptionOfGlobal = G->getName(); DescriptionOfGlobal += " ("; DescriptionOfGlobal += M.getModuleIdentifier(); DescriptionOfGlobal += ")"; GlobalVariable *Name = createPrivateGlobalForString(M, DescriptionOfGlobal); // Create a new global variable with enough space for a redzone. GlobalVariable *NewGlobal = new GlobalVariable( M, NewTy, G->isConstant(), G->getLinkage(), NewInitializer, "", G, G->getThreadLocalMode()); NewGlobal->copyAttributesFrom(G); NewGlobal->setAlignment(RedzoneSize); Value *Indices2[2]; Indices2[0] = IRB.getInt32(0); Indices2[1] = IRB.getInt32(0); G->replaceAllUsesWith( ConstantExpr::getGetElementPtr(NewGlobal, Indices2, true)); NewGlobal->takeName(G); G->eraseFromParent(); Initializers[i] = ConstantStruct::get( GlobalStructTy, ConstantExpr::getPointerCast(NewGlobal, IntptrTy), ConstantInt::get(IntptrTy, SizeInBytes), ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize), ConstantExpr::getPointerCast(Name, IntptrTy), ConstantInt::get(IntptrTy, GlobalHasDynamicInitializer), NULL); // Populate the first and last globals declared in this TU. if (ClInitializers && GlobalHasDynamicInitializer) { LastDynamic = ConstantExpr::getPointerCast(NewGlobal, IntptrTy); if (FirstDynamic == 0) FirstDynamic = LastDynamic; } DEBUG(dbgs() << "NEW GLOBAL:\n" << *NewGlobal); } ArrayType *ArrayOfGlobalStructTy = ArrayType::get(GlobalStructTy, n); GlobalVariable *AllGlobals = new GlobalVariable( M, ArrayOfGlobalStructTy, false, GlobalVariable::PrivateLinkage, ConstantArray::get(ArrayOfGlobalStructTy, Initializers), ""); // Create calls for poisoning before initializers run and unpoisoning after. if (ClInitializers && FirstDynamic && LastDynamic) createInitializerPoisonCalls(M, FirstDynamic, LastDynamic); Function *AsanRegisterGlobals = checkInterfaceFunction(M.getOrInsertFunction( kAsanRegisterGlobalsName, IRB.getVoidTy(), IntptrTy, IntptrTy, NULL)); AsanRegisterGlobals->setLinkage(Function::ExternalLinkage); IRB.CreateCall2(AsanRegisterGlobals, IRB.CreatePointerCast(AllGlobals, IntptrTy), ConstantInt::get(IntptrTy, n)); // We also need to unregister globals at the end, e.g. when a shared library // gets closed. Function *AsanDtorFunction = Function::Create( FunctionType::get(Type::getVoidTy(*C), false), GlobalValue::InternalLinkage, kAsanModuleDtorName, &M); BasicBlock *AsanDtorBB = BasicBlock::Create(*C, "", AsanDtorFunction); IRBuilder<> IRB_Dtor(ReturnInst::Create(*C, AsanDtorBB)); Function *AsanUnregisterGlobals = checkInterfaceFunction(M.getOrInsertFunction( kAsanUnregisterGlobalsName, IRB.getVoidTy(), IntptrTy, IntptrTy, NULL)); AsanUnregisterGlobals->setLinkage(Function::ExternalLinkage); IRB_Dtor.CreateCall2(AsanUnregisterGlobals, IRB.CreatePointerCast(AllGlobals, IntptrTy), ConstantInt::get(IntptrTy, n)); appendToGlobalDtors(M, AsanDtorFunction, kAsanCtorAndCtorPriority); DEBUG(dbgs() << M); return true; }
/// GetConstantStringInfo - This function computes the length of a /// null-terminated C string pointed to by V. If successful, it returns true /// and returns the string in Str. If unsuccessful, it returns false. bool llvm::GetConstantStringInfo(Value *V, std::string &Str, uint64_t Offset, bool StopAtNul) { // If V is NULL then return false; if (V == NULL) return false; // Look through bitcast instructions. if (BitCastInst *BCI = dyn_cast<BitCastInst>(V)) return GetConstantStringInfo(BCI->getOperand(0), Str, Offset, StopAtNul); // If the value is not a GEP instruction nor a constant expression with a // GEP instruction, then return false because ConstantArray can't occur // any other way User *GEP = 0; if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(V)) { GEP = GEPI; } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) { if (CE->getOpcode() == Instruction::BitCast) return GetConstantStringInfo(CE->getOperand(0), Str, Offset, StopAtNul); if (CE->getOpcode() != Instruction::GetElementPtr) return false; GEP = CE; } if (GEP) { // Make sure the GEP has exactly three arguments. if (GEP->getNumOperands() != 3) return false; // Make sure the index-ee is a pointer to array of i8. const PointerType *PT = cast<PointerType>(GEP->getOperand(0)->getType()); const ArrayType *AT = dyn_cast<ArrayType>(PT->getElementType()); if (AT == 0 || AT->getElementType() != Type::Int8Ty) return false; // Check to make sure that the first operand of the GEP is an integer and // has value 0 so that we are sure we're indexing into the initializer. ConstantInt *FirstIdx = dyn_cast<ConstantInt>(GEP->getOperand(1)); if (FirstIdx == 0 || !FirstIdx->isZero()) return false; // If the second index isn't a ConstantInt, then this is a variable index // into the array. If this occurs, we can't say anything meaningful about // the string. uint64_t StartIdx = 0; if (ConstantInt *CI = dyn_cast<ConstantInt>(GEP->getOperand(2))) StartIdx = CI->getZExtValue(); else return false; return GetConstantStringInfo(GEP->getOperand(0), Str, StartIdx+Offset, StopAtNul); } // The GEP instruction, constant or instruction, must reference a global // variable that is a constant and is initialized. The referenced constant // initializer is the array that we'll use for optimization. GlobalVariable* GV = dyn_cast<GlobalVariable>(V); if (!GV || !GV->isConstant() || !GV->hasInitializer()) return false; Constant *GlobalInit = GV->getInitializer(); // Handle the ConstantAggregateZero case if (isa<ConstantAggregateZero>(GlobalInit)) { // This is a degenerate case. The initializer is constant zero so the // length of the string must be zero. Str.clear(); return true; } // Must be a Constant Array ConstantArray *Array = dyn_cast<ConstantArray>(GlobalInit); if (Array == 0 || Array->getType()->getElementType() != Type::Int8Ty) return false; // Get the number of elements in the array uint64_t NumElts = Array->getType()->getNumElements(); if (Offset > NumElts) return false; // Traverse the constant array from 'Offset' which is the place the GEP refers // to in the array. Str.reserve(NumElts-Offset); for (unsigned i = Offset; i != NumElts; ++i) { Constant *Elt = Array->getOperand(i); ConstantInt *CI = dyn_cast<ConstantInt>(Elt); if (!CI) // This array isn't suitable, non-int initializer. return false; if (StopAtNul && CI->isZero()) return true; // we found end of string, success! Str += (char)CI->getZExtValue(); } // The array isn't null terminated, but maybe this is a memcpy, not a strcpy. return true; }
void PrivilegedCallAnalysis::doAnalysis(Module& M, SandboxVector& sandboxes) { // first find all methods annotated as being privileged and then check calls within sandboxes if (GlobalVariable* lga = M.getNamedGlobal("llvm.global.annotations")) { ConstantArray* lgaArray = dyn_cast<ConstantArray>(lga->getInitializer()->stripPointerCasts()); for (User::op_iterator i=lgaArray->op_begin(), e = lgaArray->op_end(); e!=i; i++) { ConstantStruct* lgaArrayElement = dyn_cast<ConstantStruct>(i->get()); // get the annotation value first GlobalVariable* annotationStrVar = dyn_cast<GlobalVariable>(lgaArrayElement->getOperand(1)->stripPointerCasts()); ConstantDataArray* annotationStrArray = dyn_cast<ConstantDataArray>(annotationStrVar->getInitializer()); StringRef annotationStrArrayCString = annotationStrArray->getAsCString(); GlobalValue* annotatedVal = dyn_cast<GlobalValue>(lgaArrayElement->getOperand(0)->stripPointerCasts()); if (isa<Function>(annotatedVal)) { Function* annotatedFunc = dyn_cast<Function>(annotatedVal); if (annotationStrArrayCString == SOAAP_PRIVILEGED) { outs() << " Found function: " << annotatedFunc->getName() << "\n"; privAnnotFuncs.push_back(annotatedFunc); } } } } // now check calls within sandboxes for (Function* privilegedFunc : privAnnotFuncs) { for (User* U : privilegedFunc->users()) { if (CallInst* C = dyn_cast<CallInst>(U)) { Function* enclosingFunc = C->getParent()->getParent(); for (Sandbox* S : sandboxes) { if (!S->hasCallgate(privilegedFunc) && S->containsFunction(enclosingFunc)) { outs() << " *** Sandbox \"" << S->getName() << "\" calls privileged function \"" << privilegedFunc->getName() << "\" that they are not allowed to. If intended, annotate this permission using the __soaap_callgates annotation.\n"; if (MDNode *N = C->getMetadata("dbg")) { // Here I is an LLVM instruction DILocation Loc(N); // DILocation is in DebugInfo.h unsigned Line = Loc.getLineNumber(); StringRef File = Loc.getFilename(); outs() << " +++ Line " << Line << " of file " << File << "\n"; } } } } } } /* for (Sandbox* S : sandboxes) { FunctionVector callgates = S->getCallgates(); for (Function* F : S->getFunctions()) { for (BasicBlock& BB : F->getBasicBlockList()) { for (Instruction& I : BB.getInstList()) { if (CallInst* C = dyn_cast<CallInst>(&I)) { if (Function* Target = C->getCalledFunction()) { if (find(privAnnotFuncs.begin(), privAnnotFuncs.end(), Target) != privAnnotFuncs.end()) { // check if this sandbox is allowed to call the privileged function DEBUG(dbgs() << " Found privileged call: "); DEBUG(C->dump()); if (find(callgates.begin(), callgates.end(), Target) == callgates.end()) { outs() << " *** Sandbox \"" << S->getName() << "\" calls privileged function \"" << Target->getName() << "\" that they are not allowed to. If intended, annotate this permission using the __soaap_callgates annotation.\n"; if (MDNode *N = C->getMetadata("dbg")) { // Here I is an LLVM instruction DILocation Loc(N); // DILocation is in DebugInfo.h unsigned Line = Loc.getLineNumber(); StringRef File = Loc.getFilename(); outs() << " +++ Line " << Line << " of file " << File << "\n"; } } } } } } } } } */ }