Symbols.cpp revision 293258
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
17using namespace llvm;
18using namespace llvm::object;
19using namespace llvm::ELF;
20
21using namespace lld;
22using namespace lld::elf2;
23
24static 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.
34template <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
76Defined::Defined(Kind K, StringRef Name, bool IsWeak, uint8_t Visibility,
77                 bool IsTls)
78    : SymbolBody(K, Name, IsWeak, Visibility, IsTls) {}
79
80Undefined::Undefined(SymbolBody::Kind K, StringRef N, bool IsWeak,
81                     uint8_t Visibility, bool IsTls)
82    : SymbolBody(K, N, IsWeak, Visibility, IsTls), CanKeepUndefined(false) {}
83
84Undefined::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
91template <typename ELFT>
92UndefinedElf<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
98template <typename ELFT>
99DefinedSynthetic<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
104DefinedCommon::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
111std::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
121template <class ELFT> static void doInitSymbols() {
122  ElfSym<ELFT>::End.setBinding(STB_GLOBAL);
123  ElfSym<ELFT>::IgnoreUndef.setBinding(STB_WEAK);
124  ElfSym<ELFT>::IgnoreUndef.setVisibility(STV_HIDDEN);
125}
126
127void lld::elf2::initSymbols() {
128  doInitSymbols<ELF32LE>();
129  doInitSymbols<ELF32BE>();
130  doInitSymbols<ELF64LE>();
131  doInitSymbols<ELF64BE>();
132}
133
134template int SymbolBody::compare<ELF32LE>(SymbolBody *Other);
135template int SymbolBody::compare<ELF32BE>(SymbolBody *Other);
136template int SymbolBody::compare<ELF64LE>(SymbolBody *Other);
137template int SymbolBody::compare<ELF64BE>(SymbolBody *Other);
138
139template class lld::elf2::UndefinedElf<ELF32LE>;
140template class lld::elf2::UndefinedElf<ELF32BE>;
141template class lld::elf2::UndefinedElf<ELF64LE>;
142template class lld::elf2::UndefinedElf<ELF64BE>;
143
144template class lld::elf2::DefinedSynthetic<ELF32LE>;
145template class lld::elf2::DefinedSynthetic<ELF32BE>;
146template class lld::elf2::DefinedSynthetic<ELF64LE>;
147template class lld::elf2::DefinedSynthetic<ELF64BE>;
148