1dff0c46cSDimitry Andric //===-- ModuleUtils.cpp - Functions to manipulate Modules -----------------===//
2dff0c46cSDimitry Andric //
3dff0c46cSDimitry Andric //                     The LLVM Compiler Infrastructure
4dff0c46cSDimitry Andric //
5dff0c46cSDimitry Andric // This file is distributed under the University of Illinois Open Source
6dff0c46cSDimitry Andric // License. See LICENSE.TXT for details.
7dff0c46cSDimitry Andric //
8dff0c46cSDimitry Andric //===----------------------------------------------------------------------===//
9dff0c46cSDimitry Andric //
10dff0c46cSDimitry Andric // This family of functions perform manipulations on Modules.
11dff0c46cSDimitry Andric //
12dff0c46cSDimitry Andric //===----------------------------------------------------------------------===//
13dff0c46cSDimitry Andric 
14dff0c46cSDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h"
15139f7f9bSDimitry Andric #include "llvm/IR/DerivedTypes.h"
16139f7f9bSDimitry Andric #include "llvm/IR/Function.h"
17139f7f9bSDimitry Andric #include "llvm/IR/IRBuilder.h"
18139f7f9bSDimitry Andric #include "llvm/IR/Module.h"
19ff0cc061SDimitry Andric #include "llvm/Support/raw_ostream.h"
20dff0c46cSDimitry Andric 
21dff0c46cSDimitry Andric using namespace llvm;
22dff0c46cSDimitry Andric 
appendToGlobalArray(const char * Array,Module & M,Function * F,int Priority,Constant * Data)233ca95b02SDimitry Andric static void appendToGlobalArray(const char *Array, Module &M, Function *F,
243ca95b02SDimitry Andric                                 int Priority, Constant *Data) {
25dff0c46cSDimitry Andric   IRBuilder<> IRB(M.getContext());
26dff0c46cSDimitry Andric   FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false);
27dff0c46cSDimitry Andric 
28dff0c46cSDimitry Andric   // Get the current set of static global constructors and add the new ctor
29dff0c46cSDimitry Andric   // to the list.
30dff0c46cSDimitry Andric   SmallVector<Constant *, 16> CurrentCtors;
3191bc56edSDimitry Andric   StructType *EltTy;
32dff0c46cSDimitry Andric   if (GlobalVariable *GVCtor = M.getNamedGlobal(Array)) {
333ca95b02SDimitry Andric     ArrayType *ATy = cast<ArrayType>(GVCtor->getValueType());
343ca95b02SDimitry Andric     StructType *OldEltTy = cast<StructType>(ATy->getElementType());
353ca95b02SDimitry Andric     // Upgrade a 2-field global array type to the new 3-field format if needed.
363ca95b02SDimitry Andric     if (Data && OldEltTy->getNumElements() < 3)
373ca95b02SDimitry Andric       EltTy = StructType::get(IRB.getInt32Ty(), PointerType::getUnqual(FnTy),
385517e702SDimitry Andric                               IRB.getInt8PtrTy());
393ca95b02SDimitry Andric     else
403ca95b02SDimitry Andric       EltTy = OldEltTy;
41dff0c46cSDimitry Andric     if (Constant *Init = GVCtor->getInitializer()) {
42dff0c46cSDimitry Andric       unsigned n = Init->getNumOperands();
43dff0c46cSDimitry Andric       CurrentCtors.reserve(n + 1);
443ca95b02SDimitry Andric       for (unsigned i = 0; i != n; ++i) {
453ca95b02SDimitry Andric         auto Ctor = cast<Constant>(Init->getOperand(i));
463ca95b02SDimitry Andric         if (EltTy != OldEltTy)
475517e702SDimitry Andric           Ctor =
485517e702SDimitry Andric               ConstantStruct::get(EltTy, Ctor->getAggregateElement((unsigned)0),
493ca95b02SDimitry Andric                                   Ctor->getAggregateElement(1),
505517e702SDimitry Andric                                   Constant::getNullValue(IRB.getInt8PtrTy()));
513ca95b02SDimitry Andric         CurrentCtors.push_back(Ctor);
523ca95b02SDimitry Andric       }
53dff0c46cSDimitry Andric     }
54dff0c46cSDimitry Andric     GVCtor->eraseFromParent();
5591bc56edSDimitry Andric   } else {
567d523365SDimitry Andric     // Use the new three-field struct if there isn't one already.
5791bc56edSDimitry Andric     EltTy = StructType::get(IRB.getInt32Ty(), PointerType::getUnqual(FnTy),
585517e702SDimitry Andric                             IRB.getInt8PtrTy());
59dff0c46cSDimitry Andric   }
60dff0c46cSDimitry Andric 
6191bc56edSDimitry Andric   // Build a 2 or 3 field global_ctor entry.  We don't take a comdat key.
6291bc56edSDimitry Andric   Constant *CSVals[3];
6391bc56edSDimitry Andric   CSVals[0] = IRB.getInt32(Priority);
6491bc56edSDimitry Andric   CSVals[1] = F;
6591bc56edSDimitry Andric   // FIXME: Drop support for the two element form in LLVM 4.0.
6691bc56edSDimitry Andric   if (EltTy->getNumElements() >= 3)
673ca95b02SDimitry Andric     CSVals[2] = Data ? ConstantExpr::getPointerCast(Data, IRB.getInt8PtrTy())
683ca95b02SDimitry Andric                      : Constant::getNullValue(IRB.getInt8PtrTy());
6991bc56edSDimitry Andric   Constant *RuntimeCtorInit =
7091bc56edSDimitry Andric       ConstantStruct::get(EltTy, makeArrayRef(CSVals, EltTy->getNumElements()));
7191bc56edSDimitry Andric 
72dff0c46cSDimitry Andric   CurrentCtors.push_back(RuntimeCtorInit);
73dff0c46cSDimitry Andric 
74dff0c46cSDimitry Andric   // Create a new initializer.
7591bc56edSDimitry Andric   ArrayType *AT = ArrayType::get(EltTy, CurrentCtors.size());
76dff0c46cSDimitry Andric   Constant *NewInit = ConstantArray::get(AT, CurrentCtors);
77dff0c46cSDimitry Andric 
78dff0c46cSDimitry Andric   // Create the new global variable and replace all uses of
79dff0c46cSDimitry Andric   // the old global variable with the new one.
80dff0c46cSDimitry Andric   (void)new GlobalVariable(M, NewInit->getType(), false,
81dff0c46cSDimitry Andric                            GlobalValue::AppendingLinkage, NewInit, Array);
82dff0c46cSDimitry Andric }
83dff0c46cSDimitry Andric 
appendToGlobalCtors(Module & M,Function * F,int Priority,Constant * Data)843ca95b02SDimitry Andric void llvm::appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data) {
853ca95b02SDimitry Andric   appendToGlobalArray("llvm.global_ctors", M, F, Priority, Data);
86dff0c46cSDimitry Andric }
87dff0c46cSDimitry Andric 
appendToGlobalDtors(Module & M,Function * F,int Priority,Constant * Data)883ca95b02SDimitry Andric void llvm::appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *Data) {
893ca95b02SDimitry Andric   appendToGlobalArray("llvm.global_dtors", M, F, Priority, Data);
90f785676fSDimitry Andric }
91ff0cc061SDimitry Andric 
appendToUsedList(Module & M,StringRef Name,ArrayRef<GlobalValue * > Values)92d88c1a5aSDimitry Andric static void appendToUsedList(Module &M, StringRef Name, ArrayRef<GlobalValue *> Values) {
93d88c1a5aSDimitry Andric   GlobalVariable *GV = M.getGlobalVariable(Name);
94d88c1a5aSDimitry Andric   SmallPtrSet<Constant *, 16> InitAsSet;
95d88c1a5aSDimitry Andric   SmallVector<Constant *, 16> Init;
96d88c1a5aSDimitry Andric   if (GV) {
97d88c1a5aSDimitry Andric     ConstantArray *CA = dyn_cast<ConstantArray>(GV->getInitializer());
98d88c1a5aSDimitry Andric     for (auto &Op : CA->operands()) {
99d88c1a5aSDimitry Andric       Constant *C = cast_or_null<Constant>(Op);
100d88c1a5aSDimitry Andric       if (InitAsSet.insert(C).second)
101d88c1a5aSDimitry Andric         Init.push_back(C);
102d88c1a5aSDimitry Andric     }
103d88c1a5aSDimitry Andric     GV->eraseFromParent();
104d88c1a5aSDimitry Andric   }
105d88c1a5aSDimitry Andric 
106d88c1a5aSDimitry Andric   Type *Int8PtrTy = llvm::Type::getInt8PtrTy(M.getContext());
107d88c1a5aSDimitry Andric   for (auto *V : Values) {
108d88c1a5aSDimitry Andric     Constant *C = ConstantExpr::getBitCast(V, Int8PtrTy);
109d88c1a5aSDimitry Andric     if (InitAsSet.insert(C).second)
110d88c1a5aSDimitry Andric       Init.push_back(C);
111d88c1a5aSDimitry Andric   }
112d88c1a5aSDimitry Andric 
113d88c1a5aSDimitry Andric   if (Init.empty())
114d88c1a5aSDimitry Andric     return;
115d88c1a5aSDimitry Andric 
116d88c1a5aSDimitry Andric   ArrayType *ATy = ArrayType::get(Int8PtrTy, Init.size());
117d88c1a5aSDimitry Andric   GV = new llvm::GlobalVariable(M, ATy, false, GlobalValue::AppendingLinkage,
118d88c1a5aSDimitry Andric                                 ConstantArray::get(ATy, Init), Name);
119d88c1a5aSDimitry Andric   GV->setSection("llvm.metadata");
120d88c1a5aSDimitry Andric }
121d88c1a5aSDimitry Andric 
appendToUsed(Module & M,ArrayRef<GlobalValue * > Values)122d88c1a5aSDimitry Andric void llvm::appendToUsed(Module &M, ArrayRef<GlobalValue *> Values) {
123d88c1a5aSDimitry Andric   appendToUsedList(M, "llvm.used", Values);
124d88c1a5aSDimitry Andric }
125d88c1a5aSDimitry Andric 
appendToCompilerUsed(Module & M,ArrayRef<GlobalValue * > Values)126d88c1a5aSDimitry Andric void llvm::appendToCompilerUsed(Module &M, ArrayRef<GlobalValue *> Values) {
127d88c1a5aSDimitry Andric   appendToUsedList(M, "llvm.compiler.used", Values);
128d88c1a5aSDimitry Andric }
129d88c1a5aSDimitry Andric 
checkSanitizerInterfaceFunction(Constant * FuncOrBitcast)130ff0cc061SDimitry Andric Function *llvm::checkSanitizerInterfaceFunction(Constant *FuncOrBitcast) {
131ff0cc061SDimitry Andric   if (isa<Function>(FuncOrBitcast))
132ff0cc061SDimitry Andric     return cast<Function>(FuncOrBitcast);
1337a7e6055SDimitry Andric   FuncOrBitcast->print(errs());
1347a7e6055SDimitry Andric   errs() << '\n';
135ff0cc061SDimitry Andric   std::string Err;
136ff0cc061SDimitry Andric   raw_string_ostream Stream(Err);
137ff0cc061SDimitry Andric   Stream << "Sanitizer interface function redefined: " << *FuncOrBitcast;
138ff0cc061SDimitry Andric   report_fatal_error(Err);
139ff0cc061SDimitry Andric }
140ff0cc061SDimitry Andric 
declareSanitizerInitFunction(Module & M,StringRef InitName,ArrayRef<Type * > InitArgTypes)1417a7e6055SDimitry Andric Function *llvm::declareSanitizerInitFunction(Module &M, StringRef InitName,
1427a7e6055SDimitry Andric                                              ArrayRef<Type *> InitArgTypes) {
1437a7e6055SDimitry Andric   assert(!InitName.empty() && "Expected init function name");
1447a7e6055SDimitry Andric   Function *F = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
1457a7e6055SDimitry Andric       InitName,
1467a7e6055SDimitry Andric       FunctionType::get(Type::getVoidTy(M.getContext()), InitArgTypes, false),
1477a7e6055SDimitry Andric       AttributeList()));
1487a7e6055SDimitry Andric   F->setLinkage(Function::ExternalLinkage);
1497a7e6055SDimitry Andric   return F;
1507a7e6055SDimitry Andric }
1517a7e6055SDimitry Andric 
createSanitizerCtorAndInitFunctions(Module & M,StringRef CtorName,StringRef InitName,ArrayRef<Type * > InitArgTypes,ArrayRef<Value * > InitArgs,StringRef VersionCheckName)152ff0cc061SDimitry Andric std::pair<Function *, Function *> llvm::createSanitizerCtorAndInitFunctions(
153ff0cc061SDimitry Andric     Module &M, StringRef CtorName, StringRef InitName,
1547d523365SDimitry Andric     ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs,
1557d523365SDimitry Andric     StringRef VersionCheckName) {
156ff0cc061SDimitry Andric   assert(!InitName.empty() && "Expected init function name");
157d88c1a5aSDimitry Andric   assert(InitArgs.size() == InitArgTypes.size() &&
158ff0cc061SDimitry Andric          "Sanitizer's init function expects different number of arguments");
1597a7e6055SDimitry Andric   Function *InitFunction =
1607a7e6055SDimitry Andric       declareSanitizerInitFunction(M, InitName, InitArgTypes);
161ff0cc061SDimitry Andric   Function *Ctor = Function::Create(
162ff0cc061SDimitry Andric       FunctionType::get(Type::getVoidTy(M.getContext()), false),
163ff0cc061SDimitry Andric       GlobalValue::InternalLinkage, CtorName, &M);
164ff0cc061SDimitry Andric   BasicBlock *CtorBB = BasicBlock::Create(M.getContext(), "", Ctor);
165ff0cc061SDimitry Andric   IRBuilder<> IRB(ReturnInst::Create(M.getContext(), CtorBB));
166ff0cc061SDimitry Andric   IRB.CreateCall(InitFunction, InitArgs);
1677d523365SDimitry Andric   if (!VersionCheckName.empty()) {
1687d523365SDimitry Andric     Function *VersionCheckFunction =
1697d523365SDimitry Andric         checkSanitizerInterfaceFunction(M.getOrInsertFunction(
1707d523365SDimitry Andric             VersionCheckName, FunctionType::get(IRB.getVoidTy(), {}, false),
1717a7e6055SDimitry Andric             AttributeList()));
1727d523365SDimitry Andric     IRB.CreateCall(VersionCheckFunction, {});
1737d523365SDimitry Andric   }
174ff0cc061SDimitry Andric   return std::make_pair(Ctor, InitFunction);
175ff0cc061SDimitry Andric }
176d88c1a5aSDimitry Andric 
177*b5893f02SDimitry Andric std::pair<Function *, Function *>
getOrCreateSanitizerCtorAndInitFunctions(Module & M,StringRef CtorName,StringRef InitName,ArrayRef<Type * > InitArgTypes,ArrayRef<Value * > InitArgs,function_ref<void (Function *,Function *)> FunctionsCreatedCallback,StringRef VersionCheckName)178*b5893f02SDimitry Andric llvm::getOrCreateSanitizerCtorAndInitFunctions(
179*b5893f02SDimitry Andric     Module &M, StringRef CtorName, StringRef InitName,
180*b5893f02SDimitry Andric     ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs,
181*b5893f02SDimitry Andric     function_ref<void(Function *, Function *)> FunctionsCreatedCallback,
182*b5893f02SDimitry Andric     StringRef VersionCheckName) {
183*b5893f02SDimitry Andric   assert(!CtorName.empty() && "Expected ctor function name");
184*b5893f02SDimitry Andric 
185*b5893f02SDimitry Andric   if (Function *Ctor = M.getFunction(CtorName))
186*b5893f02SDimitry Andric     // FIXME: Sink this logic into the module, similar to the handling of
187*b5893f02SDimitry Andric     // globals. This will make moving to a concurrent model much easier.
188*b5893f02SDimitry Andric     if (Ctor->arg_size() == 0 ||
189*b5893f02SDimitry Andric         Ctor->getReturnType() == Type::getVoidTy(M.getContext()))
190*b5893f02SDimitry Andric       return {Ctor, declareSanitizerInitFunction(M, InitName, InitArgTypes)};
191*b5893f02SDimitry Andric 
192*b5893f02SDimitry Andric   Function *Ctor, *InitFunction;
193*b5893f02SDimitry Andric   std::tie(Ctor, InitFunction) = llvm::createSanitizerCtorAndInitFunctions(
194*b5893f02SDimitry Andric       M, CtorName, InitName, InitArgTypes, InitArgs, VersionCheckName);
195*b5893f02SDimitry Andric   FunctionsCreatedCallback(Ctor, InitFunction);
196*b5893f02SDimitry Andric   return std::make_pair(Ctor, InitFunction);
197*b5893f02SDimitry Andric }
198*b5893f02SDimitry Andric 
getOrCreateInitFunction(Module & M,StringRef Name)199*b5893f02SDimitry Andric Function *llvm::getOrCreateInitFunction(Module &M, StringRef Name) {
200*b5893f02SDimitry Andric   assert(!Name.empty() && "Expected init function name");
201*b5893f02SDimitry Andric   if (Function *F = M.getFunction(Name)) {
202*b5893f02SDimitry Andric     if (F->arg_size() != 0 ||
203*b5893f02SDimitry Andric         F->getReturnType() != Type::getVoidTy(M.getContext())) {
204*b5893f02SDimitry Andric       std::string Err;
205*b5893f02SDimitry Andric       raw_string_ostream Stream(Err);
206*b5893f02SDimitry Andric       Stream << "Sanitizer interface function defined with wrong type: " << *F;
207*b5893f02SDimitry Andric       report_fatal_error(Err);
208*b5893f02SDimitry Andric     }
209*b5893f02SDimitry Andric     return F;
210*b5893f02SDimitry Andric   }
211*b5893f02SDimitry Andric   Function *F = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
212*b5893f02SDimitry Andric       Name, AttributeList(), Type::getVoidTy(M.getContext())));
213*b5893f02SDimitry Andric   F->setLinkage(Function::ExternalLinkage);
214*b5893f02SDimitry Andric 
215*b5893f02SDimitry Andric   appendToGlobalCtors(M, F, 0);
216*b5893f02SDimitry Andric 
217*b5893f02SDimitry Andric   return F;
218*b5893f02SDimitry Andric }
219*b5893f02SDimitry Andric 
filterDeadComdatFunctions(Module & M,SmallVectorImpl<Function * > & DeadComdatFunctions)220d88c1a5aSDimitry Andric void llvm::filterDeadComdatFunctions(
221d88c1a5aSDimitry Andric     Module &M, SmallVectorImpl<Function *> &DeadComdatFunctions) {
222d88c1a5aSDimitry Andric   // Build a map from the comdat to the number of entries in that comdat we
223d88c1a5aSDimitry Andric   // think are dead. If this fully covers the comdat group, then the entire
224d88c1a5aSDimitry Andric   // group is dead. If we find another entry in the comdat group though, we'll
225d88c1a5aSDimitry Andric   // have to preserve the whole group.
226d88c1a5aSDimitry Andric   SmallDenseMap<Comdat *, int, 16> ComdatEntriesCovered;
227d88c1a5aSDimitry Andric   for (Function *F : DeadComdatFunctions) {
228d88c1a5aSDimitry Andric     Comdat *C = F->getComdat();
229d88c1a5aSDimitry Andric     assert(C && "Expected all input GVs to be in a comdat!");
230d88c1a5aSDimitry Andric     ComdatEntriesCovered[C] += 1;
231d88c1a5aSDimitry Andric   }
232d88c1a5aSDimitry Andric 
233d88c1a5aSDimitry Andric   auto CheckComdat = [&](Comdat &C) {
234d88c1a5aSDimitry Andric     auto CI = ComdatEntriesCovered.find(&C);
235d88c1a5aSDimitry Andric     if (CI == ComdatEntriesCovered.end())
236d88c1a5aSDimitry Andric       return;
237d88c1a5aSDimitry Andric 
238d88c1a5aSDimitry Andric     // If this could have been covered by a dead entry, just subtract one to
239d88c1a5aSDimitry Andric     // account for it.
240d88c1a5aSDimitry Andric     if (CI->second > 0) {
241d88c1a5aSDimitry Andric       CI->second -= 1;
242d88c1a5aSDimitry Andric       return;
243d88c1a5aSDimitry Andric     }
244d88c1a5aSDimitry Andric 
245d88c1a5aSDimitry Andric     // If we've already accounted for all the entries that were dead, the
246d88c1a5aSDimitry Andric     // entire comdat is alive so remove it from the map.
247d88c1a5aSDimitry Andric     ComdatEntriesCovered.erase(CI);
248d88c1a5aSDimitry Andric   };
249d88c1a5aSDimitry Andric 
250d88c1a5aSDimitry Andric   auto CheckAllComdats = [&] {
251d88c1a5aSDimitry Andric     for (Function &F : M.functions())
252d88c1a5aSDimitry Andric       if (Comdat *C = F.getComdat()) {
253d88c1a5aSDimitry Andric         CheckComdat(*C);
254d88c1a5aSDimitry Andric         if (ComdatEntriesCovered.empty())
255d88c1a5aSDimitry Andric           return;
256d88c1a5aSDimitry Andric       }
257d88c1a5aSDimitry Andric     for (GlobalVariable &GV : M.globals())
258d88c1a5aSDimitry Andric       if (Comdat *C = GV.getComdat()) {
259d88c1a5aSDimitry Andric         CheckComdat(*C);
260d88c1a5aSDimitry Andric         if (ComdatEntriesCovered.empty())
261d88c1a5aSDimitry Andric           return;
262d88c1a5aSDimitry Andric       }
263d88c1a5aSDimitry Andric     for (GlobalAlias &GA : M.aliases())
264d88c1a5aSDimitry Andric       if (Comdat *C = GA.getComdat()) {
265d88c1a5aSDimitry Andric         CheckComdat(*C);
266d88c1a5aSDimitry Andric         if (ComdatEntriesCovered.empty())
267d88c1a5aSDimitry Andric           return;
268d88c1a5aSDimitry Andric       }
269d88c1a5aSDimitry Andric   };
270d88c1a5aSDimitry Andric   CheckAllComdats();
271d88c1a5aSDimitry Andric 
272d88c1a5aSDimitry Andric   if (ComdatEntriesCovered.empty()) {
273d88c1a5aSDimitry Andric     DeadComdatFunctions.clear();
274d88c1a5aSDimitry Andric     return;
275d88c1a5aSDimitry Andric   }
276d88c1a5aSDimitry Andric 
277d88c1a5aSDimitry Andric   // Remove the entries that were not covering.
278d88c1a5aSDimitry Andric   erase_if(DeadComdatFunctions, [&](GlobalValue *GV) {
279d88c1a5aSDimitry Andric     return ComdatEntriesCovered.find(GV->getComdat()) ==
280d88c1a5aSDimitry Andric            ComdatEntriesCovered.end();
281d88c1a5aSDimitry Andric   });
282d88c1a5aSDimitry Andric }
283f37b6182SDimitry Andric 
getUniqueModuleId(Module * M)284f37b6182SDimitry Andric std::string llvm::getUniqueModuleId(Module *M) {
285f37b6182SDimitry Andric   MD5 Md5;
286f37b6182SDimitry Andric   bool ExportsSymbols = false;
287f37b6182SDimitry Andric   auto AddGlobal = [&](GlobalValue &GV) {
288f37b6182SDimitry Andric     if (GV.isDeclaration() || GV.getName().startswith("llvm.") ||
2892cab237bSDimitry Andric         !GV.hasExternalLinkage() || GV.hasComdat())
290f37b6182SDimitry Andric       return;
291f37b6182SDimitry Andric     ExportsSymbols = true;
292f37b6182SDimitry Andric     Md5.update(GV.getName());
293f37b6182SDimitry Andric     Md5.update(ArrayRef<uint8_t>{0});
294f37b6182SDimitry Andric   };
295f37b6182SDimitry Andric 
296f37b6182SDimitry Andric   for (auto &F : *M)
297f37b6182SDimitry Andric     AddGlobal(F);
298f37b6182SDimitry Andric   for (auto &GV : M->globals())
299f37b6182SDimitry Andric     AddGlobal(GV);
300f37b6182SDimitry Andric   for (auto &GA : M->aliases())
301f37b6182SDimitry Andric     AddGlobal(GA);
302f37b6182SDimitry Andric   for (auto &IF : M->ifuncs())
303f37b6182SDimitry Andric     AddGlobal(IF);
304f37b6182SDimitry Andric 
305f37b6182SDimitry Andric   if (!ExportsSymbols)
306f37b6182SDimitry Andric     return "";
307f37b6182SDimitry Andric 
308f37b6182SDimitry Andric   MD5::MD5Result R;
309f37b6182SDimitry Andric   Md5.final(R);
310f37b6182SDimitry Andric 
311f37b6182SDimitry Andric   SmallString<32> Str;
312f37b6182SDimitry Andric   MD5::stringifyResult(R, Str);
313f37b6182SDimitry Andric   return ("$" + Str).str();
314f37b6182SDimitry Andric }
315