Skip to content

Commit d766653

Browse files
committed
COFF: Handle undefined symbols starting with __imp_ in a special way.
MSVC linker is able to link an object file created from the following code. Note that __imp_hello is not defined anywhere. void hello() { printf("Hello\n"); } extern void (*__imp_hello)(); int main() { __imp_hello(); } Function symbols exported from DLLs are automatically mangled by appending __imp_ prefix, so they have two names (original one and with the prefix). This "feature" seems to simulate that behavior even for non-DLL symbols. This is in my opnion very odd feature. Even MSVC linker warns if you use this. I'm adding that anyway for the sake of compatibiltiy. llvm-svn: 240620
1 parent 7a1372c commit d766653

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

lld/COFF/SymbolTable.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,17 +70,26 @@ bool SymbolTable::reportRemainingUndefines() {
7070
auto *Undef = dyn_cast<Undefined>(Sym->Body);
7171
if (!Undef)
7272
continue;
73+
StringRef Name = Undef->getName();
7374
if (SymbolBody *Alias = Undef->getWeakAlias()) {
7475
Sym->Body = Alias->getReplacement();
7576
if (!isa<Defined>(Sym->Body)) {
7677
// Aliases are yet another symbols pointed by other symbols
7778
// that could also remain undefined.
78-
llvm::errs() << "undefined symbol: " << Undef->getName() << "\n";
79+
llvm::errs() << "undefined symbol: " << Name << "\n";
7980
Ret = true;
8081
}
8182
continue;
8283
}
83-
llvm::errs() << "undefined symbol: " << Undef->getName() << "\n";
84+
// If we can resolve a symbol by removing __imp_ prefix, do that.
85+
// This odd rule is for compatibility with MSVC linker.
86+
if (Name.startswith("__imp_")) {
87+
if (Defined *Imp = find(Name.substr(strlen("__imp_")))) {
88+
Sym->Body = Imp;
89+
continue;
90+
}
91+
}
92+
llvm::errs() << "undefined symbol: " << Name << "\n";
8493
Ret = true;
8594
}
8695
return Ret;

lld/test/COFF/locally-imported.test

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# RUN: yaml2obj < %s > %t.obj
2+
# RUN: lld -flavor link2 /out:%t.exe %t.obj
3+
4+
# The linker automatically removes __imp_ prefix if it helps to resolve all symbols.
5+
6+
---
7+
header:
8+
Machine: IMAGE_FILE_MACHINE_AMD64
9+
Characteristics: []
10+
sections:
11+
- Name: .text
12+
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
13+
Alignment: 4
14+
SectionData: B82A000000C3
15+
symbols:
16+
- Name: .text
17+
Value: 0
18+
SectionNumber: 1
19+
SimpleType: IMAGE_SYM_TYPE_NULL
20+
ComplexType: IMAGE_SYM_DTYPE_NULL
21+
StorageClass: IMAGE_SYM_CLASS_STATIC
22+
SectionDefinition:
23+
Length: 6
24+
NumberOfRelocations: 0
25+
NumberOfLinenumbers: 0
26+
CheckSum: 0
27+
Number: 0
28+
Selection: IMAGE_COMDAT_SELECT_ANY
29+
- Name: mainCRTStartup
30+
Value: 0
31+
SectionNumber: 1
32+
SimpleType: IMAGE_SYM_TYPE_NULL
33+
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
34+
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
35+
- Name: __imp_mainCRTStartup
36+
Value: 0
37+
SectionNumber: 0
38+
SimpleType: IMAGE_SYM_TYPE_NULL
39+
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
40+
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
41+
...

0 commit comments

Comments
 (0)