diff options
-rw-r--r-- | lld/COFF/Chunks.cpp | 4 | ||||
-rw-r--r-- | lld/COFF/SymbolTable.cpp | 26 | ||||
-rw-r--r-- | lld/COFF/Symbols.h | 6 | ||||
-rw-r--r-- | lld/test/COFF/Inputs/gnu-implib-data.s | 23 | ||||
-rw-r--r-- | lld/test/COFF/autoimport-gnu-implib.s | 26 |
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 |