mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 12:43:36 +01:00
[tools] Introduce llvm-strip
llvm-strip is supposed to be a drop-in replacement for binutils strip. To start the ball rolling this diff adds the initial bits for llvm-strip, more features will be added incrementally over time. Test plan: make check-all Differential revision: https://reviews.llvm.org/D46407 llvm-svn: 331663
This commit is contained in:
parent
3e43e69679
commit
ebcba7c93c
@ -2,6 +2,14 @@
|
||||
# RUN: llvm-objcopy --strip-all %t %t2
|
||||
# RUN: llvm-readobj -file-headers -sections %t2 | FileCheck %s
|
||||
|
||||
# We run yaml2obj again rather than copy %t to avoid interfering
|
||||
# with llvm-objcopy's test (which potentially could have corrupted/updated the binary).
|
||||
|
||||
# RUN: yaml2obj %s > %t3
|
||||
# RUN: llvm-strip %t3
|
||||
# RUN: llvm-readobj -file-headers -sections %t3 | FileCheck %s
|
||||
# RUN: cmp %t2 %t3
|
||||
|
||||
!ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
|
@ -2,6 +2,16 @@
|
||||
# RUN: llvm-objcopy -strip-debug %t %t2
|
||||
# RUN: llvm-readobj -file-headers -sections -symbols %t2 | FileCheck %s
|
||||
|
||||
# We run yaml2obj again rather than copy %t to avoid interfering
|
||||
# with llvm-objcopy's test (which potentially could have corrupted/updated the binary).
|
||||
|
||||
# RUN: yaml2obj %s > %t3
|
||||
# RUN: llvm-strip -strip-debug %t3
|
||||
# RUN: llvm-readobj -file-headers -sections -symbols %t3 | FileCheck %s
|
||||
# RUN: cmp %t2 %t3
|
||||
|
||||
# RUN: not llvm-strip -strip-debug 2>&1 | FileCheck %s --check-prefix=NO-INPUT-FILES
|
||||
|
||||
!ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
@ -52,3 +62,5 @@ Symbols:
|
||||
# CHECK-NEXT: Section: .text
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: ]
|
||||
|
||||
# NO-INPUT-FILES: No input file specified
|
||||
|
@ -5,18 +5,25 @@ set(LLVM_LINK_COMPONENTS
|
||||
MC
|
||||
)
|
||||
|
||||
set(LLVM_TARGET_DEFINITIONS Opts.td)
|
||||
set(LLVM_TARGET_DEFINITIONS ObjcopyOpts.td)
|
||||
tablegen(LLVM ObjcopyOpts.inc -gen-opt-parser-defs)
|
||||
add_public_tablegen_target(ObjcopyOptsTableGen)
|
||||
|
||||
tablegen(LLVM Opts.inc -gen-opt-parser-defs)
|
||||
add_public_tablegen_target(ObjcopyTableGen)
|
||||
set(LLVM_TARGET_DEFINITIONS StripOpts.td)
|
||||
tablegen(LLVM StripOpts.inc -gen-opt-parser-defs)
|
||||
add_public_tablegen_target(StripOptsTableGen)
|
||||
|
||||
add_llvm_tool(llvm-objcopy
|
||||
llvm-objcopy.cpp
|
||||
Object.cpp
|
||||
DEPENDS
|
||||
ObjcopyTableGen
|
||||
ObjcopyOptsTableGen
|
||||
StripOptsTableGen
|
||||
)
|
||||
|
||||
add_llvm_tool_symlink(llvm-strip llvm-objcopy)
|
||||
|
||||
if(LLVM_INSTALL_BINUTILS_SYMLINKS)
|
||||
add_llvm_tool_symlink(objcopy llvm-objcopy)
|
||||
add_llvm_tool_symlink(strip llvm-objcopy)
|
||||
endif()
|
||||
|
12
tools/llvm-objcopy/StripOpts.td
Normal file
12
tools/llvm-objcopy/StripOpts.td
Normal file
@ -0,0 +1,12 @@
|
||||
include "llvm/Option/OptParser.td"
|
||||
|
||||
multiclass Eq<string name> {
|
||||
def NAME: Separate<["--", "-"], name>;
|
||||
def NAME # _eq: Joined<["--", "-"], name # "=">, Alias<!cast<Separate>(NAME)>;
|
||||
}
|
||||
|
||||
def help : Flag<["-", "--"], "help">;
|
||||
|
||||
def strip_debug : Flag<["-", "--"], "strip-debug">,
|
||||
HelpText<"Remove debugging symbols only">;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
#include "llvm/Support/FileOutputBuffer.h"
|
||||
#include "llvm/Support/InitLLVM.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
@ -45,17 +46,17 @@ using namespace ELF;
|
||||
|
||||
namespace {
|
||||
|
||||
enum ID {
|
||||
enum ObjcopyID {
|
||||
OBJCOPY_INVALID = 0, // This is not an option ID.
|
||||
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
|
||||
HELPTEXT, METAVAR, VALUES) \
|
||||
OBJCOPY_##ID,
|
||||
#include "Opts.inc"
|
||||
#include "ObjcopyOpts.inc"
|
||||
#undef OPTION
|
||||
};
|
||||
|
||||
#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
|
||||
#include "Opts.inc"
|
||||
#include "ObjcopyOpts.inc"
|
||||
#undef PREFIX
|
||||
|
||||
static const opt::OptTable::Info ObjcopyInfoTable[] = {
|
||||
@ -65,7 +66,7 @@ static const opt::OptTable::Info ObjcopyInfoTable[] = {
|
||||
METAVAR, OBJCOPY_##ID, opt::Option::KIND##Class, \
|
||||
PARAM, FLAGS, OBJCOPY_##GROUP, \
|
||||
OBJCOPY_##ALIAS, ALIASARGS, VALUES},
|
||||
#include "Opts.inc"
|
||||
#include "ObjcopyOpts.inc"
|
||||
#undef OPTION
|
||||
};
|
||||
|
||||
@ -74,6 +75,31 @@ public:
|
||||
ObjcopyOptTable() : OptTable(ObjcopyInfoTable, true) {}
|
||||
};
|
||||
|
||||
enum StripID {
|
||||
STRIP_INVALID = 0, // This is not an option ID.
|
||||
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
|
||||
HELPTEXT, METAVAR, VALUES) \
|
||||
STRIP_##ID,
|
||||
#include "StripOpts.inc"
|
||||
#undef OPTION
|
||||
};
|
||||
|
||||
static const opt::OptTable::Info StripInfoTable[] = {
|
||||
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
|
||||
HELPTEXT, METAVAR, VALUES) \
|
||||
{PREFIX, NAME, HELPTEXT, \
|
||||
METAVAR, STRIP_##ID, opt::Option::KIND##Class, \
|
||||
PARAM, FLAGS, STRIP_##GROUP, \
|
||||
STRIP_##ALIAS, ALIASARGS, VALUES},
|
||||
#include "StripOpts.inc"
|
||||
#undef OPTION
|
||||
};
|
||||
|
||||
class StripOptTable : public opt::OptTable {
|
||||
public:
|
||||
StripOptTable() : OptTable(StripInfoTable, true) {}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// The name this program was invoked as.
|
||||
@ -122,16 +148,16 @@ struct CopyConfig {
|
||||
std::vector<StringRef> SymbolsToGlobalize;
|
||||
std::vector<StringRef> SymbolsToWeaken;
|
||||
StringMap<StringRef> SymbolsToRename;
|
||||
bool StripAll;
|
||||
bool StripAllGNU;
|
||||
bool StripDebug;
|
||||
bool StripSections;
|
||||
bool StripNonAlloc;
|
||||
bool StripDWO;
|
||||
bool ExtractDWO;
|
||||
bool LocalizeHidden;
|
||||
bool Weaken;
|
||||
bool DiscardAll;
|
||||
bool StripAll = false;
|
||||
bool StripAllGNU = false;
|
||||
bool StripDebug = false;
|
||||
bool StripSections = false;
|
||||
bool StripNonAlloc = false;
|
||||
bool StripDWO = false;
|
||||
bool ExtractDWO = false;
|
||||
bool LocalizeHidden = false;
|
||||
bool Weaken = false;
|
||||
bool DiscardAll = false;
|
||||
};
|
||||
|
||||
using SectionPred = std::function<bool(const SectionBase &Sec)>;
|
||||
@ -449,10 +475,50 @@ CopyConfig ParseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
|
||||
return Config;
|
||||
}
|
||||
|
||||
// ParseStripOptions returns the config and sets the input arguments. If a
|
||||
// help flag is set then ParseStripOptions will print the help messege and
|
||||
// exit.
|
||||
CopyConfig ParseStripOptions(ArrayRef<const char *> ArgsArr) {
|
||||
StripOptTable T;
|
||||
unsigned MissingArgumentIndex, MissingArgumentCount;
|
||||
llvm::opt::InputArgList InputArgs =
|
||||
T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
|
||||
|
||||
if (InputArgs.size() == 0 || InputArgs.hasArg(STRIP_help)) {
|
||||
T.PrintHelp(outs(), "llvm-strip <input> [ <output> ]", "strip tool");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
SmallVector<const char *, 2> Positional;
|
||||
for (auto Arg : InputArgs.filtered(STRIP_UNKNOWN))
|
||||
error("unknown argument '" + Arg->getAsString(InputArgs) + "'");
|
||||
for (auto Arg : InputArgs.filtered(STRIP_INPUT))
|
||||
Positional.push_back(Arg->getValue());
|
||||
|
||||
if (Positional.empty())
|
||||
error("No input file specified");
|
||||
|
||||
if (Positional.size() > 2)
|
||||
error("Support for multiple input files is not implemented yet");
|
||||
|
||||
CopyConfig Config;
|
||||
Config.InputFilename = Positional[0];
|
||||
Config.OutputFilename = Positional[0];
|
||||
|
||||
// Strip debug info only.
|
||||
Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug);
|
||||
if (!Config.StripDebug)
|
||||
Config.StripAll = true;
|
||||
return Config;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
InitLLVM X(argc, argv);
|
||||
ToolName = argv[0];
|
||||
|
||||
CopyConfig Config = ParseObjcopyOptions(makeArrayRef(argv + 1, argc));
|
||||
CopyConfig Config;
|
||||
if (sys::path::stem(ToolName).endswith_lower("strip"))
|
||||
Config = ParseStripOptions(makeArrayRef(argv + 1, argc));
|
||||
else
|
||||
Config = ParseObjcopyOptions(makeArrayRef(argv + 1, argc));
|
||||
ExecuteElfObjcopy(Config);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user