llvm-project

Форк
0
/
Relocations.cpp 
179 строк · 6.0 Кб
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::wasm {
20

21
static bool requiresGOTAccess(const Symbol *sym) {
22
  if (!ctx.isPic &&
23
      config->unresolvedSymbols != UnresolvedPolicy::ImportDynamic)
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

34
static bool allowUndefined(const Symbol* sym) {
35
  // Symbols that are explicitly imported are always allowed to be undefined at
36
  // link time.
37
  if (sym->isImported())
38
    return true;
39
  if (isa<UndefinedFunction>(sym) && config->importUndefined)
40
    return true;
41

42
  return config->allowUndefinedSymbols.count(sym->getName()) != 0;
43
}
44

45
static void reportUndefined(ObjFile *file, Symbol *sym) {
46
  if (!allowUndefined(sym)) {
47
    switch (config->unresolvedSymbols) {
48
    case UnresolvedPolicy::ReportError:
49
      error(toString(file) + ": undefined symbol: " + toString(*sym));
50
      break;
51
    case UnresolvedPolicy::Warn:
52
      warn(toString(file) + ": undefined symbol: " + toString(*sym));
53
      break;
54
    case UnresolvedPolicy::Ignore:
55
      LLVM_DEBUG(dbgs() << "ignoring undefined symbol: " + toString(*sym) +
56
                               "\n");
57
      break;
58
    case UnresolvedPolicy::ImportDynamic:
59
      break;
60
    }
61

62
    if (auto *f = dyn_cast<UndefinedFunction>(sym)) {
63
      if (!f->stubFunction &&
64
          config->unresolvedSymbols != UnresolvedPolicy::ImportDynamic &&
65
          !config->importUndefined) {
66
        f->stubFunction = symtab->createUndefinedStub(*f->getSignature());
67
        f->stubFunction->markLive();
68
        // Mark the function itself as a stub which prevents it from being
69
        // assigned a table entry.
70
        f->isStub = true;
71
      }
72
    }
73
  }
74
}
75

76
static void addGOTEntry(Symbol *sym) {
77
  if (requiresGOTAccess(sym))
78
    out.importSec->addGOTEntry(sym);
79
  else
80
    out.globalSec->addInternalGOTEntry(sym);
81
}
82

83
void scanRelocations(InputChunk *chunk) {
84
  if (!chunk->live)
85
    return;
86
  ObjFile *file = chunk->file;
87
  ArrayRef<WasmSignature> types = file->getWasmObj()->types();
88
  for (const WasmRelocation &reloc : chunk->getRelocations()) {
89
    if (reloc.Type == R_WASM_TYPE_INDEX_LEB) {
90
      // Mark target type as live
91
      file->typeMap[reloc.Index] =
92
          out.typeSec->registerType(types[reloc.Index]);
93
      file->typeIsUsed[reloc.Index] = true;
94
      continue;
95
    }
96

97
    // Other relocation types all have a corresponding symbol
98
    Symbol *sym = file->getSymbols()[reloc.Index];
99

100
    switch (reloc.Type) {
101
    case R_WASM_TABLE_INDEX_I32:
102
    case R_WASM_TABLE_INDEX_I64:
103
    case R_WASM_TABLE_INDEX_SLEB:
104
    case R_WASM_TABLE_INDEX_SLEB64:
105
    case R_WASM_TABLE_INDEX_REL_SLEB:
106
    case R_WASM_TABLE_INDEX_REL_SLEB64:
107
      if (requiresGOTAccess(sym))
108
        break;
109
      out.elemSec->addEntry(cast<FunctionSymbol>(sym));
110
      break;
111
    case R_WASM_GLOBAL_INDEX_LEB:
112
    case R_WASM_GLOBAL_INDEX_I32:
113
      if (!isa<GlobalSymbol>(sym))
114
        addGOTEntry(sym);
115
      break;
116
    case R_WASM_MEMORY_ADDR_TLS_SLEB:
117
    case R_WASM_MEMORY_ADDR_TLS_SLEB64:
118
      if (!sym->isDefined()) {
119
        error(toString(file) + ": relocation " + relocTypeToString(reloc.Type) +
120
              " cannot be used against an undefined symbol `" + toString(*sym) +
121
              "`");
122
      }
123
      // In single-threaded builds TLS is lowered away and TLS data can be
124
      // merged with normal data and allowing TLS relocation in non-TLS
125
      // segments.
126
      if (config->sharedMemory) {
127
        if (!sym->isTLS()) {
128
          error(toString(file) + ": relocation " +
129
                relocTypeToString(reloc.Type) +
130
                " cannot be used against non-TLS symbol `" + toString(*sym) +
131
                "`");
132
        }
133
        if (auto *D = dyn_cast<DefinedData>(sym)) {
134
          if (!D->segment->outputSeg->isTLS()) {
135
            error(toString(file) + ": relocation " +
136
                  relocTypeToString(reloc.Type) + " cannot be used against `" +
137
                  toString(*sym) +
138
                  "` in non-TLS section: " + D->segment->outputSeg->name);
139
          }
140
        }
141
      }
142
      break;
143
    }
144

145
    if (ctx.isPic ||
146
        (sym->isUndefined() &&
147
         config->unresolvedSymbols == UnresolvedPolicy::ImportDynamic)) {
148
      switch (reloc.Type) {
149
      case R_WASM_TABLE_INDEX_SLEB:
150
      case R_WASM_TABLE_INDEX_SLEB64:
151
      case R_WASM_MEMORY_ADDR_SLEB:
152
      case R_WASM_MEMORY_ADDR_LEB:
153
      case R_WASM_MEMORY_ADDR_SLEB64:
154
      case R_WASM_MEMORY_ADDR_LEB64:
155
        // Certain relocation types can't be used when building PIC output,
156
        // since they would require absolute symbol addresses at link time.
157
        error(toString(file) + ": relocation " + relocTypeToString(reloc.Type) +
158
              " cannot be used against symbol `" + toString(*sym) +
159
              "`; recompile with -fPIC");
160
        break;
161
      case R_WASM_TABLE_INDEX_I32:
162
      case R_WASM_TABLE_INDEX_I64:
163
      case R_WASM_MEMORY_ADDR_I32:
164
      case R_WASM_MEMORY_ADDR_I64:
165
        // These relocation types are only present in the data section and
166
        // will be converted into code by `generateRelocationCode`.  This code
167
        // requires the symbols to have GOT entries.
168
        if (requiresGOTAccess(sym))
169
          addGOTEntry(sym);
170
        break;
171
      }
172
    } else if (sym->isUndefined() && !config->relocatable && !sym->isWeak()) {
173
      // Report undefined symbols
174
      reportUndefined(file, sym);
175
    }
176
  }
177
}
178

179
} // namespace lld::wasm
180

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.