//===- 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 #include #include 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 InputFilename(cl::Positional, cl::desc("")); cl::opt OutputFilename(cl::Positional, cl::desc(""), cl::init("-")); void CopyBinary(const ELFObjectFile &ObjFile) { std::unique_ptr Buffer; Object Obj{ObjFile}; Obj.finalize(); ErrorOr> BufferOrErr = FileOutputBuffer::create(OutputFilename, Obj.totalSize(), FileOutputBuffer::F_executable); if (auto EC = BufferOrErr.getError()) error("failed to open " + OutputFilename); else Buffer = std::move(*BufferOrErr); std::error_code EC; std::unique_ptr Out = make_unique(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> BinaryOrErr = createBinary(InputFilename); if (!BinaryOrErr) reportError(InputFilename, BinaryOrErr.takeError()); Binary &Binary = *BinaryOrErr.get().getBinary(); if (ELFObjectFile *o = dyn_cast>(&Binary)) { CopyBinary(*o); return 0; } reportError(InputFilename, object_error::invalid_file_type); }