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 
16 using namespace llvm;
17 using namespace llvm::object;
18 using namespace llvm::objdump;
19 
20 constexpr const char OffloadSectionString[] = ".llvm.offloading";
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   for (SectionRef Sec : O.sections()) {
70     Expected<StringRef> Name = Sec.getName();
71     if (!Name || !Name->startswith(OffloadSectionString))
72       continue;
73 
74     Expected<StringRef> Contents = Sec.getContents();
75     if (!Contents)
76       reportError(Contents.takeError(), O.getFileName());
77 
78     MemoryBufferRef Buffer = MemoryBufferRef(*Contents, O.getFileName());
79     auto BinaryOrErr = OffloadBinary::create(Buffer);
80     if (!BinaryOrErr)
81       reportError(O.getFileName(), "while extracting offloading files: " +
82                                        toString(BinaryOrErr.takeError()));
83     OffloadBinary &Binary = **BinaryOrErr;
84 
85     // Print out all the binaries that are contained in this buffer. If we fail
86     // to parse a binary before reaching the end of the buffer emit a warning.
87     if (Error Err = visitAllBinaries(Binary))
88       reportWarning("while parsing offloading files: " +
89                         toString(std::move(Err)),
90                     O.getFileName());
91   }
92 }
93 
94 /// Print the contents of an offload binary file \p OB. This may contain
95 /// multiple binaries stored in the same buffer.
96 void llvm::dumpOffloadSections(const OffloadBinary &OB) {
97   // Print out all the binaries that are contained at this buffer. If we fail to
98   // parse a binary before reaching the end of the buffer emit a warning.
99   if (Error Err = visitAllBinaries(OB))
100     reportWarning("while parsing offloading files: " + toString(std::move(Err)),
101                   OB.getFileName());
102 }
103