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