xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-objdump/OffloadDump.cpp (revision 753f127f3ace09432b2baeffd71a308760641a62)
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