// Define a symbol.
Symbol *Sym;
uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT;
- std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, /*Type*/ 0, Visibility,
+ std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, Visibility,
/*CanOmitFromDynSym*/ false,
/*File*/ nullptr);
ExprValue Value = Cmd->Expression();
// We can't calculate final value right now.
Symbol *Sym;
uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT;
- std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, /*Type*/ 0, Visibility,
+ std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, Visibility,
/*CanOmitFromDynSym*/ false,
/*File*/ nullptr);
replaceSymbol<Defined>(Sym, nullptr, Cmd->Name, STB_GLOBAL, Visibility,
return {SymVector[SymIndex], false};
auto *Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
+ Sym->SymbolKind = Symbol::PlaceholderKind;
Sym->Visibility = STV_DEFAULT;
Sym->IsUsedInRegularObj = false;
Sym->ExportDynamic = false;
// Find an existing symbol or create and insert a new one, then apply the given
// attributes.
-std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, uint8_t Type,
+std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name,
uint8_t Visibility,
bool CanOmitFromDynSym,
InputFile *File) {
if (!File || File->kind() == InputFile::ObjKind)
S->IsUsedInRegularObj = true;
- bool HasTlsAttr = !WasInserted && (!S->isLazy() || S->isTls());
- if (HasTlsAttr && (Type == STT_TLS) != S->isTls())
- error("TLS attribute mismatch: " + toString(*S) + "\n>>> defined in " +
- toString(S->File) + "\n>>> defined in " + toString(File));
-
return {S, WasInserted};
}
Symbol *S;
bool WasInserted;
uint8_t Visibility = getVisibility(StOther);
- std::tie(S, WasInserted) =
- insert(Name, Type, Visibility, CanOmitFromDynSym, File);
+ std::tie(S, WasInserted) = insert(Name, Visibility, CanOmitFromDynSym, File);
// An undefined symbol with non default visibility must be satisfied
// in the same DSO.
InputFile &File) {
Symbol *S;
bool WasInserted;
- std::tie(S, WasInserted) = insert(N, Type, getVisibility(StOther),
+ std::tie(S, WasInserted) = insert(N, getVisibility(StOther),
/*CanOmitFromDynSym*/ false, &File);
int Cmp = compareDefined(S, WasInserted, Binding, N);
SectionBase *Section, InputFile *File) {
Symbol *S;
bool WasInserted;
- std::tie(S, WasInserted) = insert(Name, Type, getVisibility(StOther),
+ std::tie(S, WasInserted) = insert(Name, getVisibility(StOther),
/*CanOmitFromDynSym*/ false, File);
int Cmp = compareDefinedNonCommon(S, WasInserted, Binding, Section == nullptr,
Value, Name);
// unchanged.
Symbol *S;
bool WasInserted;
- std::tie(S, WasInserted) = insert(Name, Sym.getType(), STV_DEFAULT,
+ std::tie(S, WasInserted) = insert(Name, STV_DEFAULT,
/*CanOmitFromDynSym*/ true, &File);
// Make sure we preempt DSO symbols with default visibility.
if (Sym.getVisibility() == STV_DEFAULT)
Symbol *S;
bool WasInserted;
std::tie(S, WasInserted) =
- insert(Name, Type, getVisibility(StOther), CanOmitFromDynSym, &F);
+ insert(Name, getVisibility(StOther), CanOmitFromDynSym, &F);
int Cmp = compareDefinedNonCommon(S, WasInserted, Binding,
/*IsAbs*/ false, /*Value*/ 0, Name);
if (Cmp > 0)
namespace lld {
namespace elf {
+class Symbol;
+class InputFile;
+} // namespace elf
+
+std::string toString(const elf::Symbol &);
+std::string toString(const elf::InputFile *);
+
+namespace elf {
class ArchiveFile;
class BitcodeFile;
class Symbol {
public:
enum Kind {
+ PlaceholderKind,
DefinedKind,
SharedKind,
UndefinedKind,
uint8_t Type; // symbol type
uint8_t StOther; // st_other field value
- const uint8_t SymbolKind;
+ uint8_t SymbolKind;
// Symbol visibility. This is the computed minimum visibility of all
// observed non-DSO symbols.
template <typename T, typename... ArgT>
void replaceSymbol(Symbol *S, ArgT &&... Arg) {
+ using llvm::ELF::STT_TLS;
+
static_assert(std::is_trivially_destructible<T>(),
"Symbol types must be trivially destructible");
static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
S->Traced = Sym.Traced;
S->ScriptDefined = Sym.ScriptDefined;
+ // Symbols representing thread-local variables must be referenced by
+ // TLS-aware relocations, and non-TLS symbols must be reference by
+ // non-TLS relocations, so there's a clear distinction between TLS
+ // and non-TLS symbols. It is an error if the same symbol is defined
+ // as a TLS symbol in one file and as a non-TLS symbol in other file.
+ bool TlsMismatch = (Sym.Type == STT_TLS && S->Type != STT_TLS) ||
+ (Sym.Type != STT_TLS && S->Type == STT_TLS);
+
+ if (Sym.SymbolKind != Symbol::PlaceholderKind && TlsMismatch && !Sym.isLazy())
+ error("TLS attribute mismatch: " + toString(Sym) + "\n>>> defined in " +
+ toString(Sym.File) + "\n>>> defined in " + toString(S->File));
+
// Print out a log message if --trace-symbol was specified.
// This is for debugging.
if (S->Traced)
void warnUnorderableSymbol(const Symbol *Sym);
} // namespace elf
-
-std::string toString(const elf::Symbol &B);
} // namespace lld
#endif