Skip to content

Instantly share code, notes, and snippets.

@aperezdc
Last active July 14, 2025 15:08
Show Gist options
  • Select an option

  • Save aperezdc/120b1af919ad65d4a2b7154339a3913c to your computer and use it in GitHub Desktop.

Select an option

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
#! /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
@aperezdc
Copy link
Author

This uses patchelf to edit ELF objects and remove version suffixes in their DT_SONAME and DT_NEEDED headers. 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 the bin/ subdirectory), rename libraries, and remove stale versioned library symlinks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment