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