1 //===- Symbols.cpp --------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "Symbols.h" 10 #include "Config.h" 11 #include "InputChunks.h" 12 #include "InputEvent.h" 13 #include "InputFiles.h" 14 #include "InputGlobal.h" 15 #include "OutputSections.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::object; 24 using namespace llvm::wasm; 25 26 namespace lld { 27 std::string toString(const wasm::Symbol &sym) { 28 return maybeDemangleSymbol(sym.getName()); 29 } 30 31 std::string maybeDemangleSymbol(StringRef name) { 32 // WebAssembly requires caller and callee signatures to match, so we mangle 33 // `main` in the case where we need to pass it arguments. 34 if (name == "__main_argc_argv") 35 return "main"; 36 if (wasm::config->demangle) 37 return demangleItanium(name); 38 return std::string(name); 39 } 40 41 std::string toString(wasm::Symbol::Kind kind) { 42 switch (kind) { 43 case wasm::Symbol::DefinedFunctionKind: 44 return "DefinedFunction"; 45 case wasm::Symbol::DefinedDataKind: 46 return "DefinedData"; 47 case wasm::Symbol::DefinedGlobalKind: 48 return "DefinedGlobal"; 49 case wasm::Symbol::DefinedEventKind: 50 return "DefinedEvent"; 51 case wasm::Symbol::UndefinedFunctionKind: 52 return "UndefinedFunction"; 53 case wasm::Symbol::UndefinedDataKind: 54 return "UndefinedData"; 55 case wasm::Symbol::UndefinedGlobalKind: 56 return "UndefinedGlobal"; 57 case wasm::Symbol::LazyKind: 58 return "LazyKind"; 59 case wasm::Symbol::SectionKind: 60 return "SectionKind"; 61 case wasm::Symbol::OutputSectionKind: 62 return "OutputSectionKind"; 63 } 64 llvm_unreachable("invalid symbol kind"); 65 } 66 67 namespace wasm { 68 DefinedFunction *WasmSym::callCtors; 69 DefinedFunction *WasmSym::callDtors; 70 DefinedFunction *WasmSym::initMemory; 71 DefinedFunction *WasmSym::applyRelocs; 72 DefinedFunction *WasmSym::initTLS; 73 DefinedData *WasmSym::dsoHandle; 74 DefinedData *WasmSym::dataEnd; 75 DefinedData *WasmSym::globalBase; 76 DefinedData *WasmSym::heapBase; 77 DefinedData *WasmSym::initMemoryFlag; 78 GlobalSymbol *WasmSym::stackPointer; 79 GlobalSymbol *WasmSym::tlsBase; 80 GlobalSymbol *WasmSym::tlsSize; 81 GlobalSymbol *WasmSym::tlsAlign; 82 UndefinedGlobal *WasmSym::tableBase; 83 DefinedData *WasmSym::definedTableBase; 84 UndefinedGlobal *WasmSym::memoryBase; 85 DefinedData *WasmSym::definedMemoryBase; 86 87 WasmSymbolType Symbol::getWasmType() const { 88 if (isa<FunctionSymbol>(this)) 89 return WASM_SYMBOL_TYPE_FUNCTION; 90 if (isa<DataSymbol>(this)) 91 return WASM_SYMBOL_TYPE_DATA; 92 if (isa<GlobalSymbol>(this)) 93 return WASM_SYMBOL_TYPE_GLOBAL; 94 if (isa<EventSymbol>(this)) 95 return WASM_SYMBOL_TYPE_EVENT; 96 if (isa<SectionSymbol>(this) || isa<OutputSectionSymbol>(this)) 97 return WASM_SYMBOL_TYPE_SECTION; 98 llvm_unreachable("invalid symbol kind"); 99 } 100 101 const WasmSignature *Symbol::getSignature() const { 102 if (auto* f = dyn_cast<FunctionSymbol>(this)) 103 return f->signature; 104 if (auto *l = dyn_cast<LazySymbol>(this)) 105 return l->signature; 106 return nullptr; 107 } 108 109 InputChunk *Symbol::getChunk() const { 110 if (auto *f = dyn_cast<DefinedFunction>(this)) 111 return f->function; 112 if (auto *d = dyn_cast<DefinedData>(this)) 113 return d->segment; 114 return nullptr; 115 } 116 117 bool Symbol::isDiscarded() const { 118 if (InputChunk *c = getChunk()) 119 return c->discarded; 120 return false; 121 } 122 123 bool Symbol::isLive() const { 124 if (auto *g = dyn_cast<DefinedGlobal>(this)) 125 return g->global->live; 126 if (auto *e = dyn_cast<DefinedEvent>(this)) 127 return e->event->live; 128 if (InputChunk *c = getChunk()) 129 return c->live; 130 return referenced; 131 } 132 133 void Symbol::markLive() { 134 assert(!isDiscarded()); 135 if (file != NULL) 136 file->markLive(); 137 if (auto *g = dyn_cast<DefinedGlobal>(this)) 138 g->global->live = true; 139 if (auto *e = dyn_cast<DefinedEvent>(this)) 140 e->event->live = true; 141 if (InputChunk *c = getChunk()) 142 c->live = true; 143 referenced = true; 144 } 145 146 uint32_t Symbol::getOutputSymbolIndex() const { 147 assert(outputSymbolIndex != INVALID_INDEX); 148 return outputSymbolIndex; 149 } 150 151 void Symbol::setOutputSymbolIndex(uint32_t index) { 152 LLVM_DEBUG(dbgs() << "setOutputSymbolIndex " << name << " -> " << index 153 << "\n"); 154 assert(outputSymbolIndex == INVALID_INDEX); 155 outputSymbolIndex = index; 156 } 157 158 void Symbol::setGOTIndex(uint32_t index) { 159 LLVM_DEBUG(dbgs() << "setGOTIndex " << name << " -> " << index << "\n"); 160 assert(gotIndex == INVALID_INDEX); 161 if (config->isPic) { 162 // Any symbol that is assigned a GOT entry must be exported otherwise the 163 // dynamic linker won't be able create the entry that contains it. 164 forceExport = true; 165 } 166 gotIndex = index; 167 } 168 169 bool Symbol::isWeak() const { 170 return (flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK; 171 } 172 173 bool Symbol::isLocal() const { 174 return (flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_LOCAL; 175 } 176 177 bool Symbol::isHidden() const { 178 return (flags & WASM_SYMBOL_VISIBILITY_MASK) == WASM_SYMBOL_VISIBILITY_HIDDEN; 179 } 180 181 void Symbol::setHidden(bool isHidden) { 182 LLVM_DEBUG(dbgs() << "setHidden: " << name << " -> " << isHidden << "\n"); 183 flags &= ~WASM_SYMBOL_VISIBILITY_MASK; 184 if (isHidden) 185 flags |= WASM_SYMBOL_VISIBILITY_HIDDEN; 186 else 187 flags |= WASM_SYMBOL_VISIBILITY_DEFAULT; 188 } 189 190 bool Symbol::isExported() const { 191 if (!isDefined() || isLocal()) 192 return false; 193 194 if (forceExport || config->exportAll) 195 return true; 196 197 if (config->exportDynamic && !isHidden()) 198 return true; 199 200 return flags & WASM_SYMBOL_EXPORTED; 201 } 202 203 bool Symbol::isNoStrip() const { 204 return flags & WASM_SYMBOL_NO_STRIP; 205 } 206 207 uint32_t FunctionSymbol::getFunctionIndex() const { 208 if (auto *f = dyn_cast<DefinedFunction>(this)) 209 return f->function->getFunctionIndex(); 210 assert(functionIndex != INVALID_INDEX); 211 return functionIndex; 212 } 213 214 void FunctionSymbol::setFunctionIndex(uint32_t index) { 215 LLVM_DEBUG(dbgs() << "setFunctionIndex " << name << " -> " << index << "\n"); 216 assert(functionIndex == INVALID_INDEX); 217 functionIndex = index; 218 } 219 220 bool FunctionSymbol::hasFunctionIndex() const { 221 if (auto *f = dyn_cast<DefinedFunction>(this)) 222 return f->function->hasFunctionIndex(); 223 return functionIndex != INVALID_INDEX; 224 } 225 226 uint32_t FunctionSymbol::getTableIndex() const { 227 if (auto *f = dyn_cast<DefinedFunction>(this)) 228 return f->function->getTableIndex(); 229 assert(tableIndex != INVALID_INDEX); 230 return tableIndex; 231 } 232 233 bool FunctionSymbol::hasTableIndex() const { 234 if (auto *f = dyn_cast<DefinedFunction>(this)) 235 return f->function->hasTableIndex(); 236 return tableIndex != INVALID_INDEX; 237 } 238 239 void FunctionSymbol::setTableIndex(uint32_t index) { 240 // For imports, we set the table index here on the Symbol; for defined 241 // functions we set the index on the InputFunction so that we don't export 242 // the same thing twice (keeps the table size down). 243 if (auto *f = dyn_cast<DefinedFunction>(this)) { 244 f->function->setTableIndex(index); 245 return; 246 } 247 LLVM_DEBUG(dbgs() << "setTableIndex " << name << " -> " << index << "\n"); 248 assert(tableIndex == INVALID_INDEX); 249 tableIndex = index; 250 } 251 252 DefinedFunction::DefinedFunction(StringRef name, uint32_t flags, InputFile *f, 253 InputFunction *function) 254 : FunctionSymbol(name, DefinedFunctionKind, flags, f, 255 function ? &function->signature : nullptr), 256 function(function) {} 257 258 uint64_t DefinedData::getVirtualAddress() const { 259 LLVM_DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n"); 260 if (segment) { 261 // For thread local data, the symbol location is relative to the start of 262 // the .tdata section, since they are used as offsets from __tls_base. 263 // Hence, we do not add in segment->outputSeg->startVA. 264 if (segment->outputSeg->name == ".tdata") 265 return segment->outputSegmentOffset + offset; 266 return segment->outputSeg->startVA + segment->outputSegmentOffset + offset; 267 } 268 return offset; 269 } 270 271 void DefinedData::setVirtualAddress(uint64_t value) { 272 LLVM_DEBUG(dbgs() << "setVirtualAddress " << name << " -> " << value << "\n"); 273 assert(!segment); 274 offset = value; 275 } 276 277 uint64_t DefinedData::getOutputSegmentOffset() const { 278 LLVM_DEBUG(dbgs() << "getOutputSegmentOffset: " << getName() << "\n"); 279 return segment->outputSegmentOffset + offset; 280 } 281 282 uint64_t DefinedData::getOutputSegmentIndex() const { 283 LLVM_DEBUG(dbgs() << "getOutputSegmentIndex: " << getName() << "\n"); 284 return segment->outputSeg->index; 285 } 286 287 uint32_t GlobalSymbol::getGlobalIndex() const { 288 if (auto *f = dyn_cast<DefinedGlobal>(this)) 289 return f->global->getGlobalIndex(); 290 assert(globalIndex != INVALID_INDEX); 291 return globalIndex; 292 } 293 294 void GlobalSymbol::setGlobalIndex(uint32_t index) { 295 LLVM_DEBUG(dbgs() << "setGlobalIndex " << name << " -> " << index << "\n"); 296 assert(globalIndex == INVALID_INDEX); 297 globalIndex = index; 298 } 299 300 bool GlobalSymbol::hasGlobalIndex() const { 301 if (auto *f = dyn_cast<DefinedGlobal>(this)) 302 return f->global->hasGlobalIndex(); 303 return globalIndex != INVALID_INDEX; 304 } 305 306 DefinedGlobal::DefinedGlobal(StringRef name, uint32_t flags, InputFile *file, 307 InputGlobal *global) 308 : GlobalSymbol(name, DefinedGlobalKind, flags, file, 309 global ? &global->getType() : nullptr), 310 global(global) {} 311 312 uint32_t EventSymbol::getEventIndex() const { 313 if (auto *f = dyn_cast<DefinedEvent>(this)) 314 return f->event->getEventIndex(); 315 assert(eventIndex != INVALID_INDEX); 316 return eventIndex; 317 } 318 319 void EventSymbol::setEventIndex(uint32_t index) { 320 LLVM_DEBUG(dbgs() << "setEventIndex " << name << " -> " << index << "\n"); 321 assert(eventIndex == INVALID_INDEX); 322 eventIndex = index; 323 } 324 325 bool EventSymbol::hasEventIndex() const { 326 if (auto *f = dyn_cast<DefinedEvent>(this)) 327 return f->event->hasEventIndex(); 328 return eventIndex != INVALID_INDEX; 329 } 330 331 DefinedEvent::DefinedEvent(StringRef name, uint32_t flags, InputFile *file, 332 InputEvent *event) 333 : EventSymbol(name, DefinedEventKind, flags, file, 334 event ? &event->getType() : nullptr, 335 event ? &event->signature : nullptr), 336 event(event) {} 337 338 const OutputSectionSymbol *SectionSymbol::getOutputSectionSymbol() const { 339 assert(section->outputSec && section->outputSec->sectionSym); 340 return section->outputSec->sectionSym; 341 } 342 343 void LazySymbol::fetch() { cast<ArchiveFile>(file)->addMember(&archiveSymbol); } 344 345 void LazySymbol::setWeak() { 346 flags |= (flags & ~WASM_SYMBOL_BINDING_MASK) | WASM_SYMBOL_BINDING_WEAK; 347 } 348 349 MemoryBufferRef LazySymbol::getMemberBuffer() { 350 Archive::Child c = 351 CHECK(archiveSymbol.getMember(), 352 "could not get the member for symbol " + toString(*this)); 353 354 return CHECK(c.getMemoryBufferRef(), 355 "could not get the buffer for the member defining symbol " + 356 toString(*this)); 357 } 358 359 void printTraceSymbolUndefined(StringRef name, const InputFile* file) { 360 message(toString(file) + ": reference to " + name); 361 } 362 363 // Print out a log message for --trace-symbol. 364 void printTraceSymbol(Symbol *sym) { 365 // Undefined symbols are traced via printTraceSymbolUndefined 366 if (sym->isUndefined()) 367 return; 368 369 std::string s; 370 if (sym->isLazy()) 371 s = ": lazy definition of "; 372 else 373 s = ": definition of "; 374 375 message(toString(sym->getFile()) + s + sym->getName()); 376 } 377 378 const char *defaultModule = "env"; 379 const char *functionTableName = "__indirect_function_table"; 380 381 } // namespace wasm 382 } // namespace lld 383