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