Instantly share code, notes, and snippets.
Created
December 18, 2019 03:46
-
Star
(1)
1
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save sdr01810/047d78c737e792b7702a6fa7e2201765 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
## Make all references relocatable in each dynamic shared library listed on stdin. | |
## By Stephen D. Rogers <inbox.c7r@steve-rogers.com>, 2019. | |
## | |
## Arguments: | |
## | |
## [--relative-to anchor_directory_pn] | |
## | |
## Typical uses: | |
## | |
## for d1 in My.app/Contents/Frameworks ; do | |
## | |
## find -H "$d1" -maxdepth 1 -type f -name '*.dylib' | | |
## mac-os.relocate-listed-dynamic-shared-libraries --relative-to "$d1" | |
## done | |
## | |
## If `anchor_directory_pn` is not specified, it defaults to the current directory. | |
## | |
set -e | |
set -o pipefail 2>&- || : | |
## | |
## from snippet library: | |
## | |
function xx() { # ... | |
echo 1>&2 "${PS4:-+}" "$@" | |
"$@" | |
} | |
function list_id_and_references_specified_in_dynamic_shared_library() { # dynamic_shared_library_pn | |
local dynamic_shared_library_pn="${1:?missing argument: dynamic_shared_library_pn}" ; shift 1 | |
objdump -macho -dylib-id "${dynamic_shared_library_pn:?}" | perl -lne ' | |
chomp; | |
if (0) {} | |
elsif ($. == 1 && m#^\s*(.*?\S):\s*$#) { | |
printf STDOUT "%-10s %s$/", "pathname", $1; | |
} | |
elsif ($. == 2) { | |
printf STDOUT "%-10s %s$/", "id", $_; | |
} | |
'; | |
objdump -macho -dylibs-used "${dynamic_shared_library_pn:?}" | perl -lne ' | |
chomp; | |
if (0) {} | |
elsif ($. == 1 && m#^\s*(.*?\S):\s*$#) { | |
printf STDOUT "%-10s %s$/", "pathname", $1; | |
} | |
elsif ($. >= 2 && m#^\s*(.*?\S)(?:\s+\(compatibility version ([\d.]+), current version ([\d.]+)\))#) { | |
printf STDOUT "%-10s %s$/", "reference", $1; | |
} | |
else { | |
printf STDERR "Unexpected dylib reference: %s$/", $_; | |
next; | |
} | |
'; | |
} | |
function relocate_mac_os_dynamic_shared_library() { # [--relative-to anchor_directory_pn] dynamic_shared_library_pn | |
local anchor_directory_pn | |
local dynamic_shared_library_pn | |
while [ $# -gt 0 ] ; do | |
case "${1}" in | |
--relative-to) | |
anchor_directory_pn="${2}" | |
shift 2 | |
break | |
;; | |
--) | |
shift 1 | |
break | |
;; | |
*) | |
break | |
;; | |
esac;done | |
anchor_directory_pn="${anchor_directory_pn:-.}" | |
dynamic_shared_library_pn="${1:?missing argument: dynamic_shared_library_pn}" ; shift 1 | |
if [ $# -gt 0 ] ; then | |
echo 1>&2 "Unexpected argument(s): ${@}" | |
false | |
fi | |
## | |
list_id_and_references_specified_in_dynamic_shared_library "${dynamic_shared_library_pn:?}" | | |
( | |
change_set=() | |
while read type value ; do | |
case "${type}" in | |
id) | |
corrected_value="$(relocate_mac_os_dynamic_shared_library_pathname_relative_to "${anchor_directory_pn}" "${value}")" | |
if [ -n "${corrected_value}" -a "${corrected_value}" != "${value}" ] ; then | |
change_set+=( -id "${corrected_value}" ) | |
fi | |
;; | |
pathname) | |
dynamic_shared_library_pn02="${value}" | |
;; | |
reference) | |
corrected_value="$(relocate_mac_os_dynamic_shared_library_pathname_relative_to "${anchor_directory_pn}" "${value}")" | |
if [ -n "${corrected_value}" -a "${corrected_value}" != "${value}" ] ; then | |
change_set+=( -change "${value}" "${corrected_value}" ) | |
fi | |
;; | |
esac;done | |
if [ ${#change_set[@]} -gt 0 ] ; then | |
xx install_name_tool "${change_set[@]}" "${dynamic_shared_library_pn02}" | |
xx : | |
fi | |
) | |
} | |
function relocate_mac_os_dynamic_shared_library_pathname_relative_to() { # anchor_directory_pn dynamic_shared_library_pn | |
local anchor_directory_pn="${1:?}" ; shift 1 | |
local dynamic_shared_library_pn="${1:?}" ; shift 1 | |
local result_untransformed="${dynamic_shared_library_pn}" | |
local result="${result_untransformed}" | |
case "${result}" in | |
'') | |
: # no transformation | |
;; | |
@executable_file/*) | |
result="${result#@executable_file/../Frameworks/}" | |
case "${result}" in | |
@executable_file/*) | |
result="${result_untransformed}" # fallback | |
;; | |
*) | |
result="@rpath/${result}" | |
;; | |
esac | |
;; | |
@loader_path/*) | |
: # no transformation | |
;; | |
@rpath/*) | |
: # no transformation | |
;; | |
*) | |
result="${result#${anchor_directory_pn%/}/}" | |
case "${result}" in | |
/*) | |
result="${result_untransformed}" # fallback | |
;; | |
*) | |
result="@rpath/${result}" | |
;; | |
esac | |
;; | |
esac | |
echo "${result}" | |
} | |
## | |
## core logic: | |
## | |
function main() { # ... | |
local f1 | |
while read -r f1 ; do | |
[ -f "$f1" ] || continue | |
relocate_mac_os_dynamic_shared_library "$@" "$f1" | |
done | |
} | |
! [ "$0" = "${BASH_SOURCE}" ] || main "$@" | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment