summaryrefslogtreecommitdiffstats
path: root/lld/ELF/Symbols.cpp
blob: 2ea419ac2b58527c135843b3efd2d5dfc541b047 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//===- Symbols.cpp --------------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Symbols.h"
#include "InputSection.h"
#include "Error.h"
#include "InputFiles.h"

#include "llvm/ADT/STLExtras.h"

using namespace llvm;
using namespace llvm::object;
using namespace llvm::ELF;

using namespace lld;
using namespace lld::elf2;

static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
  if (VA == STV_DEFAULT)
    return VB;
  if (VB == STV_DEFAULT)
    return VA;
  return std::min(VA, VB);
}

// Returns 1, 0 or -1 if this symbol should take precedence
// over the Other, tie or lose, respectively.
template <class ELFT> int SymbolBody::compare(SymbolBody *Other) {
  assert(!isLazy() && !Other->isLazy());
  std::pair<bool, bool> L(isDefined(), !isWeak());
  std::pair<bool, bool> R(Other->isDefined(), !Other->isWeak());

  // Normalize
  if (L > R)
    return -Other->compare<ELFT>(this);

  uint8_t LV = getMostConstrainingVisibility();
  uint8_t RV = Other->getMostConstrainingVisibility();
  MostConstrainingVisibility = getMinVisibility(LV, RV);
  Other->MostConstrainingVisibility = MostConstrainingVisibility;

  IsUsedInRegularObj |= Other->IsUsedInRegularObj;
  Other->IsUsedInRegularObj |= IsUsedInRegularObj;

  if (L != R)
    return -1;
  if (!L.first || !L.second)
    return 1;
  if (isShared())
    return -1;
  if (Other->isShared())
    return 1;
  if (isCommon()) {
    if (!Other->isCommon())
      return -1;
    auto *ThisC = cast<DefinedCommon<ELFT>>(this);
    auto *OtherC = cast<DefinedCommon<ELFT>>(Other);
    typename DefinedCommon<ELFT>::uintX_t MaxAlign =
        std::max(ThisC->MaxAlignment, OtherC->MaxAlignment);
    if (ThisC->Sym.st_size >= OtherC->Sym.st_size) {
      ThisC->MaxAlignment = MaxAlign;
      return 1;
    }
    OtherC->MaxAlignment = MaxAlign;
    return -1;
  }
  if (Other->isCommon())
    return 1;
  return 0;
}

std::unique_ptr<InputFile> Lazy::getMember() {
  MemoryBufferRef MBRef = File->getMember(&Sym);

  // getMember returns an empty buffer if the member was already
  // read from the library.
  if (MBRef.getBuffer().empty())
    return std::unique_ptr<InputFile>(nullptr);

  return createELFFile<ObjectFile>(MBRef);
}

void lld::elf2::initSymbols() {
  Undefined<ELF32LE>::SyntheticOptional.setVisibility(STV_HIDDEN);
  Undefined<ELF32BE>::SyntheticOptional.setVisibility(STV_HIDDEN);
  Undefined<ELF64LE>::SyntheticOptional.setVisibility(STV_HIDDEN);
  Undefined<ELF64BE>::SyntheticOptional.setVisibility(STV_HIDDEN);
}

template int SymbolBody::compare<ELF32LE>(SymbolBody *Other);
template int SymbolBody::compare<ELF32BE>(SymbolBody *Other);
template int SymbolBody::compare<ELF64LE>(SymbolBody *Other);
template int SymbolBody::compare<ELF64BE>(SymbolBody *Other);
OpenPOWER on IntegriCloud