2017-11-18 02:14:09 +08:00
|
|
|
//===- Symbols.cpp --------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Linker
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "Symbols.h"
|
|
|
|
|
|
|
|
#include "Config.h"
|
2018-01-10 09:13:34 +08:00
|
|
|
#include "InputChunks.h"
|
2017-11-18 02:14:09 +08:00
|
|
|
#include "InputFiles.h"
|
|
|
|
#include "lld/Common/ErrorHandler.h"
|
2017-12-06 11:10:39 +08:00
|
|
|
#include "lld/Common/Strings.h"
|
2017-11-18 02:14:09 +08:00
|
|
|
|
|
|
|
#define DEBUG_TYPE "lld"
|
|
|
|
|
|
|
|
using namespace llvm;
|
2018-01-10 08:52:20 +08:00
|
|
|
using namespace llvm::wasm;
|
2017-11-18 02:14:09 +08:00
|
|
|
using namespace lld;
|
|
|
|
using namespace lld::wasm;
|
|
|
|
|
2018-02-03 06:59:56 +08:00
|
|
|
Symbol *WasmSym::CallCtors;
|
|
|
|
Symbol *WasmSym::DsoHandle;
|
2018-02-07 11:04:53 +08:00
|
|
|
Symbol *WasmSym::DataEnd;
|
2018-02-03 06:59:56 +08:00
|
|
|
Symbol *WasmSym::HeapBase;
|
|
|
|
Symbol *WasmSym::StackPointer;
|
|
|
|
|
2017-11-30 09:40:08 +08:00
|
|
|
const WasmSignature &Symbol::getFunctionType() const {
|
2018-01-29 03:57:01 +08:00
|
|
|
if (Chunk != nullptr)
|
|
|
|
return dyn_cast<InputFunction>(Chunk)->Signature;
|
2018-01-10 07:56:44 +08:00
|
|
|
|
2017-11-30 09:40:08 +08:00
|
|
|
assert(FunctionType != nullptr);
|
|
|
|
return *FunctionType;
|
2017-11-18 02:14:09 +08:00
|
|
|
}
|
|
|
|
|
2018-01-10 07:56:44 +08:00
|
|
|
void Symbol::setFunctionType(const WasmSignature *Type) {
|
|
|
|
assert(FunctionType == nullptr);
|
2018-01-29 03:57:01 +08:00
|
|
|
assert(!Chunk);
|
2018-01-10 07:56:44 +08:00
|
|
|
FunctionType = Type;
|
|
|
|
}
|
|
|
|
|
2017-11-18 02:14:09 +08:00
|
|
|
uint32_t Symbol::getVirtualAddress() const {
|
|
|
|
assert(isGlobal());
|
|
|
|
DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n");
|
2018-01-29 03:57:02 +08:00
|
|
|
return Chunk ? dyn_cast<InputSegment>(Chunk)->translateVA(VirtualAddress)
|
|
|
|
: VirtualAddress;
|
2017-11-18 02:14:09 +08:00
|
|
|
}
|
|
|
|
|
2018-01-10 07:56:44 +08:00
|
|
|
bool Symbol::hasOutputIndex() const {
|
2018-01-29 03:57:02 +08:00
|
|
|
if (auto *F = dyn_cast_or_null<InputFunction>(Chunk))
|
2018-01-29 03:57:01 +08:00
|
|
|
return F->hasOutputIndex();
|
2018-01-10 07:56:44 +08:00
|
|
|
return OutputIndex.hasValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t Symbol::getOutputIndex() const {
|
2018-01-29 03:57:02 +08:00
|
|
|
if (auto *F = dyn_cast_or_null<InputFunction>(Chunk))
|
2018-01-29 03:57:01 +08:00
|
|
|
return F->getOutputIndex();
|
2018-01-10 07:56:44 +08:00
|
|
|
return OutputIndex.getValue();
|
|
|
|
}
|
|
|
|
|
2017-12-06 03:05:45 +08:00
|
|
|
void Symbol::setVirtualAddress(uint32_t Value) {
|
|
|
|
DEBUG(dbgs() << "setVirtualAddress " << Name << " -> " << Value << "\n");
|
2018-01-10 08:52:20 +08:00
|
|
|
assert(isGlobal());
|
2017-12-06 03:05:45 +08:00
|
|
|
VirtualAddress = Value;
|
|
|
|
}
|
|
|
|
|
2017-11-18 02:14:09 +08:00
|
|
|
void Symbol::setOutputIndex(uint32_t Index) {
|
|
|
|
DEBUG(dbgs() << "setOutputIndex " << Name << " -> " << Index << "\n");
|
2018-01-29 03:57:01 +08:00
|
|
|
assert(!dyn_cast_or_null<InputFunction>(Chunk));
|
2017-12-12 06:00:56 +08:00
|
|
|
assert(!OutputIndex.hasValue());
|
2017-11-18 02:14:09 +08:00
|
|
|
OutputIndex = Index;
|
|
|
|
}
|
2017-12-12 06:00:56 +08:00
|
|
|
|
2018-01-25 05:45:25 +08:00
|
|
|
uint32_t Symbol::getTableIndex() const {
|
2018-01-29 03:57:02 +08:00
|
|
|
if (auto *F = dyn_cast_or_null<InputFunction>(Chunk))
|
2018-01-29 03:57:01 +08:00
|
|
|
return F->getTableIndex();
|
2018-01-25 05:45:25 +08:00
|
|
|
return TableIndex.getValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Symbol::hasTableIndex() const {
|
2018-01-29 03:57:02 +08:00
|
|
|
if (auto *F = dyn_cast_or_null<InputFunction>(Chunk))
|
2018-01-29 03:57:01 +08:00
|
|
|
return F->hasTableIndex();
|
2018-01-25 05:45:25 +08:00
|
|
|
return TableIndex.hasValue();
|
|
|
|
}
|
|
|
|
|
2017-12-12 06:00:56 +08:00
|
|
|
void Symbol::setTableIndex(uint32_t Index) {
|
2018-01-25 05:45:25 +08:00
|
|
|
// For imports, we set the table index here on the Symbol; for defined
|
|
|
|
// functions we set the index on the InputFunction so that we don't export
|
|
|
|
// the same thing twice (keeps the table size down).
|
2018-01-29 03:57:02 +08:00
|
|
|
if (auto *F = dyn_cast_or_null<InputFunction>(Chunk)) {
|
2018-01-29 03:57:01 +08:00
|
|
|
F->setTableIndex(Index);
|
2018-01-25 05:45:25 +08:00
|
|
|
return;
|
|
|
|
}
|
2017-12-12 06:00:56 +08:00
|
|
|
DEBUG(dbgs() << "setTableIndex " << Name << " -> " << Index << "\n");
|
|
|
|
assert(!TableIndex.hasValue());
|
|
|
|
TableIndex = Index;
|
|
|
|
}
|
2017-11-18 02:14:09 +08:00
|
|
|
|
2018-01-29 03:57:02 +08:00
|
|
|
void Symbol::update(Kind K, InputFile *F, uint32_t Flags_, InputChunk *Chunk_,
|
2018-01-10 08:52:20 +08:00
|
|
|
uint32_t Address) {
|
2017-11-18 02:14:09 +08:00
|
|
|
SymbolKind = K;
|
|
|
|
File = F;
|
2018-01-10 08:52:20 +08:00
|
|
|
Flags = Flags_;
|
2018-01-29 03:57:01 +08:00
|
|
|
Chunk = Chunk_;
|
2018-01-10 08:52:20 +08:00
|
|
|
if (Address != UINT32_MAX)
|
|
|
|
setVirtualAddress(Address);
|
2017-11-18 02:14:09 +08:00
|
|
|
}
|
|
|
|
|
2018-01-10 08:52:20 +08:00
|
|
|
bool Symbol::isWeak() const {
|
|
|
|
return (Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK;
|
|
|
|
}
|
2017-11-18 02:14:09 +08:00
|
|
|
|
2018-01-10 08:52:20 +08:00
|
|
|
bool Symbol::isLocal() const {
|
|
|
|
return (Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_LOCAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Symbol::isHidden() const {
|
|
|
|
return (Flags & WASM_SYMBOL_VISIBILITY_MASK) == WASM_SYMBOL_VISIBILITY_HIDDEN;
|
|
|
|
}
|
2017-12-03 10:38:04 +08:00
|
|
|
|
2018-01-13 06:10:35 +08:00
|
|
|
void Symbol::setHidden(bool IsHidden) {
|
2018-01-20 09:44:45 +08:00
|
|
|
DEBUG(dbgs() << "setHidden: " << Name << " -> " << IsHidden << "\n");
|
2018-01-13 06:10:35 +08:00
|
|
|
Flags &= ~WASM_SYMBOL_VISIBILITY_MASK;
|
|
|
|
if (IsHidden)
|
|
|
|
Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN;
|
|
|
|
else
|
|
|
|
Flags |= WASM_SYMBOL_VISIBILITY_DEFAULT;
|
|
|
|
}
|
|
|
|
|
2017-12-06 00:50:46 +08:00
|
|
|
std::string lld::toString(const wasm::Symbol &Sym) {
|
2017-12-06 11:10:39 +08:00
|
|
|
if (Config->Demangle)
|
|
|
|
if (Optional<std::string> S = demangleItanium(Sym.getName()))
|
|
|
|
return "`" + *S + "'";
|
|
|
|
return Sym.getName();
|
2017-11-18 02:14:09 +08:00
|
|
|
}
|
|
|
|
|
2017-12-06 00:50:46 +08:00
|
|
|
std::string lld::toString(wasm::Symbol::Kind Kind) {
|
2017-11-18 02:14:09 +08:00
|
|
|
switch (Kind) {
|
|
|
|
case wasm::Symbol::DefinedFunctionKind:
|
|
|
|
return "DefinedFunction";
|
|
|
|
case wasm::Symbol::DefinedGlobalKind:
|
|
|
|
return "DefinedGlobal";
|
|
|
|
case wasm::Symbol::UndefinedFunctionKind:
|
|
|
|
return "UndefinedFunction";
|
|
|
|
case wasm::Symbol::UndefinedGlobalKind:
|
|
|
|
return "UndefinedGlobal";
|
|
|
|
case wasm::Symbol::LazyKind:
|
|
|
|
return "LazyKind";
|
|
|
|
}
|
|
|
|
llvm_unreachable("Invalid symbol kind!");
|
|
|
|
}
|