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 "Config.h" 12 #include "InputChunks.h" 13 #include "InputFiles.h" 14 #include "InputGlobal.h" 15 #include "OutputSegment.h" 16 #include "lld/Common/ErrorHandler.h" 17 #include "lld/Common/Strings.h" 18 19 #define DEBUG_TYPE "lld" 20 21 using namespace llvm; 22 using namespace llvm::wasm; 23 using namespace lld; 24 using namespace lld::wasm; 25 26 DefinedFunction *WasmSym::CallCtors; 27 DefinedData *WasmSym::DsoHandle; 28 DefinedData *WasmSym::DataEnd; 29 DefinedData *WasmSym::HeapBase; 30 GlobalSymbol *WasmSym::StackPointer; 31 UndefinedGlobal *WasmSym::TableBase; 32 UndefinedGlobal *WasmSym::MemoryBase; 33 34 WasmSymbolType Symbol::getWasmType() const { 35 if (isa<FunctionSymbol>(this)) 36 return WASM_SYMBOL_TYPE_FUNCTION; 37 if (isa<DataSymbol>(this)) 38 return WASM_SYMBOL_TYPE_DATA; 39 if (isa<GlobalSymbol>(this)) 40 return WASM_SYMBOL_TYPE_GLOBAL; 41 if (isa<SectionSymbol>(this)) 42 return WASM_SYMBOL_TYPE_SECTION; 43 llvm_unreachable("invalid symbol kind"); 44 } 45 46 InputChunk *Symbol::getChunk() const { 47 if (auto *F = dyn_cast<DefinedFunction>(this)) 48 return F->Function; 49 if (auto *D = dyn_cast<DefinedData>(this)) 50 return D->Segment; 51 return nullptr; 52 } 53 54 bool Symbol::isLive() const { 55 if (auto *G = dyn_cast<DefinedGlobal>(this)) 56 return G->Global->Live; 57 if (InputChunk *C = getChunk()) 58 return C->Live; 59 return Referenced; 60 } 61 62 void Symbol::markLive() { 63 if (auto *G = dyn_cast<DefinedGlobal>(this)) 64 G->Global->Live = true; 65 if (InputChunk *C = getChunk()) 66 C->Live = true; 67 Referenced = true; 68 } 69 70 uint32_t Symbol::getOutputSymbolIndex() const { 71 assert(OutputSymbolIndex != INVALID_INDEX); 72 return OutputSymbolIndex; 73 } 74 75 void Symbol::setOutputSymbolIndex(uint32_t Index) { 76 LLVM_DEBUG(dbgs() << "setOutputSymbolIndex " << Name << " -> " << Index 77 << "\n"); 78 assert(OutputSymbolIndex == INVALID_INDEX); 79 OutputSymbolIndex = Index; 80 } 81 82 bool Symbol::isWeak() const { 83 return (Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK; 84 } 85 86 bool Symbol::isLocal() const { 87 return (Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_LOCAL; 88 } 89 90 bool Symbol::isHidden() const { 91 return (Flags & WASM_SYMBOL_VISIBILITY_MASK) == WASM_SYMBOL_VISIBILITY_HIDDEN; 92 } 93 94 void Symbol::setHidden(bool IsHidden) { 95 LLVM_DEBUG(dbgs() << "setHidden: " << Name << " -> " << IsHidden << "\n"); 96 Flags &= ~WASM_SYMBOL_VISIBILITY_MASK; 97 if (IsHidden) 98 Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN; 99 else 100 Flags |= WASM_SYMBOL_VISIBILITY_DEFAULT; 101 } 102 103 bool Symbol::isExported() const { 104 if (!isDefined() || isLocal()) 105 return false; 106 107 if (ForceExport || Config->ExportAll) 108 return true; 109 110 if (Config->ExportDynamic && !isHidden()) 111 return true; 112 113 return false; 114 } 115 116 uint32_t FunctionSymbol::getFunctionIndex() const { 117 if (auto *F = dyn_cast<DefinedFunction>(this)) 118 return F->Function->getFunctionIndex(); 119 assert(FunctionIndex != INVALID_INDEX); 120 return FunctionIndex; 121 } 122 123 void FunctionSymbol::setFunctionIndex(uint32_t Index) { 124 LLVM_DEBUG(dbgs() << "setFunctionIndex " << Name << " -> " << Index << "\n"); 125 assert(FunctionIndex == INVALID_INDEX); 126 FunctionIndex = Index; 127 } 128 129 bool FunctionSymbol::hasFunctionIndex() const { 130 if (auto *F = dyn_cast<DefinedFunction>(this)) 131 return F->Function->hasFunctionIndex(); 132 return FunctionIndex != INVALID_INDEX; 133 } 134 135 uint32_t FunctionSymbol::getTableIndex() const { 136 if (auto *F = dyn_cast<DefinedFunction>(this)) 137 return F->Function->getTableIndex(); 138 assert(TableIndex != INVALID_INDEX); 139 return TableIndex; 140 } 141 142 bool FunctionSymbol::hasTableIndex() const { 143 if (auto *F = dyn_cast<DefinedFunction>(this)) 144 return F->Function->hasTableIndex(); 145 return TableIndex != INVALID_INDEX; 146 } 147 148 void FunctionSymbol::setTableIndex(uint32_t Index) { 149 // For imports, we set the table index here on the Symbol; for defined 150 // functions we set the index on the InputFunction so that we don't export 151 // the same thing twice (keeps the table size down). 152 if (auto *F = dyn_cast<DefinedFunction>(this)) { 153 F->Function->setTableIndex(Index); 154 return; 155 } 156 LLVM_DEBUG(dbgs() << "setTableIndex " << Name << " -> " << Index << "\n"); 157 assert(TableIndex == INVALID_INDEX); 158 TableIndex = Index; 159 } 160 161 DefinedFunction::DefinedFunction(StringRef Name, uint32_t Flags, InputFile *F, 162 InputFunction *Function) 163 : FunctionSymbol(Name, DefinedFunctionKind, Flags, F, 164 Function ? &Function->Signature : nullptr), 165 Function(Function) {} 166 167 uint32_t DefinedData::getVirtualAddress() const { 168 LLVM_DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n"); 169 if (Segment) 170 return Segment->OutputSeg->StartVA + Segment->OutputSegmentOffset + Offset; 171 return Offset; 172 } 173 174 void DefinedData::setVirtualAddress(uint32_t Value) { 175 LLVM_DEBUG(dbgs() << "setVirtualAddress " << Name << " -> " << Value << "\n"); 176 assert(!Segment); 177 Offset = Value; 178 } 179 180 uint32_t DefinedData::getOutputSegmentOffset() const { 181 LLVM_DEBUG(dbgs() << "getOutputSegmentOffset: " << getName() << "\n"); 182 return Segment->OutputSegmentOffset + Offset; 183 } 184 185 uint32_t DefinedData::getOutputSegmentIndex() const { 186 LLVM_DEBUG(dbgs() << "getOutputSegmentIndex: " << getName() << "\n"); 187 return Segment->OutputSeg->Index; 188 } 189 190 uint32_t GlobalSymbol::getGlobalIndex() const { 191 if (auto *F = dyn_cast<DefinedGlobal>(this)) 192 return F->Global->getGlobalIndex(); 193 assert(GlobalIndex != INVALID_INDEX); 194 return GlobalIndex; 195 } 196 197 void GlobalSymbol::setGlobalIndex(uint32_t Index) { 198 LLVM_DEBUG(dbgs() << "setGlobalIndex " << Name << " -> " << Index << "\n"); 199 assert(GlobalIndex == INVALID_INDEX); 200 GlobalIndex = Index; 201 } 202 203 bool GlobalSymbol::hasGlobalIndex() const { 204 if (auto *F = dyn_cast<DefinedGlobal>(this)) 205 return F->Global->hasGlobalIndex(); 206 return GlobalIndex != INVALID_INDEX; 207 } 208 209 DefinedGlobal::DefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File, 210 InputGlobal *Global) 211 : GlobalSymbol(Name, DefinedGlobalKind, Flags, File, 212 Global ? &Global->getType() : nullptr), 213 Global(Global) {} 214 215 uint32_t SectionSymbol::getOutputSectionIndex() const { 216 LLVM_DEBUG(dbgs() << "getOutputSectionIndex: " << getName() << "\n"); 217 assert(OutputSectionIndex != INVALID_INDEX); 218 return OutputSectionIndex; 219 } 220 221 void SectionSymbol::setOutputSectionIndex(uint32_t Index) { 222 LLVM_DEBUG(dbgs() << "setOutputSectionIndex: " << getName() << " -> " << Index 223 << "\n"); 224 assert(Index != INVALID_INDEX); 225 OutputSectionIndex = Index; 226 } 227 228 void LazySymbol::fetch() { cast<ArchiveFile>(File)->addMember(&ArchiveSymbol); } 229 230 std::string lld::toString(const wasm::Symbol &Sym) { 231 return lld::maybeDemangleSymbol(Sym.getName()); 232 } 233 234 std::string lld::maybeDemangleSymbol(StringRef Name) { 235 if (Config->Demangle) 236 if (Optional<std::string> S = demangleItanium(Name)) 237 return *S; 238 return Name; 239 } 240 241 std::string lld::toString(wasm::Symbol::Kind Kind) { 242 switch (Kind) { 243 case wasm::Symbol::DefinedFunctionKind: 244 return "DefinedFunction"; 245 case wasm::Symbol::DefinedDataKind: 246 return "DefinedData"; 247 case wasm::Symbol::DefinedGlobalKind: 248 return "DefinedGlobal"; 249 case wasm::Symbol::UndefinedFunctionKind: 250 return "UndefinedFunction"; 251 case wasm::Symbol::UndefinedDataKind: 252 return "UndefinedData"; 253 case wasm::Symbol::UndefinedGlobalKind: 254 return "UndefinedGlobal"; 255 case wasm::Symbol::LazyKind: 256 return "LazyKind"; 257 case wasm::Symbol::SectionKind: 258 return "SectionKind"; 259 } 260 llvm_unreachable("invalid symbol kind"); 261 } 262