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