//===-- 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/Support/Alignment.h" using namespace llvm; using namespace llvm::object; using namespace llvm::objdump; /// 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 "<none>"; } } 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"; } static Error visitAllBinaries(const OffloadBinary &OB) { uint64_t Offset = 0; uint64_t Index = 0; while (Offset < OB.getMemoryBufferRef().getBufferSize()) { MemoryBufferRef Buffer = MemoryBufferRef(OB.getData().drop_front(Offset), OB.getFileName()); auto BinaryOrErr = OffloadBinary::create(Buffer); if (!BinaryOrErr) return BinaryOrErr.takeError(); OffloadBinary &Binary = **BinaryOrErr; printBinary(Binary, Index++); Offset += Binary.getSize(); } return Error::success(); } /// 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()); return; } for (ELFSectionRef Sec : O.sections()) { if (Sec.getType() != ELF::SHT_LLVM_OFFLOADING) continue; Expected<StringRef> Contents = Sec.getContents(); if (!Contents) reportError(Contents.takeError(), O.getFileName()); std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer(*Contents, O.getFileName(), false); if (!isAddrAligned(Align(OffloadBinary::getAlignment()), Buffer->getBufferStart())) Buffer = MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(), Buffer->getBufferIdentifier()); auto BinaryOrErr = OffloadBinary::create(*Buffer); if (!BinaryOrErr) reportError(O.getFileName(), "while extracting offloading files: " + toString(BinaryOrErr.takeError())); OffloadBinary &Binary = **BinaryOrErr; // Print out all the binaries that are contained in this buffer. If we fail // to parse a binary before reaching the end of the buffer emit a warning. if (Error Err = visitAllBinaries(Binary)) reportWarning("while parsing offloading files: " + toString(std::move(Err)), O.getFileName()); } } /// 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) { // Print out all the binaries that are contained at this buffer. If we fail to // parse a binary before reaching the end of the buffer emit a warning. if (Error Err = visitAllBinaries(OB)) reportWarning("while parsing offloading files: " + toString(std::move(Err)), OB.getFileName()); }