Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions llvm/docs/CommandGuide/llvm-objcopy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ multiple file formats.
example, file and section symbols in ELF objects will not be discarded.
Additionally, remove all debug sections.

.. option:: --dump-offload-bundle=<URI>

Dump the HIP Offload Bundle entry specified by the URI syntax given, into a
code object file.

.. option:: --dump-section <section>=<file>

Dump the contents of section ``<section>`` into the file ``<file>``. Can be
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/ObjCopy/CommonConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ struct CommonConfig {
bool StripUnneeded = false;
bool Weaken = false;
bool DecompressDebugSections = false;
bool DumpOffloadBundle = false;
bool NeedPositional = true;

DebugCompressionType CompressionType = DebugCompressionType::None;

Expand Down
6 changes: 3 additions & 3 deletions llvm/include/llvm/Object/OffloadBundle.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ struct OffloadBundleURI {
OffsetStr.getAsInteger(10, O);
Str = Str.drop_front(OffsetStr.size());

if (Str.consume_front("&size="))
if (!Str.consume_front("&size="))
return createStringError(object_error::parse_failed,
"Reading 'size' in URI");

Expand All @@ -188,8 +188,8 @@ LLVM_ABI Error extractOffloadBundleFatBinary(

/// Extract code object memory from the given \p Source object file at \p Offset
/// and of \p Size, and copy into \p OutputFileName.
LLVM_ABI Error extractCodeObject(const ObjectFile &Source, int64_t Offset,
int64_t Size, StringRef OutputFileName);
LLVM_ABI Error extractCodeObject(const ObjectFile &Source, size_t Offset,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if the fixes in this file should be spun off into a separate PR?

size_t Size, StringRef OutputFileName);

/// Extracts an Offload Bundle Entry given by URI
LLVM_ABI Error extractOffloadBundleByURI(StringRef URIstr);
Expand Down
12 changes: 8 additions & 4 deletions llvm/lib/ObjCopy/ConfigManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ Expected<const COFFConfig &> ConfigManager::getCOFFConfig() const {
Common.DiscardMode == DiscardType::Locals ||
!Common.SymbolsToAdd.empty() || Common.GapFill != 0 ||
Common.PadTo != 0 || Common.ChangeSectionLMAValAll != 0 ||
!Common.ChangeSectionAddress.empty() || !Common.ExtractSection.empty())
!Common.ChangeSectionAddress.empty() || Common.DumpOffloadBundle ||
!Common.ExtractSection.empty())
return createStringError(llvm::errc::invalid_argument,
"option is not supported for COFF");

Expand All @@ -55,7 +56,8 @@ Expected<const MachOConfig &> ConfigManager::getMachOConfig() const {
Common.DiscardMode == DiscardType::Locals ||
!Common.SymbolsToAdd.empty() || Common.GapFill != 0 ||
Common.PadTo != 0 || Common.ChangeSectionLMAValAll != 0 ||
!Common.ChangeSectionAddress.empty() || !Common.ExtractSection.empty())
!Common.ChangeSectionAddress.empty() || Common.DumpOffloadBundle ||
!Common.ExtractSection.empty())
return createStringError(llvm::errc::invalid_argument,
"option is not supported for MachO");

Expand All @@ -76,7 +78,8 @@ Expected<const WasmConfig &> ConfigManager::getWasmConfig() const {
!Common.SetSectionFlags.empty() || !Common.SetSectionType.empty() ||
!Common.SymbolsToRename.empty() || Common.GapFill != 0 ||
Common.PadTo != 0 || Common.ChangeSectionLMAValAll != 0 ||
!Common.ChangeSectionAddress.empty() || !Common.ExtractSection.empty())
!Common.ChangeSectionAddress.empty() || Common.DumpOffloadBundle ||
!Common.ExtractSection.empty())
return createStringError(llvm::errc::invalid_argument,
"only flags for section dumping, removal, and "
"addition are supported");
Expand Down Expand Up @@ -106,7 +109,8 @@ Expected<const XCOFFConfig &> ConfigManager::getXCOFFConfig() const {
Common.Weaken || Common.StripUnneeded || Common.DecompressDebugSections ||
Common.GapFill != 0 || Common.PadTo != 0 ||
Common.ChangeSectionLMAValAll != 0 ||
!Common.ChangeSectionAddress.empty() || !Common.ExtractSection.empty()) {
!Common.ChangeSectionAddress.empty() || Common.DumpOffloadBundle ||
!Common.ExtractSection.empty()) {
return createStringError(
llvm::errc::invalid_argument,
"no flags are supported yet, only basic copying is allowed");
Expand Down
19 changes: 15 additions & 4 deletions llvm/lib/Object/OffloadBundle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ Error object::extractOffloadBundleFatBinary(
return Error::success();
}

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

Expand All @@ -211,12 +211,23 @@ Error object::extractCodeObject(const ObjectFile &Source, int64_t Offset,
if (Error Err = InputBuffOrErr.takeError())
return Err;

if (Size > InputBuffOrErr->getBufferSize())
return createStringError(inconvertibleErrorCode(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a createStringError overload that doesn't need the error code argument.

"size in URI is larger than source");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The LLVM style guide says that error messages should include additional relevant context. In this case, it could be something like the source size. Similar comments apply below.

if (Offset > InputBuffOrErr->getBufferSize())
return createStringError(inconvertibleErrorCode(),
"offset in URI is beyond the size of the source");
if (Offset + Size > InputBuffOrErr->getBufferSize())
return createStringError(
inconvertibleErrorCode(),
"offset + size in URI is beyond the size of the source");

std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr);
std::copy(InputBuffOrErr->getBufferStart() + Offset,
InputBuffOrErr->getBufferStart() + Offset + Size,
Buf->getBufferStart());
if (Error E = Buf->commit())
return E;
return createFileError(OutputFileName, std::move(E));

return Error::success();
}
Expand All @@ -238,7 +249,7 @@ Error object::extractOffloadBundleByURI(StringRef URIstr) {
// Create an ObjectFile object from uri.file_uri
auto ObjOrErr = ObjectFile::createObjectFile(Uri.FileName);
if (!ObjOrErr)
return ObjOrErr.takeError();
return createFileError(Uri.FileName, ObjOrErr.takeError());

auto Obj = ObjOrErr->getBinary();
if (Error Err =
Expand Down
73 changes: 73 additions & 0 deletions llvm/test/tools/llvm-objcopy/ELF/dump-offload-bundle.test

Large diffs are not rendered by default.

67 changes: 44 additions & 23 deletions llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include "llvm/ObjCopy/ConfigManager.h"
#include "llvm/ObjCopy/MachO/MachOConfig.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/OffloadBinary.h"
#include "llvm/Object/OffloadBundle.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/CRC.h"
Expand Down Expand Up @@ -284,6 +286,13 @@ static Expected<uint8_t> parseVisibilityType(StringRef VisType) {
return type;
}

Expected<StringRef> llvm::objcopy::parseDumpOffloadBundle(StringRef URI) {
if (Error Err = object::extractOffloadBundleByURI(URI))
return std::move(Err);

return URI;
}

namespace {
struct TargetInfo {
FileFormat Format;
Expand Down Expand Up @@ -729,34 +738,47 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> ArgsArr,

SmallVector<const char *, 2> Positional;

ConfigManager ConfigMgr;
CommonConfig &Config = ConfigMgr.Common;
COFFConfig &COFFConfig = ConfigMgr.COFF;
ELFConfig &ELFConfig = ConfigMgr.ELF;
MachOConfig &MachOConfig = ConfigMgr.MachO;

if (InputArgs.hasArg(OBJCOPY_dump_offload_bundle))
Config.NeedPositional = false;

for (auto *Arg : InputArgs.filtered(OBJCOPY_UNKNOWN))
return createStringError(errc::invalid_argument, "unknown argument '%s'",
Arg->getAsString(InputArgs).c_str());

for (auto *Arg : InputArgs.filtered(OBJCOPY_INPUT))
Positional.push_back(Arg->getValue());

if (Positional.empty())
if (Positional.empty() && Config.NeedPositional)
return createStringError(errc::invalid_argument, "no input file specified");

if (Positional.size() > 2)
if (Positional.size() > 2 && Config.NeedPositional)
return createStringError(errc::invalid_argument,
"too many positional arguments");

ConfigManager ConfigMgr;
CommonConfig &Config = ConfigMgr.Common;
COFFConfig &COFFConfig = ConfigMgr.COFF;
ELFConfig &ELFConfig = ConfigMgr.ELF;
MachOConfig &MachOConfig = ConfigMgr.MachO;
Config.InputFilename = Positional[0];
Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1];
if (InputArgs.hasArg(OBJCOPY_target) &&
(InputArgs.hasArg(OBJCOPY_input_target) ||
InputArgs.hasArg(OBJCOPY_output_target)))
return createStringError(
errc::invalid_argument,
"--target cannot be used with --input-target or --output-target");
if (Arg *A = InputArgs.getLastArg(OBJCOPY_dump_offload_bundle)) {
for (StringRef URIStr : llvm::split(A->getValue(), ",")) {
Expected<StringRef> res = llvm::objcopy::parseDumpOffloadBundle(URIStr);
if (!res)
return res.takeError();
}
}

if (Config.NeedPositional) {
Config.InputFilename = Positional[0];
Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1];
if (InputArgs.hasArg(OBJCOPY_target) &&
(InputArgs.hasArg(OBJCOPY_input_target) ||
InputArgs.hasArg(OBJCOPY_output_target)))
return createStringError(
errc::invalid_argument,
"--target cannot be used with --input-target or --output-target");
}
if (InputArgs.hasArg(OBJCOPY_regex) && InputArgs.hasArg(OBJCOPY_wildcard))
return createStringError(errc::invalid_argument,
"--regex and --wildcard are incompatible");
Expand Down Expand Up @@ -1427,9 +1449,9 @@ objcopy::parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) {
Arg->getAsString(InputArgs).c_str());
for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_INPUT))
Positional.push_back(Arg->getValue());
if (Positional.empty())
if (Positional.empty() && Config.NeedPositional)
return createStringError(errc::invalid_argument, "no input file specified");
if (Positional.size() > 1)
if (Positional.size() > 1 && Config.NeedPositional)
return createStringError(
errc::invalid_argument,
"llvm-install-name-tool expects a single input file");
Expand All @@ -1445,7 +1467,6 @@ objcopy::parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) {
return createStringError(errc::invalid_argument,
"input file: %s is not a Mach-O file",
Config.InputFilename.str().c_str());

DC.CopyConfigs.push_back(std::move(ConfigMgr));
return std::move(DC);
}
Expand Down Expand Up @@ -1552,6 +1573,11 @@ objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr,
exit(0);
}

ConfigManager ConfigMgr;
CommonConfig &Config = ConfigMgr.Common;
ELFConfig &ELFConfig = ConfigMgr.ELF;
MachOConfig &MachOConfig = ConfigMgr.MachO;

SmallVector<StringRef, 2> Positional;
for (auto *Arg : InputArgs.filtered(STRIP_UNKNOWN))
return createStringError(errc::invalid_argument, "unknown argument '%s'",
Expand All @@ -1568,11 +1594,6 @@ objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr,
errc::invalid_argument,
"multiple input files cannot be used in combination with -o");

ConfigManager ConfigMgr;
CommonConfig &Config = ConfigMgr.Common;
ELFConfig &ELFConfig = ConfigMgr.ELF;
MachOConfig &MachOConfig = ConfigMgr.MachO;

if (InputArgs.hasArg(STRIP_regex) && InputArgs.hasArg(STRIP_wildcard))
return createStringError(errc::invalid_argument,
"--regex and --wildcard are incompatible");
Expand Down
5 changes: 5 additions & 0 deletions llvm/tools/llvm-objcopy/ObjcopyOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr,
Expected<DriverConfig>
parseStripOptions(ArrayRef<const char *> ArgsArr,
llvm::function_ref<Error(Error)> ErrorCallback);

// parseDumpOffloadBundle reads a URI as a string and extracts the raw memory
// into a code object file named from the URI string given.
Expected<StringRef> parseDumpOffloadBundle(StringRef URI);

} // namespace objcopy
} // namespace llvm

Expand Down
3 changes: 3 additions & 0 deletions llvm/tools/llvm-objcopy/ObjcopyOpts.td
Original file line number Diff line number Diff line change
Expand Up @@ -235,10 +235,13 @@ defm skip_symbols
"be repeated to read symbols from many files">,
MetaVarName<"filename">;

defm dump_offload_bundle : Eq<"dump-offload-bundle", "Dump the contents specified by URI">;

defm dump_section
: Eq<"dump-section",
"Dump contents of section named <section> into file <file>">,
MetaVarName<"section=file">;

defm prefix_symbols
: Eq<"prefix-symbols", "Add <prefix> to the start of every symbol name">,
MetaVarName<"prefix">;
Expand Down
Loading