Author: Alex Duran
Date: 2026-05-08T11:32:29+02:00
New Revision: 0041fa4aeb725a422399c48d7e6d933246e22bfe

URL: 
https://github.com/llvm/llvm-project/commit/0041fa4aeb725a422399c48d7e6d933246e22bfe
DIFF: 
https://github.com/llvm/llvm-project/commit/0041fa4aeb725a422399c48d7e6d933246e22bfe.diff

LOG: [llvm][tools] Extend llvm-objdump to support nested OffloadBinaries 
(#185425)

Extends llvm-objdump to print the information of images contained in
nested OffloadBinaries. For example, for a binary compiled with #185413
it shows
```
 $llvm-objdump --offloading ./a.out

./a.out:        file format elf64-x86-64

OFFLOADING IMAGE [0]:
kind            elf
arch
triple          spirv64-intel
producer        openmp
image size      43104 bytes
  [Nested OffloadBinary format detected]
  Number of inner images: 1
  kind            spir-v
  arch
  triple          spirv64-intel
  producer        openmp
  image size      42944 bytes
```  

New tests are added for clang-ling-wrapper and llvm-offload-binary using
this new functionality.

Depends on #185413

---------

Co-authored-by: Yury Plyakhin <[email protected]>

Added: 
    clang/test/Tooling/clang-linker-wrapper-spirv.cpp
    llvm/test/tools/llvm-objdump/Offloading/nested-offload-binary-fails.test
    llvm/test/tools/llvm-objdump/Offloading/nested-offload-binary.test

Modified: 
    llvm/test/tools/llvm-objdump/Offloading/coff.test
    llvm/test/tools/llvm-objdump/Offloading/elf.test
    llvm/test/tools/llvm-offload-binary/llvm-offload-binary.ll
    llvm/tools/llvm-objdump/OffloadDump.cpp

Removed: 
    


################################################################################
diff  --git a/clang/test/Tooling/clang-linker-wrapper-spirv.cpp 
b/clang/test/Tooling/clang-linker-wrapper-spirv.cpp
new file mode 100644
index 0000000000000..ecbfe626129db
--- /dev/null
+++ b/clang/test/Tooling/clang-linker-wrapper-spirv.cpp
@@ -0,0 +1,13 @@
+// Verify the ELF packaging of OpenMP SPIR-V device images.
+// REQUIRES: system-linux
+// REQUIRES: spirv-tools
+// REQUIRES: spirv-registered-target
+// RUN: %clangxx -fopenmp -fopenmp-targets=spirv64-intel -nogpulib -o %t %s
+// RUN: llvm-objdump --offloading %t | FileCheck -check-prefix=CHECK %s
+
+// CHECK: nested images   1
+// CHECK:   triple          spirv64-intel
+
+int main(int argc, char** argv) {
+  return 0;
+}

diff  --git a/llvm/test/tools/llvm-objdump/Offloading/coff.test 
b/llvm/test/tools/llvm-objdump/Offloading/coff.test
index 022277d137bd4..5bec7d60cb83e 100644
--- a/llvm/test/tools/llvm-objdump/Offloading/coff.test
+++ b/llvm/test/tools/llvm-objdump/Offloading/coff.test
@@ -22,21 +22,25 @@ symbols:
 # CHECK-NEXT:arch            gfx908
 # CHECK-NEXT:triple          amdgcn-amd-amdhsa
 # CHECK-NEXT:producer        openmp
+# CHECK-NEXT:image size      0 bytes
 # CHECK-EMPTY:
 # CHECK-NEXT:OFFLOADING IMAGE [1]:
 # CHECK-NEXT:kind            llvm ir
 # CHECK-NEXT:arch            gfx90a
 # CHECK-NEXT:triple          amdgcn-amd-amdhsa
 # CHECK-NEXT:producer        openmp
+# CHECK-NEXT:image size      0 bytes
 # CHECK-EMPTY:
 # CHECK-NEXT:OFFLOADING IMAGE [2]:
 # CHECK-NEXT:kind            cubin
 # CHECK-NEXT:arch            sm_52
 # CHECK-NEXT:triple          nvptx64-nvidia-cuda
 # CHECK-NEXT:producer        openmp
+# CHECK-NEXT:image size      0 bytes
 # CHECK-EMPTY:
 # CHECK-NEXT:OFFLOADING IMAGE [3]:
 # CHECK-NEXT:kind            <none>
 # CHECK-NEXT:arch            sm_70
 # CHECK-NEXT:triple          nvptx64-nvidia-cuda
 # CHECK-NEXT:producer        none
+# CHECK-NEXT:image size      0 bytes

diff  --git a/llvm/test/tools/llvm-objdump/Offloading/elf.test 
b/llvm/test/tools/llvm-objdump/Offloading/elf.test
index 10182aeb856cd..3064286b9fea1 100644
--- a/llvm/test/tools/llvm-objdump/Offloading/elf.test
+++ b/llvm/test/tools/llvm-objdump/Offloading/elf.test
@@ -31,21 +31,25 @@ Sections:
 # CHECK-NEXT:arch            gfx908
 # CHECK-NEXT:triple          amdgcn-amd-amdhsa
 # CHECK-NEXT:producer        openmp
+# CHECK-NEXT:image size      0 bytes
 # CHECK-EMPTY:
 # CHECK-NEXT:OFFLOADING IMAGE [1]:
 # CHECK-NEXT:kind            llvm ir
 # CHECK-NEXT:arch            gfx90a
 # CHECK-NEXT:triple          amdgcn-amd-amdhsa
 # CHECK-NEXT:producer        openmp
+# CHECK-NEXT:image size      0 bytes
 # CHECK-EMPTY:
 # CHECK-NEXT:OFFLOADING IMAGE [2]:
 # CHECK-NEXT:kind            cubin
 # CHECK-NEXT:arch            sm_52
 # CHECK-NEXT:triple          nvptx64-nvidia-cuda
 # CHECK-NEXT:producer        openmp
+# CHECK-NEXT:image size      0 bytes
 # CHECK-EMPTY:
 # CHECK-NEXT:OFFLOADING IMAGE [3]:
 # CHECK-NEXT:kind            <none>
 # CHECK-NEXT:arch            sm_70
 # CHECK-NEXT:triple          nvptx64-nvidia-cuda
 # CHECK-NEXT:producer        none
+# CHECK-NEXT:image size      0 bytes

diff  --git 
a/llvm/test/tools/llvm-objdump/Offloading/nested-offload-binary-fails.test 
b/llvm/test/tools/llvm-objdump/Offloading/nested-offload-binary-fails.test
new file mode 100644
index 0000000000000..cb16915d5feb2
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Offloading/nested-offload-binary-fails.test
@@ -0,0 +1,19 @@
+## Test that llvm-objdump will display an error for incorrect nested 
OffloadBinary images.
+
+# RUN: yaml2obj %s -o %t.bin 
+# RUN: llvm-objdump --offloading %t.bin 2>&1 | FileCheck %s -DFILENAME=%t.bin 
"-DROOT=OFFLOADING IMAGE"
+
+!Offload
+Members:
+  - ImageKind:      IMG_Object
+    OffloadKind:    OFK_OpenMP
+    String:
+    - Key:            "triple"
+      Value:          "x-y-z"
+    - Key:            "arch"
+      Value:          "none"
+    Content:        10ff10ad
+
+# CHECK:     [[ROOT]]
+# CHECK-NOT: [[ROOT]]
+# CHECK: warning: '[[FILENAME]]': failed to extract nested OffloadBinary: 
Invalid data was encountered while parsing the file

diff  --git 
a/llvm/test/tools/llvm-objdump/Offloading/nested-offload-binary.test 
b/llvm/test/tools/llvm-objdump/Offloading/nested-offload-binary.test
new file mode 100644
index 0000000000000..d46180242144e
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Offloading/nested-offload-binary.test
@@ -0,0 +1,85 @@
+## Test that llvm-objdump can display nested OffloadBinary images.
+
+## The content blobs below were generated from the following YAML Input
+##!Offload
+##Members:
+##  - ImageKind:      IMG_Bitcode
+##    OffloadKind:    OFK_OpenMP
+##    String:
+##    - Key:            "triple"
+##      Value:          "x-y-z"
+##    - Key:            "arch"
+##      Value:          "arch1"
+##  - ImageKind:      IMG_Bitcode
+##    OffloadKind:    OFK_OpenMP
+##    String:
+##    - Key:            "triple"
+##      Value:          "x-y-z"
+##    - Key:            "arch"
+##      Value:          "arch2"
+
+# RUN: yaml2obj %s -o %t.bin
+# RUN: llvm-objdump --offloading %t.bin | FileCheck --match-full-lines 
--strict-whitespace --implicit-check-not={{.}} %s
+
+!Offload
+Members:
+  - ImageKind:      IMG_Object
+    OffloadKind:    OFK_OpenMP
+    String:
+    - Key:            "triple"
+      Value:          "x-y-z"
+    - Key:            "arch"
+      Value:          "none"
+    Content:        
10ff10ad02000000f00000000000000020000000000000000200000000000000020001000000000070000000000000000200000000000000f00000000000000000000000000000000200010000000000a0000000000000000200000000000000f0000000000000000000000000000000dc00000000000000d1000000000000000500000000000000d700000000000000e9000000000000000500000000000000dc00000000000000d1000000000000000500000000000000d700000000000000e300000000000000050000000000000000782d792d7a006172636800747269706c650061726368320061726368310000
+  - ImageKind:      IMG_Object
+    OffloadKind:    OFK_OpenMP
+    String:
+    - Key:            "triple"
+      Value:          "a-b-c"
+    - Key:            "arch"
+      Value:          "none"
+    Content:        
10ff10ad02000000f00000000000000020000000000000000200000000000000020001000000000070000000000000000200000000000000f00000000000000000000000000000000200010000000000a0000000000000000200000000000000f0000000000000000000000000000000dc00000000000000d1000000000000000500000000000000d700000000000000e9000000000000000500000000000000dc00000000000000d1000000000000000500000000000000d700000000000000e300000000000000050000000000000000782d792d7a006172636800747269706c650061726368320061726368310000
+
+#      CHECK:OFFLOADING IMAGE [0]:
+# CHECK-NEXT:kind            elf
+# CHECK-NEXT:arch            none
+# CHECK-NEXT:triple          x-y-z
+# CHECK-NEXT:producer        openmp
+# CHECK-NEXT:image size      {{[0-9]+}} bytes
+# CHECK-NEXT:nested images   2
+# CHECK-EMPTY:
+# CHECK-NEXT:  OFFLOADING IMAGE [0.0]:
+# CHECK-NEXT:  kind            llvm ir
+# CHECK-NEXT:  arch            arch1
+# CHECK-NEXT:  triple          x-y-z
+# CHECK-NEXT:  producer        openmp
+# CHECK-NEXT:  image size      {{[0-9]+}} bytes
+# CHECK-EMPTY:
+# CHECK-NEXT:  OFFLOADING IMAGE [0.1]:
+# CHECK-NEXT:  kind            llvm ir
+# CHECK-NEXT:  arch            arch2
+# CHECK-NEXT:  triple          x-y-z
+# CHECK-NEXT:  producer        openmp
+# CHECK-NEXT:  image size      {{[0-9]+}} bytes
+# CHECK-EMPTY:
+# CHECK-NEXT:OFFLOADING IMAGE [1]:
+# CHECK-NEXT:kind            elf
+# CHECK-NEXT:arch            none
+# CHECK-NEXT:triple          a-b-c
+# CHECK-NEXT:producer        openmp
+# CHECK-NEXT:image size      {{[0-9]+}} bytes
+# CHECK-NEXT:nested images   2
+# CHECK-EMPTY:
+# CHECK-NEXT:  OFFLOADING IMAGE [1.0]:
+# CHECK-NEXT:  kind            llvm ir
+# CHECK-NEXT:  arch            arch1
+# CHECK-NEXT:  triple          x-y-z
+# CHECK-NEXT:  producer        openmp
+# CHECK-NEXT:  image size      {{[0-9]+}} bytes
+# CHECK-EMPTY:
+# CHECK-NEXT:  OFFLOADING IMAGE [1.1]:
+# CHECK-NEXT:  kind            llvm ir
+# CHECK-NEXT:  arch            arch2
+# CHECK-NEXT:  triple          x-y-z
+# CHECK-NEXT:  producer        openmp
+# CHECK-NEXT:  image size      {{[0-9]+}} bytes

diff  --git a/llvm/test/tools/llvm-offload-binary/llvm-offload-binary.ll 
b/llvm/test/tools/llvm-offload-binary/llvm-offload-binary.ll
index df46ad3a0d38a..31ee5e286717f 100644
--- a/llvm/test/tools/llvm-offload-binary/llvm-offload-binary.ll
+++ b/llvm/test/tools/llvm-offload-binary/llvm-offload-binary.ll
@@ -15,3 +15,41 @@
 ; RUN: llvm-offload-binary -o %t3 --image=file=%s
 ; RUN: llvm-offload-binary %t3 --image=file=%t4
 ; RUN: 
diff  %s %t4
+
+; Test nested OffloadBinary construction with multiple inner images.
+; RUN: llvm-offload-binary -o %t5 --image=file=%s,arch=abc,triple=x-y-z 
--image=file=%s,arch=def,triple=x-y-z
+; RUN: llvm-offload-binary -o %t6 --image=file=%t5,arch=nested,triple=x-y-z
+; RUN: llvm-objdump --offloading %t6 | FileCheck %s --check-prefix=NESTED
+
+; NESTED: OFFLOADING IMAGE [0]:
+; NESTED: arch            nested
+; NESTED: nested images   2
+; NESTED:   OFFLOADING IMAGE [0.0]:
+; NESTED:   arch            abc
+; NESTED:   OFFLOADING IMAGE [0.1]:
+; NESTED:   arch            def
+
+; Test complex nested OffloadBinary construction with multiple levels.
+; RUN: llvm-offload-binary -o %t7 --image=file=%s,arch=abc,triple=x-y-z 
--image=file=%t5,arch=nested,triple=x-y-z
+; RUN: llvm-offload-binary -o %t8 --image=file=%t7,arch=nested,triple=x-y-z 
--image=file=%t5,arch=nested2,triple=x-y-z
+; RUN: llvm-objdump --offloading %t8 | FileCheck %s --check-prefix=NESTED2
+
+; NESTED2: OFFLOADING IMAGE [0]:
+; NESTED2: arch            nested
+; NESTED2: nested images   2
+; NESTED2:   OFFLOADING IMAGE [0.0]:
+; NESTED2:   arch            abc
+; NESTED2:   OFFLOADING IMAGE [0.1]:
+; NESTED2:   arch            nested
+; NESTED2:   nested images   2
+; NESTED2:     OFFLOADING IMAGE [0.1.0]:
+; NESTED2:     arch            abc
+; NESTED2:     OFFLOADING IMAGE [0.1.1]:
+; NESTED2:     arch            def
+; NESTED2: OFFLOADING IMAGE [1]:
+; NESTED2: arch            nested2
+; NESTED2: nested images   2
+; NESTED2:   OFFLOADING IMAGE [1.0]:
+; NESTED2:   arch            abc
+; NESTED2:   OFFLOADING IMAGE [1.1]:
+; NESTED2:   arch            def

diff  --git a/llvm/tools/llvm-objdump/OffloadDump.cpp 
b/llvm/tools/llvm-objdump/OffloadDump.cpp
index cd2727069c2e9..c0ba4d86d9209 100644
--- a/llvm/tools/llvm-objdump/OffloadDump.cpp
+++ b/llvm/tools/llvm-objdump/OffloadDump.cpp
@@ -13,6 +13,7 @@
 
 #include "OffloadDump.h"
 #include "llvm-objdump.h"
+#include "llvm/BinaryFormat/Magic.h"
 #include "llvm/Object/ELFObjectFile.h"
 #include "llvm/Object/OffloadBinary.h"
 #include "llvm/Object/OffloadBundle.h"
@@ -43,13 +44,54 @@ static StringRef getImageName(const OffloadBinary &OB) {
   }
 }
 
-static void printBinary(const OffloadBinary &OB, uint64_t Index) {
-  outs() << "\nOFFLOADING IMAGE [" << Index << "]:\n";
-  outs() << left_justify("kind", 16) << getImageName(OB) << "\n";
-  outs() << left_justify("arch", 16) << OB.getArch() << "\n";
-  outs() << left_justify("triple", 16) << OB.getTriple() << "\n";
-  outs() << left_justify("producer", 16)
-         << getOffloadKindName(OB.getOffloadKind()) << "\n";
+/// Print metadata from an OffloadBinary.
+static void printOffloadBinaryMetadata(const OffloadBinary &OB,
+                                       uint64_t Level) {
+  outs().indent(Level * 2) << left_justify("kind", 16) << getImageName(OB)
+                           << "\n";
+  outs().indent(Level * 2) << left_justify("arch", 16) << OB.getArch() << "\n";
+  outs().indent(Level * 2) << left_justify("triple", 16) << OB.getTriple()
+                           << "\n";
+  outs().indent(Level * 2) << left_justify("producer", 16)
+                           << getOffloadKindName(OB.getOffloadKind()) << "\n";
+
+  StringRef InnerImage = OB.getImage();
+  outs().indent(Level * 2) << left_justify("image size", 16)
+                           << InnerImage.size() << " bytes\n";
+}
+
+static void printBinary(const OffloadBinary &OB, uint64_t Index,
+                        uint64_t Level = 0, Twine ParentIndexPrefix = "") {
+  outs() << "\n";
+  outs().indent(Level * 2) << "OFFLOADING IMAGE [" << ParentIndexPrefix << 
Index
+                           << "]:\n";
+
+  printOffloadBinaryMetadata(OB, Level);
+
+  StringRef ImageData = OB.getImage();
+  if (identify_magic(ImageData) != file_magic::offload_binary)
+    return;
+
+  MemoryBufferRef InnerBuffer(ImageData, "inner-offload-binary");
+  SmallVector<OffloadFile> InnerBinaries;
+  Error Err = extractOffloadBinaries(InnerBuffer, InnerBinaries);
+  if (Err) {
+    reportWarning("failed to extract nested OffloadBinary: " +
+                      toString(std::move(Err)),
+                  OB.getFileName());
+    return;
+  }
+  assert(!InnerBinaries.empty() &&
+         "An offload binary with a magic number should contain at least one "
+         "binary");
+
+  outs().indent(Level * 2) << left_justify("nested images", 16)
+                           << InnerBinaries.size() << "\n";
+
+  for (uint64_t I = 0, E = InnerBinaries.size(); I != E; ++I) {
+    const OffloadBinary *InnerOB = InnerBinaries[I].getBinary();
+    printBinary(*InnerOB, I, Level + 1, ParentIndexPrefix + Twine(Index) + 
".");
+  }
 }
 
 /// Print the embedded offloading contents of an ObjectFile \p O.


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to