xref: /llvm-project-15.0.7/lld/ELF/Symbols.cpp (revision ff9e596b)
1 //===- Symbols.cpp --------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "Symbols.h"
10 #include "Driver.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 <cstring>
20 
21 using namespace llvm;
22 using namespace llvm::object;
23 using namespace llvm::ELF;
24 using namespace lld;
25 using namespace lld::elf;
26 
27 std::string lld::toString(const elf::Symbol &sym) {
28   StringRef name = sym.getName();
29   std::string ret = demangle(name, config->demangle);
30 
31   const char *suffix = sym.getVersionSuffix();
32   if (*suffix == '@')
33     ret += suffix;
34   return ret;
35 }
36 
37 Defined *ElfSym::bss;
38 Defined *ElfSym::etext1;
39 Defined *ElfSym::etext2;
40 Defined *ElfSym::edata1;
41 Defined *ElfSym::edata2;
42 Defined *ElfSym::end1;
43 Defined *ElfSym::end2;
44 Defined *ElfSym::globalOffsetTable;
45 Defined *ElfSym::mipsGp;
46 Defined *ElfSym::mipsGpDisp;
47 Defined *ElfSym::mipsLocalGp;
48 Defined *ElfSym::relaIpltStart;
49 Defined *ElfSym::relaIpltEnd;
50 Defined *ElfSym::riscvGlobalPointer;
51 Defined *ElfSym::tlsModuleBase;
52 SmallVector<SymbolAux, 0> elf::symAux;
53 
54 static uint64_t getSymVA(const Symbol &sym, int64_t addend) {
55   switch (sym.kind()) {
56   case Symbol::DefinedKind: {
57     auto &d = cast<Defined>(sym);
58     SectionBase *isec = d.section;
59 
60     // This is an absolute symbol.
61     if (!isec)
62       return d.value;
63 
64     assert(isec != &InputSection::discarded);
65 
66     uint64_t offset = d.value;
67 
68     // An object in an SHF_MERGE section might be referenced via a
69     // section symbol (as a hack for reducing the number of local
70     // symbols).
71     // Depending on the addend, the reference via a section symbol
72     // refers to a different object in the merge section.
73     // Since the objects in the merge section are not necessarily
74     // contiguous in the output, the addend can thus affect the final
75     // VA in a non-linear way.
76     // To make this work, we incorporate the addend into the section
77     // offset (and zero out the addend for later processing) so that
78     // we find the right object in the section.
79     if (d.isSection())
80       offset += addend;
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 = isec->getVA(offset);
93     if (d.isSection())
94       va -= addend;
95 
96     // MIPS relocatable files can mix regular and microMIPS code.
97     // Linker needs to distinguish such code. To do so microMIPS
98     // symbols has the `STO_MIPS_MICROMIPS` flag in the `st_other`
99     // field. Unfortunately, the `MIPS::relocate()` method has
100     // a symbol value only. To pass type of the symbol (regular/microMIPS)
101     // to that routine as well as other places where we write
102     // a symbol value as-is (.dynamic section, `Elf_Ehdr::e_entry`
103     // field etc) do the same trick as compiler uses to mark microMIPS
104     // for CPU - set the less-significant bit.
105     if (config->emachine == EM_MIPS && isMicroMips() &&
106         ((sym.stOther & STO_MIPS_MICROMIPS) || sym.needsCopy))
107       va |= 1;
108 
109     if (d.isTls() && !config->relocatable) {
110       // Use the address of the TLS segment's first section rather than the
111       // segment's address, because segment addresses aren't initialized until
112       // after sections are finalized. (e.g. Measuring the size of .rela.dyn
113       // for Android relocation packing requires knowing TLS symbol addresses
114       // during section finalization.)
115       if (!Out::tlsPhdr || !Out::tlsPhdr->firstSec)
116         fatal(toString(d.file) +
117               " has an STT_TLS symbol but doesn't have an SHF_TLS section");
118       return va - Out::tlsPhdr->firstSec->addr;
119     }
120     return va;
121   }
122   case Symbol::SharedKind:
123   case Symbol::UndefinedKind:
124     return 0;
125   case Symbol::LazyObjectKind:
126     llvm_unreachable("lazy symbol reached writer");
127   case Symbol::CommonKind:
128     llvm_unreachable("common symbol reached writer");
129   case Symbol::PlaceholderKind:
130     llvm_unreachable("placeholder symbol reached writer");
131   }
132   llvm_unreachable("invalid symbol kind");
133 }
134 
135 uint64_t Symbol::getVA(int64_t addend) const {
136   return getSymVA(*this, addend) + addend;
137 }
138 
139 uint64_t Symbol::getGotVA() const {
140   if (gotInIgot)
141     return in.igotPlt->getVA() + getGotPltOffset();
142   return in.got->getVA() + getGotOffset();
143 }
144 
145 uint64_t Symbol::getGotOffset() const {
146   return getGotIdx() * target->gotEntrySize;
147 }
148 
149 uint64_t Symbol::getGotPltVA() const {
150   if (isInIplt)
151     return in.igotPlt->getVA() + getGotPltOffset();
152   return in.gotPlt->getVA() + getGotPltOffset();
153 }
154 
155 uint64_t Symbol::getGotPltOffset() const {
156   if (isInIplt)
157     return getPltIdx() * target->gotEntrySize;
158   return (getPltIdx() + target->gotPltHeaderEntriesNum) * target->gotEntrySize;
159 }
160 
161 uint64_t Symbol::getPltVA() const {
162   uint64_t outVA = isInIplt
163                        ? in.iplt->getVA() + getPltIdx() * target->ipltEntrySize
164                        : in.plt->getVA() + in.plt->headerSize +
165                              getPltIdx() * target->pltEntrySize;
166 
167   // While linking microMIPS code PLT code are always microMIPS
168   // code. Set the less-significant bit to track that fact.
169   // See detailed comment in the `getSymVA` function.
170   if (config->emachine == EM_MIPS && isMicroMips())
171     outVA |= 1;
172   return outVA;
173 }
174 
175 uint64_t Symbol::getSize() const {
176   if (const auto *dr = dyn_cast<Defined>(this))
177     return dr->size;
178   return cast<SharedSymbol>(this)->size;
179 }
180 
181 OutputSection *Symbol::getOutputSection() const {
182   if (auto *s = dyn_cast<Defined>(this)) {
183     if (auto *sec = s->section)
184       return sec->getOutputSection();
185     return nullptr;
186   }
187   return nullptr;
188 }
189 
190 // If a symbol name contains '@', the characters after that is
191 // a symbol version name. This function parses that.
192 void Symbol::parseSymbolVersion() {
193   // Return if localized by a local: pattern in a version script.
194   if (versionId == VER_NDX_LOCAL)
195     return;
196   StringRef s = getName();
197   size_t pos = s.find('@');
198   if (pos == StringRef::npos)
199     return;
200   StringRef verstr = s.substr(pos + 1);
201 
202   // Truncate the symbol name so that it doesn't include the version string.
203   nameSize = pos;
204 
205   if (verstr.empty())
206     return;
207 
208   // If this is not in this DSO, it is not a definition.
209   if (!isDefined())
210     return;
211 
212   // '@@' in a symbol name means the default version.
213   // It is usually the most recent one.
214   bool isDefault = (verstr[0] == '@');
215   if (isDefault)
216     verstr = verstr.substr(1);
217 
218   for (const VersionDefinition &ver : namedVersionDefs()) {
219     if (ver.name != verstr)
220       continue;
221 
222     if (isDefault)
223       versionId = ver.id;
224     else
225       versionId = ver.id | VERSYM_HIDDEN;
226     return;
227   }
228 
229   // It is an error if the specified version is not defined.
230   // Usually version script is not provided when linking executable,
231   // but we may still want to override a versioned symbol from DSO,
232   // so we do not report error in this case. We also do not error
233   // if the symbol has a local version as it won't be in the dynamic
234   // symbol table.
235   if (config->shared && versionId != VER_NDX_LOCAL)
236     error(toString(file) + ": symbol " + s + " has undefined version " +
237           verstr);
238 }
239 
240 void Symbol::extract() const {
241   if (file->lazy) {
242     file->lazy = false;
243     parseFile(file);
244   }
245 }
246 
247 uint8_t Symbol::computeBinding() const {
248   if ((visibility != STV_DEFAULT && visibility != STV_PROTECTED) ||
249       versionId == VER_NDX_LOCAL)
250     return STB_LOCAL;
251   if (binding == STB_GNU_UNIQUE && !config->gnuUnique)
252     return STB_GLOBAL;
253   return binding;
254 }
255 
256 bool Symbol::includeInDynsym() const {
257   if (computeBinding() == STB_LOCAL)
258     return false;
259   if (!isDefined() && !isCommon())
260     // This should unconditionally return true, unfortunately glibc -static-pie
261     // expects undefined weak symbols not to exist in .dynsym, e.g.
262     // __pthread_mutex_lock reference in _dl_add_to_namespace_list,
263     // __pthread_initialize_minimal reference in csu/libc-start.c.
264     return !(isUndefWeak() && config->noDynamicLinker);
265 
266   return exportDynamic || inDynamicList;
267 }
268 
269 // Print out a log message for --trace-symbol.
270 void elf::printTraceSymbol(const Symbol &sym, StringRef name) {
271   std::string s;
272   if (sym.isUndefined())
273     s = ": reference to ";
274   else if (sym.isLazy())
275     s = ": lazy definition of ";
276   else if (sym.isShared())
277     s = ": shared definition of ";
278   else if (sym.isCommon())
279     s = ": common definition of ";
280   else
281     s = ": definition of ";
282 
283   message(toString(sym.file) + s + name);
284 }
285 
286 static void recordWhyExtract(const InputFile *reference,
287                              const InputFile &extracted, const Symbol &sym) {
288   driver->whyExtract.emplace_back(toString(reference), &extracted, sym);
289 }
290 
291 void elf::maybeWarnUnorderableSymbol(const Symbol *sym) {
292   if (!config->warnSymbolOrdering)
293     return;
294 
295   // If UnresolvedPolicy::Ignore is used, no "undefined symbol" error/warning
296   // is emitted. It makes sense to not warn on undefined symbols.
297   //
298   // Note, ld.bfd --symbol-ordering-file= does not warn on undefined symbols,
299   // but we don't have to be compatible here.
300   if (sym->isUndefined() &&
301       config->unresolvedSymbols == UnresolvedPolicy::Ignore)
302     return;
303 
304   const InputFile *file = sym->file;
305   auto *d = dyn_cast<Defined>(sym);
306 
307   auto report = [&](StringRef s) { warn(toString(file) + s + sym->getName()); };
308 
309   if (sym->isUndefined())
310     report(": unable to order undefined symbol: ");
311   else if (sym->isShared())
312     report(": unable to order shared symbol: ");
313   else if (d && !d->section)
314     report(": unable to order absolute symbol: ");
315   else if (d && isa<OutputSection>(d->section))
316     report(": unable to order synthetic symbol: ");
317   else if (d && !d->section->isLive())
318     report(": unable to order discarded symbol: ");
319 }
320 
321 // Returns true if a symbol can be replaced at load-time by a symbol
322 // with the same name defined in other ELF executable or DSO.
323 bool elf::computeIsPreemptible(const Symbol &sym) {
324   assert(!sym.isLocal() || sym.isPlaceholder());
325 
326   // Only symbols with default visibility that appear in dynsym can be
327   // preempted. Symbols with protected visibility cannot be preempted.
328   if (!sym.includeInDynsym() || sym.visibility != STV_DEFAULT)
329     return false;
330 
331   // At this point copy relocations have not been created yet, so any
332   // symbol that is not defined locally is preemptible.
333   if (!sym.isDefined())
334     return true;
335 
336   if (!config->shared)
337     return false;
338 
339   // If -Bsymbolic or --dynamic-list is specified, or -Bsymbolic-functions is
340   // specified and the symbol is STT_FUNC, the symbol is preemptible iff it is
341   // in the dynamic list. -Bsymbolic-non-weak-functions is a non-weak subset of
342   // -Bsymbolic-functions.
343   if (config->symbolic ||
344       (config->bsymbolic == BsymbolicKind::Functions && sym.isFunc()) ||
345       (config->bsymbolic == BsymbolicKind::NonWeakFunctions && sym.isFunc() &&
346        sym.binding != STB_WEAK))
347     return sym.inDynamicList;
348   return true;
349 }
350 
351 static uint8_t getMinVisibility(uint8_t va, uint8_t vb) {
352   if (va == STV_DEFAULT)
353     return vb;
354   if (vb == STV_DEFAULT)
355     return va;
356   return std::min(va, vb);
357 }
358 
359 // Merge symbol properties.
360 //
361 // When we have many symbols of the same name, we choose one of them,
362 // and that's the result of symbol resolution. However, symbols that
363 // were not chosen still affect some symbol properties.
364 void Symbol::mergeProperties(const Symbol &other) {
365   if (other.exportDynamic)
366     exportDynamic = true;
367 
368   // DSO symbols do not affect visibility in the output.
369   if (!other.isShared())
370     visibility = getMinVisibility(visibility, other.visibility);
371 }
372 
373 void Symbol::resolve(const Symbol &other) {
374   mergeProperties(other);
375 
376   if (isPlaceholder()) {
377     replace(other);
378     return;
379   }
380 
381   switch (other.kind()) {
382   case Symbol::UndefinedKind:
383     resolveUndefined(cast<Undefined>(other));
384     break;
385   case Symbol::CommonKind:
386     resolveCommon(cast<CommonSymbol>(other));
387     break;
388   case Symbol::DefinedKind:
389     resolveDefined(cast<Defined>(other));
390     break;
391   case Symbol::LazyObjectKind:
392     resolveLazy(cast<LazyObject>(other));
393     break;
394   case Symbol::SharedKind:
395     resolveShared(cast<SharedSymbol>(other));
396     break;
397   case Symbol::PlaceholderKind:
398     llvm_unreachable("bad symbol kind");
399   }
400 }
401 
402 void Symbol::resolveUndefined(const Undefined &other) {
403   // An undefined symbol with non default visibility must be satisfied
404   // in the same DSO.
405   //
406   // If this is a non-weak defined symbol in a discarded section, override the
407   // existing undefined symbol for better error message later.
408   if ((isShared() && other.visibility != STV_DEFAULT) ||
409       (isUndefined() && other.binding != STB_WEAK && other.discardedSecIdx)) {
410     replace(other);
411     return;
412   }
413 
414   if (traced)
415     printTraceSymbol(other, getName());
416 
417   if (isLazy()) {
418     // An undefined weak will not extract archive members. See comment on Lazy
419     // in Symbols.h for the details.
420     if (other.binding == STB_WEAK) {
421       binding = STB_WEAK;
422       type = other.type;
423       return;
424     }
425 
426     // Do extra check for --warn-backrefs.
427     //
428     // --warn-backrefs is an option to prevent an undefined reference from
429     // extracting an archive member written earlier in the command line. It can
430     // be used to keep compatibility with GNU linkers to some degree. I'll
431     // explain the feature and why you may find it useful in this comment.
432     //
433     // lld's symbol resolution semantics is more relaxed than traditional Unix
434     // linkers. For example,
435     //
436     //   ld.lld foo.a bar.o
437     //
438     // succeeds even if bar.o contains an undefined symbol that has to be
439     // resolved by some object file in foo.a. Traditional Unix linkers don't
440     // allow this kind of backward reference, as they visit each file only once
441     // from left to right in the command line while resolving all undefined
442     // symbols at the moment of visiting.
443     //
444     // In the above case, since there's no undefined symbol when a linker visits
445     // foo.a, no files are pulled out from foo.a, and because the linker forgets
446     // about foo.a after visiting, it can't resolve undefined symbols in bar.o
447     // that could have been resolved otherwise.
448     //
449     // That lld accepts more relaxed form means that (besides it'd make more
450     // sense) you can accidentally write a command line or a build file that
451     // works only with lld, even if you have a plan to distribute it to wider
452     // users who may be using GNU linkers. With --warn-backrefs, you can detect
453     // a library order that doesn't work with other Unix linkers.
454     //
455     // The option is also useful to detect cyclic dependencies between static
456     // archives. Again, lld accepts
457     //
458     //   ld.lld foo.a bar.a
459     //
460     // even if foo.a and bar.a depend on each other. With --warn-backrefs, it is
461     // handled as an error.
462     //
463     // Here is how the option works. We assign a group ID to each file. A file
464     // with a smaller group ID can pull out object files from an archive file
465     // with an equal or greater group ID. Otherwise, it is a reverse dependency
466     // and an error.
467     //
468     // A file outside --{start,end}-group gets a fresh ID when instantiated. All
469     // files within the same --{start,end}-group get the same group ID. E.g.
470     //
471     //   ld.lld A B --start-group C D --end-group E
472     //
473     // A forms group 0. B form group 1. C and D (including their member object
474     // files) form group 2. E forms group 3. I think that you can see how this
475     // group assignment rule simulates the traditional linker's semantics.
476     bool backref = config->warnBackrefs && other.file &&
477                    file->groupId < other.file->groupId;
478     extract();
479 
480     if (!config->whyExtract.empty())
481       recordWhyExtract(other.file, *file, *this);
482 
483     // We don't report backward references to weak symbols as they can be
484     // overridden later.
485     //
486     // A traditional linker does not error for -ldef1 -lref -ldef2 (linking
487     // sandwich), where def2 may or may not be the same as def1. We don't want
488     // to warn for this case, so dismiss the warning if we see a subsequent lazy
489     // definition. this->file needs to be saved because in the case of LTO it
490     // may be reset to nullptr or be replaced with a file named lto.tmp.
491     if (backref && !isWeak())
492       driver->backwardReferences.try_emplace(this,
493                                              std::make_pair(other.file, file));
494     return;
495   }
496 
497   // Undefined symbols in a SharedFile do not change the binding.
498   if (isa_and_nonnull<SharedFile>(other.file))
499     return;
500 
501   if (isUndefined() || isShared()) {
502     // The binding will be weak if there is at least one reference and all are
503     // weak. The binding has one opportunity to change to weak: if the first
504     // reference is weak.
505     if (other.binding != STB_WEAK || !referenced)
506       binding = other.binding;
507   }
508 }
509 
510 // Compare two symbols. Return true if the new symbol should win.
511 bool Symbol::shouldReplace(const Defined &other) const {
512   if (LLVM_UNLIKELY(isCommon())) {
513     if (config->warnCommon)
514       warn("common " + getName() + " is overridden");
515     return !other.isWeak();
516   }
517   if (!isDefined())
518     return true;
519 
520   // .symver foo,foo@@VER unfortunately creates two defined symbols: foo and
521   // foo@@VER. In GNU ld, if foo and foo@@VER are in the same file, foo is
522   // ignored. In our implementation, when this is foo, this->getName() may still
523   // contain @@, return true in this case as well.
524   if (LLVM_UNLIKELY(file == other.file)) {
525     if (other.getName().contains("@@"))
526       return true;
527     if (getName().contains("@@"))
528       return false;
529   }
530 
531   // Incoming STB_GLOBAL overrides STB_WEAK/STB_GNU_UNIQUE. -fgnu-unique changes
532   // some vague linkage data in COMDAT from STB_WEAK to STB_GNU_UNIQUE. Treat
533   // STB_GNU_UNIQUE like STB_WEAK so that we prefer the first among all
534   // STB_WEAK/STB_GNU_UNIQUE copies. If we prefer an incoming STB_GNU_UNIQUE to
535   // an existing STB_WEAK, there may be discarded section errors because the
536   // selected copy may be in a non-prevailing COMDAT.
537   return !isGlobal() && other.isGlobal();
538 }
539 
540 void elf::reportDuplicate(const Symbol &sym, const InputFile *newFile,
541                           InputSectionBase *errSec, uint64_t errOffset) {
542   if (config->allowMultipleDefinition)
543     return;
544   // In glibc<2.32, crti.o has .gnu.linkonce.t.__x86.get_pc_thunk.bx, which
545   // is sort of proto-comdat. There is actually no duplicate if we have
546   // full support for .gnu.linkonce.
547   const Defined *d = dyn_cast<Defined>(&sym);
548   if (!d || d->getName() == "__x86.get_pc_thunk.bx")
549     return;
550   // Allow absolute symbols with the same value for GNU ld compatibility.
551   if (!d->section && !errSec && errOffset && d->value == errOffset)
552     return;
553   if (!d->section || !errSec) {
554     error("duplicate symbol: " + toString(sym) + "\n>>> defined in " +
555           toString(sym.file) + "\n>>> defined in " + toString(newFile));
556     return;
557   }
558 
559   // Construct and print an error message in the form of:
560   //
561   //   ld.lld: error: duplicate symbol: foo
562   //   >>> defined at bar.c:30
563   //   >>>            bar.o (/home/alice/src/bar.o)
564   //   >>> defined at baz.c:563
565   //   >>>            baz.o in archive libbaz.a
566   auto *sec1 = cast<InputSectionBase>(d->section);
567   std::string src1 = sec1->getSrcMsg(sym, d->value);
568   std::string obj1 = sec1->getObjMsg(d->value);
569   std::string src2 = errSec->getSrcMsg(sym, errOffset);
570   std::string obj2 = errSec->getObjMsg(errOffset);
571 
572   std::string msg = "duplicate symbol: " + toString(sym) + "\n>>> defined at ";
573   if (!src1.empty())
574     msg += src1 + "\n>>>            ";
575   msg += obj1 + "\n>>> defined at ";
576   if (!src2.empty())
577     msg += src2 + "\n>>>            ";
578   msg += obj2;
579   error(msg);
580 }
581 
582 void Symbol::checkDuplicate(const Defined &other) const {
583   if (isDefined() && !isWeak() && !other.isWeak())
584     reportDuplicate(*this, other.file,
585                     dyn_cast_or_null<InputSectionBase>(other.section),
586                     other.value);
587 }
588 
589 void Symbol::resolveCommon(const CommonSymbol &other) {
590   if (isDefined() && !isWeak()) {
591     if (config->warnCommon)
592       warn("common " + getName() + " is overridden");
593     return;
594   }
595 
596   if (CommonSymbol *oldSym = dyn_cast<CommonSymbol>(this)) {
597     if (config->warnCommon)
598       warn("multiple common of " + getName());
599     oldSym->alignment = std::max(oldSym->alignment, other.alignment);
600     if (oldSym->size < other.size) {
601       oldSym->file = other.file;
602       oldSym->size = other.size;
603     }
604     return;
605   }
606 
607   if (auto *s = dyn_cast<SharedSymbol>(this)) {
608     // Increase st_size if the shared symbol has a larger st_size. The shared
609     // symbol may be created from common symbols. The fact that some object
610     // files were linked into a shared object first should not change the
611     // regular rule that picks the largest st_size.
612     uint64_t size = s->size;
613     replace(other);
614     if (size > cast<CommonSymbol>(this)->size)
615       cast<CommonSymbol>(this)->size = size;
616   } else {
617     replace(other);
618   }
619 }
620 
621 void Symbol::resolveDefined(const Defined &other) {
622   if (shouldReplace(other))
623     replace(other);
624 }
625 
626 void Symbol::resolveLazy(const LazyObject &other) {
627   // For common objects, we want to look for global or weak definitions that
628   // should be extracted as the canonical definition instead.
629   if (LLVM_UNLIKELY(isCommon()) && elf::config->fortranCommon &&
630       other.file->shouldExtractForCommon(getName())) {
631     driver->backwardReferences.erase(this);
632     replace(other);
633     other.extract();
634     return;
635   }
636 
637   if (!isUndefined()) {
638     // See the comment in resolveUndefined().
639     if (isDefined())
640       driver->backwardReferences.erase(this);
641     return;
642   }
643 
644   // An undefined weak will not extract archive members. See comment on Lazy in
645   // Symbols.h for the details.
646   if (isWeak()) {
647     uint8_t ty = type;
648     replace(other);
649     type = ty;
650     binding = STB_WEAK;
651     return;
652   }
653 
654   const InputFile *oldFile = file;
655   other.extract();
656   if (!config->whyExtract.empty())
657     recordWhyExtract(oldFile, *file, *this);
658 }
659 
660 void Symbol::resolveShared(const SharedSymbol &other) {
661   if (isCommon()) {
662     // See the comment in resolveCommon() above.
663     if (other.size > cast<CommonSymbol>(this)->size)
664       cast<CommonSymbol>(this)->size = other.size;
665     return;
666   }
667   if (visibility == STV_DEFAULT && (isUndefined() || isLazy())) {
668     // An undefined symbol with non default visibility must be satisfied
669     // in the same DSO.
670     uint8_t bind = binding;
671     replace(other);
672     binding = bind;
673   } else if (traced)
674     printTraceSymbol(other, getName());
675 }
676