//===-- OffloadDump.cpp - Offloading dumper ---------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// /// \file /// This file implements the offloading-specific dumper for llvm-objdump. /// //===----------------------------------------------------------------------===// #include "OffloadDump.h" #include "llvm-objdump.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/OffloadBinary.h" #include "llvm/Object/OffloadBundle.h" using namespace llvm; using namespace llvm::object; using namespace llvm::objdump; void disassembleObject(llvm::object::ObjectFile *, bool InlineRelocs); /// Get the printable name of the image kind. static StringRef getImageName(const OffloadBinary &OB) { switch (OB.getImageKind()) { case IMG_Object: return "elf"; case IMG_Bitcode: return "llvm ir"; case IMG_Cubin: return "cubin"; case IMG_Fatbinary: return "fatbinary"; case IMG_PTX: return "ptx"; default: return ""; } } 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 the embedded offloading contents of an ObjectFile \p O. void llvm::dumpOffloadBinary(const ObjectFile &O, StringRef ArchName) { if (!O.isELF() && !O.isCOFF()) { reportWarning( "--offloading is currently only supported for COFF and ELF targets", O.getFileName()); return; } SmallVector Binaries; if (Error Err = extractOffloadBinaries(O.getMemoryBufferRef(), Binaries)) reportError(O.getFileName(), "while extracting offloading files: " + toString(std::move(Err))); // Print out all the binaries that are contained in this buffer. for (uint64_t I = 0, E = Binaries.size(); I != E; ++I) printBinary(*Binaries[I].getBinary(), I); dumpOffloadBundleFatBinary(O, ArchName); } // Given an Object file, collect all Bundles of FatBin Binaries // and dump them into Code Object files // if -arch=-name is specified, only dump the Entries that match the target arch void llvm::dumpOffloadBundleFatBinary(const ObjectFile &O, StringRef ArchName) { if (!O.isELF() && !O.isCOFF()) { reportWarning( "--offloading is currently only supported for COFF and ELF targets", O.getFileName()); return; } SmallVector FoundBundles; if (Error Err = llvm::object::extractOffloadBundleFatBinary(O, FoundBundles)) reportError(O.getFileName(), "while extracting offload FatBin bundles: " + toString(std::move(Err))); for (const auto &[BundleNum, Bundle] : llvm::enumerate(FoundBundles)) { for (OffloadBundleEntry &Entry : Bundle.getEntries()) { if (!ArchName.empty() && !Entry.ID.contains(ArchName)) continue; // create file name for this object file: .. std::string str = Bundle.getFileName().str() + "." + itostr(BundleNum) + "." + Entry.ID.str(); if (Error Err = object::extractCodeObject(O, Entry.Offset, Entry.Size, StringRef(str))) reportError(O.getFileName(), "while extracting offload Bundle Entries: " + toString(std::move(Err))); outs() << "Extracting offload bundle: " << str << "\n"; } } } /// Print the contents of an offload binary file \p OB. This may contain /// multiple binaries stored in the same buffer. void llvm::dumpOffloadSections(const OffloadBinary &OB) { SmallVector Binaries; if (Error Err = extractOffloadBinaries(OB.getMemoryBufferRef(), Binaries)) reportError(OB.getFileName(), "while extracting offloading files: " + toString(std::move(Err))); // Print out all the binaries that are contained in this buffer. for (uint64_t I = 0, E = Binaries.size(); I != E; ++I) printBinary(*Binaries[I].getBinary(), I); }