diff --git a/llvm/test/tools/llvm-objcopy/MachO/install-name-tool-delete-rpath.test b/llvm/test/tools/llvm-objcopy/MachO/install-name-tool-delete-rpath.test --- a/llvm/test/tools/llvm-objcopy/MachO/install-name-tool-delete-rpath.test +++ b/llvm/test/tools/llvm-objcopy/MachO/install-name-tool-delete-rpath.test @@ -42,6 +42,21 @@ # COMBINED: cannot specify both -add_rpath @executable_b/. and -delete_rpath @executable_b/. +## Remove all RPATHS +# RUN: yaml2obj %s -o %t2 +# RUN: llvm-install-name-tool -delete_all_rpaths %t2 +# RUN: llvm-objdump -p %t2 | FileCheck %s + +# CHECK-NOT: LC_RPATH + +## Remove all RPATHS and add a new one. +# RUN: yaml2obj %s -o %t3 +# RUN: llvm-install-name-tool --delete_all_rpaths -add_rpath @executable_b/. %t3 +# RUN: llvm-objdump -p %t3 | \ +# RUN: FileCheck %s --check-prefix=DELETE_AND_ADD --implicit-check-not=@executable + +# DELETE_AND_ADD: @executable_b/. + --- !mach-o FileHeader: magic: 0xFEEDFACF diff --git a/llvm/tools/llvm-objcopy/CopyConfig.h b/llvm/tools/llvm-objcopy/CopyConfig.h --- a/llvm/tools/llvm-objcopy/CopyConfig.h +++ b/llvm/tools/llvm-objcopy/CopyConfig.h @@ -230,6 +230,9 @@ bool StripUnneeded = false; bool Weaken = false; bool DecompressDebugSections = false; + // install-name-tool's --delete_all_rpaths + bool RemoveAllRpaths = false; + DebugCompressionType CompressionType = DebugCompressionType::None; // parseELFConfig performs ELF-specific command-line parsing. Fills `ELF` on diff --git a/llvm/tools/llvm-objcopy/CopyConfig.cpp b/llvm/tools/llvm-objcopy/CopyConfig.cpp --- a/llvm/tools/llvm-objcopy/CopyConfig.cpp +++ b/llvm/tools/llvm-objcopy/CopyConfig.cpp @@ -953,6 +953,9 @@ for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_change)) Config.InstallNamesToUpdate.insert({Arg->getValue(0), Arg->getValue(1)}); + Config.RemoveAllRpaths = + InputArgs.hasArg(INSTALL_NAME_TOOL_delete_all_rpaths); + SmallVector Positional; for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_UNKNOWN)) return createStringError(errc::invalid_argument, "unknown argument '%s'", diff --git a/llvm/tools/llvm-objcopy/InstallNameToolOpts.td b/llvm/tools/llvm-objcopy/InstallNameToolOpts.td --- a/llvm/tools/llvm-objcopy/InstallNameToolOpts.td +++ b/llvm/tools/llvm-objcopy/InstallNameToolOpts.td @@ -21,6 +21,9 @@ def delete_rpath: Option<["-", "--"], "delete_rpath", KIND_SEPARATE>, HelpText<"Delete specified rpath">; +def delete_all_rpaths: Flag<["-", "--"], "delete_all_rpaths">, + HelpText<"Delete all rpath directives">; + def rpath: MultiArg<["-", "--"], "rpath", 2>, HelpText<"Change rpath path name">; diff --git a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp b/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp --- a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp +++ b/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp @@ -133,8 +133,14 @@ DenseSet RPathsToRemove(Config.RPathsToRemove.begin(), Config.RPathsToRemove.end()); - LoadCommandPred RemovePred = [&RPathsToRemove](const LoadCommand &LC) { + LoadCommandPred RemovePred = [&RPathsToRemove, + &Config](const LoadCommand &LC) { if (LC.MachOLoadCommand.load_command_data.cmd == MachO::LC_RPATH) { + // When removing all RPaths we don't need to care + // about what it contains + if (Config.RemoveAllRpaths) + return true; + StringRef RPath = getPayloadString(LC); if (RPathsToRemove.count(RPath)) { RPathsToRemove.erase(RPath);