auto *bss = make<BssSection>("COMMON", s->size, s->alignment);
bss->file = s->file;
inputSections.push_back(bss);
- s->replace(Defined{s->file, StringRef(), s->binding, s->stOther, s->type,
- /*value=*/0, s->size, bss});
+ Defined(s->file, StringRef(), s->binding, s->stOther, s->type,
+ /*value=*/0, s->size, bss)
+ .overwrite(*s);
}
}
}
if (!(s && !cast<SharedFile>(s->file)->isNeeded) && !sym->isLazy())
continue;
- bool used = sym->used;
uint8_t binding = sym->isLazy() ? sym->binding : uint8_t(STB_WEAK);
- sym->replace(
- Undefined{nullptr, sym->getName(), binding, sym->stOther, sym->type});
- sym->used = used;
+ Undefined(nullptr, sym->getName(), binding, sym->stOther, sym->type)
+ .overwrite(*sym);
sym->versionId = VER_NDX_GLOBAL;
}
}
[](BitcodeFile *file) { file->postParse(); });
for (auto &it : ctx->nonPrevailingSyms) {
Symbol &sym = *it.first;
- sym.replace(Undefined{sym.file, sym.getName(), sym.binding, sym.stOther,
- sym.type, it.second});
+ Undefined(sym.file, sym.getName(), sym.binding, sym.stOther, sym.type,
+ it.second)
+ .overwrite(sym);
cast<Undefined>(sym).nonPrevailing = true;
}
ctx->nonPrevailingSyms.clear();
new (symbols[i]) Defined(this, name, STB_LOCAL, eSym.st_other, type,
eSym.st_value, eSym.st_size, sec);
symbols[i]->isUsedInRegularObj = true;
+ symbols[i]->auxIdx = -1;
+ symbols[i]->dynsymIndex = 0;
}
}
!(dr->section == nullptr && (!sym->file || sym->file->isElf()));
if (r.Prevailing)
- sym->replace(
- Undefined{nullptr, StringRef(), STB_GLOBAL, STV_DEFAULT, sym->type});
+ Undefined(nullptr, StringRef(), STB_GLOBAL, STV_DEFAULT, sym->type)
+ .overwrite(*sym);
// We tell LTO to not apply interprocedural optimization for wrapped
// (with --wrap) symbols because otherwise LTO would inline them while
Symbol *sym = symtab->insert(cmd->name);
sym->mergeProperties(newSym);
- sym->replace(newSym);
+ newSym.overwrite(*sym);
sym->isUsedInRegularObj = true;
cmd->sym = cast<Defined>(sym);
}
// We can't calculate final value right now.
Symbol *sym = symtab->insert(cmd->name);
sym->mergeProperties(newSym);
- sym->replace(newSym);
+ newSym.overwrite(*sym);
cmd->sym = cast<Defined>(sym);
cmd->provide = false;
static void replaceWithDefined(Symbol &sym, SectionBase &sec, uint64_t value,
uint64_t size) {
Symbol old = sym;
+ Defined(sym.file, StringRef(), sym.binding, sym.stOther, sym.type, value,
+ size, &sec)
+ .overwrite(sym);
- sym.replace(Defined{sym.file, StringRef(), sym.binding, sym.stOther,
- sym.type, value, size, &sec});
-
- sym.auxIdx = old.auxIdx;
- sym.verdefIndex = old.verdefIndex;
sym.exportDynamic = true;
sym.isUsedInRegularObj = true;
// A copy relocated alias may need a GOT entry.
- if (old.hasFlag(NEEDS_GOT))
- sym.setFlags(NEEDS_GOT);
+ sym.flags.store(old.flags.load(std::memory_order_relaxed) & NEEDS_GOT,
+ std::memory_order_relaxed);
}
// Reserve space in .bss or .bss.rel.ro for copy relocation.
Symbol *sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
symVector.push_back(sym);
- // *sym was not initialized by a constructor. Fields that may get referenced
- // when it is a placeholder must be initialized here.
+ // *sym was not initialized by a constructor. Initialize all Symbol fields.
+ memset(sym, 0, sizeof(Symbol));
sym->setName(name);
- sym->symbolKind = Symbol::PlaceholderKind;
sym->partition = 1;
- sym->setVisibility(STV_DEFAULT);
- sym->isUsedInRegularObj = false;
- sym->exportDynamic = false;
- sym->inDynamicList = false;
- sym->referenced = false;
- sym->traced = false;
- sym->scriptDefined = false;
+ sym->auxIdx = -1;
+ sym->verdefIndex = -1;
sym->versionId = VER_NDX_GLOBAL;
if (pos != StringRef::npos)
sym->hasVersionSuffix = true;
// existing undefined symbol for better error message later.
if (isPlaceholder() || (isShared() && other.visibility() != STV_DEFAULT) ||
(isUndefined() && other.binding != STB_WEAK && other.discardedSecIdx)) {
- replace(other);
+ other.overwrite(*this);
return;
}
// files were linked into a shared object first should not change the
// regular rule that picks the largest st_size.
uint64_t size = s->size;
- replace(other);
+ other.overwrite(*this);
if (size > cast<CommonSymbol>(this)->size)
cast<CommonSymbol>(this)->size = size;
} else {
- replace(other);
+ other.overwrite(*this);
}
}
void Symbol::resolveDefined(const Defined &other) {
if (shouldReplace(other))
- replace(other);
+ other.overwrite(*this);
}
void Symbol::resolveLazy(const LazyObject &other) {
if (isPlaceholder()) {
- replace(other);
+ other.overwrite(*this);
return;
}
if (LLVM_UNLIKELY(isCommon()) && elf::config->fortranCommon &&
other.file->shouldExtractForCommon(getName())) {
ctx->backwardReferences.erase(this);
- replace(other);
+ other.overwrite(*this);
other.extract();
return;
}
// Symbols.h for the details.
if (isWeak()) {
uint8_t ty = type;
- replace(other);
+ other.overwrite(*this);
type = ty;
binding = STB_WEAK;
return;
void Symbol::resolveShared(const SharedSymbol &other) {
if (isPlaceholder()) {
- replace(other);
+ other.overwrite(*this);
return;
}
if (isCommon()) {
// An undefined symbol with non default visibility must be satisfied
// in the same DSO.
uint8_t bind = binding;
- replace(other);
+ other.overwrite(*this);
binding = bind;
} else if (traced)
printTraceSymbol(other, getName());
class LazyObject;
class InputFile;
+void printTraceSymbol(const Symbol &sym, StringRef name);
+
enum {
NEEDS_GOT = 1 << 0,
NEEDS_PLT = 1 << 1,
// True if the name contains '@'.
uint8_t hasVersionSuffix : 1;
- inline void replace(const Symbol &other);
-
// Symbol visibility. This is the computed minimum visibility of all
// observed non-DSO symbols.
uint8_t visibility() const { return stOther & 3; }
gotInIgot(false), folded(false), needsTocRestore(false),
scriptDefined(false), dsoProtected(false) {}
+ void overwrite(Symbol &sym, Kind k) const {
+ if (sym.traced)
+ printTraceSymbol(*this, sym.getName());
+ sym.file = file;
+ sym.type = type;
+ sym.binding = binding;
+ sym.stOther = (stOther & ~3) | sym.visibility();
+ sym.symbolKind = k;
+ }
+
public:
// True if this symbol is in the Iplt sub-section of the Plt and the Igot
// sub-section of the .got.plt or .got.
// A symAux index used to access GOT/PLT entry indexes. This is allocated in
// postScanRelocations().
- uint32_t auxIdx = -1;
- uint32_t dynsymIndex = 0;
+ uint32_t auxIdx;
+ uint32_t dynsymIndex;
// This field is a index to the symbol's version definition.
- uint16_t verdefIndex = -1;
+ uint16_t verdefIndex;
// Version definition index.
uint16_t versionId;
size(size), section(section) {
exportDynamic = config->exportDynamic;
}
+ void overwrite(Symbol &sym) const {
+ Symbol::overwrite(sym, DefinedKind);
+ auto &s = static_cast<Defined &>(sym);
+ s.value = value;
+ s.size = size;
+ s.section = section;
+ }
static bool classof(const Symbol *s) { return s->isDefined(); }
alignment(alignment), size(size) {
exportDynamic = config->exportDynamic;
}
+ void overwrite(Symbol &sym) const {
+ Symbol::overwrite(sym, CommonKind);
+ auto &s = static_cast<CommonSymbol &>(sym);
+ s.alignment = alignment;
+ s.size = size;
+ }
static bool classof(const Symbol *s) { return s->isCommon(); }
uint8_t type, uint32_t discardedSecIdx = 0)
: Symbol(UndefinedKind, file, name, binding, stOther, type),
discardedSecIdx(discardedSecIdx) {}
+ void overwrite(Symbol &sym) const {
+ Symbol::overwrite(sym, UndefinedKind);
+ auto &s = static_cast<Undefined &>(sym);
+ s.discardedSecIdx = discardedSecIdx;
+ s.nonPrevailing = nonPrevailing;
+ }
static bool classof(const Symbol *s) { return s->kind() == UndefinedKind; }
if (this->type == llvm::ELF::STT_GNU_IFUNC)
this->type = llvm::ELF::STT_FUNC;
}
+ void overwrite(Symbol &sym) const {
+ Symbol::overwrite(sym, SharedKind);
+ auto &s = static_cast<SharedSymbol &>(sym);
+ s.dsoProtected = dsoProtected;
+ s.value = value;
+ s.size = size;
+ s.alignment = alignment;
+ }
uint64_t value; // st_value
uint64_t size; // st_size
LazyObject(InputFile &file)
: Symbol(LazyObjectKind, &file, {}, llvm::ELF::STB_GLOBAL,
llvm::ELF::STV_DEFAULT, llvm::ELF::STT_NOTYPE) {}
+ void overwrite(Symbol &sym) const { Symbol::overwrite(sym, LazyObjectKind); }
static bool classof(const Symbol *s) { return s->kind() == LazyObjectKind; }
};
alignas(LazyObject) char e[sizeof(LazyObject)];
};
-void printTraceSymbol(const Symbol &sym, StringRef name);
-
size_t Symbol::getSymbolSize() const {
switch (kind()) {
case CommonKind:
llvm_unreachable("unknown symbol kind");
}
-// replace() replaces "this" object with a given symbol by memcpy'ing
-// it over to "this". This function is called as a result of name
-// resolution, e.g. to replace an undefind symbol with a defined symbol.
-void Symbol::replace(const Symbol &other) {
- Symbol old = *this;
- memcpy(this, &other, other.getSymbolSize());
-
- // old may be a placeholder. The referenced fields must be initialized in
- // SymbolTable::insert.
- nameData = old.nameData;
- nameSize = old.nameSize;
- partition = old.partition;
- setVisibility(old.visibility());
- isPreemptible = old.isPreemptible;
- isUsedInRegularObj = old.isUsedInRegularObj;
- exportDynamic = old.exportDynamic;
- inDynamicList = old.inDynamicList;
- referenced = old.referenced;
- traced = old.traced;
- hasVersionSuffix = old.hasVersionSuffix;
- scriptDefined = old.scriptDefined;
- versionId = old.versionId;
-
- // Print out a log message if --trace-symbol was specified.
- // This is for debugging.
- if (traced)
- printTraceSymbol(*this, getName());
-}
-
template <typename... T> Defined *makeDefined(T &&...args) {
- return new (reinterpret_cast<Defined *>(
+ auto *sym = new (reinterpret_cast<Defined *>(
getSpecificAllocSingleton<SymbolUnion>().Allocate()))
Defined(std::forward<T>(args)...);
+ sym->auxIdx = -1;
+ return sym;
}
void reportDuplicate(const Symbol &sym, const InputFile *newFile,