mirror of
https://github.com/intel/llvm.git
synced 2026-02-02 10:08:59 +08:00
Main executable did not export symbols that exist both in the main executable and in DSOs before this patch. Symbols from object files that override symbols in DSO should be added to .dynsym table. Differential revision: http://reviews.llvm.org/D16405 llvm-svn: 258672
183 lines
5.8 KiB
C++
183 lines
5.8 KiB
C++
//===- 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 "InputSection.h"
|
|
#include "Error.h"
|
|
#include "InputFiles.h"
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/Config/config.h"
|
|
|
|
#ifdef HAVE_CXXABI_H
|
|
#include <cxxabi.h>
|
|
#endif
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::object;
|
|
using namespace llvm::ELF;
|
|
|
|
using namespace lld;
|
|
using namespace lld::elf2;
|
|
|
|
static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
|
|
if (VA == STV_DEFAULT)
|
|
return VB;
|
|
if (VB == STV_DEFAULT)
|
|
return VA;
|
|
return std::min(VA, VB);
|
|
}
|
|
|
|
// Returns 1, 0 or -1 if this symbol should take precedence
|
|
// over the Other, tie or lose, respectively.
|
|
template <class ELFT> int SymbolBody::compare(SymbolBody *Other) {
|
|
typedef typename ELFFile<ELFT>::uintX_t uintX_t;
|
|
assert(!isLazy() && !Other->isLazy());
|
|
std::tuple<bool, bool, bool> L(isDefined(), !isShared(), !isWeak());
|
|
std::tuple<bool, bool, bool> R(Other->isDefined(), !Other->isShared(),
|
|
!Other->isWeak());
|
|
|
|
// Normalize
|
|
if (L > R)
|
|
return -Other->compare<ELFT>(this);
|
|
|
|
Visibility = Other->Visibility =
|
|
getMinVisibility(Visibility, Other->Visibility);
|
|
|
|
if (IsUsedInRegularObj || Other->IsUsedInRegularObj)
|
|
IsUsedInRegularObj = Other->IsUsedInRegularObj = true;
|
|
|
|
// We want to export all symbols that exist both in the executable
|
|
// and in DSOs, so that the symbols in the executable can interrupt
|
|
// symbols in the DSO at runtime.
|
|
if (isShared() != Other->isShared())
|
|
if (isa<DefinedRegular<ELFT>>(isShared() ? Other : this))
|
|
IsUsedInDynamicReloc = Other->IsUsedInDynamicReloc = true;
|
|
|
|
if (L != R)
|
|
return -1;
|
|
if (!std::get<0>(L) || !std::get<1>(L) || !std::get<2>(L))
|
|
return 1;
|
|
if (isCommon()) {
|
|
if (!Other->isCommon())
|
|
return -1;
|
|
auto *ThisC = cast<DefinedCommon>(this);
|
|
auto *OtherC = cast<DefinedCommon>(Other);
|
|
uintX_t Align = std::max(ThisC->MaxAlignment, OtherC->MaxAlignment);
|
|
if (ThisC->Size >= OtherC->Size) {
|
|
ThisC->MaxAlignment = Align;
|
|
return 1;
|
|
}
|
|
OtherC->MaxAlignment = Align;
|
|
return -1;
|
|
}
|
|
if (Other->isCommon())
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
Defined::Defined(Kind K, StringRef Name, bool IsWeak, uint8_t Visibility,
|
|
bool IsTls)
|
|
: SymbolBody(K, Name, IsWeak, Visibility, IsTls) {}
|
|
|
|
Undefined::Undefined(SymbolBody::Kind K, StringRef N, bool IsWeak,
|
|
uint8_t Visibility, bool IsTls)
|
|
: SymbolBody(K, N, IsWeak, Visibility, IsTls), CanKeepUndefined(false) {}
|
|
|
|
Undefined::Undefined(StringRef N, bool IsWeak, uint8_t Visibility,
|
|
bool CanKeepUndefined)
|
|
: Undefined(SymbolBody::UndefinedKind, N, IsWeak, Visibility,
|
|
/*IsTls*/ false) {
|
|
this->CanKeepUndefined = CanKeepUndefined;
|
|
}
|
|
|
|
template <typename ELFT>
|
|
UndefinedElf<ELFT>::UndefinedElf(StringRef N, const Elf_Sym &Sym)
|
|
: Undefined(SymbolBody::UndefinedElfKind, N,
|
|
Sym.getBinding() == llvm::ELF::STB_WEAK, Sym.getVisibility(),
|
|
Sym.getType() == llvm::ELF::STT_TLS),
|
|
Sym(Sym) {}
|
|
|
|
template <typename ELFT>
|
|
DefinedSynthetic<ELFT>::DefinedSynthetic(StringRef N, uintX_t Value,
|
|
OutputSectionBase<ELFT> &Section)
|
|
: Defined(SymbolBody::DefinedSyntheticKind, N, false, STV_DEFAULT, false),
|
|
Value(Value), Section(Section) {}
|
|
|
|
DefinedCommon::DefinedCommon(StringRef N, uint64_t Size, uint64_t Alignment,
|
|
bool IsWeak, uint8_t Visibility)
|
|
: Defined(SymbolBody::DefinedCommonKind, N, IsWeak, Visibility, false) {
|
|
MaxAlignment = Alignment;
|
|
this->Size = Size;
|
|
}
|
|
|
|
std::unique_ptr<InputFile> Lazy::getMember() {
|
|
MemoryBufferRef MBRef = File->getMember(&Sym);
|
|
|
|
// getMember returns an empty buffer if the member was already
|
|
// read from the library.
|
|
if (MBRef.getBuffer().empty())
|
|
return std::unique_ptr<InputFile>(nullptr);
|
|
return createObjectFile(MBRef);
|
|
}
|
|
|
|
template <class ELFT> static void doInitSymbols() {
|
|
ElfSym<ELFT>::End.setBinding(STB_GLOBAL);
|
|
ElfSym<ELFT>::Ignored.setBinding(STB_WEAK);
|
|
ElfSym<ELFT>::Ignored.setVisibility(STV_HIDDEN);
|
|
}
|
|
|
|
void elf2::initSymbols() {
|
|
doInitSymbols<ELF32LE>();
|
|
doInitSymbols<ELF32BE>();
|
|
doInitSymbols<ELF64LE>();
|
|
doInitSymbols<ELF64BE>();
|
|
}
|
|
|
|
// Returns the demangled C++ symbol name for Name.
|
|
std::string elf2::demangle(StringRef Name) {
|
|
#if !defined(HAVE_CXXABI_H)
|
|
return Name;
|
|
#else
|
|
if (!Config->Demangle)
|
|
return Name;
|
|
|
|
// __cxa_demangle can be used to demangle strings other than symbol
|
|
// names which do not necessarily start with "_Z". Name can be
|
|
// either a C or C++ symbol. Don't call __cxa_demangle if the name
|
|
// does not look like a C++ symbol name to avoid getting unexpected
|
|
// result for a C symbol that happens to match a mangled type name.
|
|
if (!Name.startswith("_Z"))
|
|
return Name;
|
|
|
|
char *Buf =
|
|
abi::__cxa_demangle(Name.str().c_str(), nullptr, nullptr, nullptr);
|
|
if (!Buf)
|
|
return Name;
|
|
std::string S(Buf);
|
|
free(Buf);
|
|
return S;
|
|
#endif
|
|
}
|
|
|
|
template int SymbolBody::compare<ELF32LE>(SymbolBody *Other);
|
|
template int SymbolBody::compare<ELF32BE>(SymbolBody *Other);
|
|
template int SymbolBody::compare<ELF64LE>(SymbolBody *Other);
|
|
template int SymbolBody::compare<ELF64BE>(SymbolBody *Other);
|
|
|
|
template class elf2::UndefinedElf<ELF32LE>;
|
|
template class elf2::UndefinedElf<ELF32BE>;
|
|
template class elf2::UndefinedElf<ELF64LE>;
|
|
template class elf2::UndefinedElf<ELF64BE>;
|
|
|
|
template class elf2::DefinedSynthetic<ELF32LE>;
|
|
template class elf2::DefinedSynthetic<ELF32BE>;
|
|
template class elf2::DefinedSynthetic<ELF64LE>;
|
|
template class elf2::DefinedSynthetic<ELF64BE>;
|