1 //===- StackSafetyAnalysis.cpp - Stack memory safety analysis -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 //===----------------------------------------------------------------------===// 10 11 #include "llvm/Analysis/StackSafetyAnalysis.h" 12 #include "llvm/ADT/APInt.h" 13 #include "llvm/ADT/SmallPtrSet.h" 14 #include "llvm/ADT/SmallVector.h" 15 #include "llvm/ADT/Statistic.h" 16 #include "llvm/Analysis/ModuleSummaryAnalysis.h" 17 #include "llvm/Analysis/ScalarEvolutionExpressions.h" 18 #include "llvm/Analysis/StackLifetime.h" 19 #include "llvm/IR/ConstantRange.h" 20 #include "llvm/IR/DerivedTypes.h" 21 #include "llvm/IR/GlobalValue.h" 22 #include "llvm/IR/InstIterator.h" 23 #include "llvm/IR/Instructions.h" 24 #include "llvm/IR/IntrinsicInst.h" 25 #include "llvm/IR/ModuleSummaryIndex.h" 26 #include "llvm/InitializePasses.h" 27 #include "llvm/Support/Casting.h" 28 #include "llvm/Support/CommandLine.h" 29 #include "llvm/Support/FormatVariadic.h" 30 #include "llvm/Support/raw_ostream.h" 31 #include <algorithm> 32 #include <memory> 33 34 using namespace llvm; 35 36 #define DEBUG_TYPE "stack-safety" 37 38 STATISTIC(NumAllocaStackSafe, "Number of safe allocas"); 39 STATISTIC(NumAllocaTotal, "Number of total allocas"); 40 41 STATISTIC(NumCombinedCalleeLookupTotal, 42 "Number of total callee lookups on combined index."); 43 STATISTIC(NumCombinedCalleeLookupFailed, 44 "Number of failed callee lookups on combined index."); 45 STATISTIC(NumModuleCalleeLookupTotal, 46 "Number of total callee lookups on module index."); 47 STATISTIC(NumModuleCalleeLookupFailed, 48 "Number of failed callee lookups on module index."); 49 STATISTIC(NumCombinedParamAccessesBefore, 50 "Number of total param accesses before generateParamAccessSummary."); 51 STATISTIC(NumCombinedParamAccessesAfter, 52 "Number of total param accesses after generateParamAccessSummary."); 53 STATISTIC(NumCombinedDataFlowNodes, 54 "Number of total nodes in combined index for dataflow processing."); 55 STATISTIC(NumIndexCalleeUnhandled, "Number of index callee which are unhandled."); 56 STATISTIC(NumIndexCalleeMultipleWeak, "Number of index callee non-unique weak."); 57 STATISTIC(NumIndexCalleeMultipleExternal, "Number of index callee non-unique external."); 58 59 60 static cl::opt<int> StackSafetyMaxIterations("stack-safety-max-iterations", 61 cl::init(20), cl::Hidden); 62 63 static cl::opt<bool> StackSafetyPrint("stack-safety-print", cl::init(false), 64 cl::Hidden); 65 66 static cl::opt<bool> StackSafetyRun("stack-safety-run", cl::init(false), 67 cl::Hidden); 68 69 namespace { 70 71 // Check if we should bailout for such ranges. 72 bool isUnsafe(const ConstantRange &R) { 73 return R.isEmptySet() || R.isFullSet() || R.isUpperSignWrapped(); 74 } 75 76 ConstantRange addOverflowNever(const ConstantRange &L, const ConstantRange &R) { 77 assert(!L.isSignWrappedSet()); 78 assert(!R.isSignWrappedSet()); 79 if (L.signedAddMayOverflow(R) != 80 ConstantRange::OverflowResult::NeverOverflows) 81 return ConstantRange::getFull(L.getBitWidth()); 82 ConstantRange Result = L.add(R); 83 assert(!Result.isSignWrappedSet()); 84 return Result; 85 } 86 87 ConstantRange unionNoWrap(const ConstantRange &L, const ConstantRange &R) { 88 assert(!L.isSignWrappedSet()); 89 assert(!R.isSignWrappedSet()); 90 auto Result = L.unionWith(R); 91 // Two non-wrapped sets can produce wrapped. 92 if (Result.isSignWrappedSet()) 93 Result = ConstantRange::getFull(Result.getBitWidth()); 94 return Result; 95 } 96 97 /// Describes use of address in as a function call argument. 98 template <typename CalleeTy> struct CallInfo { 99 /// Function being called. 100 const CalleeTy *Callee = nullptr; 101 /// Index of argument which pass address. 102 size_t ParamNo = 0; 103 104 CallInfo(const CalleeTy *Callee, size_t ParamNo) 105 : Callee(Callee), ParamNo(ParamNo) {} 106 107 struct Less { 108 bool operator()(const CallInfo &L, const CallInfo &R) const { 109 return std::tie(L.ParamNo, L.Callee) < std::tie(R.ParamNo, R.Callee); 110 } 111 }; 112 }; 113 114 /// Describe uses of address (alloca or parameter) inside of the function. 115 template <typename CalleeTy> struct UseInfo { 116 // Access range if the address (alloca or parameters). 117 // It is allowed to be empty-set when there are no known accesses. 118 ConstantRange Range; 119 120 // List of calls which pass address as an argument. 121 // Value is offset range of address from base address (alloca or calling 122 // function argument). Range should never set to empty-set, that is an invalid 123 // access range that can cause empty-set to be propagated with 124 // ConstantRange::add 125 using CallsTy = std::map<CallInfo<CalleeTy>, ConstantRange, 126 typename CallInfo<CalleeTy>::Less>; 127 CallsTy Calls; 128 129 UseInfo(unsigned PointerSize) : Range{PointerSize, false} {} 130 131 void updateRange(const ConstantRange &R) { Range = unionNoWrap(Range, R); } 132 void addRange(const Instruction *I, const ConstantRange &R) { 133 updateRange(R); 134 } 135 }; 136 137 template <typename CalleeTy> 138 raw_ostream &operator<<(raw_ostream &OS, const UseInfo<CalleeTy> &U) { 139 OS << U.Range; 140 for (auto &Call : U.Calls) 141 OS << ", " 142 << "@" << Call.first.Callee->getName() << "(arg" << Call.first.ParamNo 143 << ", " << Call.second << ")"; 144 return OS; 145 } 146 147 /// Calculate the allocation size of a given alloca. Returns empty range 148 // in case of confution. 149 ConstantRange getStaticAllocaSizeRange(const AllocaInst &AI) { 150 const DataLayout &DL = AI.getModule()->getDataLayout(); 151 TypeSize TS = DL.getTypeAllocSize(AI.getAllocatedType()); 152 unsigned PointerSize = DL.getMaxPointerSizeInBits(); 153 // Fallback to empty range for alloca size. 154 ConstantRange R = ConstantRange::getEmpty(PointerSize); 155 if (TS.isScalable()) 156 return R; 157 APInt APSize(PointerSize, TS.getFixedSize(), true); 158 if (APSize.isNonPositive()) 159 return R; 160 if (AI.isArrayAllocation()) { 161 const auto *C = dyn_cast<ConstantInt>(AI.getArraySize()); 162 if (!C) 163 return R; 164 bool Overflow = false; 165 APInt Mul = C->getValue(); 166 if (Mul.isNonPositive()) 167 return R; 168 Mul = Mul.sextOrTrunc(PointerSize); 169 APSize = APSize.smul_ov(Mul, Overflow); 170 if (Overflow) 171 return R; 172 } 173 R = ConstantRange(APInt::getZero(PointerSize), APSize); 174 assert(!isUnsafe(R)); 175 return R; 176 } 177 178 template <typename CalleeTy> struct FunctionInfo { 179 std::map<const AllocaInst *, UseInfo<CalleeTy>> Allocas; 180 std::map<uint32_t, UseInfo<CalleeTy>> Params; 181 // TODO: describe return value as depending on one or more of its arguments. 182 183 // StackSafetyDataFlowAnalysis counter stored here for faster access. 184 int UpdateCount = 0; 185 186 void print(raw_ostream &O, StringRef Name, const Function *F) const { 187 // TODO: Consider different printout format after 188 // StackSafetyDataFlowAnalysis. Calls and parameters are irrelevant then. 189 O << " @" << Name << ((F && F->isDSOLocal()) ? "" : " dso_preemptable") 190 << ((F && F->isInterposable()) ? " interposable" : "") << "\n"; 191 192 O << " args uses:\n"; 193 for (auto &KV : Params) { 194 O << " "; 195 if (F) 196 O << F->getArg(KV.first)->getName(); 197 else 198 O << formatv("arg{0}", KV.first); 199 O << "[]: " << KV.second << "\n"; 200 } 201 202 O << " allocas uses:\n"; 203 if (F) { 204 for (auto &I : instructions(F)) { 205 if (const AllocaInst *AI = dyn_cast<AllocaInst>(&I)) { 206 auto &AS = Allocas.find(AI)->second; 207 O << " " << AI->getName() << "[" 208 << getStaticAllocaSizeRange(*AI).getUpper() << "]: " << AS << "\n"; 209 } 210 } 211 } else { 212 assert(Allocas.empty()); 213 } 214 } 215 }; 216 217 using GVToSSI = std::map<const GlobalValue *, FunctionInfo<GlobalValue>>; 218 219 } // namespace 220 221 struct StackSafetyInfo::InfoTy { 222 FunctionInfo<GlobalValue> Info; 223 }; 224 225 struct StackSafetyGlobalInfo::InfoTy { 226 GVToSSI Info; 227 SmallPtrSet<const AllocaInst *, 8> SafeAllocas; 228 }; 229 230 namespace { 231 232 class StackSafetyLocalAnalysis { 233 Function &F; 234 const DataLayout &DL; 235 ScalarEvolution &SE; 236 unsigned PointerSize = 0; 237 238 const ConstantRange UnknownRange; 239 240 ConstantRange offsetFrom(Value *Addr, Value *Base); 241 ConstantRange getAccessRange(Value *Addr, Value *Base, 242 const ConstantRange &SizeRange); 243 ConstantRange getAccessRange(Value *Addr, Value *Base, TypeSize Size); 244 ConstantRange getMemIntrinsicAccessRange(const MemIntrinsic *MI, const Use &U, 245 Value *Base); 246 247 void analyzeAllUses(Value *Ptr, UseInfo<GlobalValue> &AS, 248 const StackLifetime &SL); 249 250 public: 251 StackSafetyLocalAnalysis(Function &F, ScalarEvolution &SE) 252 : F(F), DL(F.getParent()->getDataLayout()), SE(SE), 253 PointerSize(DL.getPointerSizeInBits()), 254 UnknownRange(PointerSize, true) {} 255 256 // Run the transformation on the associated function. 257 FunctionInfo<GlobalValue> run(); 258 }; 259 260 ConstantRange StackSafetyLocalAnalysis::offsetFrom(Value *Addr, Value *Base) { 261 if (!SE.isSCEVable(Addr->getType()) || !SE.isSCEVable(Base->getType())) 262 return UnknownRange; 263 264 auto *PtrTy = IntegerType::getInt8PtrTy(SE.getContext()); 265 const SCEV *AddrExp = SE.getTruncateOrZeroExtend(SE.getSCEV(Addr), PtrTy); 266 const SCEV *BaseExp = SE.getTruncateOrZeroExtend(SE.getSCEV(Base), PtrTy); 267 const SCEV *Diff = SE.getMinusSCEV(AddrExp, BaseExp); 268 if (isa<SCEVCouldNotCompute>(Diff)) 269 return UnknownRange; 270 271 ConstantRange Offset = SE.getSignedRange(Diff); 272 if (isUnsafe(Offset)) 273 return UnknownRange; 274 return Offset.sextOrTrunc(PointerSize); 275 } 276 277 ConstantRange 278 StackSafetyLocalAnalysis::getAccessRange(Value *Addr, Value *Base, 279 const ConstantRange &SizeRange) { 280 // Zero-size loads and stores do not access memory. 281 if (SizeRange.isEmptySet()) 282 return ConstantRange::getEmpty(PointerSize); 283 assert(!isUnsafe(SizeRange)); 284 285 ConstantRange Offsets = offsetFrom(Addr, Base); 286 if (isUnsafe(Offsets)) 287 return UnknownRange; 288 289 Offsets = addOverflowNever(Offsets, SizeRange); 290 if (isUnsafe(Offsets)) 291 return UnknownRange; 292 return Offsets; 293 } 294 295 ConstantRange StackSafetyLocalAnalysis::getAccessRange(Value *Addr, Value *Base, 296 TypeSize Size) { 297 if (Size.isScalable()) 298 return UnknownRange; 299 APInt APSize(PointerSize, Size.getFixedSize(), true); 300 if (APSize.isNegative()) 301 return UnknownRange; 302 return getAccessRange(Addr, Base, 303 ConstantRange(APInt::getZero(PointerSize), APSize)); 304 } 305 306 ConstantRange StackSafetyLocalAnalysis::getMemIntrinsicAccessRange( 307 const MemIntrinsic *MI, const Use &U, Value *Base) { 308 if (const auto *MTI = dyn_cast<MemTransferInst>(MI)) { 309 if (MTI->getRawSource() != U && MTI->getRawDest() != U) 310 return ConstantRange::getEmpty(PointerSize); 311 } else { 312 if (MI->getRawDest() != U) 313 return ConstantRange::getEmpty(PointerSize); 314 } 315 316 auto *CalculationTy = IntegerType::getIntNTy(SE.getContext(), PointerSize); 317 if (!SE.isSCEVable(MI->getLength()->getType())) 318 return UnknownRange; 319 320 const SCEV *Expr = 321 SE.getTruncateOrZeroExtend(SE.getSCEV(MI->getLength()), CalculationTy); 322 ConstantRange Sizes = SE.getSignedRange(Expr); 323 if (Sizes.getUpper().isNegative() || isUnsafe(Sizes)) 324 return UnknownRange; 325 Sizes = Sizes.sextOrTrunc(PointerSize); 326 ConstantRange SizeRange(APInt::getZero(PointerSize), Sizes.getUpper() - 1); 327 return getAccessRange(U, Base, SizeRange); 328 } 329 330 /// The function analyzes all local uses of Ptr (alloca or argument) and 331 /// calculates local access range and all function calls where it was used. 332 void StackSafetyLocalAnalysis::analyzeAllUses(Value *Ptr, 333 UseInfo<GlobalValue> &US, 334 const StackLifetime &SL) { 335 SmallPtrSet<const Value *, 16> Visited; 336 SmallVector<const Value *, 8> WorkList; 337 WorkList.push_back(Ptr); 338 const AllocaInst *AI = dyn_cast<AllocaInst>(Ptr); 339 340 // A DFS search through all uses of the alloca in bitcasts/PHI/GEPs/etc. 341 while (!WorkList.empty()) { 342 const Value *V = WorkList.pop_back_val(); 343 for (const Use &UI : V->uses()) { 344 const auto *I = cast<Instruction>(UI.getUser()); 345 if (!SL.isReachable(I)) 346 continue; 347 348 assert(V == UI.get()); 349 350 switch (I->getOpcode()) { 351 case Instruction::Load: { 352 if (AI && !SL.isAliveAfter(AI, I)) { 353 US.addRange(I, UnknownRange); 354 return; 355 } 356 US.addRange(I, 357 getAccessRange(UI, Ptr, DL.getTypeStoreSize(I->getType()))); 358 break; 359 } 360 361 case Instruction::VAArg: 362 // "va-arg" from a pointer is safe. 363 break; 364 case Instruction::Store: { 365 if (V == I->getOperand(0)) { 366 // Stored the pointer - conservatively assume it may be unsafe. 367 US.addRange(I, UnknownRange); 368 return; 369 } 370 if (AI && !SL.isAliveAfter(AI, I)) { 371 US.addRange(I, UnknownRange); 372 return; 373 } 374 US.addRange( 375 I, getAccessRange( 376 UI, Ptr, DL.getTypeStoreSize(I->getOperand(0)->getType()))); 377 break; 378 } 379 380 case Instruction::Ret: 381 // Information leak. 382 // FIXME: Process parameters correctly. This is a leak only if we return 383 // alloca. 384 US.addRange(I, UnknownRange); 385 return; 386 387 case Instruction::Call: 388 case Instruction::Invoke: { 389 if (I->isLifetimeStartOrEnd()) 390 break; 391 392 if (AI && !SL.isAliveAfter(AI, I)) { 393 US.addRange(I, UnknownRange); 394 return; 395 } 396 397 if (const MemIntrinsic *MI = dyn_cast<MemIntrinsic>(I)) { 398 US.addRange(I, getMemIntrinsicAccessRange(MI, UI, Ptr)); 399 break; 400 } 401 402 const auto &CB = cast<CallBase>(*I); 403 if (!CB.isArgOperand(&UI)) { 404 US.addRange(I, UnknownRange); 405 return; 406 } 407 408 unsigned ArgNo = CB.getArgOperandNo(&UI); 409 if (CB.isByValArgument(ArgNo)) { 410 US.addRange(I, getAccessRange( 411 UI, Ptr, 412 DL.getTypeStoreSize(CB.getParamByValType(ArgNo)))); 413 break; 414 } 415 416 // FIXME: consult devirt? 417 // Do not follow aliases, otherwise we could inadvertently follow 418 // dso_preemptable aliases or aliases with interposable linkage. 419 const GlobalValue *Callee = 420 dyn_cast<GlobalValue>(CB.getCalledOperand()->stripPointerCasts()); 421 if (!Callee) { 422 US.addRange(I, UnknownRange); 423 return; 424 } 425 426 assert(isa<Function>(Callee) || isa<GlobalAlias>(Callee)); 427 ConstantRange Offsets = offsetFrom(UI, Ptr); 428 auto Insert = 429 US.Calls.emplace(CallInfo<GlobalValue>(Callee, ArgNo), Offsets); 430 if (!Insert.second) 431 Insert.first->second = Insert.first->second.unionWith(Offsets); 432 break; 433 } 434 435 default: 436 if (Visited.insert(I).second) 437 WorkList.push_back(cast<const Instruction>(I)); 438 } 439 } 440 } 441 } 442 443 FunctionInfo<GlobalValue> StackSafetyLocalAnalysis::run() { 444 FunctionInfo<GlobalValue> Info; 445 assert(!F.isDeclaration() && 446 "Can't run StackSafety on a function declaration"); 447 448 LLVM_DEBUG(dbgs() << "[StackSafety] " << F.getName() << "\n"); 449 450 SmallVector<AllocaInst *, 64> Allocas; 451 for (auto &I : instructions(F)) 452 if (auto *AI = dyn_cast<AllocaInst>(&I)) 453 Allocas.push_back(AI); 454 StackLifetime SL(F, Allocas, StackLifetime::LivenessType::Must); 455 SL.run(); 456 457 for (auto *AI : Allocas) { 458 auto &UI = Info.Allocas.emplace(AI, PointerSize).first->second; 459 analyzeAllUses(AI, UI, SL); 460 } 461 462 for (Argument &A : F.args()) { 463 // Non pointers and bypass arguments are not going to be used in any global 464 // processing. 465 if (A.getType()->isPointerTy() && !A.hasByValAttr()) { 466 auto &UI = Info.Params.emplace(A.getArgNo(), PointerSize).first->second; 467 analyzeAllUses(&A, UI, SL); 468 } 469 } 470 471 LLVM_DEBUG(Info.print(dbgs(), F.getName(), &F)); 472 LLVM_DEBUG(dbgs() << "\n[StackSafety] done\n"); 473 return Info; 474 } 475 476 template <typename CalleeTy> class StackSafetyDataFlowAnalysis { 477 using FunctionMap = std::map<const CalleeTy *, FunctionInfo<CalleeTy>>; 478 479 FunctionMap Functions; 480 const ConstantRange UnknownRange; 481 482 // Callee-to-Caller multimap. 483 DenseMap<const CalleeTy *, SmallVector<const CalleeTy *, 4>> Callers; 484 SetVector<const CalleeTy *> WorkList; 485 486 bool updateOneUse(UseInfo<CalleeTy> &US, bool UpdateToFullSet); 487 void updateOneNode(const CalleeTy *Callee, FunctionInfo<CalleeTy> &FS); 488 void updateOneNode(const CalleeTy *Callee) { 489 updateOneNode(Callee, Functions.find(Callee)->second); 490 } 491 void updateAllNodes() { 492 for (auto &F : Functions) 493 updateOneNode(F.first, F.second); 494 } 495 void runDataFlow(); 496 #ifndef NDEBUG 497 void verifyFixedPoint(); 498 #endif 499 500 public: 501 StackSafetyDataFlowAnalysis(uint32_t PointerBitWidth, FunctionMap Functions) 502 : Functions(std::move(Functions)), 503 UnknownRange(ConstantRange::getFull(PointerBitWidth)) {} 504 505 const FunctionMap &run(); 506 507 ConstantRange getArgumentAccessRange(const CalleeTy *Callee, unsigned ParamNo, 508 const ConstantRange &Offsets) const; 509 }; 510 511 template <typename CalleeTy> 512 ConstantRange StackSafetyDataFlowAnalysis<CalleeTy>::getArgumentAccessRange( 513 const CalleeTy *Callee, unsigned ParamNo, 514 const ConstantRange &Offsets) const { 515 auto FnIt = Functions.find(Callee); 516 // Unknown callee (outside of LTO domain or an indirect call). 517 if (FnIt == Functions.end()) 518 return UnknownRange; 519 auto &FS = FnIt->second; 520 auto ParamIt = FS.Params.find(ParamNo); 521 if (ParamIt == FS.Params.end()) 522 return UnknownRange; 523 auto &Access = ParamIt->second.Range; 524 if (Access.isEmptySet()) 525 return Access; 526 if (Access.isFullSet()) 527 return UnknownRange; 528 return addOverflowNever(Access, Offsets); 529 } 530 531 template <typename CalleeTy> 532 bool StackSafetyDataFlowAnalysis<CalleeTy>::updateOneUse(UseInfo<CalleeTy> &US, 533 bool UpdateToFullSet) { 534 bool Changed = false; 535 for (auto &KV : US.Calls) { 536 assert(!KV.second.isEmptySet() && 537 "Param range can't be empty-set, invalid offset range"); 538 539 ConstantRange CalleeRange = 540 getArgumentAccessRange(KV.first.Callee, KV.first.ParamNo, KV.second); 541 if (!US.Range.contains(CalleeRange)) { 542 Changed = true; 543 if (UpdateToFullSet) 544 US.Range = UnknownRange; 545 else 546 US.updateRange(CalleeRange); 547 } 548 } 549 return Changed; 550 } 551 552 template <typename CalleeTy> 553 void StackSafetyDataFlowAnalysis<CalleeTy>::updateOneNode( 554 const CalleeTy *Callee, FunctionInfo<CalleeTy> &FS) { 555 bool UpdateToFullSet = FS.UpdateCount > StackSafetyMaxIterations; 556 bool Changed = false; 557 for (auto &KV : FS.Params) 558 Changed |= updateOneUse(KV.second, UpdateToFullSet); 559 560 if (Changed) { 561 LLVM_DEBUG(dbgs() << "=== update [" << FS.UpdateCount 562 << (UpdateToFullSet ? ", full-set" : "") << "] " << &FS 563 << "\n"); 564 // Callers of this function may need updating. 565 for (auto &CallerID : Callers[Callee]) 566 WorkList.insert(CallerID); 567 568 ++FS.UpdateCount; 569 } 570 } 571 572 template <typename CalleeTy> 573 void StackSafetyDataFlowAnalysis<CalleeTy>::runDataFlow() { 574 SmallVector<const CalleeTy *, 16> Callees; 575 for (auto &F : Functions) { 576 Callees.clear(); 577 auto &FS = F.second; 578 for (auto &KV : FS.Params) 579 for (auto &CS : KV.second.Calls) 580 Callees.push_back(CS.first.Callee); 581 582 llvm::sort(Callees); 583 Callees.erase(std::unique(Callees.begin(), Callees.end()), Callees.end()); 584 585 for (auto &Callee : Callees) 586 Callers[Callee].push_back(F.first); 587 } 588 589 updateAllNodes(); 590 591 while (!WorkList.empty()) { 592 const CalleeTy *Callee = WorkList.back(); 593 WorkList.pop_back(); 594 updateOneNode(Callee); 595 } 596 } 597 598 #ifndef NDEBUG 599 template <typename CalleeTy> 600 void StackSafetyDataFlowAnalysis<CalleeTy>::verifyFixedPoint() { 601 WorkList.clear(); 602 updateAllNodes(); 603 assert(WorkList.empty()); 604 } 605 #endif 606 607 template <typename CalleeTy> 608 const typename StackSafetyDataFlowAnalysis<CalleeTy>::FunctionMap & 609 StackSafetyDataFlowAnalysis<CalleeTy>::run() { 610 runDataFlow(); 611 LLVM_DEBUG(verifyFixedPoint()); 612 return Functions; 613 } 614 615 FunctionSummary *findCalleeFunctionSummary(ValueInfo VI, StringRef ModuleId) { 616 if (!VI) 617 return nullptr; 618 auto SummaryList = VI.getSummaryList(); 619 GlobalValueSummary* S = nullptr; 620 for (const auto& GVS : SummaryList) { 621 if (!GVS->isLive()) 622 continue; 623 if (const AliasSummary *AS = dyn_cast<AliasSummary>(GVS.get())) 624 if (!AS->hasAliasee()) 625 continue; 626 if (!isa<FunctionSummary>(GVS->getBaseObject())) 627 continue; 628 if (GlobalValue::isLocalLinkage(GVS->linkage())) { 629 if (GVS->modulePath() == ModuleId) { 630 S = GVS.get(); 631 break; 632 } 633 } else if (GlobalValue::isExternalLinkage(GVS->linkage())) { 634 if (S) { 635 ++NumIndexCalleeMultipleExternal; 636 return nullptr; 637 } 638 S = GVS.get(); 639 } else if (GlobalValue::isWeakLinkage(GVS->linkage())) { 640 if (S) { 641 ++NumIndexCalleeMultipleWeak; 642 return nullptr; 643 } 644 S = GVS.get(); 645 } else if (GlobalValue::isAvailableExternallyLinkage(GVS->linkage()) || 646 GlobalValue::isLinkOnceLinkage(GVS->linkage())) { 647 if (SummaryList.size() == 1) 648 S = GVS.get(); 649 // According thinLTOResolvePrevailingGUID these are unlikely prevailing. 650 } else { 651 ++NumIndexCalleeUnhandled; 652 } 653 }; 654 while (S) { 655 if (!S->isLive() || !S->isDSOLocal()) 656 return nullptr; 657 if (FunctionSummary *FS = dyn_cast<FunctionSummary>(S)) 658 return FS; 659 AliasSummary *AS = dyn_cast<AliasSummary>(S); 660 if (!AS || !AS->hasAliasee()) 661 return nullptr; 662 S = AS->getBaseObject(); 663 if (S == AS) 664 return nullptr; 665 } 666 return nullptr; 667 } 668 669 const Function *findCalleeInModule(const GlobalValue *GV) { 670 while (GV) { 671 if (GV->isDeclaration() || GV->isInterposable() || !GV->isDSOLocal()) 672 return nullptr; 673 if (const Function *F = dyn_cast<Function>(GV)) 674 return F; 675 const GlobalAlias *A = dyn_cast<GlobalAlias>(GV); 676 if (!A) 677 return nullptr; 678 GV = A->getBaseObject(); 679 if (GV == A) 680 return nullptr; 681 } 682 return nullptr; 683 } 684 685 const ConstantRange *findParamAccess(const FunctionSummary &FS, 686 uint32_t ParamNo) { 687 assert(FS.isLive()); 688 assert(FS.isDSOLocal()); 689 for (auto &PS : FS.paramAccesses()) 690 if (ParamNo == PS.ParamNo) 691 return &PS.Use; 692 return nullptr; 693 } 694 695 void resolveAllCalls(UseInfo<GlobalValue> &Use, 696 const ModuleSummaryIndex *Index) { 697 ConstantRange FullSet(Use.Range.getBitWidth(), true); 698 // Move Use.Calls to a temp storage and repopulate - don't use std::move as it 699 // leaves Use.Calls in an undefined state. 700 UseInfo<GlobalValue>::CallsTy TmpCalls; 701 std::swap(TmpCalls, Use.Calls); 702 for (const auto &C : TmpCalls) { 703 const Function *F = findCalleeInModule(C.first.Callee); 704 if (F) { 705 Use.Calls.emplace(CallInfo<GlobalValue>(F, C.first.ParamNo), C.second); 706 continue; 707 } 708 709 if (!Index) 710 return Use.updateRange(FullSet); 711 FunctionSummary *FS = 712 findCalleeFunctionSummary(Index->getValueInfo(C.first.Callee->getGUID()), 713 C.first.Callee->getParent()->getModuleIdentifier()); 714 ++NumModuleCalleeLookupTotal; 715 if (!FS) { 716 ++NumModuleCalleeLookupFailed; 717 return Use.updateRange(FullSet); 718 } 719 const ConstantRange *Found = findParamAccess(*FS, C.first.ParamNo); 720 if (!Found || Found->isFullSet()) 721 return Use.updateRange(FullSet); 722 ConstantRange Access = Found->sextOrTrunc(Use.Range.getBitWidth()); 723 if (!Access.isEmptySet()) 724 Use.updateRange(addOverflowNever(Access, C.second)); 725 } 726 } 727 728 GVToSSI createGlobalStackSafetyInfo( 729 std::map<const GlobalValue *, FunctionInfo<GlobalValue>> Functions, 730 const ModuleSummaryIndex *Index) { 731 GVToSSI SSI; 732 if (Functions.empty()) 733 return SSI; 734 735 // FIXME: Simplify printing and remove copying here. 736 auto Copy = Functions; 737 738 for (auto &FnKV : Copy) 739 for (auto &KV : FnKV.second.Params) { 740 resolveAllCalls(KV.second, Index); 741 if (KV.second.Range.isFullSet()) 742 KV.second.Calls.clear(); 743 } 744 745 uint32_t PointerSize = Copy.begin() 746 ->first->getParent() 747 ->getDataLayout() 748 .getMaxPointerSizeInBits(); 749 StackSafetyDataFlowAnalysis<GlobalValue> SSDFA(PointerSize, std::move(Copy)); 750 751 for (auto &F : SSDFA.run()) { 752 auto FI = F.second; 753 auto &SrcF = Functions[F.first]; 754 for (auto &KV : FI.Allocas) { 755 auto &A = KV.second; 756 resolveAllCalls(A, Index); 757 for (auto &C : A.Calls) { 758 A.updateRange(SSDFA.getArgumentAccessRange(C.first.Callee, 759 C.first.ParamNo, C.second)); 760 } 761 // FIXME: This is needed only to preserve calls in print() results. 762 A.Calls = SrcF.Allocas.find(KV.first)->second.Calls; 763 } 764 for (auto &KV : FI.Params) { 765 auto &P = KV.second; 766 P.Calls = SrcF.Params.find(KV.first)->second.Calls; 767 } 768 SSI[F.first] = std::move(FI); 769 } 770 771 return SSI; 772 } 773 774 } // end anonymous namespace 775 776 StackSafetyInfo::StackSafetyInfo() = default; 777 778 StackSafetyInfo::StackSafetyInfo(Function *F, 779 std::function<ScalarEvolution &()> GetSE) 780 : F(F), GetSE(GetSE) {} 781 782 StackSafetyInfo::StackSafetyInfo(StackSafetyInfo &&) = default; 783 784 StackSafetyInfo &StackSafetyInfo::operator=(StackSafetyInfo &&) = default; 785 786 StackSafetyInfo::~StackSafetyInfo() = default; 787 788 const StackSafetyInfo::InfoTy &StackSafetyInfo::getInfo() const { 789 if (!Info) { 790 StackSafetyLocalAnalysis SSLA(*F, GetSE()); 791 Info.reset(new InfoTy{SSLA.run()}); 792 } 793 return *Info; 794 } 795 796 void StackSafetyInfo::print(raw_ostream &O) const { 797 getInfo().Info.print(O, F->getName(), dyn_cast<Function>(F)); 798 O << "\n"; 799 } 800 801 const StackSafetyGlobalInfo::InfoTy &StackSafetyGlobalInfo::getInfo() const { 802 if (!Info) { 803 std::map<const GlobalValue *, FunctionInfo<GlobalValue>> Functions; 804 for (auto &F : M->functions()) { 805 if (!F.isDeclaration()) { 806 auto FI = GetSSI(F).getInfo().Info; 807 Functions.emplace(&F, std::move(FI)); 808 } 809 } 810 Info.reset(new InfoTy{ 811 createGlobalStackSafetyInfo(std::move(Functions), Index), {}}); 812 for (auto &FnKV : Info->Info) { 813 for (auto &KV : FnKV.second.Allocas) { 814 ++NumAllocaTotal; 815 const AllocaInst *AI = KV.first; 816 if (getStaticAllocaSizeRange(*AI).contains(KV.second.Range)) { 817 Info->SafeAllocas.insert(AI); 818 ++NumAllocaStackSafe; 819 } 820 } 821 } 822 if (StackSafetyPrint) 823 print(errs()); 824 } 825 return *Info; 826 } 827 828 std::vector<FunctionSummary::ParamAccess> 829 StackSafetyInfo::getParamAccesses(ModuleSummaryIndex &Index) const { 830 // Implementation transforms internal representation of parameter information 831 // into FunctionSummary format. 832 std::vector<FunctionSummary::ParamAccess> ParamAccesses; 833 for (const auto &KV : getInfo().Info.Params) { 834 auto &PS = KV.second; 835 // Parameter accessed by any or unknown offset, represented as FullSet by 836 // StackSafety, is handled as the parameter for which we have no 837 // StackSafety info at all. So drop it to reduce summary size. 838 if (PS.Range.isFullSet()) 839 continue; 840 841 ParamAccesses.emplace_back(KV.first, PS.Range); 842 FunctionSummary::ParamAccess &Param = ParamAccesses.back(); 843 844 Param.Calls.reserve(PS.Calls.size()); 845 for (auto &C : PS.Calls) { 846 // Parameter forwarded into another function by any or unknown offset 847 // will make ParamAccess::Range as FullSet anyway. So we can drop the 848 // entire parameter like we did above. 849 // TODO(vitalybuka): Return already filtered parameters from getInfo(). 850 if (C.second.isFullSet()) { 851 ParamAccesses.pop_back(); 852 break; 853 } 854 Param.Calls.emplace_back(C.first.ParamNo, 855 Index.getOrInsertValueInfo(C.first.Callee), 856 C.second); 857 } 858 } 859 for (FunctionSummary::ParamAccess &Param : ParamAccesses) { 860 sort(Param.Calls, [](const FunctionSummary::ParamAccess::Call &L, 861 const FunctionSummary::ParamAccess::Call &R) { 862 return std::tie(L.ParamNo, L.Callee) < std::tie(R.ParamNo, R.Callee); 863 }); 864 } 865 return ParamAccesses; 866 } 867 868 StackSafetyGlobalInfo::StackSafetyGlobalInfo() = default; 869 870 StackSafetyGlobalInfo::StackSafetyGlobalInfo( 871 Module *M, std::function<const StackSafetyInfo &(Function &F)> GetSSI, 872 const ModuleSummaryIndex *Index) 873 : M(M), GetSSI(GetSSI), Index(Index) { 874 if (StackSafetyRun) 875 getInfo(); 876 } 877 878 StackSafetyGlobalInfo::StackSafetyGlobalInfo(StackSafetyGlobalInfo &&) = 879 default; 880 881 StackSafetyGlobalInfo & 882 StackSafetyGlobalInfo::operator=(StackSafetyGlobalInfo &&) = default; 883 884 StackSafetyGlobalInfo::~StackSafetyGlobalInfo() = default; 885 886 bool StackSafetyGlobalInfo::isSafe(const AllocaInst &AI) const { 887 const auto &Info = getInfo(); 888 return Info.SafeAllocas.count(&AI); 889 } 890 891 void StackSafetyGlobalInfo::print(raw_ostream &O) const { 892 auto &SSI = getInfo().Info; 893 if (SSI.empty()) 894 return; 895 const Module &M = *SSI.begin()->first->getParent(); 896 for (auto &F : M.functions()) { 897 if (!F.isDeclaration()) { 898 SSI.find(&F)->second.print(O, F.getName(), &F); 899 O << "\n"; 900 O << "\n"; 901 } 902 } 903 } 904 905 LLVM_DUMP_METHOD void StackSafetyGlobalInfo::dump() const { print(dbgs()); } 906 907 AnalysisKey StackSafetyAnalysis::Key; 908 909 StackSafetyInfo StackSafetyAnalysis::run(Function &F, 910 FunctionAnalysisManager &AM) { 911 return StackSafetyInfo(&F, [&AM, &F]() -> ScalarEvolution & { 912 return AM.getResult<ScalarEvolutionAnalysis>(F); 913 }); 914 } 915 916 PreservedAnalyses StackSafetyPrinterPass::run(Function &F, 917 FunctionAnalysisManager &AM) { 918 OS << "'Stack Safety Local Analysis' for function '" << F.getName() << "'\n"; 919 AM.getResult<StackSafetyAnalysis>(F).print(OS); 920 return PreservedAnalyses::all(); 921 } 922 923 char StackSafetyInfoWrapperPass::ID = 0; 924 925 StackSafetyInfoWrapperPass::StackSafetyInfoWrapperPass() : FunctionPass(ID) { 926 initializeStackSafetyInfoWrapperPassPass(*PassRegistry::getPassRegistry()); 927 } 928 929 void StackSafetyInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { 930 AU.addRequiredTransitive<ScalarEvolutionWrapperPass>(); 931 AU.setPreservesAll(); 932 } 933 934 void StackSafetyInfoWrapperPass::print(raw_ostream &O, const Module *M) const { 935 SSI.print(O); 936 } 937 938 bool StackSafetyInfoWrapperPass::runOnFunction(Function &F) { 939 auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE(); 940 SSI = {&F, [SE]() -> ScalarEvolution & { return *SE; }}; 941 return false; 942 } 943 944 AnalysisKey StackSafetyGlobalAnalysis::Key; 945 946 StackSafetyGlobalInfo 947 StackSafetyGlobalAnalysis::run(Module &M, ModuleAnalysisManager &AM) { 948 // FIXME: Lookup Module Summary. 949 FunctionAnalysisManager &FAM = 950 AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 951 return {&M, 952 [&FAM](Function &F) -> const StackSafetyInfo & { 953 return FAM.getResult<StackSafetyAnalysis>(F); 954 }, 955 nullptr}; 956 } 957 958 PreservedAnalyses StackSafetyGlobalPrinterPass::run(Module &M, 959 ModuleAnalysisManager &AM) { 960 OS << "'Stack Safety Analysis' for module '" << M.getName() << "'\n"; 961 AM.getResult<StackSafetyGlobalAnalysis>(M).print(OS); 962 return PreservedAnalyses::all(); 963 } 964 965 char StackSafetyGlobalInfoWrapperPass::ID = 0; 966 967 StackSafetyGlobalInfoWrapperPass::StackSafetyGlobalInfoWrapperPass() 968 : ModulePass(ID) { 969 initializeStackSafetyGlobalInfoWrapperPassPass( 970 *PassRegistry::getPassRegistry()); 971 } 972 973 StackSafetyGlobalInfoWrapperPass::~StackSafetyGlobalInfoWrapperPass() = default; 974 975 void StackSafetyGlobalInfoWrapperPass::print(raw_ostream &O, 976 const Module *M) const { 977 SSGI.print(O); 978 } 979 980 void StackSafetyGlobalInfoWrapperPass::getAnalysisUsage( 981 AnalysisUsage &AU) const { 982 AU.setPreservesAll(); 983 AU.addRequired<StackSafetyInfoWrapperPass>(); 984 } 985 986 bool StackSafetyGlobalInfoWrapperPass::runOnModule(Module &M) { 987 const ModuleSummaryIndex *ImportSummary = nullptr; 988 if (auto *IndexWrapperPass = 989 getAnalysisIfAvailable<ImmutableModuleSummaryIndexWrapperPass>()) 990 ImportSummary = IndexWrapperPass->getIndex(); 991 992 SSGI = {&M, 993 [this](Function &F) -> const StackSafetyInfo & { 994 return getAnalysis<StackSafetyInfoWrapperPass>(F).getResult(); 995 }, 996 ImportSummary}; 997 return false; 998 } 999 1000 bool llvm::needsParamAccessSummary(const Module &M) { 1001 if (StackSafetyRun) 1002 return true; 1003 for (auto &F : M.functions()) 1004 if (F.hasFnAttribute(Attribute::SanitizeMemTag)) 1005 return true; 1006 return false; 1007 } 1008 1009 void llvm::generateParamAccessSummary(ModuleSummaryIndex &Index) { 1010 if (!Index.hasParamAccess()) 1011 return; 1012 const ConstantRange FullSet(FunctionSummary::ParamAccess::RangeWidth, true); 1013 1014 auto CountParamAccesses = [&](auto &Stat) { 1015 if (!AreStatisticsEnabled()) 1016 return; 1017 for (auto &GVS : Index) 1018 for (auto &GV : GVS.second.SummaryList) 1019 if (FunctionSummary *FS = dyn_cast<FunctionSummary>(GV.get())) 1020 Stat += FS->paramAccesses().size(); 1021 }; 1022 1023 CountParamAccesses(NumCombinedParamAccessesBefore); 1024 1025 std::map<const FunctionSummary *, FunctionInfo<FunctionSummary>> Functions; 1026 1027 // Convert the ModuleSummaryIndex to a FunctionMap 1028 for (auto &GVS : Index) { 1029 for (auto &GV : GVS.second.SummaryList) { 1030 FunctionSummary *FS = dyn_cast<FunctionSummary>(GV.get()); 1031 if (!FS || FS->paramAccesses().empty()) 1032 continue; 1033 if (FS->isLive() && FS->isDSOLocal()) { 1034 FunctionInfo<FunctionSummary> FI; 1035 for (auto &PS : FS->paramAccesses()) { 1036 auto &US = 1037 FI.Params 1038 .emplace(PS.ParamNo, FunctionSummary::ParamAccess::RangeWidth) 1039 .first->second; 1040 US.Range = PS.Use; 1041 for (auto &Call : PS.Calls) { 1042 assert(!Call.Offsets.isFullSet()); 1043 FunctionSummary *S = 1044 findCalleeFunctionSummary(Call.Callee, FS->modulePath()); 1045 ++NumCombinedCalleeLookupTotal; 1046 if (!S) { 1047 ++NumCombinedCalleeLookupFailed; 1048 US.Range = FullSet; 1049 US.Calls.clear(); 1050 break; 1051 } 1052 US.Calls.emplace(CallInfo<FunctionSummary>(S, Call.ParamNo), 1053 Call.Offsets); 1054 } 1055 } 1056 Functions.emplace(FS, std::move(FI)); 1057 } 1058 // Reset data for all summaries. Alive and DSO local will be set back from 1059 // of data flow results below. Anything else will not be accessed 1060 // by ThinLTO backend, so we can save on bitcode size. 1061 FS->setParamAccesses({}); 1062 } 1063 } 1064 NumCombinedDataFlowNodes += Functions.size(); 1065 StackSafetyDataFlowAnalysis<FunctionSummary> SSDFA( 1066 FunctionSummary::ParamAccess::RangeWidth, std::move(Functions)); 1067 for (auto &KV : SSDFA.run()) { 1068 std::vector<FunctionSummary::ParamAccess> NewParams; 1069 NewParams.reserve(KV.second.Params.size()); 1070 for (auto &Param : KV.second.Params) { 1071 // It's not needed as FullSet is processed the same as a missing value. 1072 if (Param.second.Range.isFullSet()) 1073 continue; 1074 NewParams.emplace_back(); 1075 FunctionSummary::ParamAccess &New = NewParams.back(); 1076 New.ParamNo = Param.first; 1077 New.Use = Param.second.Range; // Only range is needed. 1078 } 1079 const_cast<FunctionSummary *>(KV.first)->setParamAccesses( 1080 std::move(NewParams)); 1081 } 1082 1083 CountParamAccesses(NumCombinedParamAccessesAfter); 1084 } 1085 1086 static const char LocalPassArg[] = "stack-safety-local"; 1087 static const char LocalPassName[] = "Stack Safety Local Analysis"; 1088 INITIALIZE_PASS_BEGIN(StackSafetyInfoWrapperPass, LocalPassArg, LocalPassName, 1089 false, true) 1090 INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass) 1091 INITIALIZE_PASS_END(StackSafetyInfoWrapperPass, LocalPassArg, LocalPassName, 1092 false, true) 1093 1094 static const char GlobalPassName[] = "Stack Safety Analysis"; 1095 INITIALIZE_PASS_BEGIN(StackSafetyGlobalInfoWrapperPass, DEBUG_TYPE, 1096 GlobalPassName, false, true) 1097 INITIALIZE_PASS_DEPENDENCY(StackSafetyInfoWrapperPass) 1098 INITIALIZE_PASS_DEPENDENCY(ImmutableModuleSummaryIndexWrapperPass) 1099 INITIALIZE_PASS_END(StackSafetyGlobalInfoWrapperPass, DEBUG_TYPE, 1100 GlobalPassName, false, true) 1101