Bug Summary

File:tools/lld/ELF/Symbols.cpp
Warning:line 271, column 35
The result of the left shift is undefined due to shifting by '64', which is greater or equal to the width of type 'uint32_t'

Annotated Source Code

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 "Strings.h"
15#include "SyntheticSections.h"
16#include "Target.h"
17#include "Writer.h"
18
19#include "lld/Common/ErrorHandler.h"
20#include "llvm/ADT/STLExtras.h"
21#include "llvm/Support/Path.h"
22#include <cstring>
23
24using namespace llvm;
25using namespace llvm::object;
26using namespace llvm::ELF;
27
28using namespace lld;
29using namespace lld::elf;
30
31DefinedRegular *ElfSym::Bss;
32DefinedRegular *ElfSym::Etext1;
33DefinedRegular *ElfSym::Etext2;
34DefinedRegular *ElfSym::Edata1;
35DefinedRegular *ElfSym::Edata2;
36DefinedRegular *ElfSym::End1;
37DefinedRegular *ElfSym::End2;
38DefinedRegular *ElfSym::GlobalOffsetTable;
39DefinedRegular *ElfSym::MipsGp;
40DefinedRegular *ElfSym::MipsGpDisp;
41DefinedRegular *ElfSym::MipsLocalGp;
42
43static uint64_t getSymVA(const SymbolBody &Body, int64_t &Addend) {
44 switch (Body.kind()) {
45 case SymbolBody::DefinedRegularKind: {
46 auto &D = cast<DefinedRegular>(Body);
47 SectionBase *IS = D.Section;
48 if (auto *ISB = dyn_cast_or_null<InputSectionBase>(IS))
49 IS = ISB->Repl;
50
51 // According to the ELF spec reference to a local symbol from outside
52 // the group are not allowed. Unfortunately .eh_frame breaks that rule
53 // and must be treated specially. For now we just replace the symbol with
54 // 0.
55 if (IS == &InputSection::Discarded)
56 return 0;
57
58 // This is an absolute symbol.
59 if (!IS)
60 return D.Value;
61
62 uint64_t Offset = D.Value;
63
64 // An object in an SHF_MERGE section might be referenced via a
65 // section symbol (as a hack for reducing the number of local
66 // symbols).
67 // Depending on the addend, the reference via a section symbol
68 // refers to a different object in the merge section.
69 // Since the objects in the merge section are not necessarily
70 // contiguous in the output, the addend can thus affect the final
71 // VA in a non-linear way.
72 // To make this work, we incorporate the addend into the section
73 // offset (and zero out the addend for later processing) so that
74 // we find the right object in the section.
75 if (D.isSection()) {
76 Offset += Addend;
77 Addend = 0;
78 }
79
80 const OutputSection *OutSec = IS->getOutputSection();
81
82 // In the typical case, this is actually very simple and boils
83 // down to adding together 3 numbers:
84 // 1. The address of the output section.
85 // 2. The offset of the input section within the output section.
86 // 3. The offset within the input section (this addition happens
87 // inside InputSection::getOffset).
88 //
89 // If you understand the data structures involved with this next
90 // line (and how they get built), then you have a pretty good
91 // understanding of the linker.
92 uint64_t VA = (OutSec ? OutSec->Addr : 0) + IS->getOffset(Offset);
93
94 if (D.isTls() && !Config->Relocatable) {
95 if (!Out::TlsPhdr)
96 fatal(toString(D.getFile()) +
97 " has an STT_TLS symbol but doesn't have an SHF_TLS section");
98 return VA - Out::TlsPhdr->p_vaddr;
99 }
100 return VA;
101 }
102 case SymbolBody::DefinedCommonKind:
103 llvm_unreachable("common are converted to bss")::llvm::llvm_unreachable_internal("common are converted to bss"
, "/build/llvm-toolchain-snapshot-6.0~svn316840/tools/lld/ELF/Symbols.cpp"
, 103)
;
104 case SymbolBody::SharedKind: {
105 auto &SS = cast<SharedSymbol>(Body);
106 if (SS.CopyRelSec)
107 return SS.CopyRelSec->getParent()->Addr + SS.CopyRelSec->OutSecOff;
108 if (SS.NeedsPltAddr)
109 return Body.getPltVA();
110 return 0;
111 }
112 case SymbolBody::UndefinedKind:
113 return 0;
114 case SymbolBody::LazyArchiveKind:
115 case SymbolBody::LazyObjectKind:
116 assert(Body.symbol()->IsUsedInRegularObj && "lazy symbol reached writer")((Body.symbol()->IsUsedInRegularObj && "lazy symbol reached writer"
) ? static_cast<void> (0) : __assert_fail ("Body.symbol()->IsUsedInRegularObj && \"lazy symbol reached writer\""
, "/build/llvm-toolchain-snapshot-6.0~svn316840/tools/lld/ELF/Symbols.cpp"
, 116, __PRETTY_FUNCTION__))
;
117 return 0;
118 }
119 llvm_unreachable("invalid symbol kind")::llvm::llvm_unreachable_internal("invalid symbol kind", "/build/llvm-toolchain-snapshot-6.0~svn316840/tools/lld/ELF/Symbols.cpp"
, 119)
;
120}
121
122// Returns true if this is a weak undefined symbol.
123bool SymbolBody::isUndefWeak() const {
124 // See comment on Lazy in Symbols.h for the details.
125 return !isLocal() && symbol()->isWeak() && (isUndefined() || isLazy());
126}
127
128InputFile *SymbolBody::getFile() const {
129 if (isLocal()) {
130 const SectionBase *Sec = cast<DefinedRegular>(this)->Section;
131 // Local absolute symbols actually have a file, but that is not currently
132 // used. We could support that by having a mostly redundant InputFile in
133 // SymbolBody, or having a special absolute section if needed.
134 return Sec ? cast<InputSectionBase>(Sec)->File : nullptr;
135 }
136 return symbol()->File;
137}
138
139// Overwrites all attributes with Other's so that this symbol becomes
140// an alias to Other. This is useful for handling some options such as
141// --wrap.
142void SymbolBody::copyFrom(SymbolBody *Other) {
143 memcpy(symbol()->Body.buffer, Other->symbol()->Body.buffer,
144 sizeof(Symbol::Body));
145}
146
147uint64_t SymbolBody::getVA(int64_t Addend) const {
148 uint64_t OutVA = getSymVA(*this, Addend);
149 return OutVA + Addend;
150}
151
152uint64_t SymbolBody::getGotVA() const {
153 return InX::Got->getVA() + getGotOffset();
154}
155
156uint64_t SymbolBody::getGotOffset() const {
157 return GotIndex * Target->GotEntrySize;
158}
159
160uint64_t SymbolBody::getGotPltVA() const {
161 if (this->IsInIgot)
162 return InX::IgotPlt->getVA() + getGotPltOffset();
163 return InX::GotPlt->getVA() + getGotPltOffset();
164}
165
166uint64_t SymbolBody::getGotPltOffset() const {
167 return GotPltIndex * Target->GotPltEntrySize;
168}
169
170uint64_t SymbolBody::getPltVA() const {
171 if (this->IsInIplt)
172 return InX::Iplt->getVA() + PltIndex * Target->PltEntrySize;
173 return InX::Plt->getVA() + Target->PltHeaderSize +
174 PltIndex * Target->PltEntrySize;
175}
176
177template <class ELFT> typename ELFT::uint SymbolBody::getSize() const {
178 if (const auto *C = dyn_cast<DefinedCommon>(this))
179 return C->Size;
180 if (const auto *DR = dyn_cast<DefinedRegular>(this))
181 return DR->Size;
182 if (const auto *S = dyn_cast<SharedSymbol>(this))
183 return S->getSize<ELFT>();
184 return 0;
185}
186
187OutputSection *SymbolBody::getOutputSection() const {
188 if (auto *S = dyn_cast<DefinedRegular>(this)) {
189 if (S->Section)
190 return S->Section->getOutputSection();
191 return nullptr;
192 }
193
194 if (auto *S = dyn_cast<SharedSymbol>(this)) {
195 if (S->CopyRelSec)
196 return S->CopyRelSec->getParent();
197 return nullptr;
198 }
199
200 if (auto *S = dyn_cast<DefinedCommon>(this)) {
201 if (Config->DefineCommon)
202 return S->Section->getParent();
203 return nullptr;
204 }
205
206 return nullptr;
207}
208
209// If a symbol name contains '@', the characters after that is
210// a symbol version name. This function parses that.
211void SymbolBody::parseSymbolVersion() {
212 StringRef S = getName();
213 size_t Pos = S.find('@');
214 if (Pos == 0 || Pos == StringRef::npos)
215 return;
216 StringRef Verstr = S.substr(Pos + 1);
217 if (Verstr.empty())
218 return;
219
220 // Truncate the symbol name so that it doesn't include the version string.
221 Name = {S.data(), Pos};
222
223 // If this is not in this DSO, it is not a definition.
224 if (!isInCurrentOutput())
225 return;
226
227 // '@@' in a symbol name means the default version.
228 // It is usually the most recent one.
229 bool IsDefault = (Verstr[0] == '@');
230 if (IsDefault)
231 Verstr = Verstr.substr(1);
232
233 for (VersionDefinition &Ver : Config->VersionDefinitions) {
234 if (Ver.Name != Verstr)
235 continue;
236
237 if (IsDefault)
238 symbol()->VersionId = Ver.Id;
239 else
240 symbol()->VersionId = Ver.Id | VERSYM_HIDDEN;
241 return;
242 }
243
244 // It is an error if the specified version is not defined.
245 // Usually version script is not provided when linking executable,
246 // but we may still want to override a versioned symbol from DSO,
247 // so we do not report error in this case.
248 if (Config->Shared)
249 error(toString(getFile()) + ": symbol " + S + " has undefined version " +
250 Verstr);
251}
252
253template <class ELFT> bool DefinedRegular::isMipsPIC() const {
254 typedef typename ELFT::Ehdr Elf_Ehdr;
255 if (!Section || !isFunc())
256 return false;
257
258 auto *Sec = cast<InputSectionBase>(Section);
259 const Elf_Ehdr *Hdr = Sec->template getFile<ELFT>()->getObj().getHeader();
260 return (this->StOther & STO_MIPS_MIPS16) == STO_MIPS_PIC ||
261 (Hdr->e_flags & EF_MIPS_PIC);
262}
263
264// If a shared symbol is referred via a copy relocation, its alignment
265// becomes part of the ABI. This function returns a symbol alignment.
266// Because symbols don't have alignment attributes, we need to infer that.
267template <class ELFT> uint32_t SharedSymbol::getAlignment() const {
268 SharedFile<ELFT> *File = getFile<ELFT>();
269 uint32_t SecAlign = File->getSection(getSym<ELFT>())->sh_addralign;
270 uint64_t SymValue = getSym<ELFT>().st_value;
271 uint32_t SymAlign = uint32_t(1) << countTrailingZeros(SymValue);
The result of the left shift is undefined due to shifting by '64', which is greater or equal to the width of type 'uint32_t'
272 return std::min(SecAlign, SymAlign);
273}
274
275InputFile *Lazy::fetch() {
276 if (auto *S = dyn_cast<LazyArchive>(this))
277 return S->fetch();
278 return cast<LazyObject>(this)->fetch();
279}
280
281ArchiveFile *LazyArchive::getFile() {
282 return cast<ArchiveFile>(SymbolBody::getFile());
283}
284
285InputFile *LazyArchive::fetch() {
286 std::pair<MemoryBufferRef, uint64_t> MBInfo = getFile()->getMember(&Sym);
287
288 // getMember returns an empty buffer if the member was already
289 // read from the library.
290 if (MBInfo.first.getBuffer().empty())
291 return nullptr;
292 return createObjectFile(MBInfo.first, getFile()->getName(), MBInfo.second);
293}
294
295LazyObjFile *LazyObject::getFile() {
296 return cast<LazyObjFile>(SymbolBody::getFile());
297}
298
299InputFile *LazyObject::fetch() { return getFile()->fetch(); }
300
301uint8_t Symbol::computeBinding() const {
302 if (Config->Relocatable)
303 return Binding;
304 if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
305 return STB_LOCAL;
306 if (VersionId == VER_NDX_LOCAL && body()->isInCurrentOutput())
307 return STB_LOCAL;
308 if (Config->NoGnuUnique && Binding == STB_GNU_UNIQUE)
309 return STB_GLOBAL;
310 return Binding;
311}
312
313bool Symbol::includeInDynsym() const {
314 if (!Config->HasDynSymTab)
315 return false;
316 if (computeBinding() == STB_LOCAL)
317 return false;
318 if (!body()->isInCurrentOutput())
319 return true;
320 return ExportDynamic;
321}
322
323// Print out a log message for --trace-symbol.
324void elf::printTraceSymbol(Symbol *Sym) {
325 SymbolBody *B = Sym->body();
326 std::string S;
327 if (B->isUndefined())
328 S = ": reference to ";
329 else if (B->isCommon())
330 S = ": common definition of ";
331 else if (B->isLazy())
332 S = ": lazy definition of ";
333 else if (B->isShared())
334 S = ": shared definition of ";
335 else
336 S = ": definition of ";
337
338 message(toString(Sym->File) + S + B->getName());
339}
340
341// Returns a symbol for an error message.
342std::string lld::toString(const SymbolBody &B) {
343 if (Config->Demangle)
344 if (Optional<std::string> S = demangle(B.getName()))
345 return *S;
346 return B.getName();
347}
348
349template uint32_t SymbolBody::template getSize<ELF32LE>() const;
350template uint32_t SymbolBody::template getSize<ELF32BE>() const;
351template uint64_t SymbolBody::template getSize<ELF64LE>() const;
352template uint64_t SymbolBody::template getSize<ELF64BE>() const;
353
354template bool DefinedRegular::template isMipsPIC<ELF32LE>() const;
355template bool DefinedRegular::template isMipsPIC<ELF32BE>() const;
356template bool DefinedRegular::template isMipsPIC<ELF64LE>() const;
357template bool DefinedRegular::template isMipsPIC<ELF64BE>() const;
358
359template uint32_t SharedSymbol::template getAlignment<ELF32LE>() const;
360template uint32_t SharedSymbol::template getAlignment<ELF32BE>() const;
361template uint32_t SharedSymbol::template getAlignment<ELF64LE>() const;
362template uint32_t SharedSymbol::template getAlignment<ELF64BE>() const;