[llvm-objcopy][MachO] Implement --strip-all

Reviewers: alexshap, rupprecht, jdoerfert, jhenderson

Reviewed By: alexshap

Subscribers: jakehehrlich, abrachet, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D66281
diff --git a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp b/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
index 73983a1..d14354e 100644
--- a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
+++ b/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
@@ -23,6 +23,16 @@
 static void removeSections(const CopyConfig &Config, Object &Obj) {
   SectionPred RemovePred = [](const Section &) { return false; };
 
+  if (Config.StripAll) {
+    // Remove all debug sections.
+    RemovePred = [RemovePred](const Section &Sec) {
+      if (Sec.Segname == "__DWARF")
+        return true;
+
+      return RemovePred(Sec);
+    };
+  }
+
   if (!Config.OnlySection.empty()) {
     RemovePred = [&Config, RemovePred](const Section &Sec) {
       return !Config.OnlySection.matches(Sec.CanonicalName);
@@ -32,6 +42,23 @@
   return Obj.removeSections(RemovePred);
 }
 
+static void markSymbols(const CopyConfig &Config, Object &Obj) {
+  // Symbols referenced from the indirect symbol table must not be removed.
+  for (IndirectSymbolEntry &ISE : Obj.IndirectSymTable.Symbols)
+    if (ISE.Symbol)
+      (*ISE.Symbol)->Referenced = true;
+}
+
+static void removeSymbols(const CopyConfig &Config, Object &Obj) {
+  auto RemovePred = [Config](const std::unique_ptr<SymbolEntry> &N) {
+    if (N->Referenced)
+      return false;
+    return Config.StripAll;
+  };
+
+  Obj.SymTable.removeSymbols(RemovePred);
+}
+
 static Error handleArgs(const CopyConfig &Config, Object &Obj) {
   if (Config.AllowBrokenLinks || !Config.BuildIdLinkDir.empty() ||
       Config.BuildIdLinkInput || Config.BuildIdLinkOutput ||
@@ -45,9 +72,9 @@
       !Config.UnneededSymbolsToRemove.empty() ||
       !Config.SetSectionAlignment.empty() || !Config.SetSectionFlags.empty() ||
       !Config.ToRemove.empty() || Config.ExtractDWO || Config.KeepFileSymbols ||
-      Config.LocalizeHidden || Config.PreserveDates || Config.StripDWO ||
-      Config.StripNonAlloc || Config.StripSections || Config.Weaken ||
-      Config.DecompressDebugSections || Config.StripDebug ||
+      Config.LocalizeHidden || Config.PreserveDates || Config.StripAllGNU ||
+      Config.StripDWO || Config.StripNonAlloc || Config.StripSections ||
+      Config.Weaken || Config.DecompressDebugSections || Config.StripDebug ||
       Config.StripNonAlloc || Config.StripSections || Config.StripUnneeded ||
       Config.DiscardMode != DiscardType::None || !Config.SymbolsToAdd.empty() ||
       Config.EntryExpr) {
@@ -56,6 +83,18 @@
   }
 
   removeSections(Config, Obj);
+
+  // Mark symbols to determine which symbols are still needed.
+  if (Config.StripAll)
+    markSymbols(Config, Obj);
+
+  removeSymbols(Config, Obj);
+
+  if (Config.StripAll)
+    for (LoadCommand &LC : Obj.LoadCommands)
+      for (Section &Sec : LC.Sections)
+        Sec.Relocations.clear();
+
   return Error::success();
 }