forked from OSchip/llvm-project
[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
This commit is contained in:
parent
71e1a56de1
commit
77cbf25953
llvm
test/tools/llvm-objcopy/MachO
tools/llvm-objcopy
|
@ -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
|
|
@ -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});
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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">;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue