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