blob: 09edc4c3327224e67066e03edf515a2ef2079812 [file] [log] [blame]
Petr Hosek05a04cb2017-08-01 00:33:58 +00001//===- llvm-objcopy.cpp -----------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#include "llvm-objcopy.h"
10#include "Object.h"
11#include "llvm/Support/CommandLine.h"
12#include "llvm/Support/FileOutputBuffer.h"
13#include "llvm/Support/PrettyStackTrace.h"
14#include "llvm/Support/Signals.h"
15#include "llvm/Support/ToolOutputFile.h"
16
17#include <memory>
18#include <string>
19#include <system_error>
20
21using namespace llvm;
22using namespace object;
23using namespace ELF;
24
25// The name this program was invoked as.
26static StringRef ToolName;
27
28namespace llvm {
29
30LLVM_ATTRIBUTE_NORETURN void error(Twine Message) {
31 errs() << ToolName << ": " << Message << ".\n";
32 errs().flush();
33 exit(1);
34}
35
36LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, std::error_code EC) {
37 assert(EC);
38 errs() << ToolName << ": '" << File << "': " << EC.message() << ".\n";
39 exit(1);
40}
41
42LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, llvm::Error E) {
43 assert(E);
44 std::string Buf;
45 raw_string_ostream OS(Buf);
46 logAllUnhandledErrors(std::move(E), OS, "");
47 OS.flush();
48 errs() << ToolName << ": '" << File << "': " << Buf;
49 exit(1);
50}
51}
52
53cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input>"));
54cl::opt<std::string> OutputFilename(cl::Positional, cl::desc("<output>"),
55 cl::init("-"));
56
57void CopyBinary(const ELFObjectFile<ELF64LE> &ObjFile) {
58 std::unique_ptr<FileOutputBuffer> Buffer;
Petr Hosekb1bb3e52017-08-04 05:33:44 +000059 Object<ELF64LE> Obj{ObjFile};
60 Obj.finalize();
Petr Hosek05a04cb2017-08-01 00:33:58 +000061 ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
Petr Hosekb1bb3e52017-08-04 05:33:44 +000062 FileOutputBuffer::create(OutputFilename, Obj.totalSize(),
Petr Hosek05a04cb2017-08-01 00:33:58 +000063 FileOutputBuffer::F_executable);
64 if (BufferOrErr.getError())
65 error("failed to open " + OutputFilename);
66 else
67 Buffer = std::move(*BufferOrErr);
68 std::error_code EC;
69 if (EC)
70 report_fatal_error(EC.message());
Petr Hosekb1bb3e52017-08-04 05:33:44 +000071 Obj.write(*Buffer);
Petr Hosek05a04cb2017-08-01 00:33:58 +000072 if (auto EC = Buffer->commit())
73 reportError(OutputFilename, EC);
74}
75
76int main(int argc, char **argv) {
77 // Print a stack trace if we signal out.
78 sys::PrintStackTraceOnErrorSignal(argv[0]);
79 PrettyStackTraceProgram X(argc, argv);
80 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
81 cl::ParseCommandLineOptions(argc, argv, "llvm objcopy utility\n");
82 ToolName = argv[0];
83 if (InputFilename.empty()) {
84 cl::PrintHelpMessage();
85 return 2;
86 }
87 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(InputFilename);
88 if (!BinaryOrErr)
89 reportError(InputFilename, BinaryOrErr.takeError());
90 Binary &Binary = *BinaryOrErr.get().getBinary();
91 if (ELFObjectFile<ELF64LE> *o = dyn_cast<ELFObjectFile<ELF64LE>>(&Binary)) {
92 CopyBinary(*o);
93 return 0;
94 }
95 reportError(InputFilename, object_error::invalid_file_type);
96}