Coverage Report

Created: 2018-01-17 21:32

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