[llvm] 77cbf25 - [llvm-install-name-tool] Add -prepend_rpath option

Alexander Shaposhnikov via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 23 15:04:29 PDT 2020


Author: Keith Smiley
Date: 2020-10-23T15:01:03-07:00
New Revision: 77cbf2595331b11018c2cffb76eb5b8db69f4577

URL: https://github.com/llvm/llvm-project/commit/77cbf2595331b11018c2cffb76eb5b8db69f4577
DIFF: https://github.com/llvm/llvm-project/commit/77cbf2595331b11018c2cffb76eb5b8db69f4577.diff

LOG: [llvm-install-name-tool] Add -prepend_rpath option

This diff adds the option -prepend_rpath which inserts an rpath as
the first rpath in the binary.

Test plan: make check-all

Differential revision: https://reviews.llvm.org/D89605

Added: 
    llvm/test/tools/llvm-objcopy/MachO/install-name-tool-prepend-rpath.test

Modified: 
    llvm/tools/llvm-objcopy/CopyConfig.cpp
    llvm/tools/llvm-objcopy/CopyConfig.h
    llvm/tools/llvm-objcopy/InstallNameToolOpts.td
    llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-objcopy/MachO/install-name-tool-prepend-rpath.test b/llvm/test/tools/llvm-objcopy/MachO/install-name-tool-prepend-rpath.test
new file mode 100644
index 000000000000..4f88f14f4219
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/MachO/install-name-tool-prepend-rpath.test
@@ -0,0 +1,63 @@
+## This test checks prepending a new LC_RPATH load command to a MachO binary.
+
+# RUN: yaml2obj %p/Inputs/i386.yaml -o %t.i386
+# RUN: llvm-install-name-tool -add_rpath @executable_path/. %t.i386
+# RUN: llvm-install-name-tool -prepend_rpath first_rpath %t.i386
+# RUN: llvm-objdump -p %t.i386 | FileCheck --check-prefix=NEW-RPATH %s
+
+# RUN: yaml2obj %p/Inputs/x86_64.yaml -o %t.x86_64
+# RUN: llvm-install-name-tool -add_rpath @executable_path/. %t.x86_64
+# RUN: llvm-install-name-tool -prepend_rpath first_rpath %t.x86_64
+# RUN: llvm-objdump -p %t.x86_64 | FileCheck --check-prefix=NEW-RPATH %s
+
+# NEW-RPATH:      cmd LC_RPATH
+# NEW-RPATH-NEXT: cmdsize
+# NEW-RPATH-NEXT: first_rpath
+
+# NEW-RPATH:      cmd LC_RPATH
+# NEW-RPATH-NEXT: cmdsize
+# NEW-RPATH-NEXT: @executable_path/.
+
+## Prepend with dylib loads:
+# RUN: yaml2obj %p/Inputs/strip-all.yaml -o %t.dylib
+# RUN: llvm-install-name-tool -prepend_rpath first_rpath %t.dylib
+# RUN: llvm-objdump -p %t.dylib | FileCheck --check-prefix=DYLIB %s
+
+# DYLIB:      cmd LC_RPATH
+# DYLIB-NEXT: cmdsize
+# DYLIB-NEXT: first_rpath
+
+# RUN: not llvm-install-name-tool -prepend_rpath first_rpath %t.i386 2>&1 | \
+# RUN:   FileCheck --check-prefix=DUPLICATE-RPATH %s
+
+# DUPLICATE-RPATH: rpath first_rpath would create a duplicate load command
+
+## Prepend same RPATH twice:
+# RUN: not llvm-install-name-tool -prepend_rpath @executable_X \
+# RUN:                            -prepend_rpath @executable_X %t.i386 2>&1 | \
+# RUN:   FileCheck --check-prefix=DOUBLE %s
+
+# DOUBLE: rpath @executable_X would create a duplicate load command
+
+## Prepend and delete RPATH:
+# RUN: not llvm-install-name-tool -prepend_rpath foo \
+# RUN:                            -delete_rpath foo %t.i386 2>&1 | \
+# RUN:   FileCheck --check-prefix=DELETE %s
+
+# DELETE: cannot specify both -prepend_rpath foo and -delete_rpath foo
+
+## Prepend and replace RPATH:
+# RUN: not llvm-install-name-tool -prepend_rpath foo \
+# RUN:                            -rpath foo bar %t.i386 2>&1 | \
+# RUN:   FileCheck --check-prefix=REPLACE %s
+
+# REPLACE: cannot specify both -prepend_rpath foo and -rpath foo bar
+
+## Check that cmdsize accounts for NULL terminator:
+# RUN: yaml2obj %p/Inputs/x86_64.yaml -o %t.x86_64
+# RUN: llvm-install-name-tool -prepend_rpath abcd %t.x86_64
+# RUN: llvm-objdump -p %t.x86_64 | FileCheck %s --check-prefix=RPATH-SIZE
+
+# RPATH-SIZE:      cmd LC_RPATH
+# RPATH-SIZE-NEXT: cmdsize 24
+# RPATH-SIZE-NEXT: path abcd

diff  --git a/llvm/tools/llvm-objcopy/CopyConfig.cpp b/llvm/tools/llvm-objcopy/CopyConfig.cpp
index cdd9147f7613..1bab7cd23b64 100644
--- a/llvm/tools/llvm-objcopy/CopyConfig.cpp
+++ b/llvm/tools/llvm-objcopy/CopyConfig.cpp
@@ -895,6 +895,9 @@ parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) {
   for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_add_rpath))
     Config.RPathToAdd.push_back(Arg->getValue());
 
+  for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_prepend_rpath))
+    Config.RPathToPrepend.push_back(Arg->getValue());
+
   for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_delete_rpath)) {
     StringRef RPath = Arg->getValue();
 
@@ -904,6 +907,11 @@ parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) {
           errc::invalid_argument,
           "cannot specify both -add_rpath %s and -delete_rpath %s",
           RPath.str().c_str(), RPath.str().c_str());
+    if (is_contained(Config.RPathToPrepend, RPath))
+      return createStringError(
+          errc::invalid_argument,
+          "cannot specify both -prepend_rpath %s and -delete_rpath %s",
+          RPath.str().c_str(), RPath.str().c_str());
 
     Config.RPathsToRemove.insert(RPath);
   }
@@ -940,6 +948,13 @@ parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) {
                                "cannot specify both -add_rpath " + *It3 +
                                    " and -rpath " + Old + " " + New);
 
+    // Cannot specify the same rpath under both -prepend_rpath and -rpath.
+    auto It4 = find_if(Config.RPathToPrepend, Match);
+    if (It4 != Config.RPathToPrepend.end())
+      return createStringError(errc::invalid_argument,
+                               "cannot specify both -prepend_rpath " + *It4 +
+                                   " and -rpath " + Old + " " + New);
+
     Config.RPathsToUpdate.insert({Old, New});
   }
 

diff  --git a/llvm/tools/llvm-objcopy/CopyConfig.h b/llvm/tools/llvm-objcopy/CopyConfig.h
index af763f24d1cc..07eac9d2bb1b 100644
--- a/llvm/tools/llvm-objcopy/CopyConfig.h
+++ b/llvm/tools/llvm-objcopy/CopyConfig.h
@@ -178,6 +178,7 @@ struct CopyConfig {
   std::vector<StringRef> DumpSection;
   std::vector<StringRef> SymbolsToAdd;
   std::vector<StringRef> RPathToAdd;
+  std::vector<StringRef> RPathToPrepend;
   DenseMap<StringRef, StringRef> RPathsToUpdate;
   DenseMap<StringRef, StringRef> InstallNamesToUpdate;
   DenseSet<StringRef> RPathsToRemove;

diff  --git a/llvm/tools/llvm-objcopy/InstallNameToolOpts.td b/llvm/tools/llvm-objcopy/InstallNameToolOpts.td
index 1c4e37f8b2ad..88dea84400fb 100644
--- a/llvm/tools/llvm-objcopy/InstallNameToolOpts.td
+++ b/llvm/tools/llvm-objcopy/InstallNameToolOpts.td
@@ -18,6 +18,9 @@ def h : Flag<["-"], "h">, Alias<help>;
 def add_rpath : Option<["-", "--"], "add_rpath", KIND_SEPARATE>,
                 HelpText<"Add new rpath">;
 
+def prepend_rpath : Option<["-", "--"], "prepend_rpath", KIND_SEPARATE>,
+                    HelpText<"Add new rpath before other rpaths">;
+
 def delete_rpath: Option<["-", "--"], "delete_rpath", KIND_SEPARATE>,
                   HelpText<"Delete specified rpath">;
 

diff  --git a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp b/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
index 4dbf1dabf9f3..311a9962a8cc 100644
--- a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
+++ b/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
@@ -228,6 +228,22 @@ static Error processLoadCommands(const CopyConfig &Config, Object &Obj) {
     Obj.LoadCommands.push_back(buildRPathLoadCommand(RPath));
   }
 
+  for (StringRef RPath : Config.RPathToPrepend) {
+    if (RPaths.count(RPath) != 0)
+      return createStringError(errc::invalid_argument,
+                               "rpath " + RPath +
+                                   " would create a duplicate load command");
+
+    RPaths.insert(RPath);
+    Obj.LoadCommands.insert(Obj.LoadCommands.begin(),
+                            buildRPathLoadCommand(RPath));
+  }
+
+  // Unlike appending rpaths, the indexes of subsequent load commands must
+  // be recalculated after prepending one.
+  if (!Config.RPathToPrepend.empty())
+    Obj.updateLoadCommandIndexes();
+
   return Error::success();
 }
 


        


More information about the llvm-commits mailing list