summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/COFF/Chunks.cpp4
-rw-r--r--lld/COFF/SymbolTable.cpp26
-rw-r--r--lld/COFF/Symbols.h6
-rw-r--r--lld/test/COFF/Inputs/gnu-implib-data.s23
-rw-r--r--lld/test/COFF/autoimport-gnu-implib.s26
5 files changed, 73 insertions, 12 deletions
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index 52d42af739e..dc471117981 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -529,8 +529,8 @@ static int getRuntimePseudoRelocSize(uint16_t Type) {
void SectionChunk::getRuntimePseudoRelocs(
std::vector<RuntimePseudoReloc> &Res) {
for (const coff_relocation &Rel : Relocs) {
- auto *Target = dyn_cast_or_null<DefinedImportData>(
- File->getSymbol(Rel.SymbolTableIndex));
+ auto *Target =
+ dyn_cast_or_null<Defined>(File->getSymbol(Rel.SymbolTableIndex));
if (!Target || !Target->IsRuntimePseudoReloc)
continue;
int SizeInBits = getRuntimePseudoRelocSize(Rel.Type);
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index b27bc3d5340..f451beb63b0 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -152,21 +152,33 @@ void SymbolTable::loadMinGWAutomaticImports() {
bool SymbolTable::handleMinGWAutomaticImport(Symbol *Sym, StringRef Name) {
if (Name.startswith("__imp_"))
return false;
- DefinedImportData *Imp =
- dyn_cast_or_null<DefinedImportData>(find(("__imp_" + Name).str()));
+ Defined *Imp = dyn_cast_or_null<Defined>(find(("__imp_" + Name).str()));
if (!Imp)
return false;
- log("Automatically importing " + Name + " from " + Imp->getDLLName());
-
// Replace the reference directly to a variable with a reference
// to the import address table instead. This obviously isn't right,
// but we mark the symbol as IsRuntimePseudoReloc, and a later pass
// will add runtime pseudo relocations for every relocation against
// this Symbol. The runtime pseudo relocation framework expects the
// reference itself to point at the IAT entry.
- Sym->replaceKeepingName(Imp, sizeof(DefinedImportData));
- cast<DefinedImportData>(Sym)->IsRuntimePseudoReloc = true;
+ size_t ImpSize = 0;
+ if (isa<DefinedImportData>(Imp)) {
+ log("Automatically importing " + Name + " from " +
+ cast<DefinedImportData>(Imp)->getDLLName());
+ ImpSize = sizeof(DefinedImportData);
+ } else if (isa<DefinedRegular>(Imp)) {
+ log("Automatically importing " + Name + " from " +
+ toString(cast<DefinedRegular>(Imp)->File));
+ ImpSize = sizeof(DefinedRegular);
+ } else {
+ warn("unable to automatically import " + Name + " from " + Imp->getName() +
+ " from " + toString(cast<DefinedRegular>(Imp)->File) +
+ "; unexpected symbol type");
+ return false;
+ }
+ Sym->replaceKeepingName(Imp, ImpSize);
+ Sym->IsRuntimePseudoReloc = true;
// There may exist symbols named .refptr.<name> which only consist
// of a single pointer to <name>. If it turns out <name> is
@@ -181,7 +193,7 @@ bool SymbolTable::handleMinGWAutomaticImport(Symbol *Sym, StringRef Name) {
if (SC && SC->Relocs.size() == 1 && *SC->symbols().begin() == Sym) {
log("Replacing .refptr." + Name + " with " + Imp->getName());
Refptr->getChunk()->Live = false;
- Refptr->replaceKeepingName(Imp, sizeof(DefinedImportData));
+ Refptr->replaceKeepingName(Imp, ImpSize);
}
}
return true;
diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h
index 35d9ff6fcbb..9e9bd73a5b1 100644
--- a/lld/COFF/Symbols.h
+++ b/lld/COFF/Symbols.h
@@ -80,7 +80,7 @@ protected:
explicit Symbol(Kind K, StringRef N = "")
: SymbolKind(K), IsExternal(true), IsCOMDAT(false),
WrittenToSymtab(false), PendingArchiveLoad(false), IsGCRoot(false),
- Name(N) {}
+ IsRuntimePseudoReloc(false), Name(N) {}
const unsigned SymbolKind : 8;
unsigned IsExternal : 1;
@@ -104,6 +104,8 @@ public:
/// True if we've already added this symbol to the list of GC roots.
unsigned IsGCRoot : 1;
+ unsigned IsRuntimePseudoReloc : 1;
+
protected:
StringRef Name;
};
@@ -309,8 +311,6 @@ public:
uint16_t getOrdinal() { return File->Hdr->OrdinalHint; }
ImportFile *File;
-
- bool IsRuntimePseudoReloc = false;
};
// This class represents a symbol for a jump table entry which jumps
diff --git a/lld/test/COFF/Inputs/gnu-implib-data.s b/lld/test/COFF/Inputs/gnu-implib-data.s
new file mode 100644
index 00000000000..d9af7756332
--- /dev/null
+++ b/lld/test/COFF/Inputs/gnu-implib-data.s
@@ -0,0 +1,23 @@
+ .global __imp_data
+
+ # The data that is emitted into .idata$7 here is isn't needed for
+ # the import data structures, but we need to emit something which
+ # produces a relocation against _head_test_lib, to pull in the
+ # header and trailer objects.
+
+ .section .idata$7
+ .rva _head_test_lib
+
+ .section .idata$5
+__imp_data:
+ .rva .Lhint_name
+ .long 0
+
+ .section .idata$4
+ .rva .Lhint_name
+ .long 0
+
+ .section .idata$6
+.Lhint_name:
+ .short 0
+ .asciz "data"
diff --git a/lld/test/COFF/autoimport-gnu-implib.s b/lld/test/COFF/autoimport-gnu-implib.s
new file mode 100644
index 00000000000..375e0a5857e
--- /dev/null
+++ b/lld/test/COFF/autoimport-gnu-implib.s
@@ -0,0 +1,26 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -triple=x86_64-windows-gnu %p/Inputs/gnu-implib-head.s -filetype=obj -o %t-dabcdh.o
+# RUN: llvm-mc -triple=x86_64-windows-gnu %p/Inputs/gnu-implib-data.s -filetype=obj -o %t-dabcds00000.o
+# RUN: llvm-mc -triple=x86_64-windows-gnu %p/Inputs/gnu-implib-tail.s -filetype=obj -o %t-dabcdt.o
+# RUN: rm -f %t-implib.a
+# RUN: llvm-ar rcs %t-implib.a %t-dabcdh.o %t-dabcds00000.o %t-dabcdt.o
+
+# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj
+# RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-implib.a -verbose
+
+# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s
+
+# IMPORTS: Import {
+# IMPORTS-NEXT: Name: foo.dll
+# IMPORTS-NEXT: ImportLookupTableRVA:
+# IMPORTS-NEXT: ImportAddressTableRVA:
+# IMPORTS-NEXT: Symbol: data (0)
+# IMPORTS-NEXT: }
+
+ .global main
+ .text
+main:
+ movl data(%rip), %eax
+ ret
+ .data
OpenPOWER on IntegriCloud