Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit 409ea28

Browse files
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@331663 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent c9a3110 commit 409ea28

File tree

6 files changed

+125
-20
lines changed

6 files changed

+125
-20
lines changed

test/tools/llvm-objcopy/strip-all.test

+8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22
# RUN: llvm-objcopy --strip-all %t %t2
33
# RUN: llvm-readobj -file-headers -sections %t2 | FileCheck %s
44

5+
# We run yaml2obj again rather than copy %t to avoid interfering
6+
# with llvm-objcopy's test (which potentially could have corrupted/updated the binary).
7+
8+
# RUN: yaml2obj %s > %t3
9+
# RUN: llvm-strip %t3
10+
# RUN: llvm-readobj -file-headers -sections %t3 | FileCheck %s
11+
# RUN: cmp %t2 %t3
12+
513
!ELF
614
FileHeader:
715
Class: ELFCLASS64

test/tools/llvm-objcopy/strip-debug.test

+12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22
# RUN: llvm-objcopy -strip-debug %t %t2
33
# RUN: llvm-readobj -file-headers -sections -symbols %t2 | FileCheck %s
44

5+
# We run yaml2obj again rather than copy %t to avoid interfering
6+
# with llvm-objcopy's test (which potentially could have corrupted/updated the binary).
7+
8+
# RUN: yaml2obj %s > %t3
9+
# RUN: llvm-strip -strip-debug %t3
10+
# RUN: llvm-readobj -file-headers -sections -symbols %t3 | FileCheck %s
11+
# RUN: cmp %t2 %t3
12+
13+
# RUN: not llvm-strip -strip-debug 2>&1 | FileCheck %s --check-prefix=NO-INPUT-FILES
14+
515
!ELF
616
FileHeader:
717
Class: ELFCLASS64
@@ -52,3 +62,5 @@ Symbols:
5262
# CHECK-NEXT: Section: .text
5363
# CHECK-NEXT: }
5464
# CHECK-NEXT: ]
65+
66+
# NO-INPUT-FILES: No input file specified

tools/llvm-objcopy/CMakeLists.txt

+11-4
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,25 @@ set(LLVM_LINK_COMPONENTS
55
MC
66
)
77

8-
set(LLVM_TARGET_DEFINITIONS Opts.td)
8+
set(LLVM_TARGET_DEFINITIONS ObjcopyOpts.td)
9+
tablegen(LLVM ObjcopyOpts.inc -gen-opt-parser-defs)
10+
add_public_tablegen_target(ObjcopyOptsTableGen)
911

10-
tablegen(LLVM Opts.inc -gen-opt-parser-defs)
11-
add_public_tablegen_target(ObjcopyTableGen)
12+
set(LLVM_TARGET_DEFINITIONS StripOpts.td)
13+
tablegen(LLVM StripOpts.inc -gen-opt-parser-defs)
14+
add_public_tablegen_target(StripOptsTableGen)
1215

1316
add_llvm_tool(llvm-objcopy
1417
llvm-objcopy.cpp
1518
Object.cpp
1619
DEPENDS
17-
ObjcopyTableGen
20+
ObjcopyOptsTableGen
21+
StripOptsTableGen
1822
)
1923

24+
add_llvm_tool_symlink(llvm-strip llvm-objcopy)
25+
2026
if(LLVM_INSTALL_BINUTILS_SYMLINKS)
2127
add_llvm_tool_symlink(objcopy llvm-objcopy)
28+
add_llvm_tool_symlink(strip llvm-objcopy)
2229
endif()
File renamed without changes.

tools/llvm-objcopy/StripOpts.td

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
include "llvm/Option/OptParser.td"
2+
3+
multiclass Eq<string name> {
4+
def NAME: Separate<["--", "-"], name>;
5+
def NAME # _eq: Joined<["--", "-"], name # "=">, Alias<!cast<Separate>(NAME)>;
6+
}
7+
8+
def help : Flag<["-", "--"], "help">;
9+
10+
def strip_debug : Flag<["-", "--"], "strip-debug">,
11+
HelpText<"Remove debugging symbols only">;
12+

tools/llvm-objcopy/llvm-objcopy.cpp

+82-16
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "llvm/Support/ErrorOr.h"
2929
#include "llvm/Support/FileOutputBuffer.h"
3030
#include "llvm/Support/InitLLVM.h"
31+
#include "llvm/Support/Path.h"
3132
#include "llvm/Support/raw_ostream.h"
3233
#include <algorithm>
3334
#include <cassert>
@@ -45,17 +46,17 @@ using namespace ELF;
4546

4647
namespace {
4748

48-
enum ID {
49+
enum ObjcopyID {
4950
OBJCOPY_INVALID = 0, // This is not an option ID.
5051
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
5152
HELPTEXT, METAVAR, VALUES) \
5253
OBJCOPY_##ID,
53-
#include "Opts.inc"
54+
#include "ObjcopyOpts.inc"
5455
#undef OPTION
5556
};
5657

5758
#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
58-
#include "Opts.inc"
59+
#include "ObjcopyOpts.inc"
5960
#undef PREFIX
6061

6162
static const opt::OptTable::Info ObjcopyInfoTable[] = {
@@ -65,7 +66,7 @@ static const opt::OptTable::Info ObjcopyInfoTable[] = {
6566
METAVAR, OBJCOPY_##ID, opt::Option::KIND##Class, \
6667
PARAM, FLAGS, OBJCOPY_##GROUP, \
6768
OBJCOPY_##ALIAS, ALIASARGS, VALUES},
68-
#include "Opts.inc"
69+
#include "ObjcopyOpts.inc"
6970
#undef OPTION
7071
};
7172

@@ -74,6 +75,31 @@ class ObjcopyOptTable : public opt::OptTable {
7475
ObjcopyOptTable() : OptTable(ObjcopyInfoTable, true) {}
7576
};
7677

78+
enum StripID {
79+
STRIP_INVALID = 0, // This is not an option ID.
80+
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
81+
HELPTEXT, METAVAR, VALUES) \
82+
STRIP_##ID,
83+
#include "StripOpts.inc"
84+
#undef OPTION
85+
};
86+
87+
static const opt::OptTable::Info StripInfoTable[] = {
88+
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
89+
HELPTEXT, METAVAR, VALUES) \
90+
{PREFIX, NAME, HELPTEXT, \
91+
METAVAR, STRIP_##ID, opt::Option::KIND##Class, \
92+
PARAM, FLAGS, STRIP_##GROUP, \
93+
STRIP_##ALIAS, ALIASARGS, VALUES},
94+
#include "StripOpts.inc"
95+
#undef OPTION
96+
};
97+
98+
class StripOptTable : public opt::OptTable {
99+
public:
100+
StripOptTable() : OptTable(StripInfoTable, true) {}
101+
};
102+
77103
} // namespace
78104

79105
// The name this program was invoked as.
@@ -122,16 +148,16 @@ struct CopyConfig {
122148
std::vector<StringRef> SymbolsToGlobalize;
123149
std::vector<StringRef> SymbolsToWeaken;
124150
StringMap<StringRef> SymbolsToRename;
125-
bool StripAll;
126-
bool StripAllGNU;
127-
bool StripDebug;
128-
bool StripSections;
129-
bool StripNonAlloc;
130-
bool StripDWO;
131-
bool ExtractDWO;
132-
bool LocalizeHidden;
133-
bool Weaken;
134-
bool DiscardAll;
151+
bool StripAll = false;
152+
bool StripAllGNU = false;
153+
bool StripDebug = false;
154+
bool StripSections = false;
155+
bool StripNonAlloc = false;
156+
bool StripDWO = false;
157+
bool ExtractDWO = false;
158+
bool LocalizeHidden = false;
159+
bool Weaken = false;
160+
bool DiscardAll = false;
135161
};
136162

137163
using SectionPred = std::function<bool(const SectionBase &Sec)>;
@@ -449,10 +475,50 @@ CopyConfig ParseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
449475
return Config;
450476
}
451477

478+
// ParseStripOptions returns the config and sets the input arguments. If a
479+
// help flag is set then ParseStripOptions will print the help messege and
480+
// exit.
481+
CopyConfig ParseStripOptions(ArrayRef<const char *> ArgsArr) {
482+
StripOptTable T;
483+
unsigned MissingArgumentIndex, MissingArgumentCount;
484+
llvm::opt::InputArgList InputArgs =
485+
T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
486+
487+
if (InputArgs.size() == 0 || InputArgs.hasArg(STRIP_help)) {
488+
T.PrintHelp(outs(), "llvm-strip <input> [ <output> ]", "strip tool");
489+
exit(0);
490+
}
491+
492+
SmallVector<const char *, 2> Positional;
493+
for (auto Arg : InputArgs.filtered(STRIP_UNKNOWN))
494+
error("unknown argument '" + Arg->getAsString(InputArgs) + "'");
495+
for (auto Arg : InputArgs.filtered(STRIP_INPUT))
496+
Positional.push_back(Arg->getValue());
497+
498+
if (Positional.empty())
499+
error("No input file specified");
500+
501+
if (Positional.size() > 2)
502+
error("Support for multiple input files is not implemented yet");
503+
504+
CopyConfig Config;
505+
Config.InputFilename = Positional[0];
506+
Config.OutputFilename = Positional[0];
507+
508+
// Strip debug info only.
509+
Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug);
510+
if (!Config.StripDebug)
511+
Config.StripAll = true;
512+
return Config;
513+
}
514+
452515
int main(int argc, char **argv) {
453516
InitLLVM X(argc, argv);
454517
ToolName = argv[0];
455-
456-
CopyConfig Config = ParseObjcopyOptions(makeArrayRef(argv + 1, argc));
518+
CopyConfig Config;
519+
if (sys::path::stem(ToolName).endswith_lower("strip"))
520+
Config = ParseStripOptions(makeArrayRef(argv + 1, argc));
521+
else
522+
Config = ParseObjcopyOptions(makeArrayRef(argv + 1, argc));
457523
ExecuteElfObjcopy(Config);
458524
}

0 commit comments

Comments
 (0)