-
-
Save ling2yt/f8d5ab3aa36d65256d6ad1473c15536b to your computer and use it in GitHub Desktop.
ldd drop-in replacement for cross-compilation toolchains.
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 | |
# ldd drop-in replacement for cross-compilation toolchains. | |
# This file is a slightly modified version of xldd.in from | |
# crosstool-ng 1.22.0 | |
# In order to use it, copy it in same directory than other | |
# toolchain binaries and rename it with same tuple. | |
# (i.e. /opt/arm-sysmic-linux-gnueabihf/bin/arm-sysmic-linux-gnueabihf-ldd) | |
# Thus, this will automaticaly detect necessary information | |
# about your toolchain. | |
export LC_ALL=C | |
version="forked from crosstool-ng 1.22.0" | |
# Change it to 64 if necessary | |
bits="32" | |
sed="${SED:-sed}" | |
grep="${GREP:-grep}" | |
my_name="$( basename "${0}" )" | |
prefix="${0%-ldd}" | |
gcc="${GCC:-"${prefix}-gcc"}" | |
readelf="${READELF:-"${prefix}-readelf"}" | |
fake_load_addr_root="$((0xdeadbeef))" | |
fake_load_addr_rpath="$((0xdeadc0de))" | |
fake_load_addr_sysroot="$((0x8badf00d))" | |
ld_library_path="/lib:/usr/lib" | |
input_bin="${INPUT_BIN}" | |
root="${ROOT:-""}" | |
do_error() { | |
printf "%s: %s\n" "${my_name}" "$*" >&2 | |
} | |
do_opt_error() { | |
do_error "$@" | |
printf "Try \`%s --help' for more information\n" "${my_name}" >&2 | |
} | |
do_trace() { | |
local depth=0 | |
[ -z "${CT_XLDD_VERBOSE}" ] && return 0 | |
for((depth=0; "${#FUNCNAME[$((depth+1))]}" != 0; depth++)); do :; done | |
printf "%*s" $((4*(depth-1))) "" >&2 | |
printf -- "$@" >&2 | |
} | |
# Sanity checks | |
sysroot="$( "${gcc}" -print-sysroot 2>/dev/null )" | |
if [ -z "${sysroot}" ]; then | |
sysroot="$( "${gcc}" -print-file-name=libc.so 2>/dev/null \ | |
|${sed} -r -e 's:/usr/lib/libc.so$::;' \ | |
)" | |
fi | |
if [ -z "${sysroot}" ]; then | |
do_error "unable to find sysroot for \`${gcc}'" | |
fi | |
if [ -z "${root}" ]; then | |
root=${sysroot} | |
fi | |
if [ ! -d "${root}" ]; then | |
do_error "\`${root}': no such file or directory" | |
exit 1 | |
fi | |
if [ ! -f "${input_bin}" ]; then | |
do_error "\'${input_bin}': no such file or directory" | |
exit 1 | |
fi | |
do_report_needed_found() { | |
local needed="${1}" | |
local path="${2}" | |
local origin="${3}" | |
local loadaddr | |
local sys | |
case "${origin}" in | |
root) | |
loadaddr="${fake_load_addr_root}" | |
;; | |
rpath) | |
loadaddr="${fake_load_addr_rpath}" | |
if [ -n "${show_system}" ]; then | |
sys=" [+]" | |
fi | |
;; | |
sysroot) | |
loadaddr="${fake_load_addr_sysroot}" | |
if [ -n "${show_system}" ]; then | |
sys=" [*]" | |
fi | |
;; | |
esac | |
printf "%8s%s => %s (0x%0*x)%s\n" \ | |
"" \ | |
"${needed}" \ | |
"${path}" \ | |
"$((bits/4))" \ | |
"${loadaddr}" \ | |
"${sys}" | |
} | |
declare -A myMap=() | |
myMap["my03"]="03" | |
# Search a needed file, scanning ${lib_dir} in the root directory | |
do_find_needed() { | |
local needed="${1}" | |
local -a list | |
local -a dirs | |
local found | |
local where | |
local base | |
local d i | |
do_trace "Searching for '%s'\n" "${needed}" | |
# rpath shall come first! | |
list=( \ | |
"rpath:${root}" \ | |
"root:${root}" \ | |
"sysroot:${sysroot}" \ | |
) | |
for i in "${list[@]}"; do | |
where="${i%%:*}" | |
base="${i#*:}" | |
if [ "${where}" = "rpath" ]; then | |
dirs=( "${search_rpath[@]}" ) | |
else | |
dirs=( "${needed_search_path[@]}" ) | |
fi | |
for d in "${dirs[@]}"; do | |
do_trace "-> looking in '%s' '%s' '%s' (%s)\n" "${base}" "${d}" "${needed})" "${where}" | |
if echo "${base}/${d}/${needed}" | grep "\$ORIGIN" > /dev/null; then | |
findPath=$(echo "${base}/${d}/${needed}" | sed 's/\$ORIGIN//g') | |
else | |
findPath="${base}/${d}/${needed}" | |
fi | |
unset ORIGIN | |
if [ -f ${findPath} ]; then | |
found="${findPath}" | |
do_trace "---> found\n" | |
break 2 | |
fi | |
done | |
done | |
if [ -n "${found}" ] && [ ! -n "${myMap[$findPath]}" ]; then | |
do_report_needed_found "${needed}" "${found}" "${where}" | |
do_process_file "${found}" | |
#myMap["$findPath"]="done" | |
elif [ ! -n "${found}" ]; then | |
printf "%8s%s not found\n" "" "${needed}" | |
fi | |
do_trace "Done searching for '%s'\n" "${needed}" | |
} | |
# Scan a file for all NEEDED tags | |
do_process_file() { | |
local file="${1}" | |
local -a save_search_rpath | |
local n m | |
local found | |
do_trace "Parsing file '%s'\n" "${file}" | |
save_search_rpath=( "${search_rpath[@]}" ) | |
for n in $( "${readelf}" -d "${file}" \ | |
|"${grep}" -E '\((RPATH|RUNPATH)\)' \ | |
|"${sed}" -r -e 's/^.*Library r(|un)path:[[:space:]]+\[(.*)\]$/\2/;'\ | |
); do | |
OIFS=$IFS; | |
IFS=":"; | |
narray=($n) | |
for subn in "${narray[@]}"; do | |
do_trace "-> adding rpath '%s'\n" "${subn}" | |
search_rpath+=( "${subn}" ) | |
done | |
IFS=$OIFS; | |
done | |
do_trace ": search path:\n" | |
for n in "${search_rpath[@]}" "${needed_search_path[@]}"; do | |
do_trace ": - '%s'\n" "${n}" | |
done | |
do_trace ": end search path\n" | |
for n in $( "${readelf}" -d "${file}" \ | |
|"${grep}" -E '\(NEEDED\)' \ | |
|"${sed}" -r -e 's/^.*Shared library:[[:space:]]+\[([^]]+)\].*/\1/;' \ | |
); do | |
found=0 | |
for m in "${needed_list[@]}"; do | |
[ "${n}" = "${m}" ] && found=1 && break | |
done | |
if [ ${found} -ne 0 ]; then | |
do_trace "-> skipping already known dependency '%s'\n" "${n}" | |
continue | |
fi | |
do_trace "-> handling new dependency '%s'\n" "${n}" | |
needed_list+=( "${n}" ) | |
do_find_needed "${n}" | |
do_trace "-> done handling dependency '%s'\n" "${n}" | |
done | |
search_rpath=( "${save_search_rpath[@]}" ) | |
do_trace "Finished parsing file '%s'\n" "${file}" | |
} | |
# Recursively scan a /etc/ld.so.conf file | |
do_scan_etc_ldsoconf() { | |
local ldsoconf="${1}" | |
local g | |
local f | |
[ -f "${ldsoconf}" ] || return 0 | |
do_trace "Parsing ld.so.conf: '%s'\n" "${ldsoconf}" | |
while read line; do | |
case "${line}" in | |
include\ *) | |
g="${root}${line#include }" | |
do_trace "-> handling include directive '%s'\n" "${g}" | |
for f in ${g}; do | |
do_scan_etc_ldsoconf "${f}" | |
done | |
do_trace "-> finished handling include directive '%s'\n" "${g}" | |
;; | |
\#*|"") | |
;; | |
*) | |
do_trace "-> adding search dir '%s'\n" "${line}" | |
needed_search_path+=( "${line}" ) | |
;; | |
esac | |
done <"${ldsoconf}" | |
do_trace "Finished parsing ld.so.conf: '%s'\n" "${ldsoconf}" | |
} | |
# Build up the full list of search directories | |
declare -a needed_search_path | |
do_trace "Adding basic lib dirs\n" | |
ld_library_path="${ld_library_path}:" | |
while [ -n "${ld_library_path}" ]; do | |
d="${ld_library_path%%:*}" | |
if [ -n "${d}" ]; then | |
do_trace "-> adding search dir '%s'\n" "${d}" | |
needed_search_path+=( "${d}" ) | |
fi | |
ld_library_path="${ld_library_path#*:}" | |
done | |
do_trace "Done adding basic lib dirs\n" | |
do_trace "Scanning '/etc/ld.so.conf'\n" | |
do_scan_etc_ldsoconf "${root}/etc/ld.so.conf" | |
do_trace "Done scanning '/etc/ld.so.conf'\n" | |
do_trace "Search path:\n" | |
for p in "${needed_search_path[@]}"; do | |
do_trace "-> '%s'\n" "${p}" | |
done | |
declare -a needed_list | |
declare -a search_rpath | |
do_trace "Scanning file '%s'\n" "${input_bin}" | |
do_process_file "${input_bin}" | |
do_trace "Done scanning file '%s'\n" "${input_bin}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
usage: