1 //===- Relocations.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 "Relocations.h" 10 11 #include "InputChunks.h" 12 #include "OutputSegment.h" 13 #include "SymbolTable.h" 14 #include "SyntheticSections.h" 15 16 using namespace llvm; 17 using namespace llvm::wasm; 18 19 namespace lld { 20 namespace wasm { 21 requiresGOTAccess(const Symbol * sym)22static bool requiresGOTAccess(const Symbol *sym) { 23 if (!config->isPic) 24 return false; 25 if (sym->isHidden() || sym->isLocal()) 26 return false; 27 // With `-Bsymbolic` (or when building an executable) as don't need to use 28 // the GOT for symbols that are defined within the current module. 29 if (sym->isDefined() && (!config->shared || config->bsymbolic)) 30 return false; 31 return true; 32 } 33 allowUndefined(const Symbol * sym)34static bool allowUndefined(const Symbol* sym) { 35 // Undefined functions and globals with explicit import name are allowed to be 36 // undefined at link time. 37 if (auto *f = dyn_cast<UndefinedFunction>(sym)) 38 if (f->importName || config->importUndefined) 39 return true; 40 if (auto *g = dyn_cast<UndefinedGlobal>(sym)) 41 if (g->importName) 42 return true; 43 if (auto *g = dyn_cast<UndefinedGlobal>(sym)) 44 if (g->importName) 45 return true; 46 return config->allowUndefinedSymbols.count(sym->getName()) != 0; 47 } 48 reportUndefined(Symbol * sym)49static void reportUndefined(Symbol *sym) { 50 if (!allowUndefined(sym)) { 51 switch (config->unresolvedSymbols) { 52 case UnresolvedPolicy::ReportError: 53 error(toString(sym->getFile()) + ": undefined symbol: " + toString(*sym)); 54 break; 55 case UnresolvedPolicy::Warn: 56 warn(toString(sym->getFile()) + ": undefined symbol: " + toString(*sym)); 57 break; 58 case UnresolvedPolicy::Ignore: 59 LLVM_DEBUG(dbgs() << "ignoring undefined symbol: " + toString(*sym) + 60 "\n"); 61 if (!config->importUndefined) { 62 if (auto *f = dyn_cast<UndefinedFunction>(sym)) { 63 if (!f->stubFunction) { 64 f->stubFunction = symtab->createUndefinedStub(*f->getSignature()); 65 f->stubFunction->markLive(); 66 // Mark the function itself as a stub which prevents it from being 67 // assigned a table entry. 68 f->isStub = true; 69 } 70 } 71 } 72 break; 73 } 74 } 75 } 76 addGOTEntry(Symbol * sym)77static void addGOTEntry(Symbol *sym) { 78 if (requiresGOTAccess(sym)) 79 out.importSec->addGOTEntry(sym); 80 else 81 out.globalSec->addInternalGOTEntry(sym); 82 } 83 scanRelocations(InputChunk * chunk)84void scanRelocations(InputChunk *chunk) { 85 if (!chunk->live) 86 return; 87 ObjFile *file = chunk->file; 88 ArrayRef<WasmSignature> types = file->getWasmObj()->types(); 89 for (const WasmRelocation &reloc : chunk->getRelocations()) { 90 if (reloc.Type == R_WASM_TYPE_INDEX_LEB) { 91 // Mark target type as live 92 file->typeMap[reloc.Index] = 93 out.typeSec->registerType(types[reloc.Index]); 94 file->typeIsUsed[reloc.Index] = true; 95 continue; 96 } 97 98 // Other relocation types all have a corresponding symbol 99 Symbol *sym = file->getSymbols()[reloc.Index]; 100 101 switch (reloc.Type) { 102 case R_WASM_TABLE_INDEX_I32: 103 case R_WASM_TABLE_INDEX_I64: 104 case R_WASM_TABLE_INDEX_SLEB: 105 case R_WASM_TABLE_INDEX_SLEB64: 106 case R_WASM_TABLE_INDEX_REL_SLEB: 107 case R_WASM_TABLE_INDEX_REL_SLEB64: 108 if (requiresGOTAccess(sym)) 109 break; 110 out.elemSec->addEntry(cast<FunctionSymbol>(sym)); 111 break; 112 case R_WASM_GLOBAL_INDEX_LEB: 113 case R_WASM_GLOBAL_INDEX_I32: 114 if (!isa<GlobalSymbol>(sym)) 115 addGOTEntry(sym); 116 break; 117 case R_WASM_MEMORY_ADDR_TLS_SLEB: 118 case R_WASM_MEMORY_ADDR_TLS_SLEB64: 119 // In single-threaded builds TLS is lowered away and TLS data can be 120 // merged with normal data and allowing TLS relocation in non-TLS 121 // segments. 122 if (config->sharedMemory) { 123 if (auto *D = dyn_cast<DefinedData>(sym)) { 124 if (!D->segment->outputSeg->isTLS()) { 125 error(toString(file) + ": relocation " + 126 relocTypeToString(reloc.Type) + " cannot be used against `" + 127 toString(*sym) + 128 "` in non-TLS section: " + D->segment->outputSeg->name); 129 } 130 } 131 } 132 break; 133 } 134 135 if (config->isPic) { 136 switch (reloc.Type) { 137 case R_WASM_TABLE_INDEX_SLEB: 138 case R_WASM_TABLE_INDEX_SLEB64: 139 case R_WASM_MEMORY_ADDR_SLEB: 140 case R_WASM_MEMORY_ADDR_LEB: 141 case R_WASM_MEMORY_ADDR_SLEB64: 142 case R_WASM_MEMORY_ADDR_LEB64: 143 // Certain relocation types can't be used when building PIC output, 144 // since they would require absolute symbol addresses at link time. 145 error(toString(file) + ": relocation " + relocTypeToString(reloc.Type) + 146 " cannot be used against symbol " + toString(*sym) + 147 "; recompile with -fPIC"); 148 break; 149 case R_WASM_MEMORY_ADDR_TLS_SLEB: 150 case R_WASM_MEMORY_ADDR_TLS_SLEB64: 151 if (!sym->isDefined()) { 152 error(toString(file) + 153 ": TLS symbol is undefined, but TLS symbols cannot yet be " 154 "imported: `" + 155 toString(*sym) + "`"); 156 } 157 break; 158 case R_WASM_TABLE_INDEX_I32: 159 case R_WASM_TABLE_INDEX_I64: 160 case R_WASM_MEMORY_ADDR_I32: 161 case R_WASM_MEMORY_ADDR_I64: 162 // These relocation types are only present in the data section and 163 // will be converted into code by `generateRelocationCode`. This code 164 // requires the symbols to have GOT entires. 165 if (requiresGOTAccess(sym)) 166 addGOTEntry(sym); 167 break; 168 } 169 } else if (sym->isUndefined() && !config->relocatable && !sym->isWeak()) { 170 // Report undefined symbols 171 reportUndefined(sym); 172 } 173 } 174 } 175 176 } // namespace wasm 177 } // namespace lld 178