Skip to content

Commit 13b5c8e

Browse files
dsalinasdavid-salinas
authored andcommitted
Extend llvm-objdump to support clang offload fat bins
extend option --offloading Change-Id: Ibc865f80e30aa1a6e5495ecfe617be68a5e15fcf
1 parent c148185 commit 13b5c8e

File tree

8 files changed

+184
-68
lines changed

8 files changed

+184
-68
lines changed

llvm/docs/CommandGuide/llvm-objdump.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ OPTIONS
217217

218218
.. option:: --offloading
219219

220-
Display the content of the LLVM offloading section.
220+
Display the content of the LLVM offloading sections and HIP offload bundles.
221221

222222
.. option:: --prefix=<prefix>
223223

llvm/include/llvm/Object/OffloadBundle.h

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
1-
//===--- OffloadBundle.h - Utilities for handling offloading code -*- C++
2-
//-*-===//
1+
//===- OffloadBundle.h - Utilities for offload bundles---*- C++ -*-===//
32
//
43
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
54
// See https://llvm.org/LICENSE.txt for license information.
65
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
76
//
8-
//===------------------------------------------------------------------------===//
7+
//===-------------------------------------------------------------------------===//
98
//
109
// This file contains the binary format used for budingling device metadata with
1110
// an associated device image. The data can then be stored inside a host object
1211
// file to create a fat binary and read by the linker. This is intended to be a
1312
// thin wrapper around the image itself. If this format becomes sufficiently
1413
// complex it should be moved to a standard binary format like msgpack or ELF.
1514
//
16-
//===------------------------------------------------------------------------===//
15+
//===-------------------------------------------------------------------------===//
1716

1817
#ifndef LLVM_OBJECT_OFFLOADBUNDLE_H
1918
#define LLVM_OBJECT_OFFLOADBUNDLE_H
@@ -109,16 +108,6 @@ class OffloadBundleFatBin {
109108
OffloadBundleFatBin(MemoryBufferRef Source, StringRef File)
110109
: FileName(File), NumberOfEntries(0),
111110
Entries(SmallVector<OffloadBundleEntry>()) {}
112-
113-
SmallVector<OffloadBundleEntry> entryIDContains(StringRef Str) {
114-
115-
SmallVector<OffloadBundleEntry> Found = SmallVector<OffloadBundleEntry>();
116-
llvm::transform(Entries, std::back_inserter(Found), [Str](auto &X) {
117-
if (X.ID.contains(Str))
118-
return X;
119-
});
120-
return Found;
121-
}
122111
};
123112

124113
enum UriTypeT { FILE_URI, MEMORY_URI };
@@ -146,9 +135,6 @@ struct OffloadBundleURI {
146135
case MEMORY_URI:
147136
return createMemoryURI(Str);
148137
break;
149-
default:
150-
return createStringError(object_error::parse_failed,
151-
"Unrecognized URI type");
152138
}
153139
}
154140

@@ -180,7 +166,7 @@ struct OffloadBundleURI {
180166
Str.getAsInteger(10, S);
181167
std::unique_ptr<OffloadBundleURI> OffloadingURI(
182168
new OffloadBundleURI(FilePathname, O, S));
183-
return OffloadingURI;
169+
return std::move(OffloadingURI);
184170
}
185171

186172
static Expected<std::unique_ptr<OffloadBundleURI>>

llvm/lib/Object/OffloadBundle.cpp

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
//===- OffloadBundle.cpp - Utilities for handling offloading code -*- C++
2-
//-*-===//
1+
//===- OffloadBundle.cpp - Utilities for offload bundles---*- C++ -*-===//
32
//
43
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
54
// See https://llvm.org/LICENSE.txt for license information.
65
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
76
//
8-
//===----------------------------------------------------------------------===//
7+
//===----------------------------------------------------------------===//
98

109
#include "llvm/Object/OffloadBundle.h"
1110
#include "llvm/ADT/StringSwitch.h"
@@ -79,9 +78,8 @@ Error OffloadBundleFatBin::readEntries(StringRef Buffer,
7978

8079
// Read the Magic String first.
8180
StringRef Magic;
82-
if (auto EC = Reader.readFixedString(Magic, 24)) {
81+
if (auto EC = Reader.readFixedString(Magic, 24))
8382
return errorCodeToError(object_error::parse_failed);
84-
}
8583

8684
// Read the number of Code Objects (Entries) in the current Bundle.
8785
if (auto EC = Reader.readInteger(NumOfEntries))
@@ -108,9 +106,8 @@ Error OffloadBundleFatBin::readEntries(StringRef Buffer,
108106
if (auto EC = Reader.readFixedString(EntryID, EntryIDSize))
109107
return errorCodeToError(object_error::parse_failed);
110108

111-
// create a Bundle Entry object:
112-
auto Entry = new OffloadBundleEntry(EntryOffset + SectionOffset, EntrySize,
113-
EntryIDSize, EntryID);
109+
auto Entry = std::make_unique<OffloadBundleEntry>(
110+
EntryOffset + SectionOffset, EntrySize, EntryIDSize, EntryID);
114111

115112
Entries.push_back(*Entry);
116113
}
@@ -142,15 +139,16 @@ Error OffloadBundleFatBin::extractBundle(const ObjectFile &Source) {
142139
// This will extract all entries in the Bundle
143140
for (OffloadBundleEntry &Entry : Entries) {
144141

145-
if (Entry.Size > 0) {
146-
// create output file name. Which should be
147-
// <fileName>-offset<Offset>-size<Size>.co"
148-
std::string Str = getFileName().str() + "-offset" + itostr(Entry.Offset) +
149-
"-size" + itostr(Entry.Size) + ".co";
150-
if (Error Err = object::extractCodeObject(Source, Entry.Offset,
151-
Entry.Size, StringRef(Str)))
152-
return Err;
153-
}
142+
if (Entry.Size == 0)
143+
continue;
144+
145+
// create output file name. Which should be
146+
// <fileName>-offset<Offset>-size<Size>.co"
147+
std::string Str = getFileName().str() + "-offset" + itostr(Entry.Offset) +
148+
"-size" + itostr(Entry.Size) + ".co";
149+
if (Error Err = object::extractCodeObject(Source, Entry.Offset, Entry.Size,
150+
StringRef(Str)))
151+
return Err;
154152
}
155153

156154
return Error::success();
@@ -160,7 +158,7 @@ Error object::extractOffloadBundleFatBinary(
160158
const ObjectFile &Obj, SmallVectorImpl<OffloadBundleFatBin> &Bundles) {
161159
assert((Obj.isELF() || Obj.isCOFF()) && "Invalid file type");
162160

163-
// iterate through Sections until we find an offload_bundle section.
161+
// Iterate through Sections until we find an offload_bundle section.
164162
for (SectionRef Sec : Obj.sections()) {
165163
Expected<StringRef> Buffer = Sec.getContents();
166164
if (!Buffer)
@@ -174,11 +172,9 @@ Error object::extractOffloadBundleFatBinary(
174172
uint64_t SectionOffset = 0;
175173
if (Obj.isELF()) {
176174
SectionOffset = ELFSectionRef(Sec).getOffset();
177-
} else if (Obj.isCOFF()) {
178-
if (const COFFObjectFile *COFFObj = dyn_cast<COFFObjectFile>(&Obj)) {
179-
const coff_section *CoffSection = COFFObj->getCOFFSection(Sec);
180-
}
181-
}
175+
} else if (Obj.isCOFF()) // TODO: add COFF Support
176+
return createStringError(object_error::parse_failed,
177+
"COFF object files not supported.\n");
182178

183179
MemoryBufferRef Contents(*Buffer, Obj.getFileName());
184180

@@ -341,7 +337,7 @@ CompressedOffloadBundle::decompress(llvm::MemoryBufferRef &Input,
341337
double DecompressionTimeSeconds =
342338
DecompressTimer.getTotalTime().getWallTime();
343339

344-
// Recalculate MD5 hash for integrity check
340+
// Recalculate MD5 hash for integrity check.
345341
llvm::Timer HashRecalcTimer("Hash Recalculation Timer",
346342
"Hash recalculation time",
347343
OffloadBundlerTimerGroup);

llvm/test/tools/llvm-objdump/Offloading/fatbin.test

Lines changed: 60 additions & 0 deletions
Large diffs are not rendered by default.

llvm/tools/llvm-objdump/OffloadDump.cpp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,16 @@
1414
#include "OffloadDump.h"
1515
#include "llvm-objdump.h"
1616
#include "llvm/Object/ELFObjectFile.h"
17+
#include "llvm/Object/OffloadBinary.h"
18+
#include "llvm/Object/OffloadBundle.h"
1719
#include "llvm/Support/Alignment.h"
1820

1921
using namespace llvm;
2022
using namespace llvm::object;
2123
using namespace llvm::objdump;
2224

25+
void disassembleObject(llvm::object::ObjectFile *, bool InlineRelocs);
26+
2327
/// Get the printable name of the image kind.
2428
static StringRef getImageName(const OffloadBinary &OB) {
2529
switch (OB.getImageKind()) {
@@ -48,7 +52,7 @@ static void printBinary(const OffloadBinary &OB, uint64_t Index) {
4852
}
4953

5054
/// Print the embedded offloading contents of an ObjectFile \p O.
51-
void llvm::dumpOffloadBinary(const ObjectFile &O) {
55+
void llvm::dumpOffloadBinary(const ObjectFile &O, StringRef ArchName) {
5256
if (!O.isELF() && !O.isCOFF()) {
5357
reportWarning(
5458
"--offloading is currently only supported for COFF and ELF targets",
@@ -64,6 +68,44 @@ void llvm::dumpOffloadBinary(const ObjectFile &O) {
6468
// Print out all the binaries that are contained in this buffer.
6569
for (uint64_t I = 0, E = Binaries.size(); I != E; ++I)
6670
printBinary(*Binaries[I].getBinary(), I);
71+
72+
dumpOffloadBundleFatBinary(O, ArchName);
73+
}
74+
75+
// Given an Object file, collect all Bundles of FatBin Binaries
76+
// and dump them into Code Object files
77+
// if -arch=-name is specified, only dump the Entries that match the target arch
78+
void llvm::dumpOffloadBundleFatBinary(const ObjectFile &O, StringRef ArchName) {
79+
if (!O.isELF() && !O.isCOFF()) {
80+
reportWarning(
81+
"--offloading is currently only supported for COFF and ELF targets",
82+
O.getFileName());
83+
return;
84+
}
85+
86+
SmallVector<llvm::object::OffloadBundleFatBin> FoundBundles;
87+
88+
if (Error Err = llvm::object::extractOffloadBundleFatBinary(O, FoundBundles))
89+
reportError(O.getFileName(), "while extracting offload FatBin bundles: " +
90+
toString(std::move(Err)));
91+
92+
for (const auto &[BundleNum, Bundle] : llvm::enumerate(FoundBundles)) {
93+
for (OffloadBundleEntry &Entry : Bundle.getEntries()) {
94+
if (!ArchName.empty() && !Entry.ID.contains(ArchName))
95+
continue;
96+
97+
// create file name for this object file: <source-filename>.<Bundle
98+
// Number>.<EntryID>
99+
std::string str = Bundle.getFileName().str() + "." + itostr(BundleNum) +
100+
"." + Entry.ID.str();
101+
if (Error Err = object::extractCodeObject(O, Entry.Offset, Entry.Size,
102+
StringRef(str)))
103+
reportError(O.getFileName(),
104+
"while extracting offload Bundle Entries: " +
105+
toString(std::move(Err)));
106+
outs() << "Extracting offload bundle: " << str << "\n";
107+
}
108+
}
67109
}
68110

69111
/// Print the contents of an offload binary file \p OB. This may contain

llvm/tools/llvm-objdump/OffloadDump.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,16 @@
1111

1212
#include "llvm/Object/ObjectFile.h"
1313
#include "llvm/Object/OffloadBinary.h"
14+
#include "llvm/Object/OffloadBundle.h"
1415

1516
namespace llvm {
1617

1718
void dumpOffloadSections(const object::OffloadBinary &OB);
18-
void dumpOffloadBinary(const object::ObjectFile &O);
19+
void dumpOffloadBinary(const object::ObjectFile &O, StringRef ArchName);
1920

21+
/// Dump fat binary in binary clang-offload-bundler format
22+
void dumpOffloadBundleFatBinary(const object::ObjectFile &O,
23+
StringRef ArchName);
2024
} // namespace llvm
2125

2226
#endif

llvm/tools/llvm-objdump/llvm-objdump.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
#include "llvm/Object/MachO.h"
5757
#include "llvm/Object/MachOUniversal.h"
5858
#include "llvm/Object/OffloadBinary.h"
59+
#include "llvm/Object/OffloadBundle.h"
5960
#include "llvm/Object/Wasm.h"
6061
#include "llvm/Option/Arg.h"
6162
#include "llvm/Option/ArgList.h"
@@ -3338,7 +3339,7 @@ static void dumpObject(ObjectFile *O, const Archive *A = nullptr,
33383339
if (FaultMapSection)
33393340
printFaultMaps(O);
33403341
if (Offloading)
3341-
dumpOffloadBinary(*O);
3342+
dumpOffloadBinary(*O, StringRef(ArchName));
33423343
}
33433344

33443345
static void dumpObject(const COFFImportFile *I, const Archive *A,
Lines changed: 49 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
// Skip running on Windows.
2+
#if !defined(_WIN32)
3+
14
#include "llvm/Object/ELFObjectFile.h"
25
#include "llvm/Object/OffloadBinary.h"
36
#include "llvm/Object/OffloadBundle.h"
47
#include "llvm/ObjectYAML/yaml2obj.h"
8+
#include "llvm/Support/FileOutputBuffer.h"
59
#include "llvm/Support/MemoryBuffer.h"
610
#include "llvm/Support/YAMLTraits.h"
711
#include "llvm/Testing/Support/Error.h"
@@ -11,27 +15,7 @@
1115
using namespace llvm;
1216
using namespace llvm::object;
1317

14-
// ELF Object creation
15-
static Expected<std::unique_ptr<ObjectFile>>
16-
toBinary(SmallVectorImpl<char> &Storage, StringRef Yaml) {
17-
raw_svector_ostream OS(Storage);
18-
yaml::Input YIn(Yaml);
19-
if (!yaml::convertYAML(YIn, OS, [](const Twine &Msg) {}))
20-
return createStringError(std::errc::invalid_argument,
21-
"unable to convert YAML");
22-
return object::ObjectFile::createELFObjectFile(
23-
MemoryBufferRef(OS.str(), "dummyELF"));
24-
}
25-
26-
TEST(OffloadingBundleTest, checkOffloadingFatBinary) {
27-
28-
// create a Memory Buffer with a fatbin offloading section
29-
MemoryBufferRef mbuf;
30-
StringRef FileName;
31-
SmallVector<OffloadBundleEntry>();
32-
SmallString<0> Storage;
33-
// Expected<ELFObjectFile<ELF64LE>> ObjOrErr = toBinary<ELF64LE>(Storage, R"(
34-
Expected<std::unique_ptr<ObjectFile>> ObjOrErr = toBinary(Storage, R"(
18+
StringRef simpleAdd = R"(
3519
--- !ELF
3620
FileHeader:
3721
Class: ELFCLASS64
@@ -52,11 +36,54 @@ TEST(OffloadingBundleTest, checkOffloadingFatBinary) {
5236
Address: 0x202FD0
5337
AddressAlign: 0x8
5438
Content: '465049480100000000102000000000000000000000000000'
55-
)");
39+
)";
40+
41+
// ELF Object creation
42+
static Expected<std::unique_ptr<ObjectFile>>
43+
toBinary(SmallVectorImpl<char> &Storage, StringRef Yaml) {
44+
raw_svector_ostream OS(Storage);
45+
yaml::Input YIn(Yaml);
46+
if (!yaml::convertYAML(YIn, OS, [](const Twine &Msg) {}))
47+
return createStringError(std::errc::invalid_argument,
48+
"unable to convert YAML");
49+
return object::ObjectFile::createELFObjectFile(
50+
MemoryBufferRef(OS.str(), "dummyELF"));
51+
}
52+
53+
TEST(OffloadingBundleTest, checkExtractOffloadBundleFatBinary) {
54+
55+
// create a Memory Buffer with a fatbin offloading section
56+
MemoryBufferRef mbuf;
57+
StringRef FileName;
58+
SmallVector<OffloadBundleEntry>();
59+
SmallString<0> Storage;
60+
// Expected<ELFObjectFile<ELF64LE>> ObjOrErr = toBinary<ELF64LE>(Storage, R"(
61+
Expected<std::unique_ptr<ObjectFile>> ObjOrErr = toBinary(Storage, simpleAdd);
5662

5763
ASSERT_THAT_EXPECTED(ObjOrErr, Succeeded());
5864

5965
SmallVector<llvm::object::OffloadBundleFatBin> Bundles;
6066
Error Err = extractOffloadBundleFatBinary(**ObjOrErr, Bundles);
6167
EXPECT_FALSE(errorToBool(std::move(Err)));
6268
}
69+
70+
TEST(OffloadingBundleTest, checkExtractCodeObject) {
71+
// create a Memory Buffer with a fatbin offloading section
72+
MemoryBufferRef mbuf;
73+
StringRef FileName;
74+
SmallVector<OffloadBundleEntry>();
75+
SmallString<0> Storage;
76+
// Expected<ELFObjectFile<ELF64LE>> ObjOrErr = toBinary<ELF64LE>(Storage, R"(
77+
Expected<std::unique_ptr<ObjectFile>> ObjOrErr = toBinary(Storage, simpleAdd);
78+
79+
ASSERT_THAT_EXPECTED(ObjOrErr, Succeeded());
80+
81+
int64_t Offset = 8192;
82+
int64_t Size = 4048;
83+
84+
Error Err = extractCodeObject(**ObjOrErr, Offset, Size,
85+
StringRef("checkExtractCodeObject.co"));
86+
EXPECT_FALSE(errorToBool(std::move(Err)));
87+
}
88+
89+
#endif

0 commit comments

Comments
 (0)