brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.1 KiB · 5f923fd Raw
227 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "Relocations.h"10 11#include "InputChunks.h"12#include "OutputSegment.h"13#include "SymbolTable.h"14#include "SyntheticSections.h"15 16using namespace llvm;17using namespace llvm::wasm;18 19namespace lld::wasm {20 21static bool requiresGOTAccess(const Symbol *sym) {22  if (sym->isShared())23    return true;24  if (!ctx.isPic &&25      ctx.arg.unresolvedSymbols != UnresolvedPolicy::ImportDynamic)26    return false;27  if (sym->isHidden() || sym->isLocal())28    return false;29  // With `-Bsymbolic` (or when building an executable) as don't need to use30  // the GOT for symbols that are defined within the current module.31  if (sym->isDefined() && (!ctx.arg.shared || ctx.arg.bsymbolic))32    return false;33  return true;34}35 36static bool allowUndefined(const Symbol* sym) {37  // Symbols that are explicitly imported are always allowed to be undefined at38  // link time.39  if (sym->isImported())40    return true;41  if (isa<UndefinedFunction>(sym) && ctx.arg.importUndefined)42    return true;43 44  return ctx.arg.allowUndefinedSymbols.count(sym->getName()) != 0;45}46 47static void reportUndefined(ObjFile *file, Symbol *sym) {48  if (!allowUndefined(sym)) {49    switch (ctx.arg.unresolvedSymbols) {50    case UnresolvedPolicy::ReportError:51      error(toString(file) + ": undefined symbol: " + toString(*sym));52      break;53    case UnresolvedPolicy::Warn:54      warn(toString(file) + ": undefined symbol: " + toString(*sym));55      break;56    case UnresolvedPolicy::Ignore:57      LLVM_DEBUG(dbgs() << "ignoring undefined symbol: " + toString(*sym) +58                               "\n");59      break;60    case UnresolvedPolicy::ImportDynamic:61      break;62    }63 64    if (auto *f = dyn_cast<UndefinedFunction>(sym)) {65      if (!f->stubFunction &&66          ctx.arg.unresolvedSymbols != UnresolvedPolicy::ImportDynamic &&67          !ctx.arg.importUndefined) {68        f->stubFunction = symtab->createUndefinedStub(*f->getSignature());69        f->stubFunction->markLive();70        // Mark the function itself as a stub which prevents it from being71        // assigned a table entry.72        f->isStub = true;73      }74    }75  }76}77 78static void addGOTEntry(Symbol *sym) {79  if (requiresGOTAccess(sym))80    out.importSec->addGOTEntry(sym);81  else82    out.globalSec->addInternalGOTEntry(sym);83}84 85void scanRelocations(InputChunk *chunk) {86  if (!chunk->live)87    return;88  ObjFile *file = chunk->file;89  ArrayRef<WasmSignature> types = file->getWasmObj()->types();90  for (const WasmRelocation &reloc : chunk->getRelocations()) {91    if (reloc.Type == R_WASM_TYPE_INDEX_LEB) {92      // Mark target type as live93      file->typeMap[reloc.Index] =94          out.typeSec->registerType(types[reloc.Index]);95      file->typeIsUsed[reloc.Index] = true;96      continue;97    }98 99    // Other relocation types all have a corresponding symbol100    Symbol *sym = file->getSymbols()[reloc.Index];101 102    switch (reloc.Type) {103    case R_WASM_TABLE_INDEX_I32:104    case R_WASM_TABLE_INDEX_I64:105    case R_WASM_TABLE_INDEX_SLEB:106    case R_WASM_TABLE_INDEX_SLEB64:107    case R_WASM_TABLE_INDEX_REL_SLEB:108    case R_WASM_TABLE_INDEX_REL_SLEB64:109      if (requiresGOTAccess(sym))110        break;111      out.elemSec->addEntry(cast<FunctionSymbol>(sym));112      break;113    case R_WASM_MEMORY_ADDR_LEB:114    case R_WASM_MEMORY_ADDR_LEB64:115    case R_WASM_MEMORY_ADDR_SLEB:116    case R_WASM_MEMORY_ADDR_SLEB64:117    case R_WASM_MEMORY_ADDR_I32:118    case R_WASM_MEMORY_ADDR_I64:119      // glibc/wasm32 (HWJS-B-1): after commit 12776b692 a strong undefined-DATA120      // reference (e.g. the target of a GNU-as alias `memset = __GI_memset`)121      // can resolve to a real FUNCTION definition. Taking the address of that122      // symbol yields a function pointer, i.e. its index in123      // __indirect_function_table. Register it in the indirect function table124      // exactly as a R_WASM_TABLE_INDEX_* reference would, so a real (non-zero)125      // table index is assigned; ObjFile::calcNewValue then emits that index.126      // Data (non-function) targets are unaffected and take the normal path.127      if (auto *f = dyn_cast<FunctionSymbol>(sym))128        if (!requiresGOTAccess(sym)) {129          // Unlike a normal R_WASM_TABLE_INDEX_* reference, an object that130          // takes a function's address through a *data* relocation need not131          // import __indirect_function_table, so the table symbol may not yet132          // exist. Materialize it (as ensureIndirectFunctionTable does for GOT133          // function entries) before adding the table entry.134          if (!ctx.sym.indirectFunctionTable)135            ctx.sym.indirectFunctionTable =136                symtab->resolveIndirectFunctionTable(/*required=*/true);137          out.elemSec->addEntry(f);138        }139      break;140    case R_WASM_GLOBAL_INDEX_LEB:141    case R_WASM_GLOBAL_INDEX_I32:142      if (!isa<GlobalSymbol>(sym))143        addGOTEntry(sym);144      break;145    case R_WASM_MEMORY_ADDR_TLS_SLEB:146    case R_WASM_MEMORY_ADDR_TLS_SLEB64:147      if (!sym->isDefined()) {148        error(toString(file) + ": relocation " + relocTypeToString(reloc.Type) +149              " cannot be used against an undefined symbol `" + toString(*sym) +150              "`");151      }152      // In single-threaded builds TLS is lowered away and TLS data can be153      // merged with normal data and allowing TLS relocation in non-TLS154      // segments.155      if (ctx.arg.sharedMemory) {156        if (!sym->isTLS()) {157          error(toString(file) + ": relocation " +158                relocTypeToString(reloc.Type) +159                " cannot be used against non-TLS symbol `" + toString(*sym) +160                "`");161        }162        if (auto *D = dyn_cast<DefinedData>(sym)) {163          if (!D->segment->outputSeg->isTLS()) {164            error(toString(file) + ": relocation " +165                  relocTypeToString(reloc.Type) + " cannot be used against `" +166                  toString(*sym) +167                  "` in non-TLS section: " + D->segment->outputSeg->name);168          }169        }170      }171      break;172    }173 174    if (ctx.isPic || sym->isShared() ||175        (sym->isUndefined() &&176         ctx.arg.unresolvedSymbols == UnresolvedPolicy::ImportDynamic)) {177      switch (reloc.Type) {178      case R_WASM_TABLE_INDEX_SLEB:179      case R_WASM_TABLE_INDEX_SLEB64:180      case R_WASM_MEMORY_ADDR_SLEB:181      case R_WASM_MEMORY_ADDR_LEB:182      case R_WASM_MEMORY_ADDR_SLEB64:183      case R_WASM_MEMORY_ADDR_LEB64:184        // Certain relocation types can't be used when building PIC output,185        // since they would require absolute symbol addresses at link time.186        error(toString(file) + ": relocation " + relocTypeToString(reloc.Type) +187              " cannot be used against symbol `" + toString(*sym) +188              "`; recompile with -fPIC");189        break;190      case R_WASM_TABLE_INDEX_I32:191      case R_WASM_TABLE_INDEX_I64:192      case R_WASM_MEMORY_ADDR_I32:193      case R_WASM_MEMORY_ADDR_I64:194        // These relocation types are only present in the data section and195        // will be converted into code by `generateRelocationCode`.  This196        // code requires the symbols to have GOT entries.197        if (requiresGOTAccess(sym))198          addGOTEntry(sym);199        break;200      }201    }202 203    if (!ctx.arg.relocatable && sym->isUndefined()) {204      switch (reloc.Type) {205      case R_WASM_TABLE_INDEX_REL_SLEB:206      case R_WASM_TABLE_INDEX_REL_SLEB64:207      case R_WASM_MEMORY_ADDR_REL_SLEB:208      case R_WASM_MEMORY_ADDR_REL_SLEB64:209        // These relocation types are for symbols that exists relative to210        // `__memory_base` or `__table_base` and as such only make sense for211        // defined symbols.212        error(toString(file) + ": relocation " + relocTypeToString(reloc.Type) +213              " is not supported against an undefined symbol `" +214              toString(*sym) + "`");215        break;216      }217 218      if (!sym->isWeak()) {219        // Report undefined symbols220        reportUndefined(file, sym);221      }222    }223  }224}225 226} // namespace lld::wasm227