Skip to content

Commit

Permalink
[LLD][COFF] Preserve original symbol name when resolving weak aliases. (
Browse files Browse the repository at this point in the history
#105897)

Instead of replacing it with target's name.
  • Loading branch information
cjacek authored Aug 26, 2024
1 parent 2ef3dcf commit ec4d5a6
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 13 deletions.
14 changes: 1 addition & 13 deletions lld/COFF/SymbolTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,20 +494,8 @@ void SymbolTable::resolveRemainingUndefines() {
StringRef name = undef->getName();

// A weak alias may have been resolved, so check for that.
if (Defined *d = undef->getWeakAlias()) {
// We want to replace Sym with D. However, we can't just blindly
// copy sizeof(SymbolUnion) bytes from D to Sym because D may be an
// internal symbol, and internal symbols are stored as "unparented"
// Symbols. For that reason we need to check which type of symbol we
// are dealing with and copy the correct number of bytes.
if (isa<DefinedRegular>(d))
memcpy(sym, d, sizeof(DefinedRegular));
else if (isa<DefinedAbsolute>(d))
memcpy(sym, d, sizeof(DefinedAbsolute));
else
memcpy(sym, d, sizeof(SymbolUnion));
if (undef->resolveWeakAlias())
continue;
}

// If we can resolve a symbol by removing __imp_ prefix, do that.
// This odd rule is for compatibility with MSVC linker.
Expand Down
23 changes: 23 additions & 0 deletions lld/COFF/Symbols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,29 @@ Defined *Undefined::getWeakAlias() {
return nullptr;
}

bool Undefined::resolveWeakAlias() {
Defined *d = getWeakAlias();
if (!d)
return false;

// We want to replace Sym with D. However, we can't just blindly
// copy sizeof(SymbolUnion) bytes from D to Sym because D may be an
// internal symbol, and internal symbols are stored as "unparented"
// Symbols. For that reason we need to check which type of symbol we
// are dealing with and copy the correct number of bytes.
StringRef name = getName();
if (isa<DefinedRegular>(d))
memcpy(this, d, sizeof(DefinedRegular));
else if (isa<DefinedAbsolute>(d))
memcpy(this, d, sizeof(DefinedAbsolute));
else
memcpy(this, d, sizeof(SymbolUnion));

nameData = name.data();
nameSize = name.size();
return true;
}

MemoryBufferRef LazyArchive::getMemberBuffer() {
Archive::Child c =
CHECK(sym.getMember(), "could not get the member for symbol " +
Expand Down
3 changes: 3 additions & 0 deletions lld/COFF/Symbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,9 @@ class Undefined : public Symbol {
// symbol by searching the chain of fallback symbols. Returns the symbol if
// successful, otherwise returns null.
Defined *getWeakAlias();

// If this symbol is external weak, replace this object with aliased symbol.
bool resolveWeakAlias();
};

// Windows-specific classes.
Expand Down
18 changes: 18 additions & 0 deletions lld/test/COFF/symtab.test
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,15 @@
# CHECK-NEXT: StorageClass: External (0x2)
# CHECK-NEXT: AuxSymbolCount: 0
# CHECK-NEXT: }
# CHECK-NEXT: Symbol {
# CHECK-NEXT: Name: weak_main
# CHECK-NEXT: Value: 0
# CHECK-NEXT: Section: .text (1)
# CHECK-NEXT: BaseType: Null (0x0)
# CHECK-NEXT: ComplexType: Null (0x0)
# CHECK-NEXT: StorageClass: External (0x2)
# CHECK-NEXT: AuxSymbolCount: 0
# CHECK-NEXT: }
# CHECK-NEXT: ]

# NO: Symbols [
Expand Down Expand Up @@ -237,4 +246,13 @@ symbols:
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_LABEL
- Name: weak_main
Value: 0
SectionNumber: 0
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_WEAK_EXTERNAL
WeakExternal:
TagIndex: 10
Characteristics: IMAGE_WEAK_EXTERN_SEARCH_ALIAS
...

0 comments on commit ec4d5a6

Please sign in to comment.