Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Transforms/IPO/StripSymbols.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- StripSymbols.cpp - Strip symbols and debug info from a module ------===//
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
// The StripSymbols transformation implements code stripping. Specifically, it
10
// can delete:
11
//
12
//   * names for virtual registers
13
//   * symbols for internal globals and functions
14
//   * debug information
15
//
16
// Note that this transformation makes code much less readable, so it should
17
// only be used in situations where the 'strip' utility would be used, such as
18
// reducing code size or making it harder to reverse engineer code.
19
//
20
//===----------------------------------------------------------------------===//
21
22
#include "llvm/ADT/SmallPtrSet.h"
23
#include "llvm/Transforms/Utils/Local.h"
24
#include "llvm/IR/Constants.h"
25
#include "llvm/IR/DebugInfo.h"
26
#include "llvm/IR/DerivedTypes.h"
27
#include "llvm/IR/Instructions.h"
28
#include "llvm/IR/Module.h"
29
#include "llvm/IR/TypeFinder.h"
30
#include "llvm/IR/ValueSymbolTable.h"
31
#include "llvm/Pass.h"
32
#include "llvm/Transforms/IPO.h"
33
using namespace llvm;
34
35
namespace {
36
  class StripSymbols : public ModulePass {
37
    bool OnlyDebugInfo;
38
  public:
39
    static char ID; // Pass identification, replacement for typeid
40
    explicit StripSymbols(bool ODI = false)
41
26
      : ModulePass(ID), OnlyDebugInfo(ODI) {
42
26
        initializeStripSymbolsPass(*PassRegistry::getPassRegistry());
43
26
      }
44
45
    bool runOnModule(Module &M) override;
46
47
26
    void getAnalysisUsage(AnalysisUsage &AU) const override {
48
26
      AU.setPreservesAll();
49
26
    }
50
  };
51
52
  class StripNonDebugSymbols : public ModulePass {
53
  public:
54
    static char ID; // Pass identification, replacement for typeid
55
    explicit StripNonDebugSymbols()
56
0
      : ModulePass(ID) {
57
0
        initializeStripNonDebugSymbolsPass(*PassRegistry::getPassRegistry());
58
0
      }
59
60
    bool runOnModule(Module &M) override;
61
62
0
    void getAnalysisUsage(AnalysisUsage &AU) const override {
63
0
      AU.setPreservesAll();
64
0
    }
65
  };
66
67
  class StripDebugDeclare : public ModulePass {
68
  public:
69
    static char ID; // Pass identification, replacement for typeid
70
    explicit StripDebugDeclare()
71
0
      : ModulePass(ID) {
72
0
        initializeStripDebugDeclarePass(*PassRegistry::getPassRegistry());
73
0
      }
74
75
    bool runOnModule(Module &M) override;
76
77
0
    void getAnalysisUsage(AnalysisUsage &AU) const override {
78
0
      AU.setPreservesAll();
79
0
    }
80
  };
81
82
  class StripDeadDebugInfo : public ModulePass {
83
  public:
84
    static char ID; // Pass identification, replacement for typeid
85
    explicit StripDeadDebugInfo()
86
21
      : ModulePass(ID) {
87
21
        initializeStripDeadDebugInfoPass(*PassRegistry::getPassRegistry());
88
21
      }
89
90
    bool runOnModule(Module &M) override;
91
92
21
    void getAnalysisUsage(AnalysisUsage &AU) const override {
93
21
      AU.setPreservesAll();
94
21
    }
95
  };
96
}
97
98
char StripSymbols::ID = 0;
99
INITIALIZE_PASS(StripSymbols, "strip",
100
                "Strip all symbols from a module", false, false)
101
102
11
ModulePass *llvm::createStripSymbolsPass(bool OnlyDebugInfo) {
103
11
  return new StripSymbols(OnlyDebugInfo);
104
11
}
105
106
char StripNonDebugSymbols::ID = 0;
107
INITIALIZE_PASS(StripNonDebugSymbols, "strip-nondebug",
108
                "Strip all symbols, except dbg symbols, from a module",
109
                false, false)
110
111
0
ModulePass *llvm::createStripNonDebugSymbolsPass() {
112
0
  return new StripNonDebugSymbols();
113
0
}
114
115
char StripDebugDeclare::ID = 0;
116
INITIALIZE_PASS(StripDebugDeclare, "strip-debug-declare",
117
                "Strip all llvm.dbg.declare intrinsics", false, false)
118
119
0
ModulePass *llvm::createStripDebugDeclarePass() {
120
0
  return new StripDebugDeclare();
121
0
}
122
123
char StripDeadDebugInfo::ID = 0;
124
INITIALIZE_PASS(StripDeadDebugInfo, "strip-dead-debug-info",
125
                "Strip debug info for unused symbols", false, false)
126
127
19
ModulePass *llvm::createStripDeadDebugInfoPass() {
128
19
  return new StripDeadDebugInfo();
129
19
}
130
131
/// OnlyUsedBy - Return true if V is only used by Usr.
132
0
static bool OnlyUsedBy(Value *V, Value *Usr) {
133
0
  for (User *U : V->users())
134
0
    if (U != Usr)
135
0
      return false;
136
0
137
0
  return true;
138
0
}
139
140
0
static void RemoveDeadConstant(Constant *C) {
141
0
  assert(C->use_empty() && "Constant is not dead!");
142
0
  SmallPtrSet<Constant*, 4> Operands;
143
0
  for (Value *Op : C->operands())
144
0
    if (OnlyUsedBy(Op, C))
145
0
      Operands.insert(cast<Constant>(Op));
146
0
  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
147
0
    if (!GV->hasLocalLinkage()) return;   // Don't delete non-static globals.
148
0
    GV->eraseFromParent();
149
0
  }
150
0
  else if (!isa<Function>(C))
151
0
    if (isa<CompositeType>(C->getType()))
152
0
      C->destroyConstant();
153
0
154
0
  // If the constant referenced anything, see if we can delete it as well.
155
0
  for (Constant *O : Operands)
156
0
    RemoveDeadConstant(O);
157
0
}
158
159
// Strip the symbol table of its names.
160
//
161
44
static void StripSymtab(ValueSymbolTable &ST, bool PreserveDbgInfo) {
162
126
  for (ValueSymbolTable::iterator VI = ST.begin(), VE = ST.end(); VI != VE; ) {
163
82
    Value *V = VI->getValue();
164
82
    ++VI;
165
82
    if (!isa<GlobalValue>(V) || 
cast<GlobalValue>(V)->hasLocalLinkage()0
) {
166
82
      if (!PreserveDbgInfo || 
!V->getName().startswith("llvm.dbg")0
)
167
82
        // Set name to "", removing from symbol table!
168
82
        V->setName("");
169
82
    }
170
82
  }
171
44
}
172
173
// Strip any named types of their names.
174
15
static void StripTypeNames(Module &M, bool PreserveDbgInfo) {
175
15
  TypeFinder StructTypes;
176
15
  StructTypes.run(M, false);
177
15
178
20
  for (unsigned i = 0, e = StructTypes.size(); i != e; 
++i5
) {
179
5
    StructType *STy = StructTypes[i];
180
5
    if (STy->isLiteral() || STy->getName().empty()) 
continue0
;
181
5
182
5
    if (PreserveDbgInfo && 
STy->getName().startswith("llvm.dbg")0
)
183
0
      continue;
184
5
185
5
    STy->setName("");
186
5
  }
187
15
}
188
189
/// Find values that are marked as llvm.used.
190
static void findUsedValues(GlobalVariable *LLVMUsed,
191
30
                           SmallPtrSetImpl<const GlobalValue*> &UsedValues) {
192
30
  if (!LLVMUsed) 
return29
;
193
1
  UsedValues.insert(LLVMUsed);
194
1
195
1
  ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
196
1
197
3
  for (unsigned i = 0, e = Inits->getNumOperands(); i != e; 
++i2
)
198
2
    if (GlobalValue *GV =
199
2
          dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
200
2
      UsedValues.insert(GV);
201
1
}
202
203
/// StripSymbolNames - Strip symbol names.
204
15
static bool StripSymbolNames(Module &M, bool PreserveDbgInfo) {
205
15
206
15
  SmallPtrSet<const GlobalValue*, 8> llvmUsedValues;
207
15
  findUsedValues(M.getGlobalVariable("llvm.used"), llvmUsedValues);
208
15
  findUsedValues(M.getGlobalVariable("llvm.compiler.used"), llvmUsedValues);
209
15
210
15
  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
211
30
       I != E; 
++I15
) {
212
15
    if (I->hasLocalLinkage() && 
llvmUsedValues.count(&*I) == 01
)
213
0
      if (!PreserveDbgInfo || !I->getName().startswith("llvm.dbg"))
214
0
        I->setName("");     // Internal symbols can't participate in linkage
215
15
  }
216
15
217
44
  for (Function &I : M) {
218
44
    if (I.hasLocalLinkage() && 
llvmUsedValues.count(&I) == 01
)
219
0
      if (!PreserveDbgInfo || !I.getName().startswith("llvm.dbg"))
220
0
        I.setName(""); // Internal symbols can't participate in linkage
221
44
    if (auto *Symtab = I.getValueSymbolTable())
222
44
      StripSymtab(*Symtab, PreserveDbgInfo);
223
44
  }
224
15
225
15
  // Remove all names from types.
226
15
  StripTypeNames(M, PreserveDbgInfo);
227
15
228
15
  return true;
229
15
}
230
231
26
bool StripSymbols::runOnModule(Module &M) {
232
26
  if (skipModule(M))
233
0
    return false;
234
26
235
26
  bool Changed = false;
236
26
  Changed |= StripDebugInfo(M);
237
26
  if (!OnlyDebugInfo)
238
15
    Changed |= StripSymbolNames(M, false);
239
26
  return Changed;
240
26
}
241
242
0
bool StripNonDebugSymbols::runOnModule(Module &M) {
243
0
  if (skipModule(M))
244
0
    return false;
245
0
246
0
  return StripSymbolNames(M, true);
247
0
}
248
249
0
bool StripDebugDeclare::runOnModule(Module &M) {
250
0
  if (skipModule(M))
251
0
    return false;
252
0
253
0
  Function *Declare = M.getFunction("llvm.dbg.declare");
254
0
  std::vector<Constant*> DeadConstants;
255
0
256
0
  if (Declare) {
257
0
    while (!Declare->use_empty()) {
258
0
      CallInst *CI = cast<CallInst>(Declare->user_back());
259
0
      Value *Arg1 = CI->getArgOperand(0);
260
0
      Value *Arg2 = CI->getArgOperand(1);
261
0
      assert(CI->use_empty() && "llvm.dbg intrinsic should have void result");
262
0
      CI->eraseFromParent();
263
0
      if (Arg1->use_empty()) {
264
0
        if (Constant *C = dyn_cast<Constant>(Arg1))
265
0
          DeadConstants.push_back(C);
266
0
        else
267
0
          RecursivelyDeleteTriviallyDeadInstructions(Arg1);
268
0
      }
269
0
      if (Arg2->use_empty())
270
0
        if (Constant *C = dyn_cast<Constant>(Arg2))
271
0
          DeadConstants.push_back(C);
272
0
    }
273
0
    Declare->eraseFromParent();
274
0
  }
275
0
276
0
  while (!DeadConstants.empty()) {
277
0
    Constant *C = DeadConstants.back();
278
0
    DeadConstants.pop_back();
279
0
    if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
280
0
      if (GV->hasLocalLinkage())
281
0
        RemoveDeadConstant(GV);
282
0
    } else
283
0
      RemoveDeadConstant(C);
284
0
  }
285
0
286
0
  return true;
287
0
}
288
289
/// Remove any debug info for global variables/functions in the given module for
290
/// which said global variable/function no longer exists (i.e. is null).
291
///
292
/// Debugging information is encoded in llvm IR using metadata. This is designed
293
/// such a way that debug info for symbols preserved even if symbols are
294
/// optimized away by the optimizer. This special pass removes debug info for
295
/// such symbols.
296
21
bool StripDeadDebugInfo::runOnModule(Module &M) {
297
21
  if (skipModule(M))
298
0
    return false;
299
21
300
21
  bool Changed = false;
301
21
302
21
  LLVMContext &C = M.getContext();
303
21
304
21
  // Find all debug info in F. This is actually overkill in terms of what we
305
21
  // want to do, but we want to try and be as resilient as possible in the face
306
21
  // of potential debug info changes by using the formal interfaces given to us
307
21
  // as much as possible.
308
21
  DebugInfoFinder F;
309
21
  F.processModule(M);
310
21
311
21
  // For each compile unit, find the live set of global variables/functions and
312
21
  // replace the current list of potentially dead global variables/functions
313
21
  // with the live list.
314
21
  SmallVector<Metadata *, 64> LiveGlobalVariables;
315
21
  DenseSet<DIGlobalVariableExpression *> VisitedSet;
316
21
317
21
  std::set<DIGlobalVariableExpression *> LiveGVs;
318
21
  for (GlobalVariable &GV : M.globals()) {
319
8
    SmallVector<DIGlobalVariableExpression *, 1> GVEs;
320
8
    GV.getDebugInfo(GVEs);
321
8
    for (auto *GVE : GVEs)
322
1
      LiveGVs.insert(GVE);
323
8
  }
324
21
325
21
  std::set<DICompileUnit *> LiveCUs;
326
21
  // Any CU referenced from a subprogram is live.
327
21
  for (DISubprogram *SP : F.subprograms()) {
328
4
    if (SP->getUnit())
329
4
      LiveCUs.insert(SP->getUnit());
330
4
  }
331
21
332
21
  bool HasDeadCUs = false;
333
21
  for (DICompileUnit *DIC : F.compile_units()) {
334
5
    // Create our live global variable list.
335
5
    bool GlobalVariableChange = false;
336
5
    for (auto *DIG : DIC->getGlobalVariables()) {
337
4
      if (DIG->getExpression() && DIG->getExpression()->isConstant())
338
1
        LiveGVs.insert(DIG);
339
4
340
4
      // Make sure we only visit each global variable only once.
341
4
      if (!VisitedSet.insert(DIG).second)
342
0
        continue;
343
4
344
4
      // If a global variable references DIG, the global variable is live.
345
4
      if (LiveGVs.count(DIG))
346
2
        LiveGlobalVariables.push_back(DIG);
347
2
      else
348
2
        GlobalVariableChange = true;
349
4
    }
350
5
351
5
    if (!LiveGlobalVariables.empty())
352
2
      LiveCUs.insert(DIC);
353
3
    else if (!LiveCUs.count(DIC))
354
1
      HasDeadCUs = true;
355
5
356
5
    // If we found dead global variables, replace the current global
357
5
    // variable list with our new live global variable list.
358
5
    if (GlobalVariableChange) {
359
2
      DIC->replaceGlobalVariables(MDTuple::get(C, LiveGlobalVariables));
360
2
      Changed = true;
361
2
    }
362
5
363
5
    // Reset lists for the next iteration.
364
5
    LiveGlobalVariables.clear();
365
5
  }
366
21
367
21
  if (HasDeadCUs) {
368
1
    // Delete the old node and replace it with a new one
369
1
    NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu");
370
1
    NMD->clearOperands();
371
1
    if (!LiveCUs.empty()) {
372
1
      for (DICompileUnit *CU : LiveCUs)
373
3
        NMD->addOperand(CU);
374
1
    }
375
1
    Changed = true;
376
1
  }
377
21
378
21
  return Changed;
379
21
}