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 "SyntheticSections.h" 13 14 using namespace llvm; 15 using namespace llvm::wasm; 16 17 using namespace lld; 18 using namespace lld::wasm; 19 20 static bool requiresGOTAccess(const Symbol *sym) { 21 return config->isPic && !sym->isHidden() && !sym->isLocal(); 22 } 23 24 static bool allowUndefined(const Symbol* sym) { 25 // Historically --allow-undefined doesn't work for data symbols since we don't 26 // have any way to represent these as imports in the final binary. The idea 27 // behind allowing undefined symbols is to allow importing these symbols from 28 // the embedder and we can't do this for data symbols (at least not without 29 // compiling with -fPIC) 30 if (isa<DataSymbol>(sym)) 31 return false; 32 return (config->allowUndefined || 33 config->allowUndefinedSymbols.count(sym->getName()) != 0); 34 } 35 36 static void reportUndefined(const Symbol* sym) { 37 assert(sym->isUndefined()); 38 assert(!sym->isWeak()); 39 if (!allowUndefined(sym)) 40 error(toString(sym->getFile()) + ": undefined symbol: " + toString(*sym)); 41 } 42 43 void lld::wasm::scanRelocations(InputChunk *chunk) { 44 if (!chunk->live) 45 return; 46 ObjFile *file = chunk->file; 47 ArrayRef<WasmSignature> types = file->getWasmObj()->types(); 48 for (const WasmRelocation &reloc : chunk->getRelocations()) { 49 if (reloc.Type == R_WASM_TYPE_INDEX_LEB) { 50 // Mark target type as live 51 file->typeMap[reloc.Index] = 52 out.typeSec->registerType(types[reloc.Index]); 53 file->typeIsUsed[reloc.Index] = true; 54 continue; 55 } 56 57 // Other relocation types all have a corresponding symbol 58 Symbol *sym = file->getSymbols()[reloc.Index]; 59 60 switch (reloc.Type) { 61 case R_WASM_TABLE_INDEX_I32: 62 case R_WASM_TABLE_INDEX_SLEB: 63 case R_WASM_TABLE_INDEX_REL_SLEB: 64 if (requiresGOTAccess(sym)) 65 break; 66 out.elemSec->addEntry(cast<FunctionSymbol>(sym)); 67 break; 68 case R_WASM_GLOBAL_INDEX_LEB: 69 if (!isa<GlobalSymbol>(sym)) 70 out.importSec->addGOTEntry(sym); 71 break; 72 } 73 74 if (config->isPic) { 75 switch (reloc.Type) { 76 case R_WASM_TABLE_INDEX_SLEB: 77 case R_WASM_MEMORY_ADDR_SLEB: 78 case R_WASM_MEMORY_ADDR_LEB: 79 // Certain relocation types can't be used when building PIC output, 80 // since they would require absolute symbol addresses at link time. 81 error(toString(file) + ": relocation " + relocTypeToString(reloc.Type) + 82 " cannot be used against symbol " + toString(*sym) + 83 "; recompile with -fPIC"); 84 break; 85 case R_WASM_TABLE_INDEX_I32: 86 case R_WASM_MEMORY_ADDR_I32: 87 // These relocation types are only present in the data section and 88 // will be converted into code by `generateRelocationCode`. This code 89 // requires the symbols to have GOT entires. 90 if (requiresGOTAccess(sym)) 91 out.importSec->addGOTEntry(sym); 92 break; 93 } 94 } else { 95 // Report undefined symbols 96 if (sym->isUndefined() && !config->relocatable && !sym->isWeak()) 97 reportUndefined(sym); 98 } 99 100 } 101 } 102