SymbolTable.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. //===- SymbolTable.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. #include "SymbolTable.h"
  9. #include "Config.h"
  10. #include "InputChunks.h"
  11. #include "InputEvent.h"
  12. #include "InputGlobal.h"
  13. #include "WriterUtils.h"
  14. #include "lld/Common/ErrorHandler.h"
  15. #include "lld/Common/Memory.h"
  16. #include "llvm/ADT/SetVector.h"
  17. #define DEBUG_TYPE "lld"
  18. using namespace llvm;
  19. using namespace llvm::wasm;
  20. using namespace llvm::object;
  21. namespace lld {
  22. namespace wasm {
  23. SymbolTable *symtab;
  24. void SymbolTable::addFile(InputFile *file) {
  25. log("Processing: " + toString(file));
  26. // .a file
  27. if (auto *f = dyn_cast<ArchiveFile>(file)) {
  28. f->parse();
  29. return;
  30. }
  31. // .so file
  32. if (auto *f = dyn_cast<SharedFile>(file)) {
  33. sharedFiles.push_back(f);
  34. return;
  35. }
  36. if (config->trace)
  37. message(toString(file));
  38. // LLVM bitcode file
  39. if (auto *f = dyn_cast<BitcodeFile>(file)) {
  40. f->parse();
  41. bitcodeFiles.push_back(f);
  42. return;
  43. }
  44. // Regular object file
  45. auto *f = cast<ObjFile>(file);
  46. f->parse(false);
  47. objectFiles.push_back(f);
  48. }
  49. // This function is where all the optimizations of link-time
  50. // optimization happens. When LTO is in use, some input files are
  51. // not in native object file format but in the LLVM bitcode format.
  52. // This function compiles bitcode files into a few big native files
  53. // using LLVM functions and replaces bitcode symbols with the results.
  54. // Because all bitcode files that the program consists of are passed
  55. // to the compiler at once, it can do whole-program optimization.
  56. void SymbolTable::addCombinedLTOObject() {
  57. if (bitcodeFiles.empty())
  58. return;
  59. // Compile bitcode files and replace bitcode symbols.
  60. lto.reset(new BitcodeCompiler);
  61. for (BitcodeFile *f : bitcodeFiles)
  62. lto->add(*f);
  63. for (StringRef filename : lto->compile()) {
  64. auto *obj = make<ObjFile>(MemoryBufferRef(filename, "lto.tmp"), "");
  65. obj->parse(true);
  66. objectFiles.push_back(obj);
  67. }
  68. }
  69. Symbol *SymbolTable::find(StringRef name) {
  70. auto it = symMap.find(CachedHashStringRef(name));
  71. if (it == symMap.end() || it->second == -1)
  72. return nullptr;
  73. return symVector[it->second];
  74. }
  75. void SymbolTable::replace(StringRef name, Symbol* sym) {
  76. auto it = symMap.find(CachedHashStringRef(name));
  77. symVector[it->second] = sym;
  78. }
  79. std::pair<Symbol *, bool> SymbolTable::insertName(StringRef name) {
  80. bool trace = false;
  81. auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()});
  82. int &symIndex = p.first->second;
  83. bool isNew = p.second;
  84. if (symIndex == -1) {
  85. symIndex = symVector.size();
  86. trace = true;
  87. isNew = true;
  88. }
  89. if (!isNew)
  90. return {symVector[symIndex], false};
  91. Symbol *sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
  92. sym->isUsedInRegularObj = false;
  93. sym->canInline = true;
  94. sym->traced = trace;
  95. symVector.emplace_back(sym);
  96. return {sym, true};
  97. }
  98. std::pair<Symbol *, bool> SymbolTable::insert(StringRef name,
  99. const InputFile *file) {
  100. Symbol *s;
  101. bool wasInserted;
  102. std::tie(s, wasInserted) = insertName(name);
  103. if (!file || file->kind() == InputFile::ObjectKind)
  104. s->isUsedInRegularObj = true;
  105. return {s, wasInserted};
  106. }
  107. static void reportTypeError(const Symbol *existing, const InputFile *file,
  108. llvm::wasm::WasmSymbolType type) {
  109. error("symbol type mismatch: " + toString(*existing) + "\n>>> defined as " +
  110. toString(existing->getWasmType()) + " in " +
  111. toString(existing->getFile()) + "\n>>> defined as " + toString(type) +
  112. " in " + toString(file));
  113. }
  114. // Check the type of new symbol matches that of the symbol is replacing.
  115. // Returns true if the function types match, false is there is a singature
  116. // mismatch.
  117. static bool signatureMatches(FunctionSymbol *existing,
  118. const WasmSignature *newSig) {
  119. const WasmSignature *oldSig = existing->signature;
  120. // If either function is missing a signature (this happend for bitcode
  121. // symbols) then assume they match. Any mismatch will be reported later
  122. // when the LTO objects are added.
  123. if (!newSig || !oldSig)
  124. return true;
  125. return *newSig == *oldSig;
  126. }
  127. static void checkGlobalType(const Symbol *existing, const InputFile *file,
  128. const WasmGlobalType *newType) {
  129. if (!isa<GlobalSymbol>(existing)) {
  130. reportTypeError(existing, file, WASM_SYMBOL_TYPE_GLOBAL);
  131. return;
  132. }
  133. const WasmGlobalType *oldType = cast<GlobalSymbol>(existing)->getGlobalType();
  134. if (*newType != *oldType) {
  135. error("Global type mismatch: " + existing->getName() + "\n>>> defined as " +
  136. toString(*oldType) + " in " + toString(existing->getFile()) +
  137. "\n>>> defined as " + toString(*newType) + " in " + toString(file));
  138. }
  139. }
  140. static void checkEventType(const Symbol *existing, const InputFile *file,
  141. const WasmEventType *newType,
  142. const WasmSignature *newSig) {
  143. auto existingEvent = dyn_cast<EventSymbol>(existing);
  144. if (!isa<EventSymbol>(existing)) {
  145. reportTypeError(existing, file, WASM_SYMBOL_TYPE_EVENT);
  146. return;
  147. }
  148. const WasmEventType *oldType = cast<EventSymbol>(existing)->getEventType();
  149. const WasmSignature *oldSig = existingEvent->signature;
  150. if (newType->Attribute != oldType->Attribute)
  151. error("Event type mismatch: " + existing->getName() + "\n>>> defined as " +
  152. toString(*oldType) + " in " + toString(existing->getFile()) +
  153. "\n>>> defined as " + toString(*newType) + " in " + toString(file));
  154. if (*newSig != *oldSig)
  155. warn("Event signature mismatch: " + existing->getName() +
  156. "\n>>> defined as " + toString(*oldSig) + " in " +
  157. toString(existing->getFile()) + "\n>>> defined as " +
  158. toString(*newSig) + " in " + toString(file));
  159. }
  160. static void checkDataType(const Symbol *existing, const InputFile *file) {
  161. if (!isa<DataSymbol>(existing))
  162. reportTypeError(existing, file, WASM_SYMBOL_TYPE_DATA);
  163. }
  164. DefinedFunction *SymbolTable::addSyntheticFunction(StringRef name,
  165. uint32_t flags,
  166. InputFunction *function) {
  167. LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << name << "\n");
  168. assert(!find(name));
  169. syntheticFunctions.emplace_back(function);
  170. return replaceSymbol<DefinedFunction>(insertName(name).first, name,
  171. flags, nullptr, function);
  172. }
  173. // Adds an optional, linker generated, data symbols. The symbol will only be
  174. // added if there is an undefine reference to it, or if it is explictly exported
  175. // via the --export flag. Otherwise we don't add the symbol and return nullptr.
  176. DefinedData *SymbolTable::addOptionalDataSymbol(StringRef name,
  177. uint32_t value) {
  178. Symbol *s = find(name);
  179. if (!s && (config->exportAll || config->exportedSymbols.count(name) != 0))
  180. s = insertName(name).first;
  181. else if (!s || s->isDefined())
  182. return nullptr;
  183. LLVM_DEBUG(dbgs() << "addOptionalDataSymbol: " << name << "\n");
  184. auto *rtn = replaceSymbol<DefinedData>(s, name, WASM_SYMBOL_VISIBILITY_HIDDEN);
  185. rtn->setVirtualAddress(value);
  186. rtn->referenced = true;
  187. return rtn;
  188. }
  189. DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef name,
  190. uint32_t flags) {
  191. LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << name << "\n");
  192. assert(!find(name));
  193. return replaceSymbol<DefinedData>(insertName(name).first, name, flags);
  194. }
  195. DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef name, uint32_t flags,
  196. InputGlobal *global) {
  197. LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << name << " -> " << global
  198. << "\n");
  199. assert(!find(name));
  200. syntheticGlobals.emplace_back(global);
  201. return replaceSymbol<DefinedGlobal>(insertName(name).first, name, flags,
  202. nullptr, global);
  203. }
  204. static bool shouldReplace(const Symbol *existing, InputFile *newFile,
  205. uint32_t newFlags) {
  206. // If existing symbol is undefined, replace it.
  207. if (!existing->isDefined()) {
  208. LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: "
  209. << existing->getName() << "\n");
  210. return true;
  211. }
  212. // Now we have two defined symbols. If the new one is weak, we can ignore it.
  213. if ((newFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
  214. LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n");
  215. return false;
  216. }
  217. // If the existing symbol is weak, we should replace it.
  218. if (existing->isWeak()) {
  219. LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n");
  220. return true;
  221. }
  222. // Neither symbol is week. They conflict.
  223. error("duplicate symbol: " + toString(*existing) + "\n>>> defined in " +
  224. toString(existing->getFile()) + "\n>>> defined in " +
  225. toString(newFile));
  226. return true;
  227. }
  228. Symbol *SymbolTable::addDefinedFunction(StringRef name, uint32_t flags,
  229. InputFile *file,
  230. InputFunction *function) {
  231. LLVM_DEBUG(dbgs() << "addDefinedFunction: " << name << " ["
  232. << (function ? toString(function->signature) : "none")
  233. << "]\n");
  234. Symbol *s;
  235. bool wasInserted;
  236. std::tie(s, wasInserted) = insert(name, file);
  237. auto replaceSym = [&](Symbol *sym) {
  238. // If the new defined function doesn't have signture (i.e. bitcode
  239. // functions) but the old symbol does, then preserve the old signature
  240. const WasmSignature *oldSig = s->getSignature();
  241. auto* newSym = replaceSymbol<DefinedFunction>(sym, name, flags, file, function);
  242. if (!newSym->signature)
  243. newSym->signature = oldSig;
  244. };
  245. if (wasInserted || s->isLazy()) {
  246. replaceSym(s);
  247. return s;
  248. }
  249. auto existingFunction = dyn_cast<FunctionSymbol>(s);
  250. if (!existingFunction) {
  251. reportTypeError(s, file, WASM_SYMBOL_TYPE_FUNCTION);
  252. return s;
  253. }
  254. bool checkSig = true;
  255. if (auto ud = dyn_cast<UndefinedFunction>(existingFunction))
  256. checkSig = ud->isCalledDirectly;
  257. if (checkSig && function && !signatureMatches(existingFunction, &function->signature)) {
  258. Symbol* variant;
  259. if (getFunctionVariant(s, &function->signature, file, &variant))
  260. // New variant, always replace
  261. replaceSym(variant);
  262. else if (shouldReplace(s, file, flags))
  263. // Variant already exists, replace it after checking shouldReplace
  264. replaceSym(variant);
  265. // This variant we found take the place in the symbol table as the primary
  266. // variant.
  267. replace(name, variant);
  268. return variant;
  269. }
  270. // Existing function with matching signature.
  271. if (shouldReplace(s, file, flags))
  272. replaceSym(s);
  273. return s;
  274. }
  275. Symbol *SymbolTable::addDefinedData(StringRef name, uint32_t flags,
  276. InputFile *file, InputSegment *segment,
  277. uint32_t address, uint32_t size) {
  278. LLVM_DEBUG(dbgs() << "addDefinedData:" << name << " addr:" << address
  279. << "\n");
  280. Symbol *s;
  281. bool wasInserted;
  282. std::tie(s, wasInserted) = insert(name, file);
  283. auto replaceSym = [&]() {
  284. replaceSymbol<DefinedData>(s, name, flags, file, segment, address, size);
  285. };
  286. if (wasInserted || s->isLazy()) {
  287. replaceSym();
  288. return s;
  289. }
  290. checkDataType(s, file);
  291. if (shouldReplace(s, file, flags))
  292. replaceSym();
  293. return s;
  294. }
  295. Symbol *SymbolTable::addDefinedGlobal(StringRef name, uint32_t flags,
  296. InputFile *file, InputGlobal *global) {
  297. LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << name << "\n");
  298. Symbol *s;
  299. bool wasInserted;
  300. std::tie(s, wasInserted) = insert(name, file);
  301. auto replaceSym = [&]() {
  302. replaceSymbol<DefinedGlobal>(s, name, flags, file, global);
  303. };
  304. if (wasInserted || s->isLazy()) {
  305. replaceSym();
  306. return s;
  307. }
  308. checkGlobalType(s, file, &global->getType());
  309. if (shouldReplace(s, file, flags))
  310. replaceSym();
  311. return s;
  312. }
  313. Symbol *SymbolTable::addDefinedEvent(StringRef name, uint32_t flags,
  314. InputFile *file, InputEvent *event) {
  315. LLVM_DEBUG(dbgs() << "addDefinedEvent:" << name << "\n");
  316. Symbol *s;
  317. bool wasInserted;
  318. std::tie(s, wasInserted) = insert(name, file);
  319. auto replaceSym = [&]() {
  320. replaceSymbol<DefinedEvent>(s, name, flags, file, event);
  321. };
  322. if (wasInserted || s->isLazy()) {
  323. replaceSym();
  324. return s;
  325. }
  326. checkEventType(s, file, &event->getType(), &event->signature);
  327. if (shouldReplace(s, file, flags))
  328. replaceSym();
  329. return s;
  330. }
  331. // This function get called when an undefined symbol is added, and there is
  332. // already an existing one in the symbols table. In this case we check that
  333. // custom 'import-module' and 'import-field' symbol attributes agree.
  334. // With LTO these attributes are not avialable when the bitcode is read and only
  335. // become available when the LTO object is read. In this case we silently
  336. // replace the empty attributes with the valid ones.
  337. template <typename T>
  338. static void setImportAttributes(T *existing, StringRef importName,
  339. StringRef importModule, InputFile *file) {
  340. if (!importName.empty()) {
  341. if (existing->importName.empty())
  342. existing->importName = importName;
  343. if (existing->importName != importName)
  344. error("import name mismatch for symbol: " + toString(*existing) +
  345. "\n>>> defined as " + existing->importName + " in " +
  346. toString(existing->getFile()) + "\n>>> defined as " + importName +
  347. " in " + toString(file));
  348. }
  349. if (!importModule.empty()) {
  350. if (existing->importModule.empty())
  351. existing->importModule = importModule;
  352. if (existing->importModule != importModule)
  353. error("import module mismatch for symbol: " + toString(*existing) +
  354. "\n>>> defined as " + existing->importModule + " in " +
  355. toString(existing->getFile()) + "\n>>> defined as " + importModule +
  356. " in " + toString(file));
  357. }
  358. }
  359. Symbol *SymbolTable::addUndefinedFunction(StringRef name, StringRef importName,
  360. StringRef importModule,
  361. uint32_t flags, InputFile *file,
  362. const WasmSignature *sig,
  363. bool isCalledDirectly) {
  364. LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << name << " ["
  365. << (sig ? toString(*sig) : "none")
  366. << "] IsCalledDirectly:" << isCalledDirectly << "\n");
  367. assert(flags & WASM_SYMBOL_UNDEFINED);
  368. Symbol *s;
  369. bool wasInserted;
  370. std::tie(s, wasInserted) = insert(name, file);
  371. if (s->traced)
  372. printTraceSymbolUndefined(name, file);
  373. auto replaceSym = [&]() {
  374. replaceSymbol<UndefinedFunction>(s, name, importName, importModule, flags,
  375. file, sig, isCalledDirectly);
  376. };
  377. if (wasInserted)
  378. replaceSym();
  379. else if (auto *lazy = dyn_cast<LazySymbol>(s))
  380. lazy->fetch();
  381. else {
  382. auto existingFunction = dyn_cast<FunctionSymbol>(s);
  383. if (!existingFunction) {
  384. reportTypeError(s, file, WASM_SYMBOL_TYPE_FUNCTION);
  385. return s;
  386. }
  387. auto *existingUndefined = dyn_cast<UndefinedFunction>(existingFunction);
  388. if (!existingFunction->signature && sig)
  389. existingFunction->signature = sig;
  390. if (isCalledDirectly && !signatureMatches(existingFunction, sig)) {
  391. // If the existing undefined functions is not called direcltly then let
  392. // this one take precedence. Otherwise the existing function is either
  393. // direclty called or defined, in which case we need a function variant.
  394. if (existingUndefined && !existingUndefined->isCalledDirectly)
  395. replaceSym();
  396. else if (getFunctionVariant(s, sig, file, &s))
  397. replaceSym();
  398. }
  399. if (existingUndefined)
  400. setImportAttributes(existingUndefined, importName, importModule, file);
  401. }
  402. return s;
  403. }
  404. Symbol *SymbolTable::addUndefinedData(StringRef name, uint32_t flags,
  405. InputFile *file) {
  406. LLVM_DEBUG(dbgs() << "addUndefinedData: " << name << "\n");
  407. assert(flags & WASM_SYMBOL_UNDEFINED);
  408. Symbol *s;
  409. bool wasInserted;
  410. std::tie(s, wasInserted) = insert(name, file);
  411. if (s->traced)
  412. printTraceSymbolUndefined(name, file);
  413. if (wasInserted)
  414. replaceSymbol<UndefinedData>(s, name, flags, file);
  415. else if (auto *lazy = dyn_cast<LazySymbol>(s))
  416. lazy->fetch();
  417. else if (s->isDefined())
  418. checkDataType(s, file);
  419. return s;
  420. }
  421. Symbol *SymbolTable::addUndefinedGlobal(StringRef name, StringRef importName,
  422. StringRef importModule, uint32_t flags,
  423. InputFile *file,
  424. const WasmGlobalType *type) {
  425. LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << name << "\n");
  426. assert(flags & WASM_SYMBOL_UNDEFINED);
  427. Symbol *s;
  428. bool wasInserted;
  429. std::tie(s, wasInserted) = insert(name, file);
  430. if (s->traced)
  431. printTraceSymbolUndefined(name, file);
  432. if (wasInserted)
  433. replaceSymbol<UndefinedGlobal>(s, name, importName, importModule, flags,
  434. file, type);
  435. else if (auto *lazy = dyn_cast<LazySymbol>(s))
  436. lazy->fetch();
  437. else if (s->isDefined())
  438. checkGlobalType(s, file, type);
  439. return s;
  440. }
  441. void SymbolTable::addLazy(ArchiveFile *file, const Archive::Symbol *sym) {
  442. LLVM_DEBUG(dbgs() << "addLazy: " << sym->getName() << "\n");
  443. StringRef name = sym->getName();
  444. Symbol *s;
  445. bool wasInserted;
  446. std::tie(s, wasInserted) = insertName(name);
  447. if (wasInserted) {
  448. replaceSymbol<LazySymbol>(s, name, 0, file, *sym);
  449. return;
  450. }
  451. if (!s->isUndefined())
  452. return;
  453. // The existing symbol is undefined, load a new one from the archive,
  454. // unless the the existing symbol is weak in which case replace the undefined
  455. // symbols with a LazySymbol.
  456. if (s->isWeak()) {
  457. const WasmSignature *oldSig = nullptr;
  458. // In the case of an UndefinedFunction we need to preserve the expected
  459. // signature.
  460. if (auto *f = dyn_cast<UndefinedFunction>(s))
  461. oldSig = f->signature;
  462. LLVM_DEBUG(dbgs() << "replacing existing weak undefined symbol\n");
  463. auto newSym = replaceSymbol<LazySymbol>(s, name, WASM_SYMBOL_BINDING_WEAK,
  464. file, *sym);
  465. newSym->signature = oldSig;
  466. return;
  467. }
  468. LLVM_DEBUG(dbgs() << "replacing existing undefined\n");
  469. file->addMember(sym);
  470. }
  471. bool SymbolTable::addComdat(StringRef name) {
  472. return comdatGroups.insert(CachedHashStringRef(name)).second;
  473. }
  474. // The new signature doesn't match. Create a variant to the symbol with the
  475. // signature encoded in the name and return that instead. These symbols are
  476. // then unified later in handleSymbolVariants.
  477. bool SymbolTable::getFunctionVariant(Symbol* sym, const WasmSignature *sig,
  478. const InputFile *file, Symbol **out) {
  479. LLVM_DEBUG(dbgs() << "getFunctionVariant: " << sym->getName() << " -> "
  480. << " " << toString(*sig) << "\n");
  481. Symbol *variant = nullptr;
  482. // Linear search through symbol variants. Should never be more than two
  483. // or three entries here.
  484. auto &variants = symVariants[CachedHashStringRef(sym->getName())];
  485. if (variants.empty())
  486. variants.push_back(sym);
  487. for (Symbol* v : variants) {
  488. if (*v->getSignature() == *sig) {
  489. variant = v;
  490. break;
  491. }
  492. }
  493. bool wasAdded = !variant;
  494. if (wasAdded) {
  495. // Create a new variant;
  496. LLVM_DEBUG(dbgs() << "added new variant\n");
  497. variant = reinterpret_cast<Symbol *>(make<SymbolUnion>());
  498. variants.push_back(variant);
  499. } else {
  500. LLVM_DEBUG(dbgs() << "variant already exists: " << toString(*variant) << "\n");
  501. assert(*variant->getSignature() == *sig);
  502. }
  503. *out = variant;
  504. return wasAdded;
  505. }
  506. // Set a flag for --trace-symbol so that we can print out a log message
  507. // if a new symbol with the same name is inserted into the symbol table.
  508. void SymbolTable::trace(StringRef name) {
  509. symMap.insert({CachedHashStringRef(name), -1});
  510. }
  511. void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) {
  512. // Swap symbols as instructed by -wrap.
  513. int &origIdx = symMap[CachedHashStringRef(sym->getName())];
  514. int &realIdx= symMap[CachedHashStringRef(real->getName())];
  515. int &wrapIdx = symMap[CachedHashStringRef(wrap->getName())];
  516. LLVM_DEBUG(dbgs() << "wrap: " << sym->getName() << "\n");
  517. // Anyone looking up __real symbols should get the original
  518. realIdx = origIdx;
  519. // Anyone looking up the original should get the __wrap symbol
  520. origIdx = wrapIdx;
  521. }
  522. static const uint8_t unreachableFn[] = {
  523. 0x03 /* ULEB length */, 0x00 /* ULEB num locals */,
  524. 0x00 /* opcode unreachable */, 0x0b /* opcode end */
  525. };
  526. // Replace the given symbol body with an unreachable function.
  527. // This is used by handleWeakUndefines in order to generate a callable
  528. // equivalent of an undefined function and also handleSymbolVariants for
  529. // undefined functions that don't match the signature of the definition.
  530. InputFunction *SymbolTable::replaceWithUnreachable(Symbol *sym,
  531. const WasmSignature &sig,
  532. StringRef debugName) {
  533. auto *func = make<SyntheticFunction>(sig, sym->getName(), debugName);
  534. func->setBody(unreachableFn);
  535. syntheticFunctions.emplace_back(func);
  536. replaceSymbol<DefinedFunction>(sym, sym->getName(), sym->getFlags(), nullptr,
  537. func);
  538. return func;
  539. }
  540. // For weak undefined functions, there may be "call" instructions that reference
  541. // the symbol. In this case, we need to synthesise a dummy/stub function that
  542. // will abort at runtime, so that relocations can still provided an operand to
  543. // the call instruction that passes Wasm validation.
  544. void SymbolTable::handleWeakUndefines() {
  545. for (Symbol *sym : getSymbols()) {
  546. if (!sym->isUndefWeak())
  547. continue;
  548. const WasmSignature *sig = sym->getSignature();
  549. if (!sig) {
  550. // It is possible for undefined functions not to have a signature (eg. if
  551. // added via "--undefined"), but weak undefined ones do have a signature.
  552. // Lazy symbols may not be functions and therefore Sig can still be null
  553. // in some circumstantce.
  554. assert(!isa<FunctionSymbol>(sym));
  555. continue;
  556. }
  557. // Add a synthetic dummy for weak undefined functions. These dummies will
  558. // be GC'd if not used as the target of any "call" instructions.
  559. StringRef debugName = saver.save("undefined:" + toString(*sym));
  560. InputFunction* func = replaceWithUnreachable(sym, *sig, debugName);
  561. // Ensure it compares equal to the null pointer, and so that table relocs
  562. // don't pull in the stub body (only call-operand relocs should do that).
  563. func->setTableIndex(0);
  564. // Hide our dummy to prevent export.
  565. sym->setHidden(true);
  566. }
  567. }
  568. static void reportFunctionSignatureMismatch(StringRef symName,
  569. FunctionSymbol *a,
  570. FunctionSymbol *b, bool isError) {
  571. std::string msg = ("function signature mismatch: " + symName +
  572. "\n>>> defined as " + toString(*a->signature) + " in " +
  573. toString(a->getFile()) + "\n>>> defined as " +
  574. toString(*b->signature) + " in " + toString(b->getFile()))
  575. .str();
  576. if (isError)
  577. error(msg);
  578. else
  579. warn(msg);
  580. }
  581. // Remove any variant symbols that were created due to function signature
  582. // mismatches.
  583. void SymbolTable::handleSymbolVariants() {
  584. for (auto pair : symVariants) {
  585. // Push the initial symbol onto the list of variants.
  586. StringRef symName = pair.first.val();
  587. std::vector<Symbol *> &variants = pair.second;
  588. #ifndef NDEBUG
  589. LLVM_DEBUG(dbgs() << "symbol with (" << variants.size()
  590. << ") variants: " << symName << "\n");
  591. for (auto *s: variants) {
  592. auto *f = cast<FunctionSymbol>(s);
  593. LLVM_DEBUG(dbgs() << " variant: " + f->getName() << " "
  594. << toString(*f->signature) << "\n");
  595. }
  596. #endif
  597. // Find the one definition.
  598. DefinedFunction *defined = nullptr;
  599. for (auto *symbol : variants) {
  600. if (auto f = dyn_cast<DefinedFunction>(symbol)) {
  601. defined = f;
  602. break;
  603. }
  604. }
  605. // If there are no definitions, and the undefined symbols disagree on
  606. // the signature, there is not we can do since we don't know which one
  607. // to use as the signature on the import.
  608. if (!defined) {
  609. reportFunctionSignatureMismatch(symName,
  610. cast<FunctionSymbol>(variants[0]),
  611. cast<FunctionSymbol>(variants[1]), true);
  612. return;
  613. }
  614. for (auto *symbol : variants) {
  615. if (symbol != defined) {
  616. auto *f = cast<FunctionSymbol>(symbol);
  617. reportFunctionSignatureMismatch(symName, f, defined, false);
  618. StringRef debugName = saver.save("unreachable:" + toString(*f));
  619. replaceWithUnreachable(f, *f->signature, debugName);
  620. }
  621. }
  622. }
  623. }
  624. } // namespace wasm
  625. } // namespace lld