blob: 9b233951b8d32c313230e28d4d8617fe433e6380 [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("-"));
Petr Hosekc4df10e2017-08-04 21:09:26 +000056cl::opt<std::string>
57 OutputFormat("O", cl::desc("set output format to one of the following:"
58 "\n\tbinary"));
Petr Hosek05a04cb2017-08-01 00:33:58 +000059
60void CopyBinary(const ELFObjectFile<ELF64LE> &ObjFile) {
61 std::unique_ptr<FileOutputBuffer> Buffer;
Petr Hosekc4df10e2017-08-04 21:09:26 +000062 std::unique_ptr<Object<ELF64LE>> Obj;
63 if (!OutputFormat.empty() && OutputFormat != "binary")
64 error("invalid output format '" + OutputFormat + "'");
Jake Ehrlichc5ff7272017-10-10 18:32:22 +000065
Petr Hosekc4df10e2017-08-04 21:09:26 +000066 if (!OutputFormat.empty() && OutputFormat == "binary")
67 Obj = llvm::make_unique<BinaryObject<ELF64LE>>(ObjFile);
68 else
69 Obj = llvm::make_unique<ELFObject<ELF64LE>>(ObjFile);
70 Obj->finalize();
Petr Hosek05a04cb2017-08-01 00:33:58 +000071 ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
Petr Hosekc4df10e2017-08-04 21:09:26 +000072 FileOutputBuffer::create(OutputFilename, Obj->totalSize(),
Petr Hosek05a04cb2017-08-01 00:33:58 +000073 FileOutputBuffer::F_executable);
74 if (BufferOrErr.getError())
75 error("failed to open " + OutputFilename);
76 else
77 Buffer = std::move(*BufferOrErr);
78 std::error_code EC;
79 if (EC)
80 report_fatal_error(EC.message());
Petr Hosekc4df10e2017-08-04 21:09:26 +000081 Obj->write(*Buffer);
Petr Hosek05a04cb2017-08-01 00:33:58 +000082 if (auto EC = Buffer->commit())
83 reportError(OutputFilename, EC);
84}
85
86int main(int argc, char **argv) {
87 // Print a stack trace if we signal out.
88 sys::PrintStackTraceOnErrorSignal(argv[0]);
89 PrettyStackTraceProgram X(argc, argv);
90 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
91 cl::ParseCommandLineOptions(argc, argv, "llvm objcopy utility\n");
92 ToolName = argv[0];
93 if (InputFilename.empty()) {
94 cl::PrintHelpMessage();
95 return 2;
96 }
97 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(InputFilename);
98 if (!BinaryOrErr)
99 reportError(InputFilename, BinaryOrErr.takeError());
100 Binary &Binary = *BinaryOrErr.get().getBinary();
101 if (ELFObjectFile<ELF64LE> *o = dyn_cast<ELFObjectFile<ELF64LE>>(&Binary)) {
102 CopyBinary(*o);
103 return 0;
104 }
105 reportError(InputFilename, object_error::invalid_file_type);
106}