Skip to content

Commit 7d7d22c

Browse files
author
Salinas, David
authored
Extend llvm objdump fatbin (llvm#140286) (llvm#2427)
2 parents 1afc1c3 + 5ac52c0 commit 7d7d22c

File tree

11 files changed

+796
-1458
lines changed

11 files changed

+796
-1458
lines changed

llvm/include/llvm/Object/OffloadBinary.h

Lines changed: 0 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -51,31 +51,6 @@ enum ImageKind : uint16_t {
5151
IMG_LAST,
5252
};
5353

54-
class CompressedOffloadBundle {
55-
private:
56-
static inline const size_t MagicSize = 4;
57-
static inline const size_t VersionFieldSize = sizeof(uint16_t);
58-
static inline const size_t MethodFieldSize = sizeof(uint16_t);
59-
static inline const size_t FileSizeFieldSize = sizeof(uint32_t);
60-
static inline const size_t UncompressedSizeFieldSize = sizeof(uint32_t);
61-
static inline const size_t HashFieldSize = sizeof(uint64_t);
62-
static inline const size_t V1HeaderSize =
63-
MagicSize + VersionFieldSize + MethodFieldSize +
64-
UncompressedSizeFieldSize + HashFieldSize;
65-
static inline const size_t V2HeaderSize =
66-
MagicSize + VersionFieldSize + FileSizeFieldSize + MethodFieldSize +
67-
UncompressedSizeFieldSize + HashFieldSize;
68-
static inline const llvm::StringRef MagicNumber = "CCOB";
69-
static inline const uint16_t Version = 2;
70-
71-
public:
72-
static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
73-
compress(llvm::compression::Params P, const llvm::MemoryBuffer &Input,
74-
bool Verbose = false);
75-
static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
76-
decompress(llvm::MemoryBufferRef &Input, bool Verbose = false);
77-
};
78-
7954
/// A simple binary serialization of an offloading file. We use this format to
8055
/// embed the offloading image into the host executable so it can be extracted
8156
/// and used by the linker.
@@ -210,160 +185,11 @@ class OffloadFile : public OwningBinary<OffloadBinary> {
210185
}
211186
};
212187

213-
/// Bundle entry in binary clang-offload-bundler format.
214-
struct OffloadBundleEntry {
215-
uint64_t Offset = 0u;
216-
uint64_t Size = 0u;
217-
uint64_t IDLength = 0u;
218-
StringRef ID;
219-
OffloadBundleEntry(uint64_t O, uint64_t S, uint64_t I, StringRef T)
220-
: Offset(O), Size(S), IDLength(I), ID(T) {}
221-
void dumpInfo(raw_ostream &OS) {
222-
OS << "Offset = " << Offset << ", Size = " << Size
223-
<< ", ID Length = " << IDLength << ", ID = " << ID;
224-
}
225-
void dumpURI(raw_ostream &OS, StringRef filePath) {
226-
OS << ID.data() << "\tfile:\/\/" << filePath << "#offset=" << Offset
227-
<< "&size=" << Size << "\n";
228-
}
229-
};
230-
231-
/// Fat binary embedded in object files in clang-offload-bundler format
232-
class OffloadBundleFatBin {
233-
234-
private:
235-
uint64_t Size = 0u;
236-
StringRef FileName;
237-
uint64_t NumberOfEntries;
238-
SmallVector<OffloadBundleEntry> Entries;
239-
240-
public:
241-
SmallVector<OffloadBundleEntry> getEntries() { return Entries; }
242-
uint64_t getSize() const { return Size; }
243-
StringRef getFileName() const { return FileName; }
244-
uint64_t getNumEntries() const { return NumberOfEntries; }
245-
246-
static Expected<std::unique_ptr<OffloadBundleFatBin>>
247-
create(MemoryBufferRef, uint64_t SectionOffset, StringRef fileName);
248-
Error extractBundle(const ObjectFile &Source);
249-
250-
Error DumpEntryToCodeObject();
251-
252-
Error ReadEntries(StringRef Section, uint64_t SectionOffset);
253-
void DumpEntries() {
254-
SmallVectorImpl<OffloadBundleEntry>::iterator it = Entries.begin();
255-
for (uint64_t I = 0; I < Entries.size(); I++) {
256-
it->dumpInfo(outs());
257-
++it;
258-
}
259-
}
260-
261-
void PrintEntriesAsURI() {
262-
SmallVectorImpl<OffloadBundleEntry>::iterator it = Entries.begin();
263-
for (uint64_t I = 0; I < NumberOfEntries; I++) {
264-
it->dumpURI(outs(), FileName);
265-
++it;
266-
}
267-
}
268-
269-
OffloadBundleFatBin(MemoryBufferRef Source, StringRef file) : FileName(file) {
270-
NumberOfEntries = 0;
271-
Entries = SmallVector<OffloadBundleEntry>();
272-
}
273-
274-
SmallVector<OffloadBundleEntry> EntryIDContains(StringRef str) {
275-
SmallVector<OffloadBundleEntry> found = SmallVector<OffloadBundleEntry>();
276-
SmallVectorImpl<OffloadBundleEntry>::iterator it = Entries.begin();
277-
for (uint64_t I = 0; I < NumberOfEntries; I++) {
278-
if (it->ID.contains(str)) {
279-
found.push_back(*it);
280-
}
281-
282-
++it;
283-
}
284-
return found;
285-
}
286-
};
287-
288-
enum uri_type_t { FILE_URI, MEMORY_URI };
289-
290-
struct OffloadBundleURI {
291-
int64_t Offset = 0;
292-
int64_t Size = 0;
293-
uint64_t ProcessID = 0;
294-
StringRef FileName;
295-
uri_type_t URIType;
296-
297-
// Constructors
298-
// TODO: add a Copy ctor ?
299-
OffloadBundleURI(StringRef file, int64_t off, int64_t size)
300-
: Offset(off), Size(size), ProcessID(0), FileName(file),
301-
URIType(FILE_URI) {}
302-
303-
OffloadBundleURI(StringRef str, uri_type_t type) {
304-
URIType = type;
305-
switch (URIType) {
306-
case FILE_URI:
307-
parseFileName(str);
308-
break;
309-
case MEMORY_URI:
310-
parseMemoryURI(str);
311-
break;
312-
default:
313-
report_fatal_error("Unrecognized URI type.");
314-
}
315-
}
316-
317-
void parseFileName(StringRef str) {
318-
ProcessID = 0;
319-
URIType = FILE_URI;
320-
if (str.consume_front("file://")) {
321-
StringRef FilePathname =
322-
str.take_until([](char c) { return (c == '#') || (c == '?'); });
323-
FileName = FilePathname;
324-
str = str.drop_front(FilePathname.size());
325-
326-
if (str.consume_front("#offset=")) {
327-
StringRef OffsetStr = str.take_until([](char c) { return c == '&'; });
328-
OffsetStr.getAsInteger(10, Offset);
329-
str = str.drop_front(OffsetStr.size());
330-
331-
if (str.consume_front("&size=")) {
332-
Size;
333-
str.getAsInteger(10, Size);
334-
} else
335-
report_fatal_error("Reading 'size' in URI.");
336-
} else
337-
report_fatal_error("Reading 'offset' in URI.");
338-
} else
339-
report_fatal_error("Reading type of URI.");
340-
}
341-
342-
void parseMemoryURI(StringRef str) {
343-
// TODO: add parseMemoryURI type
344-
}
345-
346-
StringRef getFileName() const { return FileName; }
347-
};
348-
349188
/// Extracts embedded device offloading code from a memory \p Buffer to a list
350189
/// of \p Binaries.
351190
Error extractOffloadBinaries(MemoryBufferRef Buffer,
352191
SmallVectorImpl<OffloadFile> &Binaries);
353192

354-
/// Extracts fat binary in binary clang-offload-bundler format from object \p
355-
/// Obj and return it in \p Bundles
356-
Error extractOffloadBundleFatBinary(
357-
const ObjectFile &Obj, SmallVectorImpl<OffloadBundleFatBin> &Bundles);
358-
359-
/// Extract code object memory from the given \p Source object file at \p Offset
360-
/// and of \p Size, and copy into \p OutputFileName.
361-
Error extractCodeObject(const ObjectFile &Source, int64_t Offset, int64_t Size,
362-
StringRef OutputFileName);
363-
364-
/// Extracts an Offload Bundle Entry given by URI
365-
Error extractOffloadBundleByURI(StringRef URIstr);
366-
367193
/// Convert a string \p Name to an image kind.
368194
ImageKind getImageKind(StringRef Name);
369195

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
//===- OffloadBundle.h - Utilities for offload bundles---*- 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+
// This file contains the binary format used for budingling device metadata with
10+
// an associated device image. The data can then be stored inside a host object
11+
// file to create a fat binary and read by the linker. This is intended to be a
12+
// thin wrapper around the image itself. If this format becomes sufficiently
13+
// complex it should be moved to a standard binary format like msgpack or ELF.
14+
//
15+
//===-------------------------------------------------------------------------===//
16+
17+
#ifndef LLVM_OBJECT_OFFLOADBUNDLE_H
18+
#define LLVM_OBJECT_OFFLOADBUNDLE_H
19+
20+
#include "llvm/ADT/MapVector.h"
21+
#include "llvm/ADT/SmallString.h"
22+
#include "llvm/ADT/StringRef.h"
23+
#include "llvm/Object/Binary.h"
24+
#include "llvm/Object/ObjectFile.h"
25+
#include "llvm/Support/Compression.h"
26+
#include "llvm/Support/Error.h"
27+
#include "llvm/Support/MemoryBuffer.h"
28+
#include <memory>
29+
30+
namespace llvm {
31+
32+
namespace object {
33+
34+
class CompressedOffloadBundle {
35+
private:
36+
static inline const size_t MagicSize = 4;
37+
static inline const size_t VersionFieldSize = sizeof(uint16_t);
38+
static inline const size_t MethodFieldSize = sizeof(uint16_t);
39+
static inline const size_t FileSizeFieldSize = sizeof(uint32_t);
40+
static inline const size_t UncompressedSizeFieldSize = sizeof(uint32_t);
41+
static inline const size_t HashFieldSize = sizeof(uint64_t);
42+
static inline const size_t V1HeaderSize =
43+
MagicSize + VersionFieldSize + MethodFieldSize +
44+
UncompressedSizeFieldSize + HashFieldSize;
45+
static inline const size_t V2HeaderSize =
46+
MagicSize + VersionFieldSize + FileSizeFieldSize + MethodFieldSize +
47+
UncompressedSizeFieldSize + HashFieldSize;
48+
static inline const llvm::StringRef MagicNumber = "CCOB";
49+
static inline const uint16_t Version = 2;
50+
51+
public:
52+
static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
53+
compress(llvm::compression::Params P, const llvm::MemoryBuffer &Input,
54+
bool Verbose = false);
55+
static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
56+
decompress(llvm::MemoryBufferRef &Input, bool Verbose = false);
57+
};
58+
59+
/// Bundle entry in binary clang-offload-bundler format.
60+
struct OffloadBundleEntry {
61+
uint64_t Offset = 0u;
62+
uint64_t Size = 0u;
63+
uint64_t IDLength = 0u;
64+
StringRef ID;
65+
OffloadBundleEntry(uint64_t O, uint64_t S, uint64_t I, StringRef T)
66+
: Offset(O), Size(S), IDLength(I), ID(T) {}
67+
void dumpInfo(raw_ostream &OS) {
68+
OS << "Offset = " << Offset << ", Size = " << Size
69+
<< ", ID Length = " << IDLength << ", ID = " << ID;
70+
}
71+
void dumpURI(raw_ostream &OS, StringRef FilePath) {
72+
OS << ID.data() << "\tfile://" << FilePath << "#offset=" << Offset
73+
<< "&size=" << Size << "\n";
74+
}
75+
};
76+
77+
/// Fat binary embedded in object files in clang-offload-bundler format
78+
class OffloadBundleFatBin {
79+
80+
uint64_t Size = 0u;
81+
StringRef FileName;
82+
uint64_t NumberOfEntries;
83+
SmallVector<OffloadBundleEntry> Entries;
84+
85+
public:
86+
SmallVector<OffloadBundleEntry> getEntries() { return Entries; }
87+
uint64_t getSize() const { return Size; }
88+
StringRef getFileName() const { return FileName; }
89+
uint64_t getNumEntries() const { return NumberOfEntries; }
90+
91+
static Expected<std::unique_ptr<OffloadBundleFatBin>>
92+
create(MemoryBufferRef, uint64_t SectionOffset, StringRef FileName);
93+
Error extractBundle(const ObjectFile &Source);
94+
95+
Error dumpEntryToCodeObject();
96+
97+
Error readEntries(StringRef Section, uint64_t SectionOffset);
98+
void dumpEntries() {
99+
for (OffloadBundleEntry &Entry : Entries)
100+
Entry.dumpInfo(outs());
101+
}
102+
103+
void printEntriesAsURI() {
104+
for (OffloadBundleEntry &Entry : Entries)
105+
Entry.dumpURI(outs(), FileName);
106+
}
107+
108+
OffloadBundleFatBin(MemoryBufferRef Source, StringRef File)
109+
: FileName(File), NumberOfEntries(0),
110+
Entries(SmallVector<OffloadBundleEntry>()) {}
111+
};
112+
113+
enum UriTypeT { FILE_URI, MEMORY_URI };
114+
115+
struct OffloadBundleURI {
116+
int64_t Offset = 0;
117+
int64_t Size = 0;
118+
uint64_t ProcessID = 0;
119+
StringRef FileName;
120+
UriTypeT URIType;
121+
122+
// Constructors
123+
// TODO: add a Copy ctor ?
124+
OffloadBundleURI(StringRef File, int64_t Off, int64_t Size)
125+
: Offset(Off), Size(Size), ProcessID(0), FileName(File),
126+
URIType(FILE_URI) {}
127+
128+
public:
129+
static Expected<std::unique_ptr<OffloadBundleURI>>
130+
createOffloadBundleURI(StringRef Str, UriTypeT Type) {
131+
switch (Type) {
132+
case FILE_URI:
133+
return createFileURI(Str);
134+
break;
135+
case MEMORY_URI:
136+
return createMemoryURI(Str);
137+
break;
138+
}
139+
llvm_unreachable("Unknown UriTypeT enum");
140+
}
141+
142+
static Expected<std::unique_ptr<OffloadBundleURI>>
143+
createFileURI(StringRef Str) {
144+
int64_t O = 0;
145+
int64_t S = 0;
146+
147+
if (!Str.consume_front("file://"))
148+
return createStringError(object_error::parse_failed,
149+
"Reading type of URI");
150+
151+
StringRef FilePathname =
152+
Str.take_until([](char C) { return (C == '#') || (C == '?'); });
153+
Str = Str.drop_front(FilePathname.size());
154+
155+
if (!Str.consume_front("#offset="))
156+
return createStringError(object_error::parse_failed,
157+
"Reading 'offset' in URI");
158+
159+
StringRef OffsetStr = Str.take_until([](char C) { return C == '&'; });
160+
OffsetStr.getAsInteger(10, O);
161+
Str = Str.drop_front(OffsetStr.size());
162+
163+
if (Str.consume_front("&size="))
164+
return createStringError(object_error::parse_failed,
165+
"Reading 'size' in URI");
166+
167+
Str.getAsInteger(10, S);
168+
std::unique_ptr<OffloadBundleURI> OffloadingURI(
169+
new OffloadBundleURI(FilePathname, O, S));
170+
return std::move(OffloadingURI);
171+
}
172+
173+
static Expected<std::unique_ptr<OffloadBundleURI>>
174+
createMemoryURI(StringRef Str) {
175+
// TODO: add parseMemoryURI type
176+
return createStringError(object_error::parse_failed,
177+
"Memory Type URI is not currently supported.");
178+
}
179+
180+
StringRef getFileName() const { return FileName; }
181+
};
182+
183+
/// Extracts fat binary in binary clang-offload-bundler format from object \p
184+
/// Obj and return it in \p Bundles
185+
Error extractOffloadBundleFatBinary(
186+
const ObjectFile &Obj, SmallVectorImpl<OffloadBundleFatBin> &Bundles);
187+
188+
/// Extract code object memory from the given \p Source object file at \p Offset
189+
/// and of \p Size, and copy into \p OutputFileName.
190+
Error extractCodeObject(const ObjectFile &Source, int64_t Offset, int64_t Size,
191+
StringRef OutputFileName);
192+
193+
/// Extracts an Offload Bundle Entry given by URI
194+
Error extractOffloadBundleByURI(StringRef URIstr);
195+
196+
} // namespace object
197+
198+
} // namespace llvm
199+
#endif

0 commit comments

Comments
 (0)