1 //===- 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 21 using namespace llvm; 22 using namespace object; 23 using namespace ELF; 24 25 // The name this program was invoked as. 26 static StringRef ToolName; 27 28 namespace llvm { 29 30 LLVM_ATTRIBUTE_NORETURN void error(Twine Message) { 31 errs() << ToolName << ": " << Message << ".\n"; 32 errs().flush(); 33 exit(1); 34 } 35 36 LLVM_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 42 LLVM_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 53 cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input>")); 54 cl::opt<std::string> OutputFilename(cl::Positional, cl::desc("<output>"), 55 cl::init("-")); 56 57 void CopyBinary(const ELFObjectFile<ELF64LE> &ObjFile) { 58 std::unique_ptr<FileOutputBuffer> Buffer; 59 Object<ELF64LE> Obj{ObjFile}; 60 Obj.finalize(); 61 ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr = 62 FileOutputBuffer::create(OutputFilename, Obj.totalSize(), 63 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()); 71 Obj.write(*Buffer); 72 if (auto EC = Buffer->commit()) 73 reportError(OutputFilename, EC); 74 } 75 76 int 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 } 97