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 namespace lld { 18 namespace wasm { requiresGOTAccess(const Symbol * sym)19static bool requiresGOTAccess(const Symbol *sym) { 20 return config->isPic && !sym->isHidden() && !sym->isLocal(); 21 } 22 allowUndefined(const Symbol * sym)23static bool allowUndefined(const Symbol* sym) { 24 // Undefined functions with explicit import name are allowed to be undefined 25 // at link time. 26 if (auto *F = dyn_cast<UndefinedFunction>(sym)) 27 if (F->importName) 28 return true; 29 return (config->allowUndefined || 30 config->allowUndefinedSymbols.count(sym->getName()) != 0); 31 } 32 reportUndefined(const Symbol * sym)33static void reportUndefined(const Symbol* sym) { 34 assert(sym->isUndefined()); 35 assert(!sym->isWeak()); 36 if (!allowUndefined(sym)) 37 error(toString(sym->getFile()) + ": undefined symbol: " + toString(*sym)); 38 } 39 addGOTEntry(Symbol * sym)40static void addGOTEntry(Symbol *sym) { 41 // In PIC mode a GOT entry is an imported global that the dynamic linker 42 // will assign. 43 // In non-PIC mode (i.e. when code compiled as fPIC is linked into a static 44 // binary) we create an internal wasm global with a fixed value that takes the 45 // place of th GOT entry and effectivly acts as an i32 const. This can 46 // potentially be optimized away at runtime or with a post-link tool. 47 // TODO(sbc): Linker relaxation might also be able to optimize this away. 48 if (config->isPic) 49 out.importSec->addGOTEntry(sym); 50 else 51 out.globalSec->addStaticGOTEntry(sym); 52 } 53 scanRelocations(InputChunk * chunk)54void scanRelocations(InputChunk *chunk) { 55 if (!chunk->live) 56 return; 57 ObjFile *file = chunk->file; 58 ArrayRef<WasmSignature> types = file->getWasmObj()->types(); 59 for (const WasmRelocation &reloc : chunk->getRelocations()) { 60 if (reloc.Type == R_WASM_TYPE_INDEX_LEB) { 61 // Mark target type as live 62 file->typeMap[reloc.Index] = 63 out.typeSec->registerType(types[reloc.Index]); 64 file->typeIsUsed[reloc.Index] = true; 65 continue; 66 } 67 68 // Other relocation types all have a corresponding symbol 69 Symbol *sym = file->getSymbols()[reloc.Index]; 70 71 switch (reloc.Type) { 72 case R_WASM_TABLE_INDEX_I32: 73 case R_WASM_TABLE_INDEX_SLEB: 74 case R_WASM_TABLE_INDEX_REL_SLEB: 75 if (requiresGOTAccess(sym)) 76 break; 77 out.elemSec->addEntry(cast<FunctionSymbol>(sym)); 78 break; 79 case R_WASM_GLOBAL_INDEX_LEB: 80 case R_WASM_GLOBAL_INDEX_I32: 81 if (!isa<GlobalSymbol>(sym)) 82 addGOTEntry(sym); 83 break; 84 } 85 86 if (config->isPic) { 87 switch (reloc.Type) { 88 case R_WASM_TABLE_INDEX_SLEB: 89 case R_WASM_MEMORY_ADDR_SLEB: 90 case R_WASM_MEMORY_ADDR_LEB: 91 case R_WASM_MEMORY_ADDR_SLEB64: 92 case R_WASM_MEMORY_ADDR_LEB64: 93 // Certain relocation types can't be used when building PIC output, 94 // since they would require absolute symbol addresses at link time. 95 error(toString(file) + ": relocation " + relocTypeToString(reloc.Type) + 96 " cannot be used against symbol " + toString(*sym) + 97 "; recompile with -fPIC"); 98 break; 99 case R_WASM_TABLE_INDEX_I32: 100 case R_WASM_MEMORY_ADDR_I32: 101 case R_WASM_MEMORY_ADDR_I64: 102 // These relocation types are only present in the data section and 103 // will be converted into code by `generateRelocationCode`. This code 104 // requires the symbols to have GOT entires. 105 if (requiresGOTAccess(sym)) 106 addGOTEntry(sym); 107 break; 108 } 109 } else { 110 // Report undefined symbols 111 if (sym->isUndefined() && !config->relocatable && !sym->isWeak()) 112 reportUndefined(sym); 113 } 114 115 } 116 } 117 118 } // namespace wasm 119 } // namespace lld 120