diff options
author | Petr Hosek <phosek@chromium.org> | 2017-07-22 02:33:45 +0000 |
---|---|---|
committer | Petr Hosek <phosek@chromium.org> | 2017-07-22 02:33:45 +0000 |
commit | badc76623c8a7d678739815b7c759edcab83e2fe (patch) | |
tree | 25aa8e6454ad729cbe4ed95216ff7f7cb2994795 /llvm/tools/llvm-objcopy/llvm-objcopy.cpp | |
parent | d4abe9e7d36623fdc41b7852d92f04ee7da312bf (diff) | |
download | bcm5719-llvm-badc76623c8a7d678739815b7c759edcab83e2fe.tar.gz bcm5719-llvm-badc76623c8a7d678739815b7c759edcab83e2fe.zip |
Reland "[LLVM][llvm-objcopy] Added basic plumbing to get things started"
As discussed on llvm-dev I've implemented the first basic steps towards
llvm-objcopy/llvm-objtool (name pending).
This change adds the ability to copy (without modification) 64-bit
little endian ELF executables that have SHT_PROGBITS, SHT_NOBITS,
SHT_NULL and SHT_STRTAB sections.
Patch by Jake Ehrlich
Differential Revision: https://reviews.llvm.org/D33964
llvm-svn: 308821
Diffstat (limited to 'llvm/tools/llvm-objcopy/llvm-objcopy.cpp')
-rw-r--r-- | llvm/tools/llvm-objcopy/llvm-objcopy.cpp | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp new file mode 100644 index 00000000000..342ef36fc30 --- /dev/null +++ b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp @@ -0,0 +1,99 @@ +//===- llvm-objcopy.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "llvm-objcopy.h" +#include "Object.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileOutputBuffer.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/ToolOutputFile.h" + +#include <memory> +#include <string> +#include <system_error> + +using namespace llvm; +using namespace object; +using namespace ELF; + +// The name this program was invoked as. +static StringRef ToolName; + +namespace llvm { + +LLVM_ATTRIBUTE_NORETURN void error(Twine Message) { + errs() << ToolName << ": " << Message << ".\n"; + errs().flush(); + exit(1); +} + +LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, std::error_code EC) { + assert(EC); + errs() << ToolName << ": '" << File << "': " << EC.message() << ".\n"; + exit(1); +} + +LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, llvm::Error E) { + assert(E); + std::string Buf; + raw_string_ostream OS(Buf); + logAllUnhandledErrors(std::move(E), OS, ""); + OS.flush(); + errs() << ToolName << ": '" << File << "': " << Buf; + exit(1); +} +} + +cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input>")); +cl::opt<std::string> OutputFilename(cl::Positional, cl::desc("<output>"), + cl::init("-")); + +void CopyBinary(const ELFObjectFile<ELF64LE> &ObjFile) { + std::unique_ptr<FileOutputBuffer> Buffer; + Object<ELF64LE> Obj{ObjFile}; + Obj.finalize(); + ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr = + FileOutputBuffer::create(OutputFilename, Obj.totalSize(), + FileOutputBuffer::F_executable); + if (BufferOrErr.getError()) + error("failed to open " + OutputFilename); + else + Buffer = std::move(*BufferOrErr); + std::error_code EC; + std::unique_ptr<tool_output_file> Out = + make_unique<tool_output_file>(OutputFilename.data(), EC, sys::fs::F_None); + if (EC) + report_fatal_error(EC.message()); + Obj.write(*Buffer); + if (auto EC = Buffer->commit()) + reportError(OutputFilename, EC); + Out->keep(); +} + +int main(int argc, char **argv) { + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(argv[0]); + PrettyStackTraceProgram X(argc, argv); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + cl::ParseCommandLineOptions(argc, argv, "llvm objcopy utility\n"); + ToolName = argv[0]; + if (InputFilename.empty()) { + cl::PrintHelpMessage(); + return 2; + } + Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(InputFilename); + if (!BinaryOrErr) + reportError(InputFilename, BinaryOrErr.takeError()); + Binary &Binary = *BinaryOrErr.get().getBinary(); + if (ELFObjectFile<ELF64LE> *o = dyn_cast<ELFObjectFile<ELF64LE>>(&Binary)) { + CopyBinary(*o); + return 0; + } + reportError(InputFilename, object_error::invalid_file_type); +} |