diff --git a/llvm/test/tools/llvm-objcopy/MachO/install-name-tool-id.test b/llvm/test/tools/llvm-objcopy/MachO/install-name-tool-id.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/MachO/install-name-tool-id.test @@ -0,0 +1,53 @@ +## This test checks updating a dynamic shared library ID in a MachO binary. + +# RUN: yaml2obj %s -o %t + +## Specifying -id once: +# RUN: llvm-install-name-tool -id /usr/lib/A_long_long_test %t +# RUN: llvm-objdump -p %t | FileCheck %s --check-prefix=ID --implicit-check-not=/usr + +# ID: /usr/lib/A_long_long_test + +## Specifying -id more than once: +# RUN: llvm-install-name-tool -id /usr/lib/B_long -id /usr/lib/K_long -id /usr/A_short %t +# RUN: llvm-objdump -p %t | FileCheck %s --check-prefix=ID-MULTIPLE --implicit-check-not=/usr + +# ID-MULTIPLE: /usr/A_short + +## Specifying -id with empty string: +# RUN: not llvm-install-name-tool -id '' %t 2>&1 | \ +# RUN: FileCheck %s --check-prefix=EMPTY + +# EMPTY: cannot specify an empty id + +## Check that -id option has no effect if binary is not a shared dylib: +# RUN: yaml2obj %p/Inputs/x86_64.yaml -o %t +# RUN: cp %t %t1 +# RUN: llvm-install-name-tool -id /usr/lib/J %t +# RUN: cmp %t %t1 + +## Missing id argument: +# RUN: not llvm-install-name-tool %t -id 2>&1 | \ +# RUN: FileCheck %s --check-prefix=MISSING + +# MISSING: missing argument to -id option + +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x01000007 + cpusubtype: 0x00000003 + filetype: 0x00000006 + ncmds: 1 + sizeofcmds: 56 + flags: 0x00002000 + reserved: 0x00000000 +LoadCommands: + - cmd: LC_ID_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 2 + current_version: 82115073 + compatibility_version: 65536 + PayloadString: '/usr/lib/A' 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 @@ -181,6 +181,9 @@ std::vector> RPathsToUpdate; DenseSet RPathsToRemove; + // install-name-tool's id option + Optional SharedLibId; + // Section matchers NameMatcher KeepSection; NameMatcher OnlySection; 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 @@ -883,6 +883,9 @@ Config.RPathsToUpdate.emplace_back(Old, New); } + if (auto *Arg = InputArgs.getLastArg(INSTALL_NAME_TOOL_id)) + Config.SharedLibId = Arg->getValue(); + 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 @@ -24,5 +24,8 @@ def rpath: MultiArg<["-", "--"], "rpath", 2>, HelpText<"Change rpath path name">; +def id : Option<["-","--"], "id", KIND_SEPARATE>, + HelpText<"Change dynamic shared library id">; + def version : Flag<["--"], "version">, HelpText<"Print the version and exit.">; 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 @@ -276,6 +276,19 @@ for (std::unique_ptr
&Sec : LC.Sections) Sec->Relocations.clear(); + if (Config.SharedLibId) { + StringRef Id = Config.SharedLibId.getValue(); + if (Id.empty()) + return createStringError(errc::invalid_argument, + "cannot specify an empty id"); + for (LoadCommand &LC : Obj.LoadCommands) { + if (LC.MachOLoadCommand.load_command_data.cmd == MachO::LC_ID_DYLIB) { + updateLoadCommandPayload(LC, Id); + break; + } + } + } + for (const auto &Flag : Config.AddSection) { std::pair SecPair = Flag.split("="); StringRef SecName = SecPair.first;