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.
getImageName(const OffloadBinary & OB)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
printBinary(const OffloadBinary & OB,uint64_t Index)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
visitAllBinaries(const OffloadBinary & OB)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.
dumpOffloadBinary(const ObjectFile & 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.
dumpOffloadSections(const OffloadBinary & OB)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