xref: /llvm-project-15.0.7/lld/ELF/Symbols.cpp (revision 2de44e65)
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   typedef typename ELFFile<ELFT>::uintX_t uintX_t;
36   assert(!isLazy() && !Other->isLazy());
37   std::pair<bool, bool> L(isDefined(), !isWeak());
38   std::pair<bool, bool> R(Other->isDefined(), !Other->isWeak());
39 
40   // Normalize
41   if (L > R)
42     return -Other->compare<ELFT>(this);
43 
44   Visibility = Other->Visibility =
45       getMinVisibility(Visibility, Other->Visibility);
46 
47   if (IsUsedInRegularObj || Other->IsUsedInRegularObj)
48     IsUsedInRegularObj = Other->IsUsedInRegularObj = true;
49 
50   if (L != R)
51     return -1;
52   if (!L.first || !L.second)
53     return 1;
54   if (isShared())
55     return -1;
56   if (Other->isShared())
57     return 1;
58   if (isCommon()) {
59     if (!Other->isCommon())
60       return -1;
61     auto *ThisC = cast<DefinedCommon>(this);
62     auto *OtherC = cast<DefinedCommon>(Other);
63     uintX_t Align = std::max(ThisC->MaxAlignment, OtherC->MaxAlignment);
64     if (ThisC->Size >= OtherC->Size) {
65       ThisC->MaxAlignment = Align;
66       return 1;
67     }
68     OtherC->MaxAlignment = Align;
69     return -1;
70   }
71   if (Other->isCommon())
72     return 1;
73   return 0;
74 }
75 
76 Defined::Defined(Kind K, StringRef Name, bool IsWeak, uint8_t Visibility,
77                  bool IsTls)
78     : SymbolBody(K, Name, IsWeak, Visibility, IsTls) {}
79 
80 Undefined::Undefined(SymbolBody::Kind K, StringRef N, bool IsWeak,
81                      uint8_t Visibility, bool IsTls)
82     : SymbolBody(K, N, IsWeak, Visibility, IsTls), CanKeepUndefined(false) {}
83 
84 Undefined::Undefined(StringRef N, bool IsWeak, uint8_t Visibility,
85                      bool CanKeepUndefined)
86     : Undefined(SymbolBody::UndefinedKind, N, IsWeak, Visibility,
87                 /*IsTls*/ false) {
88   this->CanKeepUndefined = CanKeepUndefined;
89 }
90 
91 template <typename ELFT>
92 UndefinedElf<ELFT>::UndefinedElf(StringRef N, const Elf_Sym &Sym)
93     : Undefined(SymbolBody::UndefinedElfKind, N,
94                 Sym.getBinding() == llvm::ELF::STB_WEAK, Sym.getVisibility(),
95                 Sym.getType() == llvm::ELF::STT_TLS),
96       Sym(Sym) {}
97 
98 template <typename ELFT>
99 DefinedSynthetic<ELFT>::DefinedSynthetic(StringRef N, uintX_t Value,
100                                          OutputSectionBase<ELFT> &Section)
101     : Defined(SymbolBody::DefinedSyntheticKind, N, false, STV_DEFAULT, false),
102       Value(Value), Section(Section) {}
103 
104 DefinedCommon::DefinedCommon(StringRef N, uint64_t Size, uint64_t Alignment,
105                              bool IsWeak, uint8_t Visibility)
106     : Defined(SymbolBody::DefinedCommonKind, N, IsWeak, Visibility, false) {
107   MaxAlignment = Alignment;
108   this->Size = Size;
109 }
110 
111 std::unique_ptr<InputFile> Lazy::getMember() {
112   MemoryBufferRef MBRef = File->getMember(&Sym);
113 
114   // getMember returns an empty buffer if the member was already
115   // read from the library.
116   if (MBRef.getBuffer().empty())
117     return std::unique_ptr<InputFile>(nullptr);
118   return createObjectFile(MBRef);
119 }
120 
121 template <class ELFT> static void doInitSymbols() {
122   ElfSym<ELFT>::End.setBinding(STB_GLOBAL);
123   ElfSym<ELFT>::IgnoredWeak.setBinding(STB_WEAK);
124   ElfSym<ELFT>::IgnoredWeak.setVisibility(STV_HIDDEN);
125   ElfSym<ELFT>::Ignored.setBinding(STB_GLOBAL);
126   ElfSym<ELFT>::Ignored.setVisibility(STV_HIDDEN);
127 }
128 
129 void elf2::initSymbols() {
130   doInitSymbols<ELF32LE>();
131   doInitSymbols<ELF32BE>();
132   doInitSymbols<ELF64LE>();
133   doInitSymbols<ELF64BE>();
134 }
135 
136 template int SymbolBody::compare<ELF32LE>(SymbolBody *Other);
137 template int SymbolBody::compare<ELF32BE>(SymbolBody *Other);
138 template int SymbolBody::compare<ELF64LE>(SymbolBody *Other);
139 template int SymbolBody::compare<ELF64BE>(SymbolBody *Other);
140 
141 template class elf2::UndefinedElf<ELF32LE>;
142 template class elf2::UndefinedElf<ELF32BE>;
143 template class elf2::UndefinedElf<ELF64LE>;
144 template class elf2::UndefinedElf<ELF64BE>;
145 
146 template class elf2::DefinedSynthetic<ELF32LE>;
147 template class elf2::DefinedSynthetic<ELF32BE>;
148 template class elf2::DefinedSynthetic<ELF64LE>;
149 template class elf2::DefinedSynthetic<ELF64BE>;
150