diff --git a/llvm/lib/Object/OffloadBinary.cpp b/llvm/lib/Object/OffloadBinary.cpp --- a/llvm/lib/Object/OffloadBinary.cpp +++ b/llvm/lib/Object/OffloadBinary.cpp @@ -17,6 +17,7 @@ #include "llvm/Object/Archive.h" #include "llvm/Object/ArchiveWriter.h" #include "llvm/Object/Binary.h" +#include "llvm/Object/COFF.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/Error.h" #include "llvm/Object/IRObjectFile.h" @@ -65,9 +66,11 @@ return Error::success(); } -// Extract offloading binaries from an Object file \p Obj. -Error extractFromBinary(const ObjectFile &Obj, - SmallVectorImpl &Binaries) { +// Extract offloading binaries from an ELF Object file \p Obj. +Error extractFromELF(const ObjectFile &Obj, + SmallVectorImpl &Binaries) { + assert(Obj.isELF() && "Invalid file type"); + for (ELFSectionRef Sec : Obj.sections()) { if (Sec.getType() != ELF::SHT_LLVM_OFFLOADING) continue; @@ -84,6 +87,32 @@ return Error::success(); } +// Extract offloading binaries from a COFF Object file \p Obj. +Error extractFromCOFF(const ObjectFile &Obj, + SmallVectorImpl &Binaries) { + assert(Obj.isCOFF() || Obj.isCOFFImportFile() && "Invalid file type"); + + for (SectionRef Sec : Obj.sections()) { + Expected NameOrErr = Sec.getName(); + if (!NameOrErr) + return NameOrErr.takeError(); + + // COFF has no section types so we rely on the name of the section. + if (!NameOrErr->equals(".llvm.offloading")) + continue; + + Expected Buffer = Sec.getContents(); + if (!Buffer) + return Buffer.takeError(); + + MemoryBufferRef Contents(*Buffer, Obj.getFileName()); + if (Error Err = extractOffloadFiles(Contents, Binaries)) + return Err; + } + + return Error::success(); +} + Error extractFromBitcode(MemoryBufferRef Buffer, SmallVectorImpl &Binaries) { LLVMContext Context; @@ -265,7 +294,14 @@ ObjectFile::createObjectFile(Buffer, Type); if (!ObjFile) return ObjFile.takeError(); - return extractFromBinary(*ObjFile->get(), Binaries); + return extractFromELF(*ObjFile->get(), Binaries); + } + case file_magic::coff_object: { + Expected> ObjFile = + ObjectFile::createObjectFile(Buffer, Type); + if (!ObjFile) + return ObjFile.takeError(); + return extractFromCOFF(*ObjFile->get(), Binaries); } case file_magic::archive: { Expected> LibFile = diff --git a/llvm/test/tools/llvm-objdump/Offloading/coff.test b/llvm/test/tools/llvm-objdump/Offloading/coff.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/Offloading/coff.test @@ -0,0 +1,42 @@ +# RUN: yaml2obj %S/Inputs/binary.yaml -o %t.bin +# RUN: yaml2obj %s -o %t.coff +# RUN: llvm-objcopy --add-section .llvm.offloading=%t.bin %t.coff +# RUN: llvm-objdump --offloading %t.coff | FileCheck %s --match-full-lines --strict-whitespace --implicit-check-not={{.}} + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [] +sections: + - Name: .rdata + Characteristics: [] + - Name: .llvm.offloading + Characteristics: [ IMAGE_SCN_LNK_REMOVE, IMAGE_SCN_MEM_DISCARDABLE ] + Alignment: 8 +symbols: + +# CHECK:{{.*}}file format coff-x86-64 +# CHECK-EMPTY: +# CHECK-NEXT:OFFLOADING IMAGE [0]: +# CHECK-NEXT:kind llvm ir +# CHECK-NEXT:arch gfx908 +# CHECK-NEXT:triple amdgcn-amd-amdhsa +# CHECK-NEXT:producer openmp +# 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-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-EMPTY: +# CHECK-NEXT:OFFLOADING IMAGE [3]: +# CHECK-NEXT:kind +# CHECK-NEXT:arch sm_70 +# CHECK-NEXT:triple nvptx64-nvidia-cuda +# CHECK-NEXT:producer none diff --git a/llvm/test/tools/llvm-objdump/Offloading/non-elf.test b/llvm/test/tools/llvm-objdump/Offloading/non-elf.test --- a/llvm/test/tools/llvm-objdump/Offloading/non-elf.test +++ b/llvm/test/tools/llvm-objdump/Offloading/non-elf.test @@ -1,14 +1,14 @@ # RUN: yaml2obj %s -o %t # RUN: llvm-objdump --offloading %t 2>&1 | FileCheck -DFILENAME=%t %s ---- !COFF -header: - Machine: IMAGE_FILE_MACHINE_AMD64 - Characteristics: [] -sections: - - Name: .rdata - Characteristics: [] - SectionData: 00 -symbols: +--- !mach-o +FileHeader: + magic: 0xFEEDFACE + cputype: 0x00000007 + cpusubtype: 0x00000003 + filetype: 0x00000001 + ncmds: 0 + sizeofcmds: 0 + flags: 0x00002000 -# CHECK: warning: '[[FILENAME]]': --offloading is currently only supported for ELF targets +# CHECK: warning: '[[FILENAME]]': --offloading is currently only supported for COFF and ELF targets diff --git a/llvm/tools/llvm-objdump/OffloadDump.cpp b/llvm/tools/llvm-objdump/OffloadDump.cpp --- a/llvm/tools/llvm-objdump/OffloadDump.cpp +++ b/llvm/tools/llvm-objdump/OffloadDump.cpp @@ -49,9 +49,10 @@ /// Print the embedded offloading contents of an ObjectFile \p O. void llvm::dumpOffloadBinary(const ObjectFile &O) { - if (!O.isELF()) { - reportWarning("--offloading is currently only supported for ELF targets", - O.getFileName()); + if (!O.isELF() && !O.isCOFF()) { + reportWarning( + "--offloading is currently only supported for COFF and ELF targets", + O.getFileName()); return; }