xref: /llvm-project-15.0.7/lld/ELF/Symbols.cpp (revision 45faf47e)
1 //===- Symbols.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 #include "Symbols.h"
11 #include "InputSection.h"
12 #include "Error.h"
13 #include "InputFiles.h"
14 
15 #include "llvm/ADT/STLExtras.h"
16 
17 using namespace llvm;
18 using namespace llvm::object;
19 using namespace llvm::ELF;
20 
21 using namespace lld;
22 using namespace lld::elf2;
23 
24 static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
25   if (VA == STV_DEFAULT)
26     return VB;
27   if (VB == STV_DEFAULT)
28     return VA;
29   return std::min(VA, VB);
30 }
31 
32 // Returns 1, 0 or -1 if this symbol should take precedence
33 // over the Other, tie or lose, respectively.
34 template <class ELFT> int SymbolBody::compare(SymbolBody *Other) {
35   assert(!isLazy() && !Other->isLazy());
36   std::pair<bool, bool> L(isDefined(), !isWeak());
37   std::pair<bool, bool> R(Other->isDefined(), !Other->isWeak());
38 
39   // Normalize
40   if (L > R)
41     return -Other->compare<ELFT>(this);
42 
43   Visibility = Other->Visibility =
44       getMinVisibility(Visibility, Other->Visibility);
45 
46   if (IsUsedInRegularObj || Other->IsUsedInRegularObj)
47     IsUsedInRegularObj = Other->IsUsedInRegularObj = true;
48 
49   if (L != R)
50     return -1;
51   if (!L.first || !L.second)
52     return 1;
53   if (isShared())
54     return -1;
55   if (Other->isShared())
56     return 1;
57   if (isCommon()) {
58     if (!Other->isCommon())
59       return -1;
60     auto *ThisC = cast<DefinedCommon<ELFT>>(this);
61     auto *OtherC = cast<DefinedCommon<ELFT>>(Other);
62     typename DefinedCommon<ELFT>::uintX_t MaxAlign =
63         std::max(ThisC->MaxAlignment, OtherC->MaxAlignment);
64     if (ThisC->Sym.st_size >= OtherC->Sym.st_size) {
65       ThisC->MaxAlignment = MaxAlign;
66       return 1;
67     }
68     OtherC->MaxAlignment = MaxAlign;
69     return -1;
70   }
71   if (Other->isCommon())
72     return 1;
73   return 0;
74 }
75 
76 std::unique_ptr<InputFile> Lazy::getMember() {
77   MemoryBufferRef MBRef = File->getMember(&Sym);
78 
79   // getMember returns an empty buffer if the member was already
80   // read from the library.
81   if (MBRef.getBuffer().empty())
82     return std::unique_ptr<InputFile>(nullptr);
83 
84   return createELFFile<ObjectFile>(MBRef);
85 }
86 
87 template <class ELFT> static void doInitSymbols() {
88   DefinedAbsolute<ELFT>::IgnoreUndef.setBinding(STB_WEAK);
89   DefinedAbsolute<ELFT>::IgnoreUndef.setVisibility(STV_HIDDEN);
90   Undefined<ELFT>::Optional.setVisibility(STV_HIDDEN);
91 }
92 
93 void lld::elf2::initSymbols() {
94   doInitSymbols<ELF32LE>();
95   doInitSymbols<ELF32BE>();
96   doInitSymbols<ELF64LE>();
97   doInitSymbols<ELF64BE>();
98 }
99 
100 template int SymbolBody::compare<ELF32LE>(SymbolBody *Other);
101 template int SymbolBody::compare<ELF32BE>(SymbolBody *Other);
102 template int SymbolBody::compare<ELF64LE>(SymbolBody *Other);
103 template int SymbolBody::compare<ELF64BE>(SymbolBody *Other);
104