blob: 37e00336c088cd9fca8e4c27041f543827224bb9 [file] [log] [blame]
Michael J. Spencer84487f12015-07-24 21:03:07 +00001//===- 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 "Chunks.h"
Rafael Espindola49a2ca62015-08-06 15:33:19 +000012#include "Error.h"
Michael J. Spencercdae0a42015-07-28 22:58:25 +000013#include "InputFiles.h"
Michael J. Spencer84487f12015-07-24 21:03:07 +000014
15using namespace llvm::object;
Rafael Espindola78471f02015-09-01 23:12:52 +000016using namespace llvm::ELF;
Michael J. Spencer84487f12015-07-24 21:03:07 +000017
18using namespace lld;
19using namespace lld::elf2;
20
Rafael Espindola78471f02015-09-01 23:12:52 +000021static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
22 if (VA == STV_DEFAULT)
23 return VB;
24 if (VB == STV_DEFAULT)
25 return VA;
26 return std::min(VA, VB);
27}
28
Michael J. Spencer84487f12015-07-24 21:03:07 +000029// Returns 1, 0 or -1 if this symbol should take precedence
30// over the Other, tie or lose, respectively.
Rafael Espindoladaa92a62015-08-31 01:16:19 +000031template <class ELFT> int SymbolBody::compare(SymbolBody *Other) {
Rafael Espindola30e17972015-08-30 23:17:30 +000032 std::pair<bool, bool> L(isDefined(), !isWeak());
33 std::pair<bool, bool> R(Other->isDefined(), !Other->isWeak());
Rui Ueyamaa7ccb292015-07-27 20:39:01 +000034
Rafael Espindola3a63f3f2015-08-28 20:19:34 +000035 // Normalize
36 if (L > R)
Rafael Espindoladaa92a62015-08-31 01:16:19 +000037 return -Other->compare<ELFT>(this);
Rui Ueyamaa7ccb292015-07-27 20:39:01 +000038
Rafael Espindola78471f02015-09-01 23:12:52 +000039 uint8_t LV = getMostConstrainingVisibility();
40 uint8_t RV = Other->getMostConstrainingVisibility();
41 MostConstrainingVisibility = getMinVisibility(LV, RV);
42 Other->MostConstrainingVisibility = MostConstrainingVisibility;
43
Rafael Espindola3a63f3f2015-08-28 20:19:34 +000044 if (L != R)
45 return -1;
Michael J. Spencer84487f12015-07-24 21:03:07 +000046
Rafael Espindola30e17972015-08-30 23:17:30 +000047 if (L.first && L.second) {
Rafael Espindoladaa92a62015-08-31 01:16:19 +000048 if (isCommon()) {
49 if (Other->isCommon()) {
Rafael Espindolaf31f9612015-09-01 01:19:12 +000050 auto *ThisC = cast<DefinedCommon<ELFT>>(this);
51 auto *OtherC = cast<DefinedCommon<ELFT>>(Other);
52 typename DefinedCommon<ELFT>::uintX_t MaxAlign =
53 std::max(ThisC->MaxAlignment, OtherC->MaxAlignment);
54 if (ThisC->Sym.st_size >= OtherC->Sym.st_size) {
55 ThisC->MaxAlignment = MaxAlign;
Rafael Espindoladaa92a62015-08-31 01:16:19 +000056 return 1;
Rafael Espindolaf31f9612015-09-01 01:19:12 +000057 }
58 OtherC->MaxAlignment = MaxAlign;
Rafael Espindoladaa92a62015-08-31 01:16:19 +000059 return -1;
60 }
Rafael Espindola30e17972015-08-30 23:17:30 +000061 return -1;
Rafael Espindoladaa92a62015-08-31 01:16:19 +000062 }
Rafael Espindola30e17972015-08-30 23:17:30 +000063 if (Other->isCommon())
64 return 1;
Michael J. Spencer84487f12015-07-24 21:03:07 +000065 return 0;
Rafael Espindola30e17972015-08-30 23:17:30 +000066 }
Rafael Espindola3a63f3f2015-08-28 20:19:34 +000067 return 1;
Michael J. Spencer84487f12015-07-24 21:03:07 +000068}
Rafael Espindoladaa92a62015-08-31 01:16:19 +000069
70template int SymbolBody::compare<ELF32LE>(SymbolBody *Other);
71template int SymbolBody::compare<ELF32BE>(SymbolBody *Other);
72template int SymbolBody::compare<ELF64LE>(SymbolBody *Other);
73template int SymbolBody::compare<ELF64BE>(SymbolBody *Other);