Coverage Report

Created: 2018-08-19 21:11

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/ELF/Symbols.cpp
Line
Count
Source (jump to first uncovered line)
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 "InputFiles.h"
12
#include "InputSection.h"
13
#include "OutputSections.h"
14
#include "SyntheticSections.h"
15
#include "Target.h"
16
#include "Writer.h"
17
#include "lld/Common/ErrorHandler.h"
18
#include "lld/Common/Strings.h"
19
#include "llvm/ADT/STLExtras.h"
20
#include "llvm/Support/Path.h"
21
#include <cstring>
22
23
using namespace llvm;
24
using namespace llvm::object;
25
using namespace llvm::ELF;
26
27
using namespace lld;
28
using namespace lld::elf;
29
30
Defined *ElfSym::Bss;
31
Defined *ElfSym::Etext1;
32
Defined *ElfSym::Etext2;
33
Defined *ElfSym::Edata1;
34
Defined *ElfSym::Edata2;
35
Defined *ElfSym::End1;
36
Defined *ElfSym::End2;
37
Defined *ElfSym::GlobalOffsetTable;
38
Defined *ElfSym::MipsGp;
39
Defined *ElfSym::MipsGpDisp;
40
Defined *ElfSym::MipsLocalGp;
41
Defined *ElfSym::RelaIpltEnd;
42
Defined *ElfSym::RISCVGlobalPointer;
43
44
100k
static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {
45
100k
  switch (Sym.kind()) {
46
100k
  case Symbol::DefinedKind: {
47
99.8k
    auto &D = cast<Defined>(Sym);
48
99.8k
    SectionBase *IS = D.Section;
49
99.8k
50
99.8k
    // According to the ELF spec reference to a local symbol from outside
51
99.8k
    // the group are not allowed. Unfortunately .eh_frame breaks that rule
52
99.8k
    // and must be treated specially. For now we just replace the symbol with
53
99.8k
    // 0.
54
99.8k
    if (IS == &InputSection::Discarded)
55
3
      return 0;
56
99.8k
57
99.8k
    // This is an absolute symbol.
58
99.8k
    if (!IS)
59
844
      return D.Value;
60
99.0k
61
99.0k
    IS = IS->Repl;
62
99.0k
63
99.0k
    uint64_t Offset = D.Value;
64
99.0k
65
99.0k
    // An object in an SHF_MERGE section might be referenced via a
66
99.0k
    // section symbol (as a hack for reducing the number of local
67
99.0k
    // symbols).
68
99.0k
    // Depending on the addend, the reference via a section symbol
69
99.0k
    // refers to a different object in the merge section.
70
99.0k
    // Since the objects in the merge section are not necessarily
71
99.0k
    // contiguous in the output, the addend can thus affect the final
72
99.0k
    // VA in a non-linear way.
73
99.0k
    // To make this work, we incorporate the addend into the section
74
99.0k
    // offset (and zero out the addend for later processing) so that
75
99.0k
    // we find the right object in the section.
76
99.0k
    if (D.isSection()) {
77
66.3k
      Offset += Addend;
78
66.3k
      Addend = 0;
79
66.3k
    }
80
99.0k
81
99.0k
    // In the typical case, this is actually very simple and boils
82
99.0k
    // down to adding together 3 numbers:
83
99.0k
    // 1. The address of the output section.
84
99.0k
    // 2. The offset of the input section within the output section.
85
99.0k
    // 3. The offset within the input section (this addition happens
86
99.0k
    //    inside InputSection::getOffset).
87
99.0k
    //
88
99.0k
    // If you understand the data structures involved with this next
89
99.0k
    // line (and how they get built), then you have a pretty good
90
99.0k
    // understanding of the linker.
91
99.0k
    uint64_t VA = IS->getVA(Offset);
92
99.0k
93
99.0k
    if (D.isTls() && 
!Config->Relocatable444
) {
94
443
      if (!Out::TlsPhdr)
95
0
        fatal(toString(D.File) +
96
0
              " has an STT_TLS symbol but doesn't have an SHF_TLS section");
97
443
      return VA - Out::TlsPhdr->p_vaddr;
98
443
    }
99
98.5k
    return VA;
100
98.5k
  }
101
98.5k
  case Symbol::SharedKind:
102
1.08k
  case Symbol::UndefinedKind:
103
1.08k
    return 0;
104
1.08k
  case Symbol::LazyArchiveKind:
105
0
  case Symbol::LazyObjectKind:
106
0
    llvm_unreachable("lazy symbol reached writer");
107
0
  }
108
0
  llvm_unreachable("invalid symbol kind");
109
0
}
110
111
100k
uint64_t Symbol::getVA(int64_t Addend) const {
112
100k
  uint64_t OutVA = getSymVA(*this, Addend);
113
100k
  return OutVA + Addend;
114
100k
}
115
116
182
uint64_t Symbol::getGotVA() const { return InX::Got->getVA() + getGotOffset(); }
117
118
389
uint64_t Symbol::getGotOffset() const {
119
389
  return GotIndex * Target->GotEntrySize;
120
389
}
121
122
336
uint64_t Symbol::getGotPltVA() const {
123
336
  if (this->IsInIgot)
124
34
    return InX::IgotPlt->getVA() + getGotPltOffset();
125
302
  return InX::GotPlt->getVA() + getGotPltOffset();
126
302
}
127
128
652
uint64_t Symbol::getGotPltOffset() const {
129
652
  if (IsInIgot)
130
66
    return PltIndex * Target->GotPltEntrySize;
131
586
  return (PltIndex + Target->GotPltHeaderEntriesNum) * Target->GotPltEntrySize;
132
586
}
133
134
576
uint64_t Symbol::getPltVA() const {
135
576
  if (this->IsInIplt)
136
54
    return InX::Iplt->getVA() + PltIndex * Target->PltEntrySize;
137
522
  return InX::Plt->getVA() + Target->getPltEntryOffset(PltIndex);
138
522
}
139
140
42
uint64_t Symbol::getPltOffset() const {
141
42
  assert(!this->IsInIplt);
142
42
  return Target->getPltEntryOffset(PltIndex);
143
42
}
144
145
84.8k
uint64_t Symbol::getSize() const {
146
84.8k
  if (const auto *DR = dyn_cast<Defined>(this))
147
84.8k
    return DR->Size;
148
51
  return cast<SharedSymbol>(this)->Size;
149
51
}
150
151
150k
OutputSection *Symbol::getOutputSection() const {
152
150k
  if (auto *S = dyn_cast<Defined>(this)) {
153
150k
    if (auto *Sec = S->Section)
154
150k
      return Sec->Repl->getOutputSection();
155
647
    return nullptr;
156
647
  }
157
3
  return nullptr;
158
3
}
159
160
// If a symbol name contains '@', the characters after that is
161
// a symbol version name. This function parses that.
162
16.0k
void Symbol::parseSymbolVersion() {
163
16.0k
  StringRef S = getName();
164
16.0k
  size_t Pos = S.find('@');
165
16.0k
  if (Pos == 0 || Pos == StringRef::npos)
166
15.9k
    return;
167
79
  StringRef Verstr = S.substr(Pos + 1);
168
79
  if (Verstr.empty())
169
1
    return;
170
78
171
78
  // Truncate the symbol name so that it doesn't include the version string.
172
78
  NameSize = Pos;
173
78
174
78
  // If this is not in this DSO, it is not a definition.
175
78
  if (!isDefined())
176
37
    return;
177
41
178
41
  // '@@' in a symbol name means the default version.
179
41
  // It is usually the most recent one.
180
41
  bool IsDefault = (Verstr[0] == '@');
181
41
  if (IsDefault)
182
20
    Verstr = Verstr.substr(1);
183
41
184
51
  for (VersionDefinition &Ver : Config->VersionDefinitions) {
185
51
    if (Ver.Name != Verstr)
186
19
      continue;
187
32
188
32
    if (IsDefault)
189
14
      VersionId = Ver.Id;
190
18
    else
191
18
      VersionId = Ver.Id | VERSYM_HIDDEN;
192
32
    return;
193
32
  }
194
41
195
41
  // It is an error if the specified version is not defined.
196
41
  // Usually version script is not provided when linking executable,
197
41
  // but we may still want to override a versioned symbol from DSO,
198
41
  // so we do not report error in this case. We also do not error
199
41
  // if the symbol has a local version as it won't be in the dynamic
200
41
  // symbol table.
201
41
  
if (9
Config->Shared9
&&
VersionId != VER_NDX_LOCAL5
)
202
3
    error(toString(File) + ": symbol " + S + " has undefined version " +
203
3
          Verstr);
204
9
}
205
206
32
InputFile *LazyArchive::fetch() { return cast<ArchiveFile>(File)->fetch(Sym); }
207
208
2
MemoryBufferRef LazyArchive::getMemberBuffer() {
209
2
  Archive::Child C = CHECK(
210
2
      Sym.getMember(), "could not get the member for symbol " + Sym.getName());
211
2
212
2
  return CHECK(C.getMemoryBufferRef(),
213
2
               "could not get the buffer for the member defining symbol " +
214
2
                   Sym.getName());
215
2
}
216
217
42.9k
uint8_t Symbol::computeBinding() const {
218
42.9k
  if (Config->Relocatable)
219
260
    return Binding;
220
42.6k
  if (Visibility != STV_DEFAULT && 
Visibility != STV_PROTECTED6.06k
)
221
5.89k
    return STB_LOCAL;
222
36.8k
  if (VersionId == VER_NDX_LOCAL && 
isDefined()429
)
223
336
    return STB_LOCAL;
224
36.4k
  if (!Config->GnuUnique && 
Binding == STB_GNU_UNIQUE10
)
225
5
    return STB_GLOBAL;
226
36.4k
  return Binding;
227
36.4k
}
228
229
21.4k
bool Symbol::includeInDynsym() const {
230
21.4k
  if (!Config->HasDynSymTab)
231
13.0k
    return false;
232
8.37k
  if (computeBinding() == STB_LOCAL)
233
3.06k
    return false;
234
5.30k
  if (!isDefined())
235
1.50k
    return true;
236
3.79k
  return ExportDynamic;
237
3.79k
}
238
239
// Print out a log message for --trace-symbol.
240
54
void elf::printTraceSymbol(Symbol *Sym) {
241
54
  std::string S;
242
54
  if (Sym->isUndefined())
243
18
    S = ": reference to ";
244
36
  else if (Sym->isLazy())
245
2
    S = ": lazy definition of ";
246
34
  else if (Sym->isShared())
247
9
    S = ": shared definition of ";
248
25
  else if (dyn_cast_or_null<BssSection>(cast<Defined>(Sym)->Section))
249
5
    S = ": common definition of ";
250
20
  else
251
20
    S = ": definition of ";
252
54
253
54
  message(toString(Sym->File) + S + Sym->getName());
254
54
}
255
256
150
void elf::warnUnorderableSymbol(const Symbol *Sym) {
257
150
  if (!Config->WarnSymbolOrdering)
258
7
    return;
259
143
260
143
  const InputFile *File = Sym->File;
261
143
  auto *D = dyn_cast<Defined>(Sym);
262
143
263
143
  auto Warn = [&](StringRef S) 
{ warn(toString(File) + S + Sym->getName()); }20
;
264
143
265
143
  if (Sym->isUndefined())
266
4
    Warn(": unable to order undefined symbol: ");
267
139
  else if (Sym->isShared())
268
2
    Warn(": unable to order shared symbol: ");
269
137
  else if (D && !D->Section)
270
7
    Warn(": unable to order absolute symbol: ");
271
130
  else if (D && isa<OutputSection>(D->Section))
272
2
    Warn(": unable to order synthetic symbol: ");
273
128
  else if (D && !D->Section->Repl->Live)
274
5
    Warn(": unable to order discarded symbol: ");
275
143
}
276
277
// Returns a symbol for an error message.
278
232
std::string lld::toString(const Symbol &B) {
279
232
  if (Config->Demangle)
280
224
    if (Optional<std::string> S = demangleItanium(B.getName()))
281
13
      return *S;
282
219
  return B.getName();
283
219
}