Last active
July 14, 2025 15:08
-
-
Save aperezdc/120b1af919ad65d4a2b7154339a3913c to your computer and use it in GitHub Desktop.
Remove version suffixes in DT_SONAME/DT_NEEDED in a set of ELF objects
This file contains hidden or 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 | |
| # | |
| # SPDX-License-Identifier: MIT | |
| # | |
| set -eu -o pipefail | |
| LOG_COMMANDS=false | |
| do_log () { | |
| local prefix | |
| prefix=$1 | |
| shift | |
| echo "$prefix $*" | |
| } 1>&2 | |
| if [[ $# -eq 0 ]] ; then | |
| do_log 'Usage:' "$0 path/to/libdir [extralib...]" | |
| exit 1 | |
| fi | |
| info () { | |
| do_log '[INFO]' "$@" | |
| } | |
| warn () { | |
| do_log '[WARN]' "$@" | |
| } | |
| if $LOG_COMMANDS ; then | |
| logcmd () { do_log ';;' "$@" ; "$@" ; } | |
| else | |
| logcmd () { "$@" ; } | |
| fi | |
| declare -A all_libs=() | |
| declare -A extra_objects=() | |
| declare -A mappings=() | |
| is_elf () { | |
| local typ | |
| typ=$(file -b -L "$1") | |
| [[ $typ = ELF* ]] | |
| } | |
| scan_one () { | |
| if ! is_elf "$1" ; then | |
| info "Skipping non-ELF object: $1" | |
| return | |
| fi | |
| all_libs["$1"]=: | |
| if [[ -L $1 ]] ; then | |
| local soname=$(patchelf --print-soname "$1") | |
| local simplename=$(basename "$1") | |
| mappings["$soname"]=$simplename | |
| # Replace .so with actual file | |
| local real_file | |
| real_file=$(readlink -f "$1") | |
| logcmd rm "$1" | |
| logcmd mv "$real_file" "$1" | |
| logcmd patchelf --set-soname "$simplename" "$1" | |
| fi | |
| } | |
| libdir=$1 | |
| shift | |
| for item in "$libdir"/*.so ; do | |
| scan_one "${item}" | |
| done | |
| if [[ ${#mappings[@]} -gt 0 ]] ; then | |
| declare -a patchelf_args | |
| for soname_from in "${!mappings[@]}" ; do | |
| soname_to=${mappings["$soname_from"]} | |
| patchelf_args+=( --replace-needed "$soname_from" "$soname_to" ) | |
| done | |
| # Filter out non-ELF extra objects passed in the command line. | |
| for f in "$@" ; do | |
| if is_elf "$f" ; then | |
| extra_objects["$f"]=: | |
| else | |
| info "Skipping non-ELF object: $f" | |
| fi | |
| done | |
| logcmd patchelf "${patchelf_args[@]}" "${!all_libs[@]}" "${!extra_objects[@]}" | |
| else | |
| info 'No soname mappings to apply' | |
| fi | |
| # Clean dangling symlinks | |
| for f in "$libdir"/* ; do | |
| if [[ -L $f ]] ; then | |
| ff=$(readlink -f "$f") | |
| if [[ ! -r $ff ]] ; then | |
| logcmd rm "$f" | |
| fi | |
| fi | |
| done |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This uses patchelf to edit ELF objects and remove version suffixes in their
DT_SONAMEandDT_NEEDEDheaders. Typically used like this:bash fixlibs.sh path/to/sysroot/lib/ path/to/sysroot/bin/*This will edit the libraries in the
lib/subdirectory, and the additional files passed after the directory (all the files under thebin/subdirectory), rename libraries, and remove stale versioned library symlinks.