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 | |
14 | #include "OffloadDump.h" |
15 | #include "llvm-objdump.h" |
16 | #include "llvm/Object/ELFObjectFile.h" |
17 | #include "llvm/Object/OffloadBinary.h" |
18 | #include "llvm/Object/OffloadBundle.h" |
19 | |
20 | using namespace llvm; |
21 | using namespace llvm::object; |
22 | using namespace llvm::objdump; |
23 | |
24 | void disassembleObject(llvm::object::ObjectFile *, bool InlineRelocs); |
25 | |
26 | /// Get the printable name of the image kind. |
27 | static StringRef getImageName(const OffloadBinary &OB) { |
28 | switch (OB.getImageKind()) { |
29 | case IMG_Object: |
30 | return "elf" ; |
31 | case IMG_Bitcode: |
32 | return "llvm ir" ; |
33 | case IMG_Cubin: |
34 | return "cubin" ; |
35 | case IMG_Fatbinary: |
36 | return "fatbinary" ; |
37 | case IMG_PTX: |
38 | return "ptx" ; |
39 | default: |
40 | return "<none>" ; |
41 | } |
42 | } |
43 | |
44 | static void printBinary(const OffloadBinary &OB, uint64_t Index) { |
45 | outs() << "\nOFFLOADING IMAGE [" << Index << "]:\n" ; |
46 | outs() << left_justify(Str: "kind" , Width: 16) << getImageName(OB) << "\n" ; |
47 | outs() << left_justify(Str: "arch" , Width: 16) << OB.getArch() << "\n" ; |
48 | outs() << left_justify(Str: "triple" , Width: 16) << OB.getTriple() << "\n" ; |
49 | outs() << left_justify(Str: "producer" , Width: 16) |
50 | << getOffloadKindName(Name: OB.getOffloadKind()) << "\n" ; |
51 | } |
52 | |
53 | /// Print the embedded offloading contents of an ObjectFile \p O. |
54 | void llvm::dumpOffloadBinary(const ObjectFile &O, StringRef ArchName) { |
55 | if (!O.isELF() && !O.isCOFF()) { |
56 | reportWarning( |
57 | Message: "--offloading is currently only supported for COFF and ELF targets" , |
58 | File: O.getFileName()); |
59 | return; |
60 | } |
61 | |
62 | SmallVector<OffloadFile> Binaries; |
63 | if (Error Err = extractOffloadBinaries(Buffer: O.getMemoryBufferRef(), Binaries)) |
64 | reportError(File: O.getFileName(), Message: "while extracting offloading files: " + |
65 | toString(E: std::move(Err))); |
66 | |
67 | // Print out all the binaries that are contained in this buffer. |
68 | for (uint64_t I = 0, E = Binaries.size(); I != E; ++I) |
69 | printBinary(OB: *Binaries[I].getBinary(), Index: I); |
70 | |
71 | dumpOffloadBundleFatBinary(O, ArchName); |
72 | } |
73 | |
74 | // Given an Object file, collect all Bundles of FatBin Binaries |
75 | // and dump them into Code Object files |
76 | // if -arch=-name is specified, only dump the Entries that match the target arch |
77 | void llvm::dumpOffloadBundleFatBinary(const ObjectFile &O, StringRef ArchName) { |
78 | if (!O.isELF() && !O.isCOFF()) { |
79 | reportWarning( |
80 | Message: "--offloading is currently only supported for COFF and ELF targets" , |
81 | File: O.getFileName()); |
82 | return; |
83 | } |
84 | |
85 | SmallVector<llvm::object::OffloadBundleFatBin> FoundBundles; |
86 | |
87 | if (Error Err = llvm::object::extractOffloadBundleFatBinary(Obj: O, Bundles&: FoundBundles)) |
88 | reportError(File: O.getFileName(), Message: "while extracting offload FatBin bundles: " + |
89 | toString(E: std::move(Err))); |
90 | |
91 | for (const auto &[BundleNum, Bundle] : llvm::enumerate(First&: FoundBundles)) { |
92 | for (OffloadBundleEntry &Entry : Bundle.getEntries()) { |
93 | if (!ArchName.empty() && !Entry.ID.contains(Other: ArchName)) |
94 | continue; |
95 | |
96 | // create file name for this object file: <source-filename>.<Bundle |
97 | // Number>.<EntryID> |
98 | std::string str = Bundle.getFileName().str() + "." + itostr(X: BundleNum) + |
99 | "." + Entry.ID.str(); |
100 | if (Error Err = object::extractCodeObject(Source: O, Offset: Entry.Offset, Size: Entry.Size, |
101 | OutputFileName: StringRef(str))) |
102 | reportError(File: O.getFileName(), |
103 | Message: "while extracting offload Bundle Entries: " + |
104 | toString(E: std::move(Err))); |
105 | outs() << "Extracting offload bundle: " << str << "\n" ; |
106 | } |
107 | } |
108 | } |
109 | |
110 | /// Print the contents of an offload binary file \p OB. This may contain |
111 | /// multiple binaries stored in the same buffer. |
112 | void llvm::dumpOffloadSections(const OffloadBinary &OB) { |
113 | SmallVector<OffloadFile> Binaries; |
114 | if (Error Err = extractOffloadBinaries(Buffer: OB.getMemoryBufferRef(), Binaries)) |
115 | reportError(File: OB.getFileName(), Message: "while extracting offloading files: " + |
116 | toString(E: std::move(Err))); |
117 | |
118 | // Print out all the binaries that are contained in this buffer. |
119 | for (uint64_t I = 0, E = Binaries.size(); I != E; ++I) |
120 | printBinary(OB: *Binaries[I].getBinary(), Index: I); |
121 | } |
122 | |