Skip to content

Commit 4491674

Browse files
author
dsalinas_amdeng
committed
Add llvm-extract-bundle-entry to extend llvm-objcopy
This commit creates llvm-extract-bundle-entry as a wrapper to llvm-objcopy, to allow extracting HIP offload fatbin bundles given a URI argument.
1 parent 45bb926 commit 4491674

File tree

8 files changed

+234
-10
lines changed

8 files changed

+234
-10
lines changed

llvm/include/llvm/Object/OffloadBundle.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,8 @@ LLVM_ABI Error extractOffloadBundleFatBinary(
210210

211211
/// Extract code object memory from the given \p Source object file at \p Offset
212212
/// and of \p Size, and copy into \p OutputFileName.
213-
LLVM_ABI Error extractCodeObject(const ObjectFile &Source, int64_t Offset,
214-
int64_t Size, StringRef OutputFileName);
213+
LLVM_ABI Error extractCodeObject(const ObjectFile &Source, size_t Offset,
214+
size_t Size, StringRef OutputFileName);
215215

216216
/// Extract code object memory from the given \p Source object file at \p Offset
217217
/// and of \p Size, and copy into \p OutputFileName.

llvm/lib/Object/OffloadBundle.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -217,24 +217,37 @@ Error object::extractOffloadBundleFatBinary(
217217
return Error::success();
218218
}
219219

220-
Error object::extractCodeObject(const ObjectFile &Source, int64_t Offset,
221-
int64_t Size, StringRef OutputFileName) {
220+
Error object::extractCodeObject(const ObjectFile &Source, size_t Offset,
221+
size_t Size, StringRef OutputFileName) {
222222
Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
223223
FileOutputBuffer::create(OutputFileName, Size);
224224

225-
if (!BufferOrErr)
226-
return BufferOrErr.takeError();
225+
if (auto EC = BufferOrErr.takeError())
226+
return EC;
227227

228228
Expected<MemoryBufferRef> InputBuffOrErr = Source.getMemoryBufferRef();
229229
if (Error Err = InputBuffOrErr.takeError())
230-
return Err;
230+
return createFileError(OutputFileName, std::move(Err));
231+
;
232+
233+
if (Size > InputBuffOrErr->getBufferSize())
234+
return createStringError("size in URI is larger than source");
235+
236+
if (Offset > InputBuffOrErr->getBufferSize())
237+
return createStringError(inconvertibleErrorCode(),
238+
"offset in URI is beyond the size of the source");
239+
240+
if (Offset + Size > InputBuffOrErr->getBufferSize())
241+
return createStringError(
242+
inconvertibleErrorCode(),
243+
"offset + size in URI is beyond the size of the source");
231244

232245
std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr);
233246
std::copy(InputBuffOrErr->getBufferStart() + Offset,
234247
InputBuffOrErr->getBufferStart() + Offset + Size,
235248
Buf->getBufferStart());
236249
if (Error E = Buf->commit())
237-
return E;
250+
return createFileError(OutputFileName, std::move(E));
238251

239252
return Error::success();
240253
}
@@ -259,6 +272,7 @@ Error object::extractOffloadBundleByURI(StringRef URIstr) {
259272
// create a URI object
260273
Expected<std::unique_ptr<OffloadBundleURI>> UriOrErr(
261274
OffloadBundleURI::createOffloadBundleURI(URIstr, FILE_URI));
275+
262276
if (!UriOrErr)
263277
return UriOrErr.takeError();
264278

@@ -275,7 +289,7 @@ Error object::extractOffloadBundleByURI(StringRef URIstr) {
275289
auto Obj = ObjOrErr->getBinary();
276290
if (Error Err =
277291
object::extractCodeObject(*Obj, Uri.Offset, Uri.Size, OutputFile))
278-
return Err;
292+
return createFileError(Uri.FileName, std::move(Err));
279293

280294
return Error::success();
281295
}

llvm/test/tools/llvm-objcopy/extract-bundle-entry.test

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

llvm/tools/llvm-objcopy/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ set(LLVM_TARGET_DEFINITIONS StripOpts.td)
2424
tablegen(LLVM StripOpts.inc -gen-opt-parser-defs)
2525
add_public_tablegen_target(StripOptsTableGen)
2626

27+
set(LLVM_TARGET_DEFINITIONS ExtractBundleEntryOpts.td)
28+
tablegen(LLVM ExtractBundleEntryOpts.inc -gen-opt-parser-defs)
29+
add_public_tablegen_target(ExtractBundleEntryOptsTableGen)
30+
2731
add_llvm_tool(llvm-objcopy
2832
ObjcopyOptions.cpp
2933
llvm-objcopy.cpp
@@ -37,10 +41,12 @@ add_llvm_tool(llvm-objcopy
3741
add_llvm_tool_symlink(llvm-install-name-tool llvm-objcopy)
3842
add_llvm_tool_symlink(llvm-bitcode-strip llvm-objcopy)
3943
add_llvm_tool_symlink(llvm-strip llvm-objcopy)
44+
add_llvm_tool_symlink(llvm-extract-bundle-entry llvm-objcopy)
4045

4146
if(LLVM_INSTALL_BINUTILS_SYMLINKS)
4247
add_llvm_tool_symlink(objcopy llvm-objcopy)
4348
add_llvm_tool_symlink(strip llvm-objcopy)
49+
add_llvm_tool_symlink(extract-bundle-entry llvm-objcopy)
4450
endif()
4551

4652
if(LLVM_INSTALL_CCTOOLS_SYMLINKS)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//===-- ExtractBundleEntryOpts.td - llvm-bitcode-strip options ---------------*-===//
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 describes the command line options of llvm-extract-offload-entry.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
include "llvm/Option/OptParser.td"
14+
15+
def help : Flag<["--"], "Help">,
16+
HelpText<"URIs can be read from STDIN, one per line.\n"
17+
"From the URIs specified, extracts code objects into files named:\n"
18+
"\t<executable_name>-[pid<number>]-offset<number>-size<number>.co\n\n"
19+
"URI syntax:\n"
20+
"\tcode_object_uri ::== file_uri | memory_uri\n"
21+
"\tfile_uri ::== \"file://\" extract_file [ range_specifier ] \n"
22+
"\tmemory_uri ::== \"memory://\" process_id range_specifier\n"
23+
"\trange_specifier ::== range_delimiter range_attribute [\"&\" range_attribute]\n"
24+
"\trange_delimiter ::== \"#\" | \"?\"\n"
25+
"\trange_attribute ::== [\"offset=\" number | \"size=\" number ]\n"
26+
"\textract_file ::== URI_ENCODED_OS_FILE_PATH\n"
27+
"\tprocess_id ::== DECIMAL_NUMBER\n"
28+
"\tnumber ::== HEX_NUMBER | DECIMAL_NUMBER | OCTAL_NUMBER\n"
29+
"\nExample: file://dir1/dir2/hello_world#offset=133&size=14472 \n"
30+
" memory://1234#offset=0x20000&size=3000\n">;
31+
def h : Flag<["-"], "h">, Alias<help>;

llvm/tools/llvm-objcopy/ObjcopyOptions.cpp

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "llvm/ObjCopy/ConfigManager.h"
1717
#include "llvm/ObjCopy/MachO/MachOConfig.h"
1818
#include "llvm/Object/Binary.h"
19+
#include "llvm/Object/OffloadBundle.h"
1920
#include "llvm/Option/Arg.h"
2021
#include "llvm/Option/ArgList.h"
2122
#include "llvm/Support/CRC.h"
@@ -164,6 +165,41 @@ class StripOptTable : public opt::GenericOptTable {
164165
}
165166
};
166167

168+
enum ExtractBundleEntryID {
169+
EXTRACT_BUNDLE_ENTRY_INVALID = 0, // This is not an option ID.
170+
#define OPTION(...) \
171+
LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(EXTRACT_BUNDLE_ENTRY_, __VA_ARGS__),
172+
#include "ExtractBundleEntryOpts.inc"
173+
#undef OPTION
174+
};
175+
176+
namespace extract_bundle_entry {
177+
#define OPTTABLE_STR_TABLE_CODE
178+
#include "ExtractBundleEntryOpts.inc"
179+
#undef OPTTABLE_STR_TABLE_CODE
180+
181+
#define OPTTABLE_PREFIXES_TABLE_CODE
182+
#include "ExtractBundleEntryOpts.inc"
183+
#undef OPTTABLE_PREFIXES_TABLE_CODE
184+
185+
static constexpr opt::OptTable::Info ExtractBundleEntryInfoTable[] = {
186+
#define OPTION(...) \
187+
LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(EXTRACT_BUNDLE_ENTRY_, __VA_ARGS__),
188+
#include "ExtractBundleEntryOpts.inc"
189+
#undef OPTION
190+
};
191+
} // namespace extract_bundle_entry
192+
193+
class ExtractBundleEntryOptTable : public opt::GenericOptTable {
194+
public:
195+
ExtractBundleEntryOptTable()
196+
: GenericOptTable(extract_bundle_entry::OptionStrTable,
197+
extract_bundle_entry::OptionPrefixesTable,
198+
extract_bundle_entry::ExtractBundleEntryInfoTable) {
199+
setGroupedShortOptions(true);
200+
}
201+
};
202+
167203
} // namespace
168204

169205
static SectionFlag parseSectionRenameFlag(StringRef SectionName) {
@@ -418,7 +454,13 @@ template <class T> static ErrorOr<T> getAsInteger(StringRef Val) {
418454

419455
namespace {
420456

421-
enum class ToolType { Objcopy, Strip, InstallNameTool, BitcodeStrip };
457+
enum class ToolType {
458+
Objcopy,
459+
Strip,
460+
InstallNameTool,
461+
BitcodeStrip,
462+
ExtractBundleEntry
463+
};
422464

423465
} // anonymous namespace
424466

@@ -442,6 +484,10 @@ static void printHelp(const opt::OptTable &OptTable, raw_ostream &OS,
442484
ToolName = "llvm-bitcode-strip";
443485
HelpText = " [options] input";
444486
break;
487+
case ToolType::ExtractBundleEntry:
488+
ToolName = "llvm-extract-bundle-entry";
489+
HelpText = " URI";
490+
break;
445491
}
446492
OptTable.printHelp(OS, (ToolName + HelpText).str().c_str(),
447493
(ToolName + " tool").str().c_str());
@@ -1670,3 +1716,44 @@ objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr,
16701716

16711717
return std::move(DC);
16721718
}
1719+
1720+
Expected<DriverConfig> objcopy::parseExtractBundleEntryOptions(
1721+
ArrayRef<const char *> ArgsArr, function_ref<Error(Error)> ErrorCallback) {
1722+
1723+
DriverConfig DC;
1724+
ConfigManager ConfigMgr;
1725+
CommonConfig &Config = ConfigMgr.Common;
1726+
MachOConfig &MachOConfig = ConfigMgr.MachO;
1727+
1728+
ExtractBundleEntryOptTable T;
1729+
unsigned MissingArgumentIndex, MissingArgumentCount;
1730+
opt::InputArgList InputArgs =
1731+
T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
1732+
1733+
if (InputArgs.size() == 0) {
1734+
printHelp(T, errs(), ToolType::ExtractBundleEntry);
1735+
exit(1);
1736+
}
1737+
1738+
if (InputArgs.hasArg(EXTRACT_BUNDLE_ENTRY_help)) {
1739+
printHelp(T, outs(), ToolType::ExtractBundleEntry);
1740+
exit(0);
1741+
}
1742+
1743+
for (auto *Arg : InputArgs.filtered(EXTRACT_BUNDLE_ENTRY_UNKNOWN))
1744+
return createStringError(errc::invalid_argument, "unknown argument '%s'",
1745+
Arg->getAsString(InputArgs).c_str());
1746+
1747+
SmallVector<StringRef, 256> Positional;
1748+
1749+
for (auto *Arg : InputArgs.filtered(EXTRACT_BUNDLE_ENTRY_INPUT))
1750+
Positional.push_back(Arg->getValue());
1751+
assert(!Positional.empty());
1752+
1753+
// iterate over all input arguments
1754+
for (auto input : Positional)
1755+
if (Error Err = object::extractOffloadBundleByURI(input))
1756+
return std::move(Err);
1757+
1758+
return std::move(DC);
1759+
}

llvm/tools/llvm-objcopy/ObjcopyOptions.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@ parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr,
5151
Expected<DriverConfig>
5252
parseStripOptions(ArrayRef<const char *> ArgsArr,
5353
llvm::function_ref<Error(Error)> ErrorCallback);
54+
55+
// ParseExtractBundleEntryOptions returns the config and sets the input
56+
// arguments. If a help flag is set then ParseExtractBundleEntryOptions will
57+
// print the help messege and exit. ErrorCallback is used to handle recoverable
58+
// errors. An Error returned by the callback aborts the parsing and is then
59+
// returned by this function.
60+
Expected<DriverConfig>
61+
parseExtractBundleEntryOptions(ArrayRef<const char *> ArgsArr,
62+
llvm::function_ref<Error(Error)> ErrorCallback);
63+
5464
} // namespace objcopy
5565
} // namespace llvm
5666

llvm/tools/llvm-objcopy/llvm-objcopy.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ static Expected<DriverConfig> getDriverConfig(ArrayRef<const char *> Args) {
7777
return parseStripOptions(Args, reportWarning);
7878
else if (Is("install-name-tool") || Is("install_name_tool"))
7979
return parseInstallNameToolOptions(Args);
80+
else if (Is("llvm-extract-bundle-entry"))
81+
return parseExtractBundleEntryOptions(Args, reportWarning);
8082
else
8183
return parseObjcopyOptions(Args, reportWarning);
8284
}

0 commit comments

Comments
 (0)