1 //===-- OffloadDump.cpp - Offloading dumper ---------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// This file implements the offloading-specific dumper for llvm-objdump. 11 /// 12 //===----------------------------------------------------------------------===// 13 #include "OffloadDump.h" 14 #include "llvm-objdump.h" 15 #include "llvm/Object/ELFObjectFile.h" 16 #include "llvm/Support/Alignment.h" 17 18 using namespace llvm; 19 using namespace llvm::object; 20 using namespace llvm::objdump; 21 22 /// Get the printable name of the image kind. 23 static StringRef getImageName(const OffloadBinary &OB) { 24 switch (OB.getImageKind()) { 25 case IMG_Object: 26 return "elf"; 27 case IMG_Bitcode: 28 return "llvm ir"; 29 case IMG_Cubin: 30 return "cubin"; 31 case IMG_Fatbinary: 32 return "fatbinary"; 33 case IMG_PTX: 34 return "ptx"; 35 default: 36 return "<none>"; 37 } 38 } 39 40 static void printBinary(const OffloadBinary &OB, uint64_t Index) { 41 outs() << "\nOFFLOADING IMAGE [" << Index << "]:\n"; 42 outs() << left_justify("kind", 16) << getImageName(OB) << "\n"; 43 outs() << left_justify("arch", 16) << OB.getArch() << "\n"; 44 outs() << left_justify("triple", 16) << OB.getTriple() << "\n"; 45 outs() << left_justify("producer", 16) 46 << getOffloadKindName(OB.getOffloadKind()) << "\n"; 47 } 48 49 static Error visitAllBinaries(const OffloadBinary &OB) { 50 uint64_t Offset = 0; 51 uint64_t Index = 0; 52 while (Offset < OB.getMemoryBufferRef().getBufferSize()) { 53 MemoryBufferRef Buffer = 54 MemoryBufferRef(OB.getData().drop_front(Offset), OB.getFileName()); 55 auto BinaryOrErr = OffloadBinary::create(Buffer); 56 if (!BinaryOrErr) 57 return BinaryOrErr.takeError(); 58 59 OffloadBinary &Binary = **BinaryOrErr; 60 printBinary(Binary, Index++); 61 62 Offset += Binary.getSize(); 63 } 64 return Error::success(); 65 } 66 67 /// Print the embedded offloading contents of an ObjectFile \p O. 68 void llvm::dumpOffloadBinary(const ObjectFile &O) { 69 if (!O.isELF()) { 70 reportWarning("--offloading is currently only supported for ELF targets", 71 O.getFileName()); 72 return; 73 } 74 75 for (ELFSectionRef Sec : O.sections()) { 76 if (Sec.getType() != ELF::SHT_LLVM_OFFLOADING) 77 continue; 78 79 Expected<StringRef> Contents = Sec.getContents(); 80 if (!Contents) 81 reportError(Contents.takeError(), O.getFileName()); 82 83 std::unique_ptr<MemoryBuffer> Buffer = 84 MemoryBuffer::getMemBuffer(*Contents, O.getFileName(), false); 85 if (!isAddrAligned(Align(OffloadBinary::getAlignment()), 86 Buffer->getBufferStart())) 87 Buffer = MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(), 88 Buffer->getBufferIdentifier()); 89 auto BinaryOrErr = OffloadBinary::create(*Buffer); 90 if (!BinaryOrErr) 91 reportError(O.getFileName(), "while extracting offloading files: " + 92 toString(BinaryOrErr.takeError())); 93 OffloadBinary &Binary = **BinaryOrErr; 94 95 // Print out all the binaries that are contained in this buffer. If we fail 96 // to parse a binary before reaching the end of the buffer emit a warning. 97 if (Error Err = visitAllBinaries(Binary)) 98 reportWarning("while parsing offloading files: " + 99 toString(std::move(Err)), 100 O.getFileName()); 101 } 102 } 103 104 /// Print the contents of an offload binary file \p OB. This may contain 105 /// multiple binaries stored in the same buffer. 106 void llvm::dumpOffloadSections(const OffloadBinary &OB) { 107 // Print out all the binaries that are contained at this buffer. If we fail to 108 // parse a binary before reaching the end of the buffer emit a warning. 109 if (Error Err = visitAllBinaries(OB)) 110 reportWarning("while parsing offloading files: " + toString(std::move(Err)), 111 OB.getFileName()); 112 } 113