map.try_emplace(&sym, sym2);
// If both foo@v1 and foo@@v1 are defined and non-weak, report a
// duplicate definition error.
- if (sym.isDefined())
+ if (sym.isDefined()) {
sym2->checkDuplicate(cast<Defined>(sym));
- sym2->resolve(sym);
+ sym2->resolve(cast<Defined>(sym));
+ } else if (sym.isUndefined()) {
+ sym2->resolve(cast<Undefined>(sym));
+ } else {
+ sym2->resolve(cast<SharedSymbol>(sym));
+ }
// Eliminate foo@v1 from the symbol table.
sym.symbolKind = Symbol::PlaceholderKind;
sym.isUsedInRegularObj = false;
}
}
-void Symbol::resolve(const Symbol &other) {
- mergeProperties(other);
-
- switch (other.kind()) {
- case Symbol::UndefinedKind:
- resolveUndefined(cast<Undefined>(other));
- break;
- case Symbol::CommonKind:
- resolveCommon(cast<CommonSymbol>(other));
- break;
- case Symbol::DefinedKind:
- resolveDefined(cast<Defined>(other));
- break;
- case Symbol::LazyObjectKind:
- resolveLazy(cast<LazyObject>(other));
- break;
- case Symbol::SharedKind:
- resolveShared(cast<SharedSymbol>(other));
- break;
- case Symbol::PlaceholderKind:
- llvm_unreachable("bad symbol kind");
+void Symbol::resolve(const Undefined &other) {
+ if (other.visibility() != STV_DEFAULT) {
+ uint8_t v = visibility(), ov = other.visibility();
+ setVisibility(v == STV_DEFAULT ? ov : std::min(v, ov));
}
-}
-
-void Symbol::resolveUndefined(const Undefined &other) {
// An undefined symbol with non default visibility must be satisfied
// in the same DSO.
//
other.value);
}
-void Symbol::resolveCommon(const CommonSymbol &other) {
+void Symbol::resolve(const CommonSymbol &other) {
+ if (other.exportDynamic)
+ exportDynamic = true;
+ if (other.visibility() != STV_DEFAULT) {
+ uint8_t v = visibility(), ov = other.visibility();
+ setVisibility(v == STV_DEFAULT ? ov : std::min(v, ov));
+ }
if (isDefined() && !isWeak()) {
if (config->warnCommon)
warn("common " + getName() + " is overridden");
}
}
-void Symbol::resolveDefined(const Defined &other) {
+void Symbol::resolve(const Defined &other) {
+ if (other.exportDynamic)
+ exportDynamic = true;
+ if (other.visibility() != STV_DEFAULT) {
+ uint8_t v = visibility(), ov = other.visibility();
+ setVisibility(v == STV_DEFAULT ? ov : std::min(v, ov));
+ }
if (shouldReplace(other))
other.overwrite(*this);
}
-void Symbol::resolveLazy(const LazyObject &other) {
+void Symbol::resolve(const LazyObject &other) {
if (isPlaceholder()) {
other.overwrite(*this);
return;
recordWhyExtract(oldFile, *file, *this);
}
-void Symbol::resolveShared(const SharedSymbol &other) {
+void Symbol::resolve(const SharedSymbol &other) {
+ exportDynamic = true;
if (isPlaceholder()) {
other.overwrite(*this);
return;
// For example, if "this" is an undefined symbol and a new symbol is
// a defined symbol, "this" is replaced with the new symbol.
void mergeProperties(const Symbol &other);
- void resolve(const Symbol &other);
+ void resolve(const Undefined &other);
+ void resolve(const CommonSymbol &other);
+ void resolve(const Defined &other);
+ void resolve(const LazyObject &other);
+ void resolve(const SharedSymbol &other);
// If this is a lazy symbol, extract an input file and add the symbol
// in the file to the symbol table. Calling this function on
void checkDuplicate(const Defined &other) const;
private:
- void resolveUndefined(const Undefined &other);
- void resolveCommon(const CommonSymbol &other);
- void resolveDefined(const Defined &other);
- void resolveLazy(const LazyObject &other);
- void resolveShared(const SharedSymbol &other);
-
bool shouldReplace(const Defined &other) const;
protected: