Reland "[llvm-objcopy] Add support for --strip-sections to remove all section headers leaving only program headers and loadable segment data"
ubsan caught an issue I made where I was converting a null pointer to a
reference.
elf utils implements a particularly extreme form of stripping that I'd
like to support. eu-strip has an option called "strip-sections" that
removes all section headers and leaves only program headers and the
segment data. I have implemented this option partly as a test but mainly
because in Fuchsia we would like to use this option to minimize the size
of our executables. The other strip options that are on my list include
--strip-all and --strip-debug. This is a preliminary implementation that
I'd like to start using in Fuchsia builds if possible. This change
implements such a stripping option for llvm-objcopy
Differential Revision: https://reviews.llvm.org/D38335
llvm-svn: 315484
diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
index d767354..7f55a43 100644
--- a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
+++ b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
@@ -56,11 +56,14 @@
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;
@@ -71,12 +74,25 @@
Obj = llvm::make_unique<BinaryObject<ELF64LE>>(ObjFile);
else
Obj = llvm::make_unique<ELFObject<ELF64LE>>(ObjFile);
+
+ SectionPred RemovePred = [](const SectionBase &) { return false; };
+
if (!ToRemove.empty()) {
- Obj->removeSections([&](const SectionBase &Sec) {
+ 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(),