| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 1 | //===- SymbolTable.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 | //===----------------------------------------------------------------------===// | 
| Rui Ueyama | 34f2924 | 2015-10-13 19:51:57 +0000 | [diff] [blame] | 9 | // | 
|  | 10 | // Symbol table is a bag of all known symbols. We put all symbols of | 
| Rui Ueyama | c9559d9 | 2016-01-05 20:47:37 +0000 | [diff] [blame] | 11 | // all input files to the symbol table. The symbol table is basically | 
| Rui Ueyama | 34f2924 | 2015-10-13 19:51:57 +0000 | [diff] [blame] | 12 | // a hash table with the logic to resolve symbol name conflicts using | 
|  | 13 | // the symbol types. | 
|  | 14 | // | 
|  | 15 | //===----------------------------------------------------------------------===// | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 16 |  | 
|  | 17 | #include "SymbolTable.h" | 
| Rafael Espindola | 4340aad | 2015-09-11 22:42:45 +0000 | [diff] [blame] | 18 | #include "Config.h" | 
| Rafael Espindola | 192e1fa | 2015-08-06 15:08:23 +0000 | [diff] [blame] | 19 | #include "Error.h" | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 20 | #include "Symbols.h" | 
| Rafael Espindola | 9f77ef0 | 2016-02-12 20:54:57 +0000 | [diff] [blame] | 21 | #include "llvm/Bitcode/ReaderWriter.h" | 
| Rui Ueyama | deb1540 | 2016-01-07 17:20:07 +0000 | [diff] [blame] | 22 | #include "llvm/Support/StringSaver.h" | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 23 |  | 
|  | 24 | using namespace llvm; | 
| Rafael Espindola | daa92a6 | 2015-08-31 01:16:19 +0000 | [diff] [blame] | 25 | using namespace llvm::object; | 
| Rafael Espindola | 01205f7 | 2015-09-22 18:19:46 +0000 | [diff] [blame] | 26 | using namespace llvm::ELF; | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 27 |  | 
|  | 28 | using namespace lld; | 
| Rafael Espindola | e0df00b | 2016-02-28 00:25:54 +0000 | [diff] [blame] | 29 | using namespace lld::elf; | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 30 |  | 
| Rui Ueyama | c9559d9 | 2016-01-05 20:47:37 +0000 | [diff] [blame] | 31 | // All input object files must be for the same architecture | 
|  | 32 | // (e.g. it does not make sense to link x86 object files with | 
|  | 33 | // MIPS object files.) This function checks for that error. | 
| Rui Ueyama | 16ba669 | 2016-01-29 19:41:13 +0000 | [diff] [blame] | 34 | template <class ELFT> static bool isCompatible(InputFile *FileP) { | 
| Rui Ueyama | 25b44c9 | 2015-12-16 23:31:22 +0000 | [diff] [blame] | 35 | auto *F = dyn_cast<ELFFileBase<ELFT>>(FileP); | 
|  | 36 | if (!F) | 
| Rui Ueyama | 16ba669 | 2016-01-29 19:41:13 +0000 | [diff] [blame] | 37 | return true; | 
| Rui Ueyama | 25b44c9 | 2015-12-16 23:31:22 +0000 | [diff] [blame] | 38 | if (F->getELFKind() == Config->EKind && F->getEMachine() == Config->EMachine) | 
| Rui Ueyama | 16ba669 | 2016-01-29 19:41:13 +0000 | [diff] [blame] | 39 | return true; | 
| Rui Ueyama | 25b44c9 | 2015-12-16 23:31:22 +0000 | [diff] [blame] | 40 | StringRef A = F->getName(); | 
|  | 41 | StringRef B = Config->Emulation; | 
|  | 42 | if (B.empty()) | 
|  | 43 | B = Config->FirstElf->getName(); | 
| Rui Ueyama | 16ba669 | 2016-01-29 19:41:13 +0000 | [diff] [blame] | 44 | error(A + " is incompatible with " + B); | 
|  | 45 | return false; | 
| Rui Ueyama | 25b44c9 | 2015-12-16 23:31:22 +0000 | [diff] [blame] | 46 | } | 
|  | 47 |  | 
| Rui Ueyama | c9559d9 | 2016-01-05 20:47:37 +0000 | [diff] [blame] | 48 | // Add symbols in File to the symbol table. | 
| Rui Ueyama | 25b44c9 | 2015-12-16 23:31:22 +0000 | [diff] [blame] | 49 | template <class ELFT> | 
| Rui Ueyama | 3ce825e | 2015-10-09 21:07:25 +0000 | [diff] [blame] | 50 | void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) { | 
| Rafael Espindola | 21f7bd4 | 2015-12-23 14:35:51 +0000 | [diff] [blame] | 51 | InputFile *FileP = File.get(); | 
| Rui Ueyama | 16ba669 | 2016-01-29 19:41:13 +0000 | [diff] [blame] | 52 | if (!isCompatible<ELFT>(FileP)) | 
|  | 53 | return; | 
| Rafael Espindola | 525914d | 2015-10-11 03:36:49 +0000 | [diff] [blame] | 54 |  | 
| Rui Ueyama | 8957574 | 2015-12-16 22:59:13 +0000 | [diff] [blame] | 55 | // .a file | 
|  | 56 | if (auto *F = dyn_cast<ArchiveFile>(FileP)) { | 
| Rafael Espindola | 21f7bd4 | 2015-12-23 14:35:51 +0000 | [diff] [blame] | 57 | ArchiveFiles.emplace_back(cast<ArchiveFile>(File.release())); | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 58 | F->parse<ELFT>(); | 
| Michael J. Spencer | 1b348a6 | 2015-09-04 22:28:10 +0000 | [diff] [blame] | 59 | return; | 
|  | 60 | } | 
| Rui Ueyama | 3d45179 | 2015-10-12 18:03:21 +0000 | [diff] [blame] | 61 |  | 
| George Rimar | 2a78fce | 2016-04-13 18:07:57 +0000 | [diff] [blame] | 62 | // Lazy object file | 
|  | 63 | if (auto *F = dyn_cast<LazyObjectFile>(FileP)) { | 
|  | 64 | LazyObjectFiles.emplace_back(cast<LazyObjectFile>(File.release())); | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 65 | F->parse<ELFT>(); | 
| George Rimar | 2a78fce | 2016-04-13 18:07:57 +0000 | [diff] [blame] | 66 | return; | 
|  | 67 | } | 
|  | 68 |  | 
|  | 69 | if (Config->Trace) | 
|  | 70 | llvm::outs() << getFilename(FileP) << "\n"; | 
|  | 71 |  | 
| Rui Ueyama | 8957574 | 2015-12-16 22:59:13 +0000 | [diff] [blame] | 72 | // .so file | 
|  | 73 | if (auto *F = dyn_cast<SharedFile<ELFT>>(FileP)) { | 
|  | 74 | // DSOs are uniquified not by filename but by soname. | 
|  | 75 | F->parseSoName(); | 
| Rui Ueyama | 131e0ff | 2016-01-08 22:17:42 +0000 | [diff] [blame] | 76 | if (!SoNames.insert(F->getSoName()).second) | 
| Rafael Espindola | 6a3b5de | 2015-10-01 19:52:48 +0000 | [diff] [blame] | 77 | return; | 
| Rui Ueyama | 8957574 | 2015-12-16 22:59:13 +0000 | [diff] [blame] | 78 |  | 
| Rafael Espindola | 21f7bd4 | 2015-12-23 14:35:51 +0000 | [diff] [blame] | 79 | SharedFiles.emplace_back(cast<SharedFile<ELFT>>(File.release())); | 
| Rui Ueyama | 7c71331 | 2016-01-06 01:56:36 +0000 | [diff] [blame] | 80 | F->parseRest(); | 
| Rui Ueyama | 8957574 | 2015-12-16 22:59:13 +0000 | [diff] [blame] | 81 | return; | 
| Rafael Espindola | 6a3b5de | 2015-10-01 19:52:48 +0000 | [diff] [blame] | 82 | } | 
| Rui Ueyama | 8957574 | 2015-12-16 22:59:13 +0000 | [diff] [blame] | 83 |  | 
| Rui Ueyama | f8baa66 | 2016-04-07 19:24:51 +0000 | [diff] [blame] | 84 | // LLVM bitcode file | 
| Rafael Espindola | 9f77ef0 | 2016-02-12 20:54:57 +0000 | [diff] [blame] | 85 | if (auto *F = dyn_cast<BitcodeFile>(FileP)) { | 
|  | 86 | BitcodeFiles.emplace_back(cast<BitcodeFile>(File.release())); | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 87 | F->parse<ELFT>(ComdatGroups); | 
| Rafael Espindola | 9f77ef0 | 2016-02-12 20:54:57 +0000 | [diff] [blame] | 88 | return; | 
|  | 89 | } | 
|  | 90 |  | 
| Rui Ueyama | f8baa66 | 2016-04-07 19:24:51 +0000 | [diff] [blame] | 91 | // Regular object file | 
| Rui Ueyama | 8957574 | 2015-12-16 22:59:13 +0000 | [diff] [blame] | 92 | auto *F = cast<ObjectFile<ELFT>>(FileP); | 
| Rafael Espindola | 21f7bd4 | 2015-12-23 14:35:51 +0000 | [diff] [blame] | 93 | ObjectFiles.emplace_back(cast<ObjectFile<ELFT>>(File.release())); | 
| Rui Ueyama | 52d3b67 | 2016-01-06 02:06:33 +0000 | [diff] [blame] | 94 | F->parse(ComdatGroups); | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 95 | } | 
|  | 96 |  | 
| Rui Ueyama | 4255475 | 2016-04-23 00:26:32 +0000 | [diff] [blame] | 97 | // This function is where all the optimizations of link-time | 
|  | 98 | // optimization happens. When LTO is in use, some input files are | 
|  | 99 | // not in native object file format but in the LLVM bitcode format. | 
|  | 100 | // This function compiles bitcode files into a few big native files | 
|  | 101 | // using LLVM functions and replaces bitcode symbols with the results. | 
|  | 102 | // Because all bitcode files that consist of a program are passed | 
|  | 103 | // to the compiler at once, it can do whole-program optimization. | 
| Rafael Espindola | 9f77ef0 | 2016-02-12 20:54:57 +0000 | [diff] [blame] | 104 | template <class ELFT> void SymbolTable<ELFT>::addCombinedLtoObject() { | 
|  | 105 | if (BitcodeFiles.empty()) | 
|  | 106 | return; | 
| Rui Ueyama | 2599248 | 2016-03-22 20:52:10 +0000 | [diff] [blame] | 107 |  | 
|  | 108 | // Compile bitcode files. | 
|  | 109 | Lto.reset(new BitcodeCompiler); | 
|  | 110 | for (const std::unique_ptr<BitcodeFile> &F : BitcodeFiles) | 
|  | 111 | Lto->add(*F); | 
| Davide Italiano | bc17663 | 2016-04-15 22:38:10 +0000 | [diff] [blame] | 112 | std::vector<std::unique_ptr<InputFile>> IFs = Lto->compile(); | 
| Rui Ueyama | 2599248 | 2016-03-22 20:52:10 +0000 | [diff] [blame] | 113 |  | 
|  | 114 | // Replace bitcode symbols. | 
| Davide Italiano | bc17663 | 2016-04-15 22:38:10 +0000 | [diff] [blame] | 115 | for (auto &IF : IFs) { | 
|  | 116 | ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(IF.release()); | 
|  | 117 |  | 
|  | 118 | llvm::DenseSet<StringRef> DummyGroups; | 
|  | 119 | Obj->parse(DummyGroups); | 
| Davide Italiano | bc17663 | 2016-04-15 22:38:10 +0000 | [diff] [blame] | 120 | ObjectFiles.emplace_back(Obj); | 
| Rafael Espindola | 9f77ef0 | 2016-02-12 20:54:57 +0000 | [diff] [blame] | 121 | } | 
|  | 122 | } | 
|  | 123 |  | 
| Rafael Espindola | 0e604f9 | 2015-09-25 18:56:53 +0000 | [diff] [blame] | 124 | template <class ELFT> | 
| Rafael Espindola | ccfe3cb | 2016-04-04 14:04:16 +0000 | [diff] [blame] | 125 | DefinedRegular<ELFT> *SymbolTable<ELFT>::addAbsolute(StringRef Name, | 
|  | 126 | uint8_t Visibility) { | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 127 | return cast<DefinedRegular<ELFT>>( | 
|  | 128 | addRegular(Name, STB_GLOBAL, Visibility)->body()); | 
| Rafael Espindola | 0e604f9 | 2015-09-25 18:56:53 +0000 | [diff] [blame] | 129 | } | 
|  | 130 |  | 
| Rui Ueyama | c9559d9 | 2016-01-05 20:47:37 +0000 | [diff] [blame] | 131 | // Add Name as an "ignored" symbol. An ignored symbol is a regular | 
| Rafael Espindola | ccfe3cb | 2016-04-04 14:04:16 +0000 | [diff] [blame] | 132 | // linker-synthesized defined symbol, but is only defined if needed. | 
| Simon Atanasyan | 09dae7c | 2015-12-16 14:45:09 +0000 | [diff] [blame] | 133 | template <class ELFT> | 
| Rafael Espindola | ccfe3cb | 2016-04-04 14:04:16 +0000 | [diff] [blame] | 134 | DefinedRegular<ELFT> *SymbolTable<ELFT>::addIgnored(StringRef Name, | 
|  | 135 | uint8_t Visibility) { | 
|  | 136 | if (!find(Name)) | 
|  | 137 | return nullptr; | 
|  | 138 | return addAbsolute(Name, Visibility); | 
| Rafael Espindola | 5d41326 | 2015-10-01 21:22:26 +0000 | [diff] [blame] | 139 | } | 
|  | 140 |  | 
| Rui Ueyama | deb1540 | 2016-01-07 17:20:07 +0000 | [diff] [blame] | 141 | // Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM. | 
|  | 142 | // Used to implement --wrap. | 
|  | 143 | template <class ELFT> void SymbolTable<ELFT>::wrap(StringRef Name) { | 
| Rui Ueyama | 1b70d66 | 2016-04-28 00:03:38 +0000 | [diff] [blame] | 144 | SymbolBody *B = find(Name); | 
|  | 145 | if (!B) | 
| Rui Ueyama | deb1540 | 2016-01-07 17:20:07 +0000 | [diff] [blame] | 146 | return; | 
|  | 147 | StringSaver Saver(Alloc); | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 148 | Symbol *Sym = B->symbol(); | 
|  | 149 | Symbol *Real = addUndefined(Saver.save("__real_" + Name)); | 
|  | 150 | Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name)); | 
|  | 151 | // We rename symbols by replacing the old symbol's SymbolBody with the new | 
|  | 152 | // symbol's SymbolBody. This causes all SymbolBody pointers referring to the | 
|  | 153 | // old symbol to instead refer to the new symbol. | 
|  | 154 | memcpy(Real->Body.buffer, Sym->Body.buffer, sizeof(Sym->Body)); | 
|  | 155 | memcpy(Sym->Body.buffer, Wrap->Body.buffer, sizeof(Wrap->Body)); | 
| Rui Ueyama | deb1540 | 2016-01-07 17:20:07 +0000 | [diff] [blame] | 156 | } | 
|  | 157 |  | 
| Peter Collingbourne | dadcc17 | 2016-04-22 18:42:48 +0000 | [diff] [blame] | 158 | static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) { | 
|  | 159 | if (VA == STV_DEFAULT) | 
|  | 160 | return VB; | 
|  | 161 | if (VB == STV_DEFAULT) | 
|  | 162 | return VA; | 
|  | 163 | return std::min(VA, VB); | 
|  | 164 | } | 
|  | 165 |  | 
| Rui Ueyama | b4de595 | 2016-01-08 22:01:33 +0000 | [diff] [blame] | 166 | // Find an existing symbol or create and insert a new one. | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 167 | template <class ELFT> | 
|  | 168 | std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef Name) { | 
| Rafael Espindola | 7f0b727 | 2016-04-14 20:42:43 +0000 | [diff] [blame] | 169 | unsigned NumSyms = SymVector.size(); | 
|  | 170 | auto P = Symtab.insert(std::make_pair(Name, NumSyms)); | 
|  | 171 | Symbol *Sym; | 
|  | 172 | if (P.second) { | 
| Peter Collingbourne | 66ac1d6 | 2016-04-22 20:21:26 +0000 | [diff] [blame] | 173 | Sym = new (Alloc) Symbol; | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 174 | Sym->Binding = STB_WEAK; | 
| Peter Collingbourne | 66ac1d6 | 2016-04-22 20:21:26 +0000 | [diff] [blame] | 175 | Sym->Visibility = STV_DEFAULT; | 
|  | 176 | Sym->IsUsedInRegularObj = false; | 
|  | 177 | Sym->ExportDynamic = false; | 
| George Rimar | d356630 | 2016-06-20 11:55:12 +0000 | [diff] [blame] | 178 | if (Config->VersionScriptGlobalByDefault) | 
|  | 179 | Sym->VersionId = VER_NDX_GLOBAL; | 
|  | 180 | else | 
|  | 181 | Sym->VersionId = VER_NDX_LOCAL; | 
| Rafael Espindola | 7f0b727 | 2016-04-14 20:42:43 +0000 | [diff] [blame] | 182 | SymVector.push_back(Sym); | 
|  | 183 | } else { | 
|  | 184 | Sym = SymVector[P.first->second]; | 
|  | 185 | } | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 186 | return {Sym, P.second}; | 
|  | 187 | } | 
| Peter Collingbourne | dadcc17 | 2016-04-22 18:42:48 +0000 | [diff] [blame] | 188 |  | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 189 | // Find an existing symbol or create and insert a new one, then apply the given | 
|  | 190 | // attributes. | 
|  | 191 | template <class ELFT> | 
|  | 192 | std::pair<Symbol *, bool> | 
|  | 193 | SymbolTable<ELFT>::insert(StringRef Name, uint8_t Type, uint8_t Visibility, | 
|  | 194 | bool CanOmitFromDynSym, bool IsUsedInRegularObj, | 
|  | 195 | InputFile *File) { | 
|  | 196 | Symbol *S; | 
|  | 197 | bool WasInserted; | 
|  | 198 | std::tie(S, WasInserted) = insert(Name); | 
|  | 199 |  | 
|  | 200 | // Merge in the new symbol's visibility. | 
|  | 201 | S->Visibility = getMinVisibility(S->Visibility, Visibility); | 
|  | 202 | if (!CanOmitFromDynSym && (Config->Shared || Config->ExportDynamic)) | 
|  | 203 | S->ExportDynamic = true; | 
|  | 204 | if (IsUsedInRegularObj) | 
|  | 205 | S->IsUsedInRegularObj = true; | 
| Peter Collingbourne | f3a2b0e | 2016-05-03 18:03:47 +0000 | [diff] [blame] | 206 | if (!WasInserted && S->body()->Type != SymbolBody::UnknownType && | 
|  | 207 | ((Type == STT_TLS) != S->body()->isTls())) | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 208 | error("TLS attribute mismatch for symbol: " + | 
|  | 209 | conflictMsg(S->body(), File)); | 
|  | 210 |  | 
|  | 211 | return {S, WasInserted}; | 
|  | 212 | } | 
|  | 213 |  | 
|  | 214 | // Construct a string in the form of "Sym in File1 and File2". | 
|  | 215 | // Used to construct an error message. | 
|  | 216 | template <typename ELFT> | 
|  | 217 | std::string SymbolTable<ELFT>::conflictMsg(SymbolBody *Existing, | 
|  | 218 | InputFile *NewFile) { | 
|  | 219 | StringRef Sym = Existing->getName(); | 
| Rui Ueyama | 6d0cd2b | 2016-05-02 21:30:42 +0000 | [diff] [blame] | 220 | return demangle(Sym) + " in " + getFilename(Existing->getSourceFile<ELFT>()) + | 
|  | 221 | " and " + getFilename(NewFile); | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 222 | } | 
|  | 223 |  | 
|  | 224 | template <class ELFT> Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name) { | 
|  | 225 | return addUndefined(Name, STB_GLOBAL, STV_DEFAULT, /*Type*/ 0, | 
| Rafael Espindola | cc70da3 | 2016-06-15 17:56:10 +0000 | [diff] [blame] | 226 | /*CanOmitFromDynSym*/ false, /*File*/ nullptr); | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 227 | } | 
|  | 228 |  | 
|  | 229 | template <class ELFT> | 
|  | 230 | Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, uint8_t Binding, | 
|  | 231 | uint8_t StOther, uint8_t Type, | 
| Rafael Espindola | cc70da3 | 2016-06-15 17:56:10 +0000 | [diff] [blame] | 232 | bool CanOmitFromDynSym, | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 233 | InputFile *File) { | 
|  | 234 | Symbol *S; | 
|  | 235 | bool WasInserted; | 
|  | 236 | std::tie(S, WasInserted) = | 
| Rafael Espindola | cc70da3 | 2016-06-15 17:56:10 +0000 | [diff] [blame] | 237 | insert(Name, Type, StOther & 3, CanOmitFromDynSym, | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 238 | /*IsUsedInRegularObj*/ !File || !isa<BitcodeFile>(File), File); | 
|  | 239 | if (WasInserted) { | 
|  | 240 | S->Binding = Binding; | 
|  | 241 | replaceBody<Undefined>(S, Name, StOther, Type); | 
| Rui Ueyama | 6d0cd2b | 2016-05-02 21:30:42 +0000 | [diff] [blame] | 242 | cast<Undefined>(S->body())->File = File; | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 243 | return S; | 
|  | 244 | } | 
| Peter Collingbourne | ca8c994 | 2016-06-09 18:01:35 +0000 | [diff] [blame] | 245 | if (Binding != STB_WEAK) { | 
|  | 246 | if (S->body()->isShared() || S->body()->isLazy()) | 
|  | 247 | S->Binding = Binding; | 
|  | 248 | if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(S->body())) | 
|  | 249 | SS->File->IsUsed = true; | 
|  | 250 | } | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 251 | if (auto *L = dyn_cast<Lazy>(S->body())) { | 
|  | 252 | // An undefined weak will not fetch archive members, but we have to remember | 
|  | 253 | // its type. See also comment in addLazyArchive. | 
|  | 254 | if (S->isWeak()) | 
|  | 255 | L->Type = Type; | 
|  | 256 | else if (auto F = L->getFile()) | 
|  | 257 | addFile(std::move(F)); | 
|  | 258 | } | 
|  | 259 | return S; | 
|  | 260 | } | 
|  | 261 |  | 
|  | 262 | // We have a new defined symbol with the specified binding. Return 1 if the new | 
|  | 263 | // symbol should win, -1 if the new symbol should lose, or 0 if both symbols are | 
|  | 264 | // strong defined symbols. | 
|  | 265 | static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding) { | 
|  | 266 | if (WasInserted) | 
|  | 267 | return 1; | 
|  | 268 | SymbolBody *Body = S->body(); | 
|  | 269 | if (Body->isLazy() || Body->isUndefined() || Body->isShared()) | 
|  | 270 | return 1; | 
|  | 271 | if (Binding == STB_WEAK) | 
|  | 272 | return -1; | 
|  | 273 | if (S->isWeak()) | 
|  | 274 | return 1; | 
|  | 275 | return 0; | 
|  | 276 | } | 
|  | 277 |  | 
|  | 278 | // We have a new non-common defined symbol with the specified binding. Return 1 | 
|  | 279 | // if the new symbol should win, -1 if the new symbol should lose, or 0 if there | 
|  | 280 | // is a conflict. If the new symbol wins, also update the binding. | 
|  | 281 | static int compareDefinedNonCommon(Symbol *S, bool WasInserted, uint8_t Binding) { | 
|  | 282 | if (int Cmp = compareDefined(S, WasInserted, Binding)) { | 
|  | 283 | if (Cmp > 0) | 
|  | 284 | S->Binding = Binding; | 
|  | 285 | return Cmp; | 
|  | 286 | } | 
|  | 287 | if (isa<DefinedCommon>(S->body())) { | 
|  | 288 | // Non-common symbols take precedence over common symbols. | 
|  | 289 | if (Config->WarnCommon) | 
|  | 290 | warning("common " + S->body()->getName() + " is overridden"); | 
|  | 291 | return 1; | 
|  | 292 | } | 
|  | 293 | return 0; | 
|  | 294 | } | 
|  | 295 |  | 
|  | 296 | template <class ELFT> | 
|  | 297 | Symbol *SymbolTable<ELFT>::addCommon(StringRef N, uint64_t Size, | 
|  | 298 | uint64_t Alignment, uint8_t Binding, | 
|  | 299 | uint8_t StOther, uint8_t Type, | 
|  | 300 | InputFile *File) { | 
|  | 301 | Symbol *S; | 
|  | 302 | bool WasInserted; | 
|  | 303 | std::tie(S, WasInserted) = | 
|  | 304 | insert(N, Type, StOther & 3, /*CanOmitFromDynSym*/ false, | 
|  | 305 | /*IsUsedInRegularObj*/ true, File); | 
|  | 306 | int Cmp = compareDefined(S, WasInserted, Binding); | 
|  | 307 | if (Cmp > 0) { | 
|  | 308 | S->Binding = Binding; | 
|  | 309 | replaceBody<DefinedCommon>(S, N, Size, Alignment, StOther, Type); | 
|  | 310 | } else if (Cmp == 0) { | 
|  | 311 | auto *C = dyn_cast<DefinedCommon>(S->body()); | 
|  | 312 | if (!C) { | 
|  | 313 | // Non-common symbols take precedence over common symbols. | 
|  | 314 | if (Config->WarnCommon) | 
|  | 315 | warning("common " + S->body()->getName() + " is overridden"); | 
|  | 316 | return S; | 
|  | 317 | } | 
|  | 318 |  | 
|  | 319 | if (Config->WarnCommon) | 
|  | 320 | warning("multiple common of " + S->body()->getName()); | 
|  | 321 |  | 
|  | 322 | C->Size = std::max(C->Size, Size); | 
|  | 323 | C->Alignment = std::max(C->Alignment, Alignment); | 
|  | 324 | } | 
|  | 325 | return S; | 
|  | 326 | } | 
|  | 327 |  | 
|  | 328 | template <class ELFT> | 
|  | 329 | void SymbolTable<ELFT>::reportDuplicate(SymbolBody *Existing, | 
|  | 330 | InputFile *NewFile) { | 
|  | 331 | std::string Msg = "duplicate symbol: " + conflictMsg(Existing, NewFile); | 
|  | 332 | if (Config->AllowMultipleDefinition) | 
|  | 333 | warning(Msg); | 
|  | 334 | else | 
|  | 335 | error(Msg); | 
|  | 336 | } | 
|  | 337 |  | 
|  | 338 | template <typename ELFT> | 
|  | 339 | Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, const Elf_Sym &Sym, | 
|  | 340 | InputSectionBase<ELFT> *Section) { | 
|  | 341 | Symbol *S; | 
|  | 342 | bool WasInserted; | 
|  | 343 | std::tie(S, WasInserted) = | 
|  | 344 | insert(Name, Sym.getType(), Sym.getVisibility(), | 
|  | 345 | /*CanOmitFromDynSym*/ false, /*IsUsedInRegularObj*/ true, | 
|  | 346 | Section ? Section->getFile() : nullptr); | 
|  | 347 | int Cmp = compareDefinedNonCommon(S, WasInserted, Sym.getBinding()); | 
|  | 348 | if (Cmp > 0) | 
|  | 349 | replaceBody<DefinedRegular<ELFT>>(S, Name, Sym, Section); | 
|  | 350 | else if (Cmp == 0) | 
|  | 351 | reportDuplicate(S->body(), Section->getFile()); | 
|  | 352 | return S; | 
|  | 353 | } | 
|  | 354 |  | 
|  | 355 | template <typename ELFT> | 
|  | 356 | Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t Binding, | 
|  | 357 | uint8_t StOther) { | 
|  | 358 | Symbol *S; | 
|  | 359 | bool WasInserted; | 
|  | 360 | std::tie(S, WasInserted) = | 
|  | 361 | insert(Name, STT_NOTYPE, StOther & 3, /*CanOmitFromDynSym*/ false, | 
|  | 362 | /*IsUsedInRegularObj*/ true, nullptr); | 
|  | 363 | int Cmp = compareDefinedNonCommon(S, WasInserted, Binding); | 
|  | 364 | if (Cmp > 0) | 
|  | 365 | replaceBody<DefinedRegular<ELFT>>(S, Name, StOther); | 
|  | 366 | else if (Cmp == 0) | 
|  | 367 | reportDuplicate(S->body(), nullptr); | 
|  | 368 | return S; | 
|  | 369 | } | 
|  | 370 |  | 
|  | 371 | template <typename ELFT> | 
|  | 372 | Symbol *SymbolTable<ELFT>::addSynthetic(StringRef N, | 
| Peter Collingbourne | 6a42259 | 2016-05-03 01:21:08 +0000 | [diff] [blame] | 373 | OutputSectionBase<ELFT> *Section, | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 374 | uintX_t Value) { | 
|  | 375 | Symbol *S; | 
|  | 376 | bool WasInserted; | 
|  | 377 | std::tie(S, WasInserted) = | 
|  | 378 | insert(N, STT_NOTYPE, STV_HIDDEN, /*CanOmitFromDynSym*/ false, | 
|  | 379 | /*IsUsedInRegularObj*/ true, nullptr); | 
|  | 380 | int Cmp = compareDefinedNonCommon(S, WasInserted, STB_GLOBAL); | 
|  | 381 | if (Cmp > 0) | 
|  | 382 | replaceBody<DefinedSynthetic<ELFT>>(S, N, Value, Section); | 
|  | 383 | else if (Cmp == 0) | 
|  | 384 | reportDuplicate(S->body(), nullptr); | 
|  | 385 | return S; | 
|  | 386 | } | 
|  | 387 |  | 
|  | 388 | template <typename ELFT> | 
|  | 389 | void SymbolTable<ELFT>::addShared(SharedFile<ELFT> *F, StringRef Name, | 
|  | 390 | const Elf_Sym &Sym, | 
|  | 391 | const typename ELFT::Verdef *Verdef) { | 
|  | 392 | // DSO symbols do not affect visibility in the output, so we pass STV_DEFAULT | 
|  | 393 | // as the visibility, which will leave the visibility in the symbol table | 
|  | 394 | // unchanged. | 
|  | 395 | Symbol *S; | 
|  | 396 | bool WasInserted; | 
|  | 397 | std::tie(S, WasInserted) = | 
|  | 398 | insert(Name, Sym.getType(), STV_DEFAULT, /*CanOmitFromDynSym*/ true, | 
|  | 399 | /*IsUsedInRegularObj*/ false, F); | 
|  | 400 | // Make sure we preempt DSO symbols with default visibility. | 
|  | 401 | if (Sym.getVisibility() == STV_DEFAULT) | 
|  | 402 | S->ExportDynamic = true; | 
| Peter Collingbourne | ca8c994 | 2016-06-09 18:01:35 +0000 | [diff] [blame] | 403 | if (WasInserted || isa<Undefined>(S->body())) { | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 404 | replaceBody<SharedSymbol<ELFT>>(S, F, Name, Sym, Verdef); | 
| Peter Collingbourne | ca8c994 | 2016-06-09 18:01:35 +0000 | [diff] [blame] | 405 | if (!S->isWeak()) | 
|  | 406 | F->IsUsed = true; | 
|  | 407 | } | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 408 | } | 
|  | 409 |  | 
|  | 410 | template <class ELFT> | 
|  | 411 | Symbol *SymbolTable<ELFT>::addBitcode(StringRef Name, bool IsWeak, | 
|  | 412 | uint8_t StOther, uint8_t Type, | 
|  | 413 | bool CanOmitFromDynSym, BitcodeFile *F) { | 
|  | 414 | Symbol *S; | 
|  | 415 | bool WasInserted; | 
|  | 416 | std::tie(S, WasInserted) = insert(Name, Type, StOther & 3, CanOmitFromDynSym, | 
|  | 417 | /*IsUsedInRegularObj*/ false, F); | 
|  | 418 | int Cmp = | 
|  | 419 | compareDefinedNonCommon(S, WasInserted, IsWeak ? STB_WEAK : STB_GLOBAL); | 
|  | 420 | if (Cmp > 0) | 
|  | 421 | replaceBody<DefinedBitcode>(S, Name, StOther, Type, F); | 
|  | 422 | else if (Cmp == 0) | 
|  | 423 | reportDuplicate(S->body(), F); | 
|  | 424 | return S; | 
| Michael J. Spencer | 1b348a6 | 2015-09-04 22:28:10 +0000 | [diff] [blame] | 425 | } | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 426 |  | 
| Rui Ueyama | f8432d9 | 2015-10-13 16:34:14 +0000 | [diff] [blame] | 427 | template <class ELFT> SymbolBody *SymbolTable<ELFT>::find(StringRef Name) { | 
|  | 428 | auto It = Symtab.find(Name); | 
|  | 429 | if (It == Symtab.end()) | 
|  | 430 | return nullptr; | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 431 | return SymVector[It->second]->body(); | 
| Michael J. Spencer | 1b348a6 | 2015-09-04 22:28:10 +0000 | [diff] [blame] | 432 | } | 
|  | 433 |  | 
| Rui Ueyama | 3d45179 | 2015-10-12 18:03:21 +0000 | [diff] [blame] | 434 | template <class ELFT> | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 435 | void SymbolTable<ELFT>::addLazyArchive( | 
|  | 436 | ArchiveFile *F, const llvm::object::Archive::Symbol Sym) { | 
|  | 437 | Symbol *S; | 
|  | 438 | bool WasInserted; | 
|  | 439 | std::tie(S, WasInserted) = insert(Sym.getName()); | 
|  | 440 | if (WasInserted) { | 
| Rafael Espindola | 07543a8 | 2016-06-14 21:40:23 +0000 | [diff] [blame] | 441 | replaceBody<LazyArchive>(S, *F, Sym, SymbolBody::UnknownType); | 
| Rui Ueyama | c5b9512 | 2015-12-16 23:23:14 +0000 | [diff] [blame] | 442 | return; | 
|  | 443 | } | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 444 | if (!S->body()->isUndefined()) | 
|  | 445 | return; | 
| Rui Ueyama | c5b9512 | 2015-12-16 23:23:14 +0000 | [diff] [blame] | 446 |  | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 447 | // Weak undefined symbols should not fetch members from archives. If we were | 
|  | 448 | // to keep old symbol we would not know that an archive member was available | 
|  | 449 | // if a strong undefined symbol shows up afterwards in the link. If a strong | 
|  | 450 | // undefined symbol never shows up, this lazy symbol will get to the end of | 
|  | 451 | // the link and must be treated as the weak undefined one. We already marked | 
|  | 452 | // this symbol as used when we added it to the symbol table, but we also need | 
|  | 453 | // to preserve its type. FIXME: Move the Type field to Symbol. | 
|  | 454 | if (S->isWeak()) { | 
| Rafael Espindola | 07543a8 | 2016-06-14 21:40:23 +0000 | [diff] [blame] | 455 | replaceBody<LazyArchive>(S, *F, Sym, S->body()->Type); | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 456 | return; | 
|  | 457 | } | 
|  | 458 | MemoryBufferRef MBRef = F->getMember(&Sym); | 
|  | 459 | if (!MBRef.getBuffer().empty()) | 
|  | 460 | addFile(createObjectFile(MBRef, F->getName())); | 
|  | 461 | } | 
|  | 462 |  | 
|  | 463 | template <class ELFT> | 
| Rafael Espindola | 65c65ce | 2016-06-14 21:56:36 +0000 | [diff] [blame] | 464 | void SymbolTable<ELFT>::addLazyObject(StringRef Name, LazyObjectFile &Obj) { | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 465 | Symbol *S; | 
|  | 466 | bool WasInserted; | 
|  | 467 | std::tie(S, WasInserted) = insert(Name); | 
|  | 468 | if (WasInserted) { | 
| Rafael Espindola | 65c65ce | 2016-06-14 21:56:36 +0000 | [diff] [blame] | 469 | replaceBody<LazyObject>(S, Name, Obj, SymbolBody::UnknownType); | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 470 | return; | 
|  | 471 | } | 
|  | 472 | if (!S->body()->isUndefined()) | 
|  | 473 | return; | 
|  | 474 |  | 
|  | 475 | // See comment for addLazyArchive above. | 
| Rafael Espindola | 65c65ce | 2016-06-14 21:56:36 +0000 | [diff] [blame] | 476 | if (S->isWeak()) { | 
|  | 477 | replaceBody<LazyObject>(S, Name, Obj, S->body()->Type); | 
|  | 478 | } else { | 
|  | 479 | MemoryBufferRef MBRef = Obj.getBuffer(); | 
|  | 480 | if (!MBRef.getBuffer().empty()) | 
|  | 481 | addFile(createObjectFile(MBRef)); | 
|  | 482 | } | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 483 | } | 
| Rafael Espindola | 0e604f9 | 2015-09-25 18:56:53 +0000 | [diff] [blame] | 484 |  | 
| Peter Collingbourne | 892d4980 | 2016-04-27 00:05:03 +0000 | [diff] [blame] | 485 | // Process undefined (-u) flags by loading lazy symbols named by those flags. | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 486 | template <class ELFT> void SymbolTable<ELFT>::scanUndefinedFlags() { | 
| Peter Collingbourne | 892d4980 | 2016-04-27 00:05:03 +0000 | [diff] [blame] | 487 | for (StringRef S : Config->Undefined) | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 488 | if (auto *L = dyn_cast_or_null<Lazy>(find(S))) | 
|  | 489 | if (std::unique_ptr<InputFile> File = L->getFile()) | 
|  | 490 | addFile(std::move(File)); | 
| Peter Collingbourne | 892d4980 | 2016-04-27 00:05:03 +0000 | [diff] [blame] | 491 | } | 
|  | 492 |  | 
| Rui Ueyama | 93bfee5 | 2015-10-13 18:10:33 +0000 | [diff] [blame] | 493 | // This function takes care of the case in which shared libraries depend on | 
|  | 494 | // the user program (not the other way, which is usual). Shared libraries | 
|  | 495 | // may have undefined symbols, expecting that the user program provides | 
|  | 496 | // the definitions for them. An example is BSD's __progname symbol. | 
|  | 497 | // We need to put such symbols to the main program's .dynsym so that | 
|  | 498 | // shared libraries can find them. | 
|  | 499 | // Except this, we ignore undefined symbols in DSOs. | 
|  | 500 | template <class ELFT> void SymbolTable<ELFT>::scanShlibUndefined() { | 
| Rui Ueyama | f8432d9 | 2015-10-13 16:34:14 +0000 | [diff] [blame] | 501 | for (std::unique_ptr<SharedFile<ELFT>> &File : SharedFiles) | 
|  | 502 | for (StringRef U : File->getUndefinedSymbols()) | 
|  | 503 | if (SymbolBody *Sym = find(U)) | 
|  | 504 | if (Sym->isDefined()) | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 505 | Sym->symbol()->ExportDynamic = true; | 
| Rui Ueyama | f8432d9 | 2015-10-13 16:34:14 +0000 | [diff] [blame] | 506 | } | 
|  | 507 |  | 
| Adhemerval Zanella | 9df0720 | 2016-04-13 18:51:11 +0000 | [diff] [blame] | 508 | // This function process the dynamic list option by marking all the symbols | 
|  | 509 | // to be exported in the dynamic table. | 
|  | 510 | template <class ELFT> void SymbolTable<ELFT>::scanDynamicList() { | 
|  | 511 | for (StringRef S : Config->DynamicList) | 
|  | 512 | if (SymbolBody *B = find(S)) | 
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 513 | B->symbol()->ExportDynamic = true; | 
| Adhemerval Zanella | 9df0720 | 2016-04-13 18:51:11 +0000 | [diff] [blame] | 514 | } | 
|  | 515 |  | 
| Peter Collingbourne | 66ac1d6 | 2016-04-22 20:21:26 +0000 | [diff] [blame] | 516 | // This function processes the --version-script option by marking all global | 
|  | 517 | // symbols with the VersionScriptGlobal flag, which acts as a filter on the | 
|  | 518 | // dynamic symbol table. | 
|  | 519 | template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() { | 
| George Rimar | d356630 | 2016-06-20 11:55:12 +0000 | [diff] [blame] | 520 | // If version script does not contain versions declarations, | 
|  | 521 | // we just should mark global symbols. | 
|  | 522 | if (!Config->VersionScriptGlobals.empty()) { | 
|  | 523 | for (StringRef S : Config->VersionScriptGlobals) | 
|  | 524 | if (SymbolBody *B = find(S)) | 
|  | 525 | B->symbol()->VersionId = VER_NDX_GLOBAL; | 
|  | 526 | return; | 
|  | 527 | } | 
|  | 528 |  | 
|  | 529 | // If we have symbols version declarations, we should | 
|  | 530 | // assign version references for each symbol. | 
|  | 531 | size_t I = 2; | 
|  | 532 | for (Version &V : Config->SymbolVersions) { | 
|  | 533 | for (StringRef Name : V.Globals) | 
|  | 534 | if (SymbolBody *B = find(Name)) | 
|  | 535 | B->symbol()->VersionId = I; | 
|  | 536 | ++I; | 
|  | 537 | } | 
| Peter Collingbourne | 66ac1d6 | 2016-04-22 20:21:26 +0000 | [diff] [blame] | 538 | } | 
|  | 539 |  | 
| Rafael Espindola | e0df00b | 2016-02-28 00:25:54 +0000 | [diff] [blame] | 540 | template class elf::SymbolTable<ELF32LE>; | 
|  | 541 | template class elf::SymbolTable<ELF32BE>; | 
|  | 542 | template class elf::SymbolTable<ELF64LE>; | 
|  | 543 | template class elf::SymbolTable<ELF64BE>; |