181ad6265SDimitry Andric //===-- OffloadDump.cpp - Offloading dumper ---------------------*- C++ -*-===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric /// 981ad6265SDimitry Andric /// \file 1081ad6265SDimitry Andric /// This file implements the offloading-specific dumper for llvm-objdump. 1181ad6265SDimitry Andric /// 1281ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1381ad6265SDimitry Andric #include "OffloadDump.h" 1481ad6265SDimitry Andric #include "llvm-objdump.h" 15*753f127fSDimitry Andric #include "llvm/Object/ELFObjectFile.h" 16*753f127fSDimitry Andric #include "llvm/Support/Alignment.h" 1781ad6265SDimitry Andric 1881ad6265SDimitry Andric using namespace llvm; 1981ad6265SDimitry Andric using namespace llvm::object; 2081ad6265SDimitry Andric using namespace llvm::objdump; 2181ad6265SDimitry Andric 2281ad6265SDimitry Andric /// Get the printable name of the image kind. 2381ad6265SDimitry Andric static StringRef getImageName(const OffloadBinary &OB) { 2481ad6265SDimitry Andric switch (OB.getImageKind()) { 2581ad6265SDimitry Andric case IMG_Object: 2681ad6265SDimitry Andric return "elf"; 2781ad6265SDimitry Andric case IMG_Bitcode: 2881ad6265SDimitry Andric return "llvm ir"; 2981ad6265SDimitry Andric case IMG_Cubin: 3081ad6265SDimitry Andric return "cubin"; 3181ad6265SDimitry Andric case IMG_Fatbinary: 3281ad6265SDimitry Andric return "fatbinary"; 3381ad6265SDimitry Andric case IMG_PTX: 3481ad6265SDimitry Andric return "ptx"; 3581ad6265SDimitry Andric default: 3681ad6265SDimitry Andric return "<none>"; 3781ad6265SDimitry Andric } 3881ad6265SDimitry Andric } 3981ad6265SDimitry Andric 4081ad6265SDimitry Andric static void printBinary(const OffloadBinary &OB, uint64_t Index) { 4181ad6265SDimitry Andric outs() << "\nOFFLOADING IMAGE [" << Index << "]:\n"; 4281ad6265SDimitry Andric outs() << left_justify("kind", 16) << getImageName(OB) << "\n"; 4381ad6265SDimitry Andric outs() << left_justify("arch", 16) << OB.getArch() << "\n"; 4481ad6265SDimitry Andric outs() << left_justify("triple", 16) << OB.getTriple() << "\n"; 4581ad6265SDimitry Andric outs() << left_justify("producer", 16) 4681ad6265SDimitry Andric << getOffloadKindName(OB.getOffloadKind()) << "\n"; 4781ad6265SDimitry Andric } 4881ad6265SDimitry Andric 4981ad6265SDimitry Andric static Error visitAllBinaries(const OffloadBinary &OB) { 5081ad6265SDimitry Andric uint64_t Offset = 0; 5181ad6265SDimitry Andric uint64_t Index = 0; 5281ad6265SDimitry Andric while (Offset < OB.getMemoryBufferRef().getBufferSize()) { 5381ad6265SDimitry Andric MemoryBufferRef Buffer = 5481ad6265SDimitry Andric MemoryBufferRef(OB.getData().drop_front(Offset), OB.getFileName()); 5581ad6265SDimitry Andric auto BinaryOrErr = OffloadBinary::create(Buffer); 5681ad6265SDimitry Andric if (!BinaryOrErr) 5781ad6265SDimitry Andric return BinaryOrErr.takeError(); 5881ad6265SDimitry Andric 5981ad6265SDimitry Andric OffloadBinary &Binary = **BinaryOrErr; 6081ad6265SDimitry Andric printBinary(Binary, Index++); 6181ad6265SDimitry Andric 6281ad6265SDimitry Andric Offset += Binary.getSize(); 6381ad6265SDimitry Andric } 6481ad6265SDimitry Andric return Error::success(); 6581ad6265SDimitry Andric } 6681ad6265SDimitry Andric 6781ad6265SDimitry Andric /// Print the embedded offloading contents of an ObjectFile \p O. 6881ad6265SDimitry Andric void llvm::dumpOffloadBinary(const ObjectFile &O) { 69*753f127fSDimitry Andric if (!O.isELF()) { 70*753f127fSDimitry Andric reportWarning("--offloading is currently only supported for ELF targets", 71*753f127fSDimitry Andric O.getFileName()); 72*753f127fSDimitry Andric return; 73*753f127fSDimitry Andric } 74*753f127fSDimitry Andric 75*753f127fSDimitry Andric for (ELFSectionRef Sec : O.sections()) { 76*753f127fSDimitry Andric if (Sec.getType() != ELF::SHT_LLVM_OFFLOADING) 7781ad6265SDimitry Andric continue; 7881ad6265SDimitry Andric 7981ad6265SDimitry Andric Expected<StringRef> Contents = Sec.getContents(); 8081ad6265SDimitry Andric if (!Contents) 8181ad6265SDimitry Andric reportError(Contents.takeError(), O.getFileName()); 8281ad6265SDimitry Andric 83*753f127fSDimitry Andric std::unique_ptr<MemoryBuffer> Buffer = 84*753f127fSDimitry Andric MemoryBuffer::getMemBuffer(*Contents, O.getFileName(), false); 85*753f127fSDimitry Andric if (!isAddrAligned(Align(OffloadBinary::getAlignment()), 86*753f127fSDimitry Andric Buffer->getBufferStart())) 87*753f127fSDimitry Andric Buffer = MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(), 88*753f127fSDimitry Andric Buffer->getBufferIdentifier()); 89*753f127fSDimitry Andric auto BinaryOrErr = OffloadBinary::create(*Buffer); 9081ad6265SDimitry Andric if (!BinaryOrErr) 9181ad6265SDimitry Andric reportError(O.getFileName(), "while extracting offloading files: " + 9281ad6265SDimitry Andric toString(BinaryOrErr.takeError())); 9381ad6265SDimitry Andric OffloadBinary &Binary = **BinaryOrErr; 9481ad6265SDimitry Andric 9581ad6265SDimitry Andric // Print out all the binaries that are contained in this buffer. If we fail 9681ad6265SDimitry Andric // to parse a binary before reaching the end of the buffer emit a warning. 9781ad6265SDimitry Andric if (Error Err = visitAllBinaries(Binary)) 9881ad6265SDimitry Andric reportWarning("while parsing offloading files: " + 9981ad6265SDimitry Andric toString(std::move(Err)), 10081ad6265SDimitry Andric O.getFileName()); 10181ad6265SDimitry Andric } 10281ad6265SDimitry Andric } 10381ad6265SDimitry Andric 10481ad6265SDimitry Andric /// Print the contents of an offload binary file \p OB. This may contain 10581ad6265SDimitry Andric /// multiple binaries stored in the same buffer. 10681ad6265SDimitry Andric void llvm::dumpOffloadSections(const OffloadBinary &OB) { 10781ad6265SDimitry Andric // Print out all the binaries that are contained at this buffer. If we fail to 10881ad6265SDimitry Andric // parse a binary before reaching the end of the buffer emit a warning. 10981ad6265SDimitry Andric if (Error Err = visitAllBinaries(OB)) 11081ad6265SDimitry Andric reportWarning("while parsing offloading files: " + toString(std::move(Err)), 11181ad6265SDimitry Andric OB.getFileName()); 11281ad6265SDimitry Andric } 113