1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 11:13:28 +01:00
llvm-mirror/tools/llvm-objcopy/llvm-objcopy.cpp
Zachary Turner ab809dc2fa [ADT] Make Twine's copy constructor private.
There's a lot of misuse of Twine scattered around LLVM.  This
ranges in severity from benign (returning a Twine from a function
by value that is just a string literal) to pretty sketchy (storing
a Twine by value in a class).  While there are some uses for
copying Twines, most of the very compelling ones are confined
to the Twine class implementation itself, and other uses are
either dubious or easily worked around.

This patch makes Twine's copy constructor private, and fixes up
all callsites.

Differential Revision: https://reviews.llvm.org/D38767

llvm-svn: 315530
2017-10-11 23:33:06 +00:00

133 lines
4.3 KiB
C++

//===- 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(const 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("-"));
cl::opt<std::string>
OutputFormat("O", cl::desc("set output format to one of the following:"
"\n\tbinary"));
cl::list<std::string> ToRemove("remove-section",
cl::desc("Remove a specific section"));
cl::alias ToRemoveA("R", cl::desc("Alias for remove-section"),
cl::aliasopt(ToRemove));
cl::opt<bool> StripSections("strip-sections",
cl::desc("Remove all section headers"));
typedef std::function<bool(const SectionBase &Sec)> SectionPred;
void CopyBinary(const ELFObjectFile<ELF64LE> &ObjFile) {
std::unique_ptr<FileOutputBuffer> Buffer;
std::unique_ptr<Object<ELF64LE>> Obj;
if (!OutputFormat.empty() && OutputFormat != "binary")
error("invalid output format '" + OutputFormat + "'");
if (!OutputFormat.empty() && OutputFormat == "binary")
Obj = llvm::make_unique<BinaryObject<ELF64LE>>(ObjFile);
else
Obj = llvm::make_unique<ELFObject<ELF64LE>>(ObjFile);
SectionPred RemovePred = [](const SectionBase &) { return false; };
if (!ToRemove.empty()) {
RemovePred = [&](const SectionBase &Sec) {
return std::find(std::begin(ToRemove), std::end(ToRemove), Sec.Name) !=
std::end(ToRemove);
};
}
if (StripSections) {
RemovePred = [RemovePred](const SectionBase &Sec) {
return RemovePred(Sec) || (Sec.Flags & SHF_ALLOC) == 0;
};
Obj->WriteSectionHeaders = false;
}
Obj->removeSections(RemovePred);
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;
if (EC)
report_fatal_error(EC.message());
Obj->write(*Buffer);
if (auto EC = Buffer->commit())
reportError(OutputFilename, EC);
}
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);
}