[llvm-branch-commits] [llvm] release/20.x: [llvm-dlltool] Add a missing dependency (PR #132483)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Mar 21 15:58:04 PDT 2025


Martin =?utf-8?q?Storsjö?= <martin at martin.st>
Message-ID: <llvm.org/llvm/llvm-project/pull/132483 at github.com>
In-Reply-To:


https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/132483

Backport dcc08a17c781a5066ab17b9791e1c455f7cedbf7 1ca93b15482d3bfa1560b35960ab46fea65b3074

Requested by: @mstorsjo

>From 0ce9b7c9b91739df4da888e5a59db93f89313da9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin at martin.st>
Date: Thu, 20 Feb 2025 21:49:19 -0100
Subject: [PATCH 1/2] [llvm-dlltool] Implement the --identify option (#127465)

This option prints the name of the DLL that gets imported, when linking
against an import library.

This is implemented using the same strategy as GNU dlltool does; looking
for the contents of .idata$6 or .idata$7 chunks. The right section name
to check for is chosen by identifying whether the library is GNU or LLVM
style. In the case of GNU import libraries, the DLL name is in an
.idata$7 chunk. However there are also other chunks with that section
name (for entries for the IAT or ILT); identify these by looking for
whether a chunk contains relocations.

Alternatively, one could also just look for .idata$2 chunks, look for
relocations at the right offset, and locate data at the symbol that the
relocation points at (which may be in the same or in another object
file).

(cherry picked from commit dcc08a17c781a5066ab17b9791e1c455f7cedbf7)
---
 .../llvm-dlltool/DlltoolDriver.cpp            | 146 +++++++++++++++++-
 llvm/lib/ToolDrivers/llvm-dlltool/Options.td  |   5 +
 .../llvm-dlltool/Inputs/gnu_foo_lib_h.yaml    | 133 ++++++++++++++++
 .../Inputs/gnu_foo_lib_s00000.yaml            | 116 ++++++++++++++
 .../llvm-dlltool/Inputs/gnu_foo_lib_t.yaml    | 119 ++++++++++++++
 .../llvm-dlltool/Inputs/llvm_foo_dll_1.yaml   |  69 +++++++++
 .../llvm-dlltool/Inputs/llvm_foo_dll_2.yaml   |  18 +++
 .../llvm-dlltool/Inputs/llvm_foo_dll_3.yaml   |  23 +++
 llvm/test/tools/llvm-dlltool/identify.test    |  69 +++++++++
 9 files changed, 697 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/tools/llvm-dlltool/Inputs/gnu_foo_lib_h.yaml
 create mode 100644 llvm/test/tools/llvm-dlltool/Inputs/gnu_foo_lib_s00000.yaml
 create mode 100644 llvm/test/tools/llvm-dlltool/Inputs/gnu_foo_lib_t.yaml
 create mode 100644 llvm/test/tools/llvm-dlltool/Inputs/llvm_foo_dll_1.yaml
 create mode 100644 llvm/test/tools/llvm-dlltool/Inputs/llvm_foo_dll_2.yaml
 create mode 100644 llvm/test/tools/llvm-dlltool/Inputs/llvm_foo_dll_3.yaml
 create mode 100644 llvm/test/tools/llvm-dlltool/identify.test

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 <typename Callable>
+int forEachCoff(object::Archive &Archive, StringRef Name, Callable Callback) {
+  Error Err = Error::success();
+  for (auto &C : Archive.children(Err)) {
+    Expected<StringRef> NameOrErr = C.getName();
+    if (!NameOrErr)
+      return printError(NameOrErr.takeError(), Name);
+    StringRef Name = *NameOrErr;
+
+    Expected<MemoryBufferRef> 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<StringRef> &Names, bool IsMsStyleImplib) {
+  StringRef TargetName = IsMsStyleImplib ? ".idata$6" : ".idata$7";
+  for (const auto &S : Obj.sections()) {
+    Expected<StringRef> 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<StringRef> 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<std::unique_ptr<MemoryBuffer>> 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<MemoryBuffer> 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<StringRef> 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<const char *> ArgsArr) {
@@ -173,7 +311,8 @@ int llvm::dlltoolDriverMain(llvm::ArrayRef<const char *> 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<const char *> 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<k>;
 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<I>;
+
+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

>From 6bbd056b0458931891ca7a5769e580db95e9305e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin at martin.st>
Date: Fri, 21 Feb 2025 01:20:29 +0200
Subject: [PATCH 2/2] [llvm-dlltool] Add a missing dependency

This was missed in dcc08a17c781a5066ab17b9791e1c455f7cedbf7.

(cherry picked from commit 1ca93b15482d3bfa1560b35960ab46fea65b3074)
---
 llvm/lib/ToolDrivers/llvm-dlltool/CMakeLists.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/lib/ToolDrivers/llvm-dlltool/CMakeLists.txt b/llvm/lib/ToolDrivers/llvm-dlltool/CMakeLists.txt
index 855ae5f048ff7..5db08e7852d03 100644
--- a/llvm/lib/ToolDrivers/llvm-dlltool/CMakeLists.txt
+++ b/llvm/lib/ToolDrivers/llvm-dlltool/CMakeLists.txt
@@ -6,6 +6,7 @@ add_llvm_component_library(LLVMDlltoolDriver
   DlltoolDriver.cpp
 
   LINK_COMPONENTS
+  BinaryFormat
   Object
   Option
   Support



More information about the llvm-branch-commits mailing list