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
