• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- Debugify.cpp - Attach synthetic debug info to everything -----------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file This pass attaches synthetic debug info to everything. It can be used
11 /// to create targeted tests for debug info preservation.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #include "Debugify.h"
16 #include "llvm/ADT/BitVector.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/IR/BasicBlock.h"
19 #include "llvm/IR/Constants.h"
20 #include "llvm/IR/DIBuilder.h"
21 #include "llvm/IR/DebugInfo.h"
22 #include "llvm/IR/Function.h"
23 #include "llvm/IR/GlobalVariable.h"
24 #include "llvm/IR/InstIterator.h"
25 #include "llvm/IR/Instruction.h"
26 #include "llvm/IR/Instructions.h"
27 #include "llvm/IR/IntrinsicInst.h"
28 #include "llvm/IR/Module.h"
29 #include "llvm/IR/Type.h"
30 #include "llvm/Pass.h"
31 #include "llvm/Support/raw_ostream.h"
32 #include "llvm/Transforms/IPO.h"
33 
34 using namespace llvm;
35 
36 namespace {
37 
38 cl::opt<bool> Quiet("debugify-quiet",
39                     cl::desc("Suppress verbose debugify output"));
40 
dbg()41 raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
42 
getAllocSizeInBits(Module & M,Type * Ty)43 uint64_t getAllocSizeInBits(Module &M, Type *Ty) {
44   return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
45 }
46 
isFunctionSkipped(Function & F)47 bool isFunctionSkipped(Function &F) {
48   return F.isDeclaration() || !F.hasExactDefinition();
49 }
50 
51 /// Find the basic block's terminating instruction.
52 ///
53 /// Special care is needed to handle musttail and deopt calls, as these behave
54 /// like (but are in fact not) terminators.
findTerminatingInstruction(BasicBlock & BB)55 Instruction *findTerminatingInstruction(BasicBlock &BB) {
56   if (auto *I = BB.getTerminatingMustTailCall())
57     return I;
58   if (auto *I = BB.getTerminatingDeoptimizeCall())
59     return I;
60   return BB.getTerminator();
61 }
62 
applyDebugifyMetadata(Module & M,iterator_range<Module::iterator> Functions,StringRef Banner)63 bool applyDebugifyMetadata(Module &M,
64                            iterator_range<Module::iterator> Functions,
65                            StringRef Banner) {
66   // Skip modules with debug info.
67   if (M.getNamedMetadata("llvm.dbg.cu")) {
68     dbg() << Banner << "Skipping module with debug info\n";
69     return false;
70   }
71 
72   DIBuilder DIB(M);
73   LLVMContext &Ctx = M.getContext();
74 
75   // Get a DIType which corresponds to Ty.
76   DenseMap<uint64_t, DIType *> TypeCache;
77   auto getCachedDIType = [&](Type *Ty) -> DIType * {
78     uint64_t Size = getAllocSizeInBits(M, Ty);
79     DIType *&DTy = TypeCache[Size];
80     if (!DTy) {
81       std::string Name = "ty" + utostr(Size);
82       DTy = DIB.createBasicType(Name, Size, dwarf::DW_ATE_unsigned);
83     }
84     return DTy;
85   };
86 
87   unsigned NextLine = 1;
88   unsigned NextVar = 1;
89   auto File = DIB.createFile(M.getName(), "/");
90   auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C, File, "debugify",
91                                   /*isOptimized=*/true, "", 0);
92 
93   // Visit each instruction.
94   for (Function &F : Functions) {
95     if (isFunctionSkipped(F))
96       continue;
97 
98     auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
99     bool IsLocalToUnit = F.hasPrivateLinkage() || F.hasInternalLinkage();
100     auto SP =
101         DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine, SPType,
102                            IsLocalToUnit, /*isDefinition=*/true, NextLine,
103                            DINode::FlagZero, /*isOptimized=*/true);
104     F.setSubprogram(SP);
105     for (BasicBlock &BB : F) {
106       // Attach debug locations.
107       for (Instruction &I : BB)
108         I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP));
109 
110       // Inserting debug values into EH pads can break IR invariants.
111       if (BB.isEHPad())
112         continue;
113 
114       // Find the terminating instruction, after which no debug values are
115       // attached.
116       Instruction *LastInst = findTerminatingInstruction(BB);
117       assert(LastInst && "Expected basic block with a terminator");
118 
119       // Maintain an insertion point which can't be invalidated when updates
120       // are made.
121       BasicBlock::iterator InsertPt = BB.getFirstInsertionPt();
122       assert(InsertPt != BB.end() && "Expected to find an insertion point");
123       Instruction *InsertBefore = &*InsertPt;
124 
125       // Attach debug values.
126       for (Instruction *I = &*BB.begin(); I != LastInst; I = I->getNextNode()) {
127         // Skip void-valued instructions.
128         if (I->getType()->isVoidTy())
129           continue;
130 
131         // Phis and EH pads must be grouped at the beginning of the block.
132         // Only advance the insertion point when we finish visiting these.
133         if (!isa<PHINode>(I) && !I->isEHPad())
134           InsertBefore = I->getNextNode();
135 
136         std::string Name = utostr(NextVar++);
137         const DILocation *Loc = I->getDebugLoc().get();
138         auto LocalVar = DIB.createAutoVariable(SP, Name, File, Loc->getLine(),
139                                                getCachedDIType(I->getType()),
140                                                /*AlwaysPreserve=*/true);
141         DIB.insertDbgValueIntrinsic(I, LocalVar, DIB.createExpression(), Loc,
142                                     InsertBefore);
143       }
144     }
145     DIB.finalizeSubprogram(SP);
146   }
147   DIB.finalize();
148 
149   // Track the number of distinct lines and variables.
150   NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.debugify");
151   auto *IntTy = Type::getInt32Ty(Ctx);
152   auto addDebugifyOperand = [&](unsigned N) {
153     NMD->addOperand(MDNode::get(
154         Ctx, ValueAsMetadata::getConstant(ConstantInt::get(IntTy, N))));
155   };
156   addDebugifyOperand(NextLine - 1); // Original number of lines.
157   addDebugifyOperand(NextVar - 1);  // Original number of variables.
158   assert(NMD->getNumOperands() == 2 &&
159          "llvm.debugify should have exactly 2 operands!");
160 
161   // Claim that this synthetic debug info is valid.
162   StringRef DIVersionKey = "Debug Info Version";
163   if (!M.getModuleFlag(DIVersionKey))
164     M.addModuleFlag(Module::Warning, DIVersionKey, DEBUG_METADATA_VERSION);
165 
166   return true;
167 }
168 
169 /// Return true if a mis-sized diagnostic is issued for \p DVI.
diagnoseMisSizedDbgValue(Module & M,DbgValueInst * DVI)170 bool diagnoseMisSizedDbgValue(Module &M, DbgValueInst *DVI) {
171   // The size of a dbg.value's value operand should match the size of the
172   // variable it corresponds to.
173   //
174   // TODO: This, along with a check for non-null value operands, should be
175   // promoted to verifier failures.
176   Value *V = DVI->getValue();
177   if (!V)
178     return false;
179 
180   // For now, don't try to interpret anything more complicated than an empty
181   // DIExpression. Eventually we should try to handle OP_deref and fragments.
182   if (DVI->getExpression()->getNumElements())
183     return false;
184 
185   Type *Ty = V->getType();
186   uint64_t ValueOperandSize = getAllocSizeInBits(M, Ty);
187   Optional<uint64_t> DbgVarSize = DVI->getFragmentSizeInBits();
188   if (!ValueOperandSize || !DbgVarSize)
189     return false;
190 
191   bool HasBadSize = false;
192   if (Ty->isIntegerTy()) {
193     auto Signedness = DVI->getVariable()->getSignedness();
194     if (Signedness && *Signedness == DIBasicType::Signedness::Signed)
195       HasBadSize = ValueOperandSize < *DbgVarSize;
196   } else {
197     HasBadSize = ValueOperandSize != *DbgVarSize;
198   }
199 
200   if (HasBadSize) {
201     dbg() << "ERROR: dbg.value operand has size " << ValueOperandSize
202           << ", but its variable has size " << *DbgVarSize << ": ";
203     DVI->print(dbg());
204     dbg() << "\n";
205   }
206   return HasBadSize;
207 }
208 
checkDebugifyMetadata(Module & M,iterator_range<Module::iterator> Functions,StringRef NameOfWrappedPass,StringRef Banner,bool Strip,DebugifyStatsMap * StatsMap)209 bool checkDebugifyMetadata(Module &M,
210                            iterator_range<Module::iterator> Functions,
211                            StringRef NameOfWrappedPass, StringRef Banner,
212                            bool Strip, DebugifyStatsMap *StatsMap) {
213   // Skip modules without debugify metadata.
214   NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");
215   if (!NMD) {
216     dbg() << Banner << "Skipping module without debugify metadata\n";
217     return false;
218   }
219 
220   auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {
221     return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0))
222         ->getZExtValue();
223   };
224   assert(NMD->getNumOperands() == 2 &&
225          "llvm.debugify should have exactly 2 operands!");
226   unsigned OriginalNumLines = getDebugifyOperand(0);
227   unsigned OriginalNumVars = getDebugifyOperand(1);
228   bool HasErrors = false;
229 
230   // Track debug info loss statistics if able.
231   DebugifyStatistics *Stats = nullptr;
232   if (StatsMap && !NameOfWrappedPass.empty())
233     Stats = &StatsMap->operator[](NameOfWrappedPass);
234 
235   BitVector MissingLines{OriginalNumLines, true};
236   BitVector MissingVars{OriginalNumVars, true};
237   for (Function &F : Functions) {
238     if (isFunctionSkipped(F))
239       continue;
240 
241     // Find missing lines.
242     for (Instruction &I : instructions(F)) {
243       if (isa<DbgValueInst>(&I))
244         continue;
245 
246       auto DL = I.getDebugLoc();
247       if (DL && DL.getLine() != 0) {
248         MissingLines.reset(DL.getLine() - 1);
249         continue;
250       }
251 
252       if (!DL) {
253         dbg() << "ERROR: Instruction with empty DebugLoc in function ";
254         dbg() << F.getName() << " --";
255         I.print(dbg());
256         dbg() << "\n";
257         HasErrors = true;
258       }
259     }
260 
261     // Find missing variables and mis-sized debug values.
262     for (Instruction &I : instructions(F)) {
263       auto *DVI = dyn_cast<DbgValueInst>(&I);
264       if (!DVI)
265         continue;
266 
267       unsigned Var = ~0U;
268       (void)to_integer(DVI->getVariable()->getName(), Var, 10);
269       assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable");
270       bool HasBadSize = diagnoseMisSizedDbgValue(M, DVI);
271       if (!HasBadSize)
272         MissingVars.reset(Var - 1);
273       HasErrors |= HasBadSize;
274     }
275   }
276 
277   // Print the results.
278   for (unsigned Idx : MissingLines.set_bits())
279     dbg() << "WARNING: Missing line " << Idx + 1 << "\n";
280 
281   for (unsigned Idx : MissingVars.set_bits())
282     dbg() << "WARNING: Missing variable " << Idx + 1 << "\n";
283 
284   // Update DI loss statistics.
285   if (Stats) {
286     Stats->NumDbgLocsExpected += OriginalNumLines;
287     Stats->NumDbgLocsMissing += MissingLines.count();
288     Stats->NumDbgValuesExpected += OriginalNumVars;
289     Stats->NumDbgValuesMissing += MissingVars.count();
290   }
291 
292   dbg() << Banner;
293   if (!NameOfWrappedPass.empty())
294     dbg() << " [" << NameOfWrappedPass << "]";
295   dbg() << ": " << (HasErrors ? "FAIL" : "PASS") << '\n';
296 
297   // Strip the Debugify Metadata if required.
298   if (Strip) {
299     StripDebugInfo(M);
300     M.eraseNamedMetadata(NMD);
301     return true;
302   }
303 
304   return false;
305 }
306 
307 /// ModulePass for attaching synthetic debug info to everything, used with the
308 /// legacy module pass manager.
309 struct DebugifyModulePass : public ModulePass {
runOnModule__anon977b711e0111::DebugifyModulePass310   bool runOnModule(Module &M) override {
311     return applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
312   }
313 
DebugifyModulePass__anon977b711e0111::DebugifyModulePass314   DebugifyModulePass() : ModulePass(ID) {}
315 
getAnalysisUsage__anon977b711e0111::DebugifyModulePass316   void getAnalysisUsage(AnalysisUsage &AU) const override {
317     AU.setPreservesAll();
318   }
319 
320   static char ID; // Pass identification.
321 };
322 
323 /// FunctionPass for attaching synthetic debug info to instructions within a
324 /// single function, used with the legacy module pass manager.
325 struct DebugifyFunctionPass : public FunctionPass {
runOnFunction__anon977b711e0111::DebugifyFunctionPass326   bool runOnFunction(Function &F) override {
327     Module &M = *F.getParent();
328     auto FuncIt = F.getIterator();
329     return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
330                                  "FunctionDebugify: ");
331   }
332 
DebugifyFunctionPass__anon977b711e0111::DebugifyFunctionPass333   DebugifyFunctionPass() : FunctionPass(ID) {}
334 
getAnalysisUsage__anon977b711e0111::DebugifyFunctionPass335   void getAnalysisUsage(AnalysisUsage &AU) const override {
336     AU.setPreservesAll();
337   }
338 
339   static char ID; // Pass identification.
340 };
341 
342 /// ModulePass for checking debug info inserted by -debugify, used with the
343 /// legacy module pass manager.
344 struct CheckDebugifyModulePass : public ModulePass {
runOnModule__anon977b711e0111::CheckDebugifyModulePass345   bool runOnModule(Module &M) override {
346     return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
347                                  "CheckModuleDebugify", Strip, StatsMap);
348   }
349 
CheckDebugifyModulePass__anon977b711e0111::CheckDebugifyModulePass350   CheckDebugifyModulePass(bool Strip = false, StringRef NameOfWrappedPass = "",
351                           DebugifyStatsMap *StatsMap = nullptr)
352       : ModulePass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass),
353         StatsMap(StatsMap) {}
354 
getAnalysisUsage__anon977b711e0111::CheckDebugifyModulePass355   void getAnalysisUsage(AnalysisUsage &AU) const override {
356     AU.setPreservesAll();
357   }
358 
359   static char ID; // Pass identification.
360 
361 private:
362   bool Strip;
363   StringRef NameOfWrappedPass;
364   DebugifyStatsMap *StatsMap;
365 };
366 
367 /// FunctionPass for checking debug info inserted by -debugify-function, used
368 /// with the legacy module pass manager.
369 struct CheckDebugifyFunctionPass : public FunctionPass {
runOnFunction__anon977b711e0111::CheckDebugifyFunctionPass370   bool runOnFunction(Function &F) override {
371     Module &M = *F.getParent();
372     auto FuncIt = F.getIterator();
373     return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
374                                  NameOfWrappedPass, "CheckFunctionDebugify",
375                                  Strip, StatsMap);
376   }
377 
CheckDebugifyFunctionPass__anon977b711e0111::CheckDebugifyFunctionPass378   CheckDebugifyFunctionPass(bool Strip = false,
379                             StringRef NameOfWrappedPass = "",
380                             DebugifyStatsMap *StatsMap = nullptr)
381       : FunctionPass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass),
382         StatsMap(StatsMap) {}
383 
getAnalysisUsage__anon977b711e0111::CheckDebugifyFunctionPass384   void getAnalysisUsage(AnalysisUsage &AU) const override {
385     AU.setPreservesAll();
386   }
387 
388   static char ID; // Pass identification.
389 
390 private:
391   bool Strip;
392   StringRef NameOfWrappedPass;
393   DebugifyStatsMap *StatsMap;
394 };
395 
396 } // end anonymous namespace
397 
exportDebugifyStats(llvm::StringRef Path,const DebugifyStatsMap & Map)398 void exportDebugifyStats(llvm::StringRef Path, const DebugifyStatsMap &Map) {
399   std::error_code EC;
400   raw_fd_ostream OS{Path, EC};
401   if (EC) {
402     errs() << "Could not open file: " << EC.message() << ", " << Path << '\n';
403     return;
404   }
405 
406   OS << "Pass Name" << ',' << "# of missing debug values" << ','
407      << "# of missing locations" << ',' << "Missing/Expected value ratio" << ','
408      << "Missing/Expected location ratio" << '\n';
409   for (const auto &Entry : Map) {
410     StringRef Pass = Entry.first;
411     DebugifyStatistics Stats = Entry.second;
412 
413     OS << Pass << ',' << Stats.NumDbgValuesMissing << ','
414        << Stats.NumDbgLocsMissing << ',' << Stats.getMissingValueRatio() << ','
415        << Stats.getEmptyLocationRatio() << '\n';
416   }
417 }
418 
createDebugifyModulePass()419 ModulePass *createDebugifyModulePass() { return new DebugifyModulePass(); }
420 
createDebugifyFunctionPass()421 FunctionPass *createDebugifyFunctionPass() {
422   return new DebugifyFunctionPass();
423 }
424 
run(Module & M,ModuleAnalysisManager &)425 PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) {
426   applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
427   return PreservedAnalyses::all();
428 }
429 
createCheckDebugifyModulePass(bool Strip,StringRef NameOfWrappedPass,DebugifyStatsMap * StatsMap)430 ModulePass *createCheckDebugifyModulePass(bool Strip,
431                                           StringRef NameOfWrappedPass,
432                                           DebugifyStatsMap *StatsMap) {
433   return new CheckDebugifyModulePass(Strip, NameOfWrappedPass, StatsMap);
434 }
435 
createCheckDebugifyFunctionPass(bool Strip,StringRef NameOfWrappedPass,DebugifyStatsMap * StatsMap)436 FunctionPass *createCheckDebugifyFunctionPass(bool Strip,
437                                               StringRef NameOfWrappedPass,
438                                               DebugifyStatsMap *StatsMap) {
439   return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass, StatsMap);
440 }
441 
run(Module & M,ModuleAnalysisManager &)442 PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M,
443                                               ModuleAnalysisManager &) {
444   checkDebugifyMetadata(M, M.functions(), "", "CheckModuleDebugify", false,
445                         nullptr);
446   return PreservedAnalyses::all();
447 }
448 
449 char DebugifyModulePass::ID = 0;
450 static RegisterPass<DebugifyModulePass> DM("debugify",
451                                            "Attach debug info to everything");
452 
453 char CheckDebugifyModulePass::ID = 0;
454 static RegisterPass<CheckDebugifyModulePass>
455     CDM("check-debugify", "Check debug info from -debugify");
456 
457 char DebugifyFunctionPass::ID = 0;
458 static RegisterPass<DebugifyFunctionPass> DF("debugify-function",
459                                              "Attach debug info to a function");
460 
461 char CheckDebugifyFunctionPass::ID = 0;
462 static RegisterPass<CheckDebugifyFunctionPass>
463     CDF("check-debugify-function", "Check debug info from -debugify-function");
464