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->Pic && !Sym->isHidden() && !Sym->isLocal();
22 }
23 
24 void lld::wasm::scanRelocations(InputChunk *Chunk) {
25   if (!Chunk->Live)
26     return;
27   ObjFile *File = Chunk->File;
28   ArrayRef<WasmSignature> Types = File->getWasmObj()->types();
29   for (const WasmRelocation &Reloc : Chunk->getRelocations()) {
30     if (Reloc.Type == R_WASM_TYPE_INDEX_LEB) {
31       // Mark target type as live
32       File->TypeMap[Reloc.Index] =
33           Out.TypeSec->registerType(Types[Reloc.Index]);
34       File->TypeIsUsed[Reloc.Index] = true;
35       continue;
36     }
37 
38     // Other relocation types all have a corresponding symbol
39     Symbol *Sym = File->getSymbols()[Reloc.Index];
40 
41     switch (Reloc.Type) {
42     case R_WASM_TABLE_INDEX_I32:
43     case R_WASM_TABLE_INDEX_SLEB:
44     case R_WASM_TABLE_INDEX_REL_SLEB:
45       if (requiresGOTAccess(Sym))
46         break;
47       Out.ElemSec->addEntry(cast<FunctionSymbol>(Sym));
48       break;
49     case R_WASM_GLOBAL_INDEX_LEB:
50       if (!isa<GlobalSymbol>(Sym))
51         Out.ImportSec->addGOTEntry(Sym);
52       break;
53     case R_WASM_MEMORY_ADDR_SLEB:
54     case R_WASM_MEMORY_ADDR_LEB:
55     case R_WASM_MEMORY_ADDR_REL_SLEB:
56       if (!Config->Relocatable && Sym->isUndefined() && !Sym->isWeak()) {
57         error(toString(File) + ": cannot resolve relocation of type " +
58               relocTypeToString(Reloc.Type) +
59               " against undefined (non-weak) data symbol: " + toString(*Sym));
60       }
61       break;
62     }
63 
64     if (Config->Pic) {
65       switch (Reloc.Type) {
66       case R_WASM_TABLE_INDEX_SLEB:
67       case R_WASM_MEMORY_ADDR_SLEB:
68       case R_WASM_MEMORY_ADDR_LEB:
69         // Certain relocation types can't be used when building PIC output,
70         // since they would require absolute symbol addresses at link time.
71         error(toString(File) + ": relocation " + relocTypeToString(Reloc.Type) +
72               " cannot be used againt symbol " + toString(*Sym) +
73               "; recompile with -fPIC");
74         break;
75       case R_WASM_TABLE_INDEX_I32:
76       case R_WASM_MEMORY_ADDR_I32:
77         // These relocation types are only present in the data section and
78         // will be converted into code by `generateRelocationCode`.  This code
79         // requires the symbols to have GOT entires.
80         if (requiresGOTAccess(Sym))
81           Out.ImportSec->addGOTEntry(Sym);
82         break;
83       }
84     }
85   }
86 }
87