mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
ab809dc2fa
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
133 lines
4.3 KiB
C++
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);
|
|
}
|