1 //===- SymbolTable.cpp ----------------------------------------------------===//
2 //
3 //                             The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Symbol table is a bag of all known symbols. We put all symbols of
11 // all input files to the symbol table. The symbol table is basically
12 // a hash table with the logic to resolve symbol name conflicts using
13 // the symbol types.
14 //
15 //===----------------------------------------------------------------------===//
16 
17 #include "SymbolTable.h"
18 #include "Config.h"
19 #include "Error.h"
20 #include "LinkerScript.h"
21 #include "SymbolListFile.h"
22 #include "Symbols.h"
23 #include "llvm/Bitcode/ReaderWriter.h"
24 #include "llvm/Support/StringSaver.h"
25 
26 using namespace llvm;
27 using namespace llvm::object;
28 using namespace llvm::ELF;
29 
30 using namespace lld;
31 using namespace lld::elf;
32 
33 // All input object files must be for the same architecture
34 // (e.g. it does not make sense to link x86 object files with
35 // MIPS object files.) This function checks for that error.
36 template <class ELFT> static bool isCompatible(InputFile *F) {
37   if (!isa<ELFFileBase<ELFT>>(F) && !isa<BitcodeFile>(F))
38     return true;
39   if (F->EKind == Config->EKind && F->EMachine == Config->EMachine)
40     return true;
41   StringRef A = F->getName();
42   StringRef B = Config->Emulation;
43   if (B.empty())
44     B = Config->FirstElf->getName();
45   error(A + " is incompatible with " + B);
46   return false;
47 }
48 
49 // Add symbols in File to the symbol table.
50 template <class ELFT>
51 void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
52   InputFile *FileP = File.get();
53   if (!isCompatible<ELFT>(FileP))
54     return;
55 
56   // .a file
57   if (auto *F = dyn_cast<ArchiveFile>(FileP)) {
58     ArchiveFiles.emplace_back(cast<ArchiveFile>(File.release()));
59     F->parse<ELFT>();
60     return;
61   }
62 
63   // Lazy object file
64   if (auto *F = dyn_cast<LazyObjectFile>(FileP)) {
65     LazyObjectFiles.emplace_back(cast<LazyObjectFile>(File.release()));
66     F->parse<ELFT>();
67     return;
68   }
69 
70   if (Config->Trace)
71     outs() << getFilename(FileP) << "\n";
72 
73   // .so file
74   if (auto *F = dyn_cast<SharedFile<ELFT>>(FileP)) {
75     // DSOs are uniquified not by filename but by soname.
76     F->parseSoName();
77     if (!SoNames.insert(F->getSoName()).second)
78       return;
79 
80     SharedFiles.emplace_back(cast<SharedFile<ELFT>>(File.release()));
81     F->parseRest();
82     return;
83   }
84 
85   // LLVM bitcode file
86   if (auto *F = dyn_cast<BitcodeFile>(FileP)) {
87     BitcodeFiles.emplace_back(cast<BitcodeFile>(File.release()));
88     F->parse<ELFT>(ComdatGroups);
89     return;
90   }
91 
92   // Regular object file
93   auto *F = cast<ObjectFile<ELFT>>(FileP);
94   ObjectFiles.emplace_back(cast<ObjectFile<ELFT>>(File.release()));
95   F->parse(ComdatGroups);
96 }
97 
98 // This function is where all the optimizations of link-time
99 // optimization happens. When LTO is in use, some input files are
100 // not in native object file format but in the LLVM bitcode format.
101 // This function compiles bitcode files into a few big native files
102 // using LLVM functions and replaces bitcode symbols with the results.
103 // Because all bitcode files that consist of a program are passed
104 // to the compiler at once, it can do whole-program optimization.
105 template <class ELFT> void SymbolTable<ELFT>::addCombinedLtoObject() {
106   if (BitcodeFiles.empty())
107     return;
108 
109   // Compile bitcode files.
110   Lto.reset(new BitcodeCompiler);
111   for (const std::unique_ptr<BitcodeFile> &F : BitcodeFiles)
112     Lto->add(*F);
113   std::vector<std::unique_ptr<InputFile>> IFs = Lto->compile();
114 
115   // Replace bitcode symbols.
116   for (auto &IF : IFs) {
117     ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(IF.release());
118 
119     DenseSet<StringRef> DummyGroups;
120     Obj->parse(DummyGroups);
121     ObjectFiles.emplace_back(Obj);
122   }
123 }
124 
125 template <class ELFT>
126 DefinedRegular<ELFT> *SymbolTable<ELFT>::addAbsolute(StringRef Name,
127                                                      uint8_t Visibility) {
128   return cast<DefinedRegular<ELFT>>(
129       addRegular(Name, STB_GLOBAL, Visibility)->body());
130 }
131 
132 // Add Name as an "ignored" symbol. An ignored symbol is a regular
133 // linker-synthesized defined symbol, but is only defined if needed.
134 template <class ELFT>
135 DefinedRegular<ELFT> *SymbolTable<ELFT>::addIgnored(StringRef Name,
136                                                     uint8_t Visibility) {
137   if (!find(Name))
138     return nullptr;
139   return addAbsolute(Name, Visibility);
140 }
141 
142 // Set a flag for --trace-symbol so that we can print out a log message
143 // if a new symbol with the same name is inserted into the symbol table.
144 template <class ELFT> void SymbolTable<ELFT>::trace(StringRef Name) {
145   Symtab.insert({Name, {-1, true}});
146 }
147 
148 // Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM.
149 // Used to implement --wrap.
150 template <class ELFT> void SymbolTable<ELFT>::wrap(StringRef Name) {
151   SymbolBody *B = find(Name);
152   if (!B)
153     return;
154   StringSaver Saver(Alloc);
155   Symbol *Sym = B->symbol();
156   Symbol *Real = addUndefined(Saver.save("__real_" + Name));
157   Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name));
158   // We rename symbols by replacing the old symbol's SymbolBody with the new
159   // symbol's SymbolBody. This causes all SymbolBody pointers referring to the
160   // old symbol to instead refer to the new symbol.
161   memcpy(Real->Body.buffer, Sym->Body.buffer, sizeof(Sym->Body));
162   memcpy(Sym->Body.buffer, Wrap->Body.buffer, sizeof(Wrap->Body));
163 }
164 
165 static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
166   if (VA == STV_DEFAULT)
167     return VB;
168   if (VB == STV_DEFAULT)
169     return VA;
170   return std::min(VA, VB);
171 }
172 
173 // Parses a symbol in the form of <name>@<version> or <name>@@<version>.
174 static std::pair<StringRef, uint16_t> getSymbolVersion(StringRef S) {
175   if (Config->VersionDefinitions.empty())
176     return {S, Config->DefaultSymbolVersion};
177 
178   size_t Pos = S.find('@');
179   if (Pos == 0 || Pos == StringRef::npos)
180     return {S, Config->DefaultSymbolVersion};
181 
182   StringRef Name = S.substr(0, Pos);
183   StringRef Verstr = S.substr(Pos + 1);
184   if (Verstr.empty())
185     return {S, Config->DefaultSymbolVersion};
186 
187   // '@@' in a symbol name means the default version.
188   // It is usually the most recent one.
189   bool IsDefault = (Verstr[0] == '@');
190   if (IsDefault)
191     Verstr = Verstr.substr(1);
192 
193   for (VersionDefinition &V : Config->VersionDefinitions) {
194     if (V.Name == Verstr)
195       return {Name, IsDefault ? V.Id : (V.Id | VERSYM_HIDDEN)};
196   }
197 
198   // It is an error if the specified version was not defined.
199   error("symbol " + S + " has undefined version " + Verstr);
200   return {S, Config->DefaultSymbolVersion};
201 }
202 
203 // Find an existing symbol or create and insert a new one.
204 template <class ELFT>
205 std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef &Name) {
206   auto P = Symtab.insert({Name, SymIndex((int)SymVector.size(), false)});
207   SymIndex &V = P.first->second;
208   bool IsNew = P.second;
209 
210   if (V.Idx == -1) {
211     IsNew = true;
212     V = SymIndex((int)SymVector.size(), true);
213   }
214 
215   Symbol *Sym;
216   if (IsNew) {
217     Sym = new (Alloc) Symbol;
218     Sym->Binding = STB_WEAK;
219     Sym->Visibility = STV_DEFAULT;
220     Sym->IsUsedInRegularObj = false;
221     Sym->HasUnnamedAddr = true;
222     Sym->ExportDynamic = false;
223     Sym->Traced = V.Traced;
224     std::tie(Name, Sym->VersionId) = getSymbolVersion(Name);
225     SymVector.push_back(Sym);
226   } else {
227     Sym = SymVector[V.Idx];
228   }
229   return {Sym, IsNew};
230 }
231 
232 // Find an existing symbol or create and insert a new one, then apply the given
233 // attributes.
234 template <class ELFT>
235 std::pair<Symbol *, bool>
236 SymbolTable<ELFT>::insert(StringRef &Name, uint8_t Type, uint8_t Visibility,
237                           bool CanOmitFromDynSym, bool HasUnnamedAddr,
238                           InputFile *File) {
239   bool IsUsedInRegularObj = !File || File->kind() == InputFile::ObjectKind;
240   Symbol *S;
241   bool WasInserted;
242   std::tie(S, WasInserted) = insert(Name);
243 
244   // Merge in the new unnamed_addr attribute.
245   S->HasUnnamedAddr &= HasUnnamedAddr;
246   // Merge in the new symbol's visibility.
247   S->Visibility = getMinVisibility(S->Visibility, Visibility);
248   if (!CanOmitFromDynSym && (Config->Shared || Config->ExportDynamic))
249     S->ExportDynamic = true;
250   if (IsUsedInRegularObj)
251     S->IsUsedInRegularObj = true;
252   if (!WasInserted && S->body()->Type != SymbolBody::UnknownType &&
253       ((Type == STT_TLS) != S->body()->isTls()))
254     error("TLS attribute mismatch for symbol: " +
255           conflictMsg(S->body(), File));
256 
257   return {S, WasInserted};
258 }
259 
260 // Construct a string in the form of "Sym in File1 and File2".
261 // Used to construct an error message.
262 template <typename ELFT>
263 std::string SymbolTable<ELFT>::conflictMsg(SymbolBody *Existing,
264                                            InputFile *NewFile) {
265   std::string Sym = Existing->getName();
266   if (Config->Demangle)
267     Sym = demangle(Sym);
268   return Sym + " in " + getFilename(Existing->File) + " and " +
269          getFilename(NewFile);
270 }
271 
272 template <class ELFT> Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name) {
273   return addUndefined(Name, STB_GLOBAL, STV_DEFAULT, /*Type*/ 0,
274                       /*CanOmitFromDynSym*/ false, /*HasUnnamedAddr*/ false,
275                       /*File*/ nullptr);
276 }
277 
278 template <class ELFT>
279 Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, uint8_t Binding,
280                                         uint8_t StOther, uint8_t Type,
281                                         bool CanOmitFromDynSym,
282                                         bool HasUnnamedAddr, InputFile *File) {
283   Symbol *S;
284   bool WasInserted;
285   std::tie(S, WasInserted) =
286       insert(Name, Type, StOther & 3, CanOmitFromDynSym, HasUnnamedAddr, File);
287   if (WasInserted) {
288     S->Binding = Binding;
289     replaceBody<Undefined>(S, Name, StOther, Type, File);
290     return S;
291   }
292   if (Binding != STB_WEAK) {
293     if (S->body()->isShared() || S->body()->isLazy())
294       S->Binding = Binding;
295     if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(S->body()))
296       SS->file()->IsUsed = true;
297   }
298   if (auto *L = dyn_cast<Lazy>(S->body())) {
299     // An undefined weak will not fetch archive members, but we have to remember
300     // its type. See also comment in addLazyArchive.
301     if (S->isWeak())
302       L->Type = Type;
303     else if (auto F = L->fetch())
304       addFile(std::move(F));
305   }
306   return S;
307 }
308 
309 // We have a new defined symbol with the specified binding. Return 1 if the new
310 // symbol should win, -1 if the new symbol should lose, or 0 if both symbols are
311 // strong defined symbols.
312 static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding) {
313   if (WasInserted)
314     return 1;
315   SymbolBody *Body = S->body();
316   if (Body->isLazy() || Body->isUndefined() || Body->isShared())
317     return 1;
318   if (Binding == STB_WEAK)
319     return -1;
320   if (S->isWeak())
321     return 1;
322   return 0;
323 }
324 
325 // We have a new non-common defined symbol with the specified binding. Return 1
326 // if the new symbol should win, -1 if the new symbol should lose, or 0 if there
327 // is a conflict. If the new symbol wins, also update the binding.
328 static int compareDefinedNonCommon(Symbol *S, bool WasInserted,
329                                    uint8_t Binding) {
330   if (int Cmp = compareDefined(S, WasInserted, Binding)) {
331     if (Cmp > 0)
332       S->Binding = Binding;
333     return Cmp;
334   }
335   if (isa<DefinedCommon>(S->body())) {
336     // Non-common symbols take precedence over common symbols.
337     if (Config->WarnCommon)
338       warning("common " + S->body()->getName() + " is overridden");
339     return 1;
340   }
341   return 0;
342 }
343 
344 template <class ELFT>
345 Symbol *SymbolTable<ELFT>::addCommon(StringRef N, uint64_t Size,
346                                      uint64_t Alignment, uint8_t Binding,
347                                      uint8_t StOther, uint8_t Type,
348                                      bool HasUnnamedAddr, InputFile *File) {
349   Symbol *S;
350   bool WasInserted;
351   std::tie(S, WasInserted) = insert(
352       N, Type, StOther & 3, /*CanOmitFromDynSym*/ false, HasUnnamedAddr, File);
353   int Cmp = compareDefined(S, WasInserted, Binding);
354   if (Cmp > 0) {
355     S->Binding = Binding;
356     replaceBody<DefinedCommon>(S, N, Size, Alignment, StOther, Type, File);
357   } else if (Cmp == 0) {
358     auto *C = dyn_cast<DefinedCommon>(S->body());
359     if (!C) {
360       // Non-common symbols take precedence over common symbols.
361       if (Config->WarnCommon)
362         warning("common " + S->body()->getName() + " is overridden");
363       return S;
364     }
365 
366     if (Config->WarnCommon)
367       warning("multiple common of " + S->body()->getName());
368 
369     Alignment = C->Alignment = std::max(C->Alignment, Alignment);
370     if (Size > C->Size)
371       replaceBody<DefinedCommon>(S, N, Size, Alignment, StOther, Type, File);
372   }
373   return S;
374 }
375 
376 template <class ELFT>
377 void SymbolTable<ELFT>::reportDuplicate(SymbolBody *Existing,
378                                         InputFile *NewFile) {
379   std::string Msg = "duplicate symbol: " + conflictMsg(Existing, NewFile);
380   if (Config->AllowMultipleDefinition)
381     warning(Msg);
382   else
383     error(Msg);
384 }
385 
386 template <typename ELFT>
387 Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, const Elf_Sym &Sym,
388                                       InputSectionBase<ELFT> *Section) {
389   Symbol *S;
390   bool WasInserted;
391   std::tie(S, WasInserted) =
392       insert(Name, Sym.getType(), Sym.getVisibility(),
393              /*CanOmitFromDynSym*/ false, /*HasUnnamedAddr*/ false,
394              Section ? Section->getFile() : nullptr);
395   int Cmp = compareDefinedNonCommon(S, WasInserted, Sym.getBinding());
396   if (Cmp > 0)
397     replaceBody<DefinedRegular<ELFT>>(S, Name, Sym, Section);
398   else if (Cmp == 0)
399     reportDuplicate(S->body(), Section->getFile());
400   return S;
401 }
402 
403 template <typename ELFT>
404 Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t Binding,
405                                       uint8_t StOther) {
406   Symbol *S;
407   bool WasInserted;
408   std::tie(S, WasInserted) =
409       insert(Name, STT_NOTYPE, StOther & 3, /*CanOmitFromDynSym*/ false,
410              /*HasUnnamedAddr*/ false, nullptr);
411   int Cmp = compareDefinedNonCommon(S, WasInserted, Binding);
412   if (Cmp > 0)
413     replaceBody<DefinedRegular<ELFT>>(S, Name, StOther);
414   else if (Cmp == 0)
415     reportDuplicate(S->body(), nullptr);
416   return S;
417 }
418 
419 template <typename ELFT>
420 Symbol *SymbolTable<ELFT>::addSynthetic(StringRef N,
421                                         OutputSectionBase<ELFT> *Section,
422                                         uintX_t Value, uint8_t StOther) {
423   Symbol *S;
424   bool WasInserted;
425   std::tie(S, WasInserted) = insert(N, STT_NOTYPE, /*Visibility*/ StOther & 0x3,
426                                     /*CanOmitFromDynSym*/ false,
427                                     /*HasUnnamedAddr*/ false, nullptr);
428   int Cmp = compareDefinedNonCommon(S, WasInserted, STB_GLOBAL);
429   if (Cmp > 0)
430     replaceBody<DefinedSynthetic<ELFT>>(S, N, Value, Section);
431   else if (Cmp == 0)
432     reportDuplicate(S->body(), nullptr);
433   return S;
434 }
435 
436 template <typename ELFT>
437 void SymbolTable<ELFT>::addShared(SharedFile<ELFT> *F, StringRef Name,
438                                   const Elf_Sym &Sym,
439                                   const typename ELFT::Verdef *Verdef) {
440   // DSO symbols do not affect visibility in the output, so we pass STV_DEFAULT
441   // as the visibility, which will leave the visibility in the symbol table
442   // unchanged.
443   Symbol *S;
444   bool WasInserted;
445   std::tie(S, WasInserted) =
446       insert(Name, Sym.getType(), STV_DEFAULT, /*CanOmitFromDynSym*/ true,
447              /*HasUnnamedAddr*/ false, F);
448   // Make sure we preempt DSO symbols with default visibility.
449   if (Sym.getVisibility() == STV_DEFAULT)
450     S->ExportDynamic = true;
451   if (WasInserted || isa<Undefined>(S->body())) {
452     replaceBody<SharedSymbol<ELFT>>(S, F, Name, Sym, Verdef);
453     if (!S->isWeak())
454       F->IsUsed = true;
455   }
456 }
457 
458 template <class ELFT>
459 Symbol *SymbolTable<ELFT>::addBitcode(StringRef Name, uint8_t Binding,
460                                       uint8_t StOther, uint8_t Type,
461                                       bool CanOmitFromDynSym,
462                                       bool HasUnnamedAddr, BitcodeFile *F) {
463   Symbol *S;
464   bool WasInserted;
465   std::tie(S, WasInserted) =
466       insert(Name, Type, StOther & 3, CanOmitFromDynSym, HasUnnamedAddr, F);
467   int Cmp = compareDefinedNonCommon(S, WasInserted, Binding);
468   if (Cmp > 0)
469     replaceBody<DefinedRegular<ELFT>>(S, Name, StOther, Type, F);
470   else if (Cmp == 0)
471     reportDuplicate(S->body(), F);
472   return S;
473 }
474 
475 template <class ELFT> SymbolBody *SymbolTable<ELFT>::find(StringRef Name) {
476   auto It = Symtab.find(Name);
477   if (It == Symtab.end())
478     return nullptr;
479   SymIndex V = It->second;
480   if (V.Idx == -1)
481     return nullptr;
482   return SymVector[V.Idx]->body();
483 }
484 
485 // Returns a list of defined symbols that match with a given regex.
486 template <class ELFT>
487 std::vector<SymbolBody *> SymbolTable<ELFT>::findAll(const Regex &Re) {
488   std::vector<SymbolBody *> Res;
489   for (Symbol *Sym : SymVector) {
490     SymbolBody *B = Sym->body();
491     StringRef Name = B->getName();
492     if (!B->isUndefined() && const_cast<Regex &>(Re).match(Name))
493       Res.push_back(B);
494   }
495   return Res;
496 }
497 
498 template <class ELFT>
499 void SymbolTable<ELFT>::addLazyArchive(ArchiveFile *F,
500                                        const object::Archive::Symbol Sym) {
501   Symbol *S;
502   bool WasInserted;
503   StringRef Name = Sym.getName();
504   std::tie(S, WasInserted) = insert(Name);
505   if (WasInserted) {
506     replaceBody<LazyArchive>(S, *F, Sym, SymbolBody::UnknownType);
507     return;
508   }
509   if (!S->body()->isUndefined())
510     return;
511 
512   // Weak undefined symbols should not fetch members from archives. If we were
513   // to keep old symbol we would not know that an archive member was available
514   // if a strong undefined symbol shows up afterwards in the link. If a strong
515   // undefined symbol never shows up, this lazy symbol will get to the end of
516   // the link and must be treated as the weak undefined one. We already marked
517   // this symbol as used when we added it to the symbol table, but we also need
518   // to preserve its type. FIXME: Move the Type field to Symbol.
519   if (S->isWeak()) {
520     replaceBody<LazyArchive>(S, *F, Sym, S->body()->Type);
521     return;
522   }
523   MemoryBufferRef MBRef = F->getMember(&Sym);
524   if (!MBRef.getBuffer().empty())
525     addFile(createObjectFile(MBRef, F->getName()));
526 }
527 
528 template <class ELFT>
529 void SymbolTable<ELFT>::addLazyObject(StringRef Name, LazyObjectFile &Obj) {
530   Symbol *S;
531   bool WasInserted;
532   std::tie(S, WasInserted) = insert(Name);
533   if (WasInserted) {
534     replaceBody<LazyObject>(S, Name, Obj, SymbolBody::UnknownType);
535     return;
536   }
537   if (!S->body()->isUndefined())
538     return;
539 
540   // See comment for addLazyArchive above.
541   if (S->isWeak()) {
542     replaceBody<LazyObject>(S, Name, Obj, S->body()->Type);
543   } else {
544     MemoryBufferRef MBRef = Obj.getBuffer();
545     if (!MBRef.getBuffer().empty())
546       addFile(createObjectFile(MBRef));
547   }
548 }
549 
550 // Process undefined (-u) flags by loading lazy symbols named by those flags.
551 template <class ELFT> void SymbolTable<ELFT>::scanUndefinedFlags() {
552   for (StringRef S : Config->Undefined)
553     if (auto *L = dyn_cast_or_null<Lazy>(find(S)))
554       if (std::unique_ptr<InputFile> File = L->fetch())
555         addFile(std::move(File));
556 }
557 
558 // This function takes care of the case in which shared libraries depend on
559 // the user program (not the other way, which is usual). Shared libraries
560 // may have undefined symbols, expecting that the user program provides
561 // the definitions for them. An example is BSD's __progname symbol.
562 // We need to put such symbols to the main program's .dynsym so that
563 // shared libraries can find them.
564 // Except this, we ignore undefined symbols in DSOs.
565 template <class ELFT> void SymbolTable<ELFT>::scanShlibUndefined() {
566   for (std::unique_ptr<SharedFile<ELFT>> &File : SharedFiles)
567     for (StringRef U : File->getUndefinedSymbols())
568       if (SymbolBody *Sym = find(U))
569         if (Sym->isDefined())
570           Sym->symbol()->ExportDynamic = true;
571 }
572 
573 // This function processes --export-dynamic-symbol and --dynamic-list.
574 template <class ELFT> void SymbolTable<ELFT>::scanDynamicList() {
575   for (StringRef S : Config->DynamicList)
576     if (SymbolBody *B = find(S))
577       B->symbol()->ExportDynamic = true;
578 }
579 
580 static void setVersionId(SymbolBody *Body, StringRef VersionName,
581                          StringRef Name, uint16_t Version) {
582   if (!Body || Body->isUndefined()) {
583     if (Config->NoUndefinedVersion)
584       error("version script assignment of " + VersionName + " to symbol " +
585             Name + " failed: symbol not defined");
586     return;
587   }
588 
589   Symbol *Sym = Body->symbol();
590   if (Sym->VersionId != Config->DefaultSymbolVersion)
591     warning("duplicate symbol " + Name + " in version script");
592   Sym->VersionId = Version;
593 }
594 
595 template <class ELFT>
596 std::map<std::string, SymbolBody *> SymbolTable<ELFT>::getDemangledSyms() {
597   std::map<std::string, SymbolBody *> Result;
598   for (Symbol *Sym : SymVector) {
599     SymbolBody *B = Sym->body();
600     Result[demangle(B->getName())] = B;
601   }
602   return Result;
603 }
604 
605 static bool hasExternCpp() {
606   for (VersionDefinition &V : Config->VersionDefinitions)
607     for (SymbolVersion Sym : V.Globals)
608       if (Sym.IsExternCpp)
609         return true;
610   return false;
611 }
612 
613 static SymbolBody *findDemangled(const std::map<std::string, SymbolBody *> &D,
614                                  StringRef Name) {
615   auto I = D.find(Name);
616   if (I != D.end())
617     return I->second;
618   return nullptr;
619 }
620 
621 static std::vector<SymbolBody *>
622 findAllDemangled(const std::map<std::string, SymbolBody *> &D,
623                  const Regex &Re) {
624   std::vector<SymbolBody *> Res;
625   for (auto &P : D) {
626     SymbolBody *Body = P.second;
627     if (!Body->isUndefined() && const_cast<Regex &>(Re).match(P.first))
628       Res.push_back(Body);
629   }
630   return Res;
631 }
632 
633 // This function processes version scripts by updating VersionId
634 // member of symbols.
635 template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() {
636   // If there's only one anonymous version definition in a version
637   // script file, the script does not actullay define any symbol version,
638   // but just specifies symbols visibilities. We assume that the script was
639   // in the form of { global: foo; bar; local *; }. So, local is default.
640   // Here, we make specified symbols global.
641   if (!Config->VersionScriptGlobals.empty()) {
642     std::vector<StringRef> Globs;
643     for (SymbolVersion &Sym : Config->VersionScriptGlobals) {
644       if (hasWildcard(Sym.Name)) {
645         Globs.push_back(Sym.Name);
646         continue;
647       }
648       if (SymbolBody *B = find(Sym.Name))
649         B->symbol()->VersionId = VER_NDX_GLOBAL;
650     }
651     if (Globs.empty())
652       return;
653     Regex Re = compileGlobPatterns(Globs);
654     std::vector<SymbolBody *> Syms = findAll(Re);
655     for (SymbolBody *B : Syms)
656       B->symbol()->VersionId = VER_NDX_GLOBAL;
657     return;
658   }
659 
660   if (Config->VersionDefinitions.empty())
661     return;
662 
663   // Now we have version definitions, so we need to set version ids to symbols.
664   // Each version definition has a glob pattern, and all symbols that match
665   // with the pattern get that version.
666 
667   // Users can use "extern C++ {}" directive to match against demangled
668   // C++ symbols. For example, you can write a pattern such as
669   // "llvm::*::foo(int, ?)". Obviously, there's no way to handle this
670   // other than trying to match a regexp against all demangled symbols.
671   // So, if "extern C++" feature is used, we demangle all known symbols.
672   std::map<std::string, SymbolBody *> Demangled;
673   if (hasExternCpp())
674     Demangled = getDemangledSyms();
675 
676   // First, we assign versions to exact matching symbols,
677   // i.e. version definitions not containing any glob meta-characters.
678   for (VersionDefinition &V : Config->VersionDefinitions) {
679     for (SymbolVersion Sym : V.Globals) {
680       if (Sym.HasWildcards)
681         continue;
682       StringRef N = Sym.Name;
683       SymbolBody *B = Sym.IsExternCpp ? findDemangled(Demangled, N) : find(N);
684       setVersionId(B, V.Name, N, V.Id);
685     }
686   }
687 
688   // Next, we assign versions to fuzzy matching symbols,
689   // i.e. version definitions containing glob meta-characters.
690   // Note that because the last match takes precedence over previous matches,
691   // we iterate over the definitions in the reverse order.
692   for (size_t I = Config->VersionDefinitions.size() - 1; I != (size_t)-1; --I) {
693     VersionDefinition &V = Config->VersionDefinitions[I];
694     for (SymbolVersion &Sym : V.Globals) {
695       if (!Sym.HasWildcards)
696         continue;
697       Regex Re = compileGlobPatterns({Sym.Name});
698       std::vector<SymbolBody *> Syms =
699           Sym.IsExternCpp ? findAllDemangled(Demangled, Re) : findAll(Re);
700 
701       // Exact matching takes precendence over fuzzy matching,
702       // so we set a version to a symbol only if no version has been assigned
703       // to the symbol. This behavior is compatible with GNU.
704       for (SymbolBody *B : Syms)
705         if (B->symbol()->VersionId == Config->DefaultSymbolVersion)
706           B->symbol()->VersionId = V.Id;
707     }
708   }
709 }
710 
711 template class elf::SymbolTable<ELF32LE>;
712 template class elf::SymbolTable<ELF32BE>;
713 template class elf::SymbolTable<ELF64LE>;
714 template class elf::SymbolTable<ELF64BE>;
715