diff --git a/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp b/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp index 1782e24287860..380fbd8b6fc6c 100644 --- a/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp +++ b/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp @@ -12,6 +12,7 @@ #include "llvm/ToolDrivers/llvm-dlltool/DlltoolDriver.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Object/Archive.h" #include "llvm/Object/COFF.h" #include "llvm/Object/COFFImportFile.h" #include "llvm/Object/COFFModuleDefinition.h" @@ -158,6 +159,143 @@ bool parseModuleDefinition(StringRef DefFileName, MachineTypes Machine, return true; } +int printError(llvm::Error E, Twine File) { + if (!E) + return 0; + handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EIB) { + llvm::errs() << "error opening " << File << ": " << EIB.message() << "\n"; + }); + return 1; +} + +template +int forEachCoff(object::Archive &Archive, StringRef Name, Callable Callback) { + Error Err = Error::success(); + for (auto &C : Archive.children(Err)) { + Expected NameOrErr = C.getName(); + if (!NameOrErr) + return printError(NameOrErr.takeError(), Name); + StringRef Name = *NameOrErr; + + Expected ChildMB = C.getMemoryBufferRef(); + if (!ChildMB) + return printError(ChildMB.takeError(), Name); + + if (identify_magic(ChildMB->getBuffer()) == file_magic::coff_object) { + auto Obj = object::COFFObjectFile::create(*ChildMB); + if (!Obj) + return printError(Obj.takeError(), Name); + if (!Callback(*Obj->get(), Name)) + return 1; + } + } + if (Err) + return printError(std::move(Err), Name); + return 0; +} + +// To find the named of the imported DLL from an import library, we can either +// inspect the object files that form the import table entries, or we could +// just look at the archive member names, for MSVC style import libraries. +// Looking at the archive member names doesn't work for GNU style import +// libraries though, while inspecting the import table entries works for +// both. (MSVC style import libraries contain a couple regular object files +// for the header/trailers.) +// +// This implementation does the same as GNU dlltool does; look at the +// content of ".idata$7" sections, or for MSVC style libraries, look +// at ".idata$6" sections. +// +// For GNU style import libraries, there are also other data chunks in sections +// named ".idata$7" (entries to the IAT or ILT); these are distinguished +// by seeing that they contain relocations. (They also look like an empty +// string when looking for null termination.) +// +// Alternatively, we could do things differently - look for any .idata$2 +// section; this would be import directory entries. At offset 0xc in them +// there is the RVA of the import DLL name; look for a relocation at this +// spot and locate the symbol that it points at. That symbol may either +// be within the same object file (in the case of MSVC style import libraries) +// or another object file (in the case of GNU import libraries). +bool identifyImportName(const COFFObjectFile &Obj, StringRef ObjName, + std::vector &Names, bool IsMsStyleImplib) { + StringRef TargetName = IsMsStyleImplib ? ".idata$6" : ".idata$7"; + for (const auto &S : Obj.sections()) { + Expected NameOrErr = S.getName(); + if (!NameOrErr) { + printError(NameOrErr.takeError(), ObjName); + return false; + } + StringRef Name = *NameOrErr; + if (Name != TargetName) + continue; + + // GNU import libraries contain .idata$7 section in the per function + // objects too, but they contain relocations. + if (!IsMsStyleImplib && !S.relocations().empty()) + continue; + + Expected ContentsOrErr = S.getContents(); + if (!ContentsOrErr) { + printError(ContentsOrErr.takeError(), ObjName); + return false; + } + StringRef Contents = *ContentsOrErr; + Contents = Contents.substr(0, Contents.find('\0')); + if (Contents.empty()) + continue; + Names.push_back(Contents); + return true; + } + return true; +} + +int doIdentify(StringRef File, bool IdentifyStrict) { + ErrorOr> MaybeBuf = MemoryBuffer::getFile( + File, /*IsText=*/false, /*RequiredNullTerminator=*/false); + if (!MaybeBuf) + return printError(errorCodeToError(MaybeBuf.getError()), File); + if (identify_magic(MaybeBuf.get()->getBuffer()) != file_magic::archive) { + llvm::errs() << File << " is not a library\n"; + return 1; + } + + std::unique_ptr B = std::move(MaybeBuf.get()); + Error Err = Error::success(); + object::Archive Archive(B->getMemBufferRef(), Err); + if (Err) + return printError(std::move(Err), B->getBufferIdentifier()); + + bool IsMsStyleImplib = false; + for (const auto &S : Archive.symbols()) { + if (S.getName() == "__NULL_IMPORT_DESCRIPTOR") { + IsMsStyleImplib = true; + break; + } + } + std::vector Names; + if (forEachCoff(Archive, B->getBufferIdentifier(), + [&](const COFFObjectFile &Obj, StringRef ObjName) -> bool { + return identifyImportName(Obj, ObjName, Names, + IsMsStyleImplib); + })) + return 1; + + if (Names.empty()) { + llvm::errs() << "No DLL import name found in " << File << "\n"; + return 1; + } + if (Names.size() > 1 && IdentifyStrict) { + llvm::errs() << File << "contains imports for two or more DLLs\n"; + return 1; + } + + for (StringRef S : Names) + llvm::outs() << S << "\n"; + + return 0; +} + } // namespace int llvm::dlltoolDriverMain(llvm::ArrayRef ArgsArr) { @@ -173,7 +311,8 @@ int llvm::dlltoolDriverMain(llvm::ArrayRef ArgsArr) { // Handle when no input or output is specified if (Args.hasArgNoClaim(OPT_INPUT) || - (!Args.hasArgNoClaim(OPT_d) && !Args.hasArgNoClaim(OPT_l))) { + (!Args.hasArgNoClaim(OPT_d) && !Args.hasArgNoClaim(OPT_l) && + !Args.hasArgNoClaim(OPT_I))) { Table.printHelp(outs(), "llvm-dlltool [options] file...", "llvm-dlltool", false); llvm::outs() @@ -185,6 +324,11 @@ int llvm::dlltoolDriverMain(llvm::ArrayRef ArgsArr) { llvm::errs() << "ignoring unknown argument: " << Arg->getAsString(Args) << "\n"; + if (Args.hasArg(OPT_I)) { + return doIdentify(Args.getLastArg(OPT_I)->getValue(), + Args.hasArg(OPT_identify_strict)); + } + if (!Args.hasArg(OPT_d)) { llvm::errs() << "no definition file specified\n"; return 1; diff --git a/llvm/lib/ToolDrivers/llvm-dlltool/Options.td b/llvm/lib/ToolDrivers/llvm-dlltool/Options.td index 7810694c98e36..4fd80189aff29 100644 --- a/llvm/lib/ToolDrivers/llvm-dlltool/Options.td +++ b/llvm/lib/ToolDrivers/llvm-dlltool/Options.td @@ -21,6 +21,11 @@ def k_alias: Flag<["--"], "kill-at">, Alias; def no_leading_underscore: Flag<["--"], "no-leading-underscore">, HelpText<"Don't add leading underscores on symbols">; +def I: JoinedOrSeparate<["-"], "I">, HelpText<"Identify DLL name from import library">; +def I_long : JoinedOrSeparate<["--"], "identify">, Alias; + +def identify_strict : Flag<["--"], "identify-strict">, HelpText<"Error out if the --identify option detects more than one DLL">; + //============================================================================== // The flags below do nothing. They are defined only for dlltool compatibility. //============================================================================== diff --git a/llvm/test/tools/llvm-dlltool/Inputs/gnu_foo_lib_h.yaml b/llvm/test/tools/llvm-dlltool/Inputs/gnu_foo_lib_h.yaml new file mode 100644 index 0000000000000..26f3493d62143 --- /dev/null +++ b/llvm/test/tools/llvm-dlltool/Inputs/gnu_foo_lib_h.yaml @@ -0,0 +1,133 @@ +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_I386 + Characteristics: [ IMAGE_FILE_LINE_NUMS_STRIPPED, IMAGE_FILE_32BIT_MACHINE ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '' + - Name: .data + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: '' + - Name: .bss + Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: '' + - Name: '.idata$2' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: '0000000000000000000000000000000000000000' + SizeOfRawData: 20 + Relocations: + - VirtualAddress: 0 + SymbolName: '.idata$4' + Type: IMAGE_REL_I386_DIR32NB + - VirtualAddress: 12 + SymbolName: __foo_lib_iname + Type: IMAGE_REL_I386_DIR32NB + - VirtualAddress: 16 + SymbolName: '.idata$5' + Type: IMAGE_REL_I386_DIR32NB + - Name: '.idata$5' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: '' + - Name: '.idata$4' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: '' +symbols: + - Name: .file + Value: 0 + SectionNumber: -2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_FILE + File: fake + - Name: hname + Value: 0 + SectionNumber: 6 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: fthunk + Value: 0 + SectionNumber: 5 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 0 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: .data + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 0 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: .bss + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 0 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.idata$2' + Value: 0 + SectionNumber: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 20 + NumberOfRelocations: 3 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.idata$4' + Value: 0 + SectionNumber: 6 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: '.idata$5' + Value: 0 + SectionNumber: 5 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: __head_foo_lib + Value: 0 + SectionNumber: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: __foo_lib_iname + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/llvm/test/tools/llvm-dlltool/Inputs/gnu_foo_lib_s00000.yaml b/llvm/test/tools/llvm-dlltool/Inputs/gnu_foo_lib_s00000.yaml new file mode 100644 index 0000000000000..f09437fc99255 --- /dev/null +++ b/llvm/test/tools/llvm-dlltool/Inputs/gnu_foo_lib_s00000.yaml @@ -0,0 +1,116 @@ +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_I386 + Characteristics: [ IMAGE_FILE_LINE_NUMS_STRIPPED, IMAGE_FILE_32BIT_MACHINE ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: FF25000000009090 + SizeOfRawData: 8 + Relocations: + - VirtualAddress: 2 + SymbolName: '.idata$5' + Type: IMAGE_REL_I386_DIR32 + - Name: .data + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: '' + - Name: .bss + Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: '' + - Name: '.idata$7' + Characteristics: [ IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: '00000000' + SizeOfRawData: 4 + Relocations: + - VirtualAddress: 0 + SymbolName: __head_foo_lib + Type: IMAGE_REL_I386_DIR32NB + - Name: '.idata$5' + Characteristics: [ IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: '00000000' + SizeOfRawData: 4 + Relocations: + - VirtualAddress: 0 + SymbolName: '.idata$6' + Type: IMAGE_REL_I386_DIR32NB + - Name: '.idata$4' + Characteristics: [ IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: '00000000' + SizeOfRawData: 4 + Relocations: + - VirtualAddress: 0 + SymbolName: '.idata$6' + Type: IMAGE_REL_I386_DIR32NB + - Name: '.idata$6' + Characteristics: [ IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 2 + SectionData: '010066756E633100' + SizeOfRawData: 8 +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: .data + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: .bss + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: '.idata$7' + Value: 0 + SectionNumber: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: '.idata$5' + Value: 0 + SectionNumber: 5 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: '.idata$4' + Value: 0 + SectionNumber: 6 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: '.idata$6' + Value: 0 + SectionNumber: 7 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: _func1 + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: __imp__func1 + Value: 0 + SectionNumber: 5 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: __head_foo_lib + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/llvm/test/tools/llvm-dlltool/Inputs/gnu_foo_lib_t.yaml b/llvm/test/tools/llvm-dlltool/Inputs/gnu_foo_lib_t.yaml new file mode 100644 index 0000000000000..e4465293bec1a --- /dev/null +++ b/llvm/test/tools/llvm-dlltool/Inputs/gnu_foo_lib_t.yaml @@ -0,0 +1,119 @@ +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_I386 + Characteristics: [ IMAGE_FILE_RELOCS_STRIPPED, IMAGE_FILE_LINE_NUMS_STRIPPED, IMAGE_FILE_32BIT_MACHINE ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '' + - Name: .data + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: '' + - Name: .bss + Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: '' + - Name: '.idata$4' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: '00000000' + SizeOfRawData: 4 + - Name: '.idata$5' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: '00000000' + SizeOfRawData: 4 + - Name: '.idata$7' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: 666F6F2E646C6C00 + SizeOfRawData: 8 +symbols: + - Name: .file + Value: 0 + SectionNumber: -2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_FILE + File: fake + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 0 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: .data + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 0 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: .bss + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 0 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.idata$4' + Value: 0 + SectionNumber: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 4 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.idata$5' + Value: 0 + SectionNumber: 5 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 4 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.idata$7' + Value: 0 + SectionNumber: 6 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 8 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: __foo_lib_iname + Value: 0 + SectionNumber: 6 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/llvm/test/tools/llvm-dlltool/Inputs/llvm_foo_dll_1.yaml b/llvm/test/tools/llvm-dlltool/Inputs/llvm_foo_dll_1.yaml new file mode 100644 index 0000000000000..f3f669d63bcad --- /dev/null +++ b/llvm/test/tools/llvm-dlltool/Inputs/llvm_foo_dll_1.yaml @@ -0,0 +1,69 @@ +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: '.idata$2' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: '0000000000000000000000000000000000000000' + SizeOfRawData: 20 + Relocations: + - VirtualAddress: 12 + SymbolName: '.idata$6' + Type: IMAGE_REL_AMD64_ADDR32NB + - VirtualAddress: 0 + SymbolName: '.idata$4' + Type: IMAGE_REL_AMD64_ADDR32NB + - VirtualAddress: 16 + SymbolName: '.idata$5' + Type: IMAGE_REL_AMD64_ADDR32NB + - Name: '.idata$6' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 2 + SectionData: 666F6F2E646C6C00 + SizeOfRawData: 8 +symbols: + - Name: __IMPORT_DESCRIPTOR_foo + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: '.idata$2' + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_SECTION + - Name: '.idata$6' + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: '.idata$4' + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_SECTION + - Name: '.idata$5' + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_SECTION + - Name: __NULL_IMPORT_DESCRIPTOR + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: "foo_NULL_THUNK_DATA" + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/llvm/test/tools/llvm-dlltool/Inputs/llvm_foo_dll_2.yaml b/llvm/test/tools/llvm-dlltool/Inputs/llvm_foo_dll_2.yaml new file mode 100644 index 0000000000000..26b601fb74c54 --- /dev/null +++ b/llvm/test/tools/llvm-dlltool/Inputs/llvm_foo_dll_2.yaml @@ -0,0 +1,18 @@ +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: '.idata$3' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: '0000000000000000000000000000000000000000' + SizeOfRawData: 20 +symbols: + - Name: __NULL_IMPORT_DESCRIPTOR + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/llvm/test/tools/llvm-dlltool/Inputs/llvm_foo_dll_3.yaml b/llvm/test/tools/llvm-dlltool/Inputs/llvm_foo_dll_3.yaml new file mode 100644 index 0000000000000..68248597cbaeb --- /dev/null +++ b/llvm/test/tools/llvm-dlltool/Inputs/llvm_foo_dll_3.yaml @@ -0,0 +1,23 @@ +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: '.idata$5' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 8 + SectionData: '0000000000000000' + SizeOfRawData: 8 + - Name: '.idata$4' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 8 + SectionData: '0000000000000000' + SizeOfRawData: 8 +symbols: + - Name: "foo_NULL_THUNK_DATA" + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/llvm/test/tools/llvm-dlltool/identify.test b/llvm/test/tools/llvm-dlltool/identify.test new file mode 100644 index 0000000000000..eb2792a8e41ae --- /dev/null +++ b/llvm/test/tools/llvm-dlltool/identify.test @@ -0,0 +1,69 @@ +Test the -I / --identify option. + +Test with both GNU style and LLVM style import libraries; using +sources from yaml to preserve the checking behaviour even if the +output of llvm-dlltool itself would change. + +RUN: rm -rf %t && mkdir -p %t +RUN: split-file %s %t + +RUN: yaml2obj %S/Inputs/gnu_foo_lib_h.yaml > %t/gnu_foo_lib_h.o +RUN: yaml2obj %S/Inputs/gnu_foo_lib_s00000.yaml > %t/gnu_foo_lib_s00000.o +RUN: yaml2obj %S/Inputs/gnu_foo_lib_t.yaml > %t/gnu_foo_lib_t.o +RUN: llvm-ar rcs %t/gnu.a %t/gnu_foo_lib_h.o %t/gnu_foo_lib_s00000.o %t/gnu_foo_lib_t.o + +RUN: yaml2obj %S/Inputs/llvm_foo_dll_1.yaml > %t/llvm_foo_dll_1.o +RUN: yaml2obj %S/Inputs/llvm_foo_dll_2.yaml > %t/llvm_foo_dll_2.o +RUN: yaml2obj %S/Inputs/llvm_foo_dll_3.yaml > %t/llvm_foo_dll_3.o +RUN: llvm-ar rcs %t/llvm.a %t/llvm_foo_dll_1.o %t/llvm_foo_dll_2.o %t/llvm_foo_dll_3.o + + +Check that we can identify the DLL name from a GNU style import library. + +RUN: llvm-dlltool -I %t/gnu.a | FileCheck --check-prefix=FOO %s +RUN: llvm-dlltool --identify %t/gnu.a | count 1 + +FOO: foo.dll + + +Check that we successfully can identify run while passing the +--identify-strict option. + +RUN: llvm-dlltool -I %t/gnu.a --identify-strict | FileCheck --check-prefix=FOO %s + + +Check that we can identify the DLL name from an LLVM style import library. + +RUN: llvm-dlltool -I %t/llvm.a | FileCheck --check-prefix=FOO %s +RUN: llvm-dlltool -I %t/llvm.a | count 1 + + +Check that we can identify the DLL names from an import library that +contains imports for multiple DLLs. + +RUN: llvm-dlltool -m i386:x86-64 -d %t/lib1.def -l %t/lib1.a +RUN: llvm-dlltool -m i386:x86-64 -d %t/lib2.def -l %t/lib2.a +RUN: llvm-ar qcsL %t/merged.a %t/lib1.a %t/lib2.a + +RUN: llvm-dlltool -I %t/merged.a | FileCheck --check-prefix=MERGED %s + +MERGED-DAG: lib1.dll +MERGED-DAG: lib2.dll + +Check that --identify-strict fails this case, when there are multiple +outputs. + +RUN: not llvm-dlltool -I %t/merged.a --identify-strict 2>&1 | FileCheck --check-prefix=ERROR %s + +ERROR: contains imports for two or more DLLs + + +#--- lib1.def +LIBRARY lib1.dll +EXPORTS + func1 + +#--- lib2.def +LIBRARY lib2.dll +EXPORTS + func2