├── .github └── workflows │ └── test.yaml ├── Makefile ├── README.md ├── lddtree.sh └── tests ├── lddtree_test ├── test_env.sh └── testdata └── x86_64 ├── lib ├── ld-musl-x86_64.so.1 ├── libc.musl-x86_64.so.1 └── x86_64-linux-gnu │ ├── ld-2.31.so │ ├── libc-2.31.so │ └── libc.so.6 ├── lib64 └── ld-linux-x86-64.so.2 └── usr ├── bin ├── hello ├── hello-rpath-cwd ├── hello-rpath-origin-lib └── hello-rpath-origin-lib2 ├── gnu ├── bin │ └── hello └── lib │ ├── libhello.so.1 │ └── libhello.so.1.0 └── lib ├── libhello.so.1 └── libhello.so.1.0 /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: test 2 | on: [push] 3 | jobs: 4 | lint: 5 | name: shellcheck 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Checkout 9 | uses: actions/checkout@v3 10 | - name: Run Shellcheck 11 | uses: ludeeus/action-shellcheck@master 12 | env: 13 | SHELLCHECK_OPTS: -e SC3043 14 | 15 | alpine: 16 | runs-on: ubuntu-latest 17 | strategy: 18 | matrix: 19 | shell: [busybox, dash, oksh, yash, zsh, bash] 20 | 21 | container: 22 | image: alpine 23 | steps: 24 | - name: Checkout 25 | uses: actions/checkout@v3 26 | - name: Install dependencies 27 | run: | 28 | apk add --update kyua make binutils scanelf ${{ matrix.shell }} 29 | - name: Set system shell 30 | run: | 31 | ln -sfv $( which ${{ matrix.shell }} ) /bin/sh 32 | - name: Run tests 33 | run: | 34 | make check 35 | 36 | debian: 37 | runs-on: ubuntu-latest 38 | container: 39 | image: debian:testing 40 | steps: 41 | - name: Checkout 42 | uses: actions/checkout@v3 43 | - name: Install dependencies 44 | run: | 45 | apt-get update 46 | apt-get install -y kyua atf-sh make binutils 47 | - name: Run tests 48 | run: | 49 | make check 50 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | check: lddtree.sh tests/Kyuafile Kyuafile 3 | kyua test || (kyua report --verbose && exit 1) 4 | 5 | tests/Kyuafile: $(wildcard tests/*_test) 6 | echo "syntax(2)" > $@.tmp 7 | echo 'test_suite("lddtree")' >> $@.tmp 8 | for i in $(notdir $(wildcard tests/*_test)); do \ 9 | echo "atf_test_program{name='$$i',timeout=5}" >> $@.tmp ; \ 10 | done 11 | mv $@.tmp $@ 12 | 13 | Kyuafile: 14 | echo "syntax(2)" > $@.tmp 15 | echo "test_suite('alpine-conf')" >> $@.tmp 16 | echo "include('tests/Kyuafile')" >> $@.tmp 17 | mv $@.tmp $@ 18 | 19 | lint: 20 | shellcheck -e SC3043 lddtree.sh 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | lddtree 2 | ======= 3 | 4 | Fork of [pax-utils](https://github.com/gentoo/pax-utils)' [lddtree.sh](https://github.com/gentoo/pax-utils/blob/master/lddtree.sh) 5 | 6 | This is a shell version of pax-utils' lddtree. This tool is useful for 7 | resolving elf dependencies when creating initramfs images. 8 | 9 | Differences from pax-utils' bash version: 10 | 11 | * don't use /bin/bash 12 | * resolv symlinks 13 | * fall back to objdump and readelf if scanelf is not found 14 | 15 | lddtree.sh depends on scanelf from pax-utils or objdump and readelf from 16 | binutils. 17 | 18 | ``` 19 | Usage: lddtree.sh [options] ELFFILE... 20 | 21 | Options: 22 | -a, --all Show all duplicated dependencies 23 | -h, --help Show this help output 24 | -l, --flat Display output in a flat format 25 | --no-auto-root Do not automatically prefix input ELFs with ROOT 26 | -R, --root ROOT Use this ROOT filesystem tree 27 | -V, --version Show version information 28 | -x, --debug Run with debugging 29 | ``` 30 | 31 | -------------------------------------------------------------------------------- /lddtree.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright 2007-2013 Gentoo Foundation 3 | # Copyright 2007-2013 Mike Frysinger 4 | # Copyright 2014-2015 Natanael Copa 5 | # Distributed under the terms of the GNU General Public License v2 6 | 7 | argv0=${0##*/} 8 | version=1.27 9 | 10 | : "${ROOT:=/}" 11 | 12 | [ "${ROOT}" = "${ROOT%/}" ] && ROOT="${ROOT}/" 13 | [ "${ROOT}" = "${ROOT#/}" ] && ROOT="${PWD}/${ROOT}" 14 | 15 | version() { 16 | exec echo "lddtree-${version}" 17 | } 18 | 19 | error() { 20 | echo "${argv0}: $*" 1>&2 21 | ret=1 22 | return 1 23 | } 24 | 25 | # functions for scanelf backend 26 | elf_rpath_scanelf() { 27 | # shellcheck disable=SC2317 28 | scanelf -qF '#F%r' "$@" 29 | } 30 | 31 | elf_interp_scanelf() { 32 | # shellcheck disable=SC2317 33 | scanelf -qF '#F%i' "$@" 34 | } 35 | 36 | elf_needed_scanelf() { 37 | # shellcheck disable=SC2317 38 | scanelf -qF '#F%n' "$@" 39 | } 40 | 41 | elf_specs_scanelf() { 42 | # %a = machine (EM) type 43 | # %M = EI class 44 | # %D = endian 45 | # %I = osabi 46 | 47 | # With glibc, the NONE, SYSV, GNU, and LINUX OSABI's are compatible. 48 | # LINUX and GNU are the same thing, as are NONE and SYSV, so normalize 49 | # GNU & LINUX to NONE. #442024 #464380 50 | # shellcheck disable=SC2317 51 | scanelf -BF '#F%a %M %D %I' "$1" | \ 52 | sed -E 's: (LINUX|GNU)$: NONE:' 53 | } 54 | 55 | # functions for binutils backend 56 | elf_rpath_binutils() { 57 | # shellcheck disable=SC2317 58 | objdump -x "$@" | awk '$1 == "RUNPATH" { if($2!="") {runpath=$2;} } $1 == "RPATH" { if($2!="") {rpath=$2;} } END { if(runpath!="") {print runpath;} else {print rpath;} }' 59 | } 60 | 61 | elf_interp_binutils() { 62 | # readelf -p .interp ouputs: 63 | # 64 | # String dump of section '.interp': 65 | # [ 0] /lib/ld-musl-x86_64.so.1 66 | # 67 | # shellcheck disable=SC2317 68 | readelf -p .interp "$1" | sed -E -n '/\[\s*[0-9]\]/s/^\s*\[.*\]\s*(.*)/\1/p' 69 | } 70 | 71 | elf_needed_binutils() { 72 | # shellcheck disable=SC2317 73 | objdump -x "$@" | awk '$1 == "NEEDED" { line=line sep $2 ; sep="," } END { print line }' 74 | } 75 | 76 | elf_specs_binutils() { 77 | # get Class, Data, Machine and OS/ABI. 78 | # the OS/ABI 'GNU', 'System V' and 'Linux' are compatible so normalize 79 | # shellcheck disable=SC2317 80 | readelf -h "$1" \ 81 | | awk -F: '$1 ~ /Class|Data|Machine|OS.ABI/ {gsub(/^ +/, "", $2); print $2}' \ 82 | | sed -E -e 's/UNIX - (System V|Linux|GNU)/UNIX/' \ 83 | | tr '\n' ' ' 84 | } 85 | 86 | # elf wrapper functions 87 | elf_rpath() { elf_rpath_$BACKEND "$@"; } 88 | elf_interp() { elf_interp_$BACKEND "$@"; } 89 | elf_needed() { elf_needed_$BACKEND "$@"; } 90 | elf_specs() { elf_specs_$BACKEND "$1"; } 91 | 92 | unset lib_paths_fallback 93 | for p in "${ROOT}"lib* "${ROOT}"usr/lib* "${ROOT}"usr/local/lib*; do 94 | lib_paths_fallback="${lib_paths_fallback}${lib_paths_fallback:+:}${p}" 95 | done 96 | c_ldso_paths_loaded='false' 97 | find_elf() { 98 | _find_elf='' 99 | 100 | local elf="$1" needed_by="$2" interp= 101 | if [ "${elf}" != "${elf##*/}" ] && [ -e "${elf}" ] ; then 102 | _find_elf=${elf} 103 | return 0 104 | else 105 | check_paths() { 106 | local elf="$1" 107 | local pathstr="$2" 108 | IFS=: 109 | # shellcheck disable=SC2086 110 | set -- $pathstr 111 | unset IFS 112 | local path pe 113 | for path ; do 114 | : "${path:=${PWD}}" 115 | if [ "${path#"${ROOT}"}" = "${path}" ]; then 116 | path="${ROOT}${path#/}" 117 | fi 118 | pe="${path%/}/${elf#/}" 119 | if [ -e "${pe}" ] ; then 120 | if [ "$(elf_specs "${pe}")" = "${elf_specs}" ] ; then 121 | _find_elf=${pe} 122 | return 0 123 | fi 124 | fi 125 | done 126 | return 1 127 | } 128 | 129 | if [ "${c_last_needed_by}" != "${needed_by}" ] ; then 130 | c_last_needed_by="${needed_by}" 131 | c_last_needed_by_rpaths=$(elf_rpath "${needed_by}" | \ 132 | sed -E -e 's|:| |g' -e "s:[$](ORIGIN|\{ORIGIN\}):${needed_by%/*}:") 133 | fi 134 | if [ -n "${c_last_needed_by_rpaths}" ]; then 135 | check_paths "${elf}" "${c_last_needed_by_rpaths}" && return 0 136 | fi 137 | 138 | if [ -n "${LD_LIBRARY_PATH}" ] ; then 139 | check_paths "${elf}" "${LD_LIBRARY_PATH}" 140 | fi 141 | 142 | if ! ${c_ldso_paths_loaded} ; then 143 | c_ldso_paths_loaded='true' 144 | c_ldso_paths= 145 | read_ldso_conf() { 146 | local line p 147 | for p ; do 148 | # if the glob didnt match anything #360041, 149 | # or the files arent readable, skip it 150 | [ -r "${p}" ] || continue 151 | while read -r line ; do 152 | case ${line} in 153 | "#"*) ;; 154 | "include "*) read_ldso_conf "${line#* }" ;; 155 | *) c_ldso_paths="$c_ldso_paths:${ROOT}${line#/}";; 156 | esac 157 | done <"${p}" 158 | done 159 | } 160 | local _oldpwd="$PWD" 161 | # the 'include' command is relative 162 | if cd "$ROOT"etc 2>/dev/null; then 163 | interp=$(elf_interp "${needed_by}") 164 | local ldso_conf="${ROOT}"etc/ld.so.conf 165 | case "$interp" in 166 | */ld-musl-*) 167 | ldso_conf="${interp%.so*}" 168 | ldso_conf="${ROOT}"etc/${ldso_conf##*/}.path 169 | ;; 170 | esac 171 | if [ -r "$ldso_conf" ]; then 172 | read_ldso_conf "$ldso_conf" 173 | fi 174 | cd "$_oldpwd" || return 175 | fi 176 | fi 177 | if [ -n "${c_ldso_paths}" ] ; then 178 | check_paths "${elf}" "${c_ldso_paths}" && return 0 179 | fi 180 | 181 | check_paths "${elf}" "${lib_paths_ldso:-${lib_paths_fallback}}" && return 0 182 | fi 183 | return 1 184 | } 185 | 186 | list_existing_file() { 187 | if [ -e "$1" ]; then 188 | echo "$1" 189 | else 190 | echo "$1: Not found." >&2 191 | fi 192 | } 193 | 194 | # echo all intermediate symlinks and return the resolved path in 195 | # global variable _resolv_links 196 | resolv_links() { 197 | _resolv_links="$1" 198 | _list_files="$2" 199 | local oldpwd="$PWD" 200 | [ "$_list_files" = yes ] && list_existing_file "${_resolv_links}" 201 | cd "${_resolv_links%/*}" || return 202 | while [ -L "$_resolv_links" ]; do 203 | _resolv_links=$(readlink "$_resolv_links") 204 | case "$_resolv_links" in 205 | /*) _resolv_links="${ROOT}${_resolv_links#/}" 206 | cd "${_resolv_links%/*}" || break 207 | ;; 208 | */*) cd "${_resolv_links%/*}" || break 209 | ;; 210 | esac 211 | _resolv_links=$(pwd -P)/${_resolv_links##*/} 212 | [ "$_list_files" = yes ] && list_existing_file "${_resolv_links}" 213 | done 214 | cd "$oldpwd" || return 215 | } 216 | 217 | show_elf() { 218 | local elf="$1" indent="$2" parent_elfs="$3" 219 | local rlib lib libs 220 | local resolved 221 | find_elf "${elf}" 222 | resolved=${_find_elf} 223 | elf=${elf##*/} 224 | 225 | ${LIST} || printf "%${indent}s%s => " "" "${elf}" 226 | case ",${parent_elfs}," in 227 | *,${elf},*) 228 | ${LIST} || printf "!!! circular loop !!!\n" 229 | return 230 | ;; 231 | esac 232 | parent_elfs="${parent_elfs},${elf}" 233 | if ${LIST} ; then 234 | resolv_links "${resolved:-$1}" yes 235 | else 236 | resolv_links "${resolved:-$1}" no 237 | printf "%s" "${resolved:-not found}" 238 | fi 239 | resolved=${_resolv_links} 240 | if [ "${indent:-0}" -eq 0 ] ; then 241 | local elf_specs interp full_interp 242 | 243 | elf_specs=$(elf_specs "${resolved}") 244 | interp=$(elf_interp "${resolved}") 245 | # ignore interpreters that do not have absolute path 246 | [ "${interp#/}" = "${interp}" ] && interp= 247 | [ -n "${interp}" ] && interp="${ROOT}${interp#/}" 248 | 249 | if ${LIST} ; then 250 | [ -n "${interp}" ] && resolv_links "${interp}" yes 251 | else 252 | printf "%s" " (interpreter => ${interp:-none})" 253 | fi 254 | if [ -r "${interp}" ] ; then 255 | # Extract the default lib paths out of the ldso. 256 | lib_paths_ldso=$( 257 | strings "${interp}" | \ 258 | sed -nr -e "/^\/.*lib/{s|^/?|${ROOT}|;s|/$||;s|/?:/?|:${ROOT}|g;p}" | \ 259 | tr '\n' ':' 260 | ) 261 | fi 262 | full_interp=${interp} 263 | interp=${interp##*/} 264 | # If we are in non-list mode, then we want to show the "duplicate" interp 265 | # lines -- first the header (interp=>xxx), and then the DT_NEEDED line to 266 | # show that the ELF is directly linked against the interp. 267 | # If we're in list mode though, we only want to show the interp once. 268 | ${LIST} && allhits="${allhits},${interp}" 269 | fi 270 | ${LIST} || printf "\n" 271 | 272 | [ -z "${resolved}" ] && return 273 | 274 | libs=$(elf_needed "${resolved}") 275 | 276 | local my_allhits 277 | if ! ${SHOW_ALL} ; then 278 | my_allhits="${allhits}" 279 | allhits="${allhits},${libs}" 280 | fi 281 | 282 | oifs="$IFS" 283 | IFS=, 284 | # shellcheck disable=SC2086 285 | set -- ${libs} 286 | IFS="$oifs" 287 | 288 | for lib; do 289 | lib=${lib##*/} 290 | # No need for leading comma w/my_allhits as we guarantee it always 291 | # starts with one due to the way we append the value above. 292 | case "${my_allhits}," in 293 | *,${lib},*) continue;; 294 | esac 295 | # If the interp is being linked against directly, re-use the existing 296 | # full path rather than perform a search for it. When systems symlink 297 | # the interp to a diff location, we might locate a different path, and 298 | # displaying both doesn't make sense as it doesn't match the runtime -- 299 | # the ldso won't load another copy of ldso into memory from the search 300 | # path, it'll re-use the existing copy that was loaded from the full 301 | # hardcoded path. 302 | if [ "${lib}" = "${interp}" ]; then 303 | rlib=${full_interp} 304 | else 305 | find_elf "${lib}" "${resolved}" 306 | rlib=${_find_elf} 307 | fi 308 | show_elf "${rlib:-${lib}}" $(( ${indent:-0} + 4)) "${parent_elfs}" 309 | done 310 | } 311 | 312 | usage() { 313 | cat <<-EOF 314 | Display ELF dependencies as a tree 315 | 316 | Usage: ${argv0} [options] ELFFILE... 317 | 318 | Options: 319 | -a, --all Show all duplicated dependencies 320 | -h, --help Show this help output 321 | -l, --flat Display output in a flat format 322 | --no-auto-root Do not automatically prefix input ELFs with ROOT 323 | -R, --root ROOT Use this ROOT filesystem tree 324 | -V, --version Show version information 325 | -x, --debug Run with debugging 326 | EOF 327 | } 328 | 329 | SHOW_ALL=false 330 | SET_X=false 331 | LIST=false 332 | AUTO_ROOT=true 333 | 334 | if ! OPTS=$(getopt -n "$argv0" -o "ahlR:Vx" -l "all,help,list,no-auto-root,root:,version,debug" -- "$@"); then 335 | usage >&2 336 | exit 1 337 | fi 338 | eval set -- "$OPTS" 339 | while true; do 340 | case "$1" in 341 | -a|--all) SHOW_ALL=true;; 342 | -x|--debug) SET_X=true;; 343 | -h|--help) usage; exit 0;; 344 | -V|--version) version;; 345 | -R|--root) shift; ROOT="$1";; 346 | -l|--list) LIST=true;; 347 | --no-auto-root) AUTO_ROOT=false;; 348 | --) shift; break;; 349 | esac 350 | shift 351 | done 352 | 353 | if [ -z "$1" ]; then 354 | usage >&2 355 | exit 1 356 | fi 357 | 358 | ${SET_X} && set -x 359 | 360 | if which scanelf >/dev/null 2>&1; then 361 | BACKEND=scanelf 362 | elif which objdump >/dev/null 2>&1 && which readelf >/dev/null 2>&1; then 363 | BACKEND=binutils 364 | else 365 | error "This tool needs either scanelf or binutils (objdump and readelf)" 366 | exit 1 367 | fi 368 | 369 | ret=0 370 | for elf ; do 371 | unset lib_paths_ldso 372 | unset c_last_needed_by 373 | if ${AUTO_ROOT} && [ -z "${elf##/*}" ] ; then 374 | elf="${ROOT}${elf#/}" 375 | fi 376 | if [ ! -e "${elf}" ] ; then 377 | error "${elf}: file does not exist" 378 | elif [ ! -r "${elf}" ] ; then 379 | error "${elf}: file is not readable" 380 | elif [ -d "${elf}" ] ; then 381 | if $LIST; then 382 | echo "${elf}" 383 | else 384 | error "${elf}: is a directory" 385 | fi 386 | else 387 | allhits="" 388 | [ "${elf##*/*}" = "${elf}" ] && elf="./${elf}" 389 | show_elf "${elf}" 390 | fi 391 | done 392 | exit ${ret} 393 | 394 | -------------------------------------------------------------------------------- /tests/lddtree_test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env atf-sh 2 | 3 | . $(atf_get_srcdir)/test_env.sh 4 | : ${SH=/bin/sh} 5 | 6 | lddtree="$SRCDIR"/lddtree.sh 7 | testdata=$(atf_get_srcdir)/testdata 8 | 9 | init_tests \ 10 | lddtree_usage \ 11 | lddtree_version \ 12 | lddtree_sh \ 13 | lddtree_sh_list \ 14 | lddtree_sh_all \ 15 | lddtree_sh_debug \ 16 | lddtree_sh_missing_scanelf \ 17 | lddtree_root \ 18 | lddtree_no_auto_root \ 19 | lddtree_no_auto_root_list \ 20 | lddtree_ldso_conf \ 21 | lddtree_ld_musl_path_conf \ 22 | lddtree_rpath_origin_lib 23 | 24 | lddtree_usage_body() { 25 | # usage to stdout, empty stderr 26 | atf_check -o match:"Usage:" "$SH" "$lddtree" -h 27 | atf_check -o match:"Usage:" "$SH" "$lddtree" --help 28 | # usage to stderr, empty stdout 29 | atf_check -s exit:1 -e match:"Usage:" "$SH" "$lddtree" 30 | } 31 | 32 | lddtree_version_body() { 33 | for arg in -V --version; do 34 | atf_check -s exit:0 \ 35 | -o match:'lddtree-[0-9]*.[0-9]*' \ 36 | "$SH" "$lddtree" "$arg" 37 | done 38 | } 39 | 40 | # test without -R 41 | lddtree_sh_body() { 42 | atf_check -s exit:0 \ 43 | -o match:'sh => /bin/sh \(interpreter .*\)' \ 44 | "$SH" "$lddtree" /bin/sh 45 | } 46 | 47 | # test without -R, flat output 48 | # should only output lines prefixed with / 49 | lddtree_sh_list_body() { 50 | for arg in -l --list; do 51 | atf_check -s exit:0 \ 52 | -o match:'/bin/sh' \ 53 | -o not-match:'\(interpreter .*\)' \ 54 | -o not-match:'^[^/]' \ 55 | "$SH" "$lddtree" "$arg" /bin/sh 56 | done 57 | } 58 | 59 | lddtree_sh_all_body() { 60 | for arg in -a --all; do 61 | atf_check -s exit:0 \ 62 | -o match:'/bin/sh' \ 63 | -o match:'\(interpreter .*\)' \ 64 | "$SH" "$lddtree" "$arg" /bin/sh 65 | done 66 | } 67 | 68 | lddtree_sh_debug_body() { 69 | for arg in -x --debug; do 70 | atf_check -s exit:0 \ 71 | -o match:'/bin/sh' \ 72 | -o match:'\(interpreter .*\)' \ 73 | -e match:'^\+' \ 74 | "$SH" "$lddtree" "$arg" /bin/sh 75 | done 76 | } 77 | 78 | lddtree_sh_missing_scanelf_body() { 79 | for tool in scanelf objdump; do 80 | if PATH=/bin command -v "$tool"; then 81 | atf_skip "$tool found in /bin" 82 | fi 83 | done 84 | PATH=/bin atf_check -s exit:1 \ 85 | -e match:"needs either scanelf or binutils" \ 86 | "$SH" "$lddtree" /bin/sh 87 | } 88 | 89 | lddtree_root_body() { 90 | cp -rva $(atf_get_srcdir)/testdata/x86_64/* "$PWD" \ 91 | || atf_fail "failed to copy test data" 92 | for arg in -R --root; do 93 | atf_check -s exit:0 \ 94 | -o match:"^hello => $PWD/usr/bin/hello \(interpreter => $PWD/lib/ld-musl-x86_64.so.1\)" \ 95 | -o match:"^ libhello.so.1 => $PWD/usr/lib/libhello.so.1" \ 96 | -o match:"^ libc.musl-x86_64.so.1 => $PWD/lib/libc.musl-x86_64.so.1" \ 97 | "$SH" "$lddtree" "$arg" "$PWD"/ /usr/bin/hello 98 | done 99 | } 100 | 101 | lddtree_no_auto_root_body() { 102 | cp -rva "$testdata"/x86_64/* "$PWD" \ 103 | || atf_fail "failed to copy test data" 104 | atf_check -s exit:0 \ 105 | -o match:"^hello => $PWD/usr/bin/hello \(interpreter => $PWD/lib/ld-musl-x86_64.so.1\)" \ 106 | -o match:"^ libhello.so.1 => $PWD/usr/lib/libhello.so.1" \ 107 | -o match:"^ libc.musl-x86_64.so.1 => $PWD/lib/libc.musl-x86_64.so.1" \ 108 | "$SH" "$lddtree" --no-auto-root --root "$PWD"/ "$PWD/usr/bin/hello" 109 | } 110 | 111 | lddtree_no_auto_root_list_body() { 112 | cp -rva "$testdata"/x86_64/* "$PWD" \ 113 | || atf_fail "failed to copy test data" 114 | atf_check -s exit:0 \ 115 | -o match:"/lib/ld-musl-x86_64.so.1" \ 116 | -o match:"/lib/libc.musl-x86_64.so.1" \ 117 | -o match:"/usr/bin/hello" \ 118 | -o match:"/usr/lib/libhello.so.1" \ 119 | -o match:"/usr/lib/libhello.so.1.0" \ 120 | -o not-match:"gnu" \ 121 | -o not-match:"ld-linux-x86-64.so.2" \ 122 | "$SH" "$lddtree" --list --no-auto-root --root "$PWD"/ "$PWD/usr/bin/hello" 123 | } 124 | 125 | lddtree_ldso_conf_body() { 126 | cp -rva "$testdata"/x86_64/* "$PWD" \ 127 | || atf_fail "failed to copy test data" 128 | mkdir etc 129 | echo "/usr/gnu/lib" > etc/ld.so.conf 130 | atf_check -s exit:0 \ 131 | -o match:"/usr/gnu/bin/hello" \ 132 | -o match:"/usr/gnu/lib/libhello.so.1" \ 133 | -o match:"/lib64/ld-linux-x86-64.so.2" \ 134 | -o match:"/lib/x86_64-linux-gnu/libc.so.6" \ 135 | -o not-match:"musl" \ 136 | -o not-match:"/usr/lib/libhello.so.1" \ 137 | "$SH" "$lddtree" --list --no-auto-root --root "$PWD"/ "$PWD/usr/gnu/bin/hello" 138 | } 139 | 140 | lddtree_ld_musl_path_conf_body() { 141 | cp -rva "$testdata"/x86_64/* "$PWD" \ 142 | || atf_fail "failed to copy test data" 143 | mkdir etc usr/musl 144 | mv usr/lib usr/musl/ 145 | echo "/usr/musl/lib" > etc/ld-musl-x86_64.path 146 | atf_check -s exit:0 \ 147 | -o match:"/usr/bin/hello" \ 148 | -o match:"/usr/musl/lib/libhello.so.1" \ 149 | -o match:"/lib/ld-musl-x86_64.so.1" \ 150 | -o match:"/lib/libc.musl-x86_64.so.1" \ 151 | -o not-match:"ld-linux-x86-64.so.2" \ 152 | -o not-match:"gnu" \ 153 | "$SH" "$lddtree" --list --no-auto-root --root "$PWD"/ "$PWD/usr/bin/hello" 154 | } 155 | 156 | lddtree_rpath_origin_lib_body() { 157 | cp -rva "$testdata"/x86_64/* "$PWD" \ 158 | || atf_fail "failed to copy test data" 159 | mkdir etc usr/musl 160 | mv -v usr/lib usr/bin usr/musl/ 161 | for bin in hello-rpath-origin-lib hello-rpath-origin-lib2; do 162 | atf_check -s exit:0 \ 163 | -o match:"/usr/musl/bin/hello" \ 164 | -o match:"/usr/musl/lib/libhello.so.1" \ 165 | -o match:"/lib/ld-musl-x86_64.so.1" \ 166 | -o match:"/lib/libc.musl-x86_64.so.1" \ 167 | -o not-match:"ld-linux-x86-64.so.2" \ 168 | -o not-match:"gnu" \ 169 | "$SH" "$lddtree" --list --no-auto-root --root "$PWD"/ "$PWD/usr/musl/bin/$bin" 170 | done 171 | } 172 | 173 | 174 | -------------------------------------------------------------------------------- /tests/test_env.sh: -------------------------------------------------------------------------------- 1 | # shellcheck shell=sh 2 | 3 | SRCDIR=$(atf_get_srcdir)/.. 4 | PATH=$SRCDIR:$PATH 5 | 6 | init_tests() { 7 | TESTS= 8 | for t; do 9 | TESTS="$TESTS $t" 10 | atf_test_case "$t" 11 | done 12 | export TESTS 13 | } 14 | 15 | atf_init_test_cases() { 16 | for t in $TESTS; do 17 | atf_add_test_case "$t" 18 | done 19 | } 20 | -------------------------------------------------------------------------------- /tests/testdata/x86_64/lib/ld-musl-x86_64.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncopa/lddtree/318c40861222540c624f010e2c16824f0c94ca3c/tests/testdata/x86_64/lib/ld-musl-x86_64.so.1 -------------------------------------------------------------------------------- /tests/testdata/x86_64/lib/libc.musl-x86_64.so.1: -------------------------------------------------------------------------------- 1 | ld-musl-x86_64.so.1 -------------------------------------------------------------------------------- /tests/testdata/x86_64/lib/x86_64-linux-gnu/ld-2.31.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncopa/lddtree/318c40861222540c624f010e2c16824f0c94ca3c/tests/testdata/x86_64/lib/x86_64-linux-gnu/ld-2.31.so -------------------------------------------------------------------------------- /tests/testdata/x86_64/lib/x86_64-linux-gnu/libc-2.31.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncopa/lddtree/318c40861222540c624f010e2c16824f0c94ca3c/tests/testdata/x86_64/lib/x86_64-linux-gnu/libc-2.31.so -------------------------------------------------------------------------------- /tests/testdata/x86_64/lib/x86_64-linux-gnu/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncopa/lddtree/318c40861222540c624f010e2c16824f0c94ca3c/tests/testdata/x86_64/lib/x86_64-linux-gnu/libc.so.6 -------------------------------------------------------------------------------- /tests/testdata/x86_64/lib64/ld-linux-x86-64.so.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncopa/lddtree/318c40861222540c624f010e2c16824f0c94ca3c/tests/testdata/x86_64/lib64/ld-linux-x86-64.so.2 -------------------------------------------------------------------------------- /tests/testdata/x86_64/usr/bin/hello: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncopa/lddtree/318c40861222540c624f010e2c16824f0c94ca3c/tests/testdata/x86_64/usr/bin/hello -------------------------------------------------------------------------------- /tests/testdata/x86_64/usr/bin/hello-rpath-cwd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncopa/lddtree/318c40861222540c624f010e2c16824f0c94ca3c/tests/testdata/x86_64/usr/bin/hello-rpath-cwd -------------------------------------------------------------------------------- /tests/testdata/x86_64/usr/bin/hello-rpath-origin-lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncopa/lddtree/318c40861222540c624f010e2c16824f0c94ca3c/tests/testdata/x86_64/usr/bin/hello-rpath-origin-lib -------------------------------------------------------------------------------- /tests/testdata/x86_64/usr/bin/hello-rpath-origin-lib2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncopa/lddtree/318c40861222540c624f010e2c16824f0c94ca3c/tests/testdata/x86_64/usr/bin/hello-rpath-origin-lib2 -------------------------------------------------------------------------------- /tests/testdata/x86_64/usr/gnu/bin/hello: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncopa/lddtree/318c40861222540c624f010e2c16824f0c94ca3c/tests/testdata/x86_64/usr/gnu/bin/hello -------------------------------------------------------------------------------- /tests/testdata/x86_64/usr/gnu/lib/libhello.so.1: -------------------------------------------------------------------------------- 1 | libhello.so.1.0 -------------------------------------------------------------------------------- /tests/testdata/x86_64/usr/gnu/lib/libhello.so.1.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncopa/lddtree/318c40861222540c624f010e2c16824f0c94ca3c/tests/testdata/x86_64/usr/gnu/lib/libhello.so.1.0 -------------------------------------------------------------------------------- /tests/testdata/x86_64/usr/lib/libhello.so.1: -------------------------------------------------------------------------------- 1 | libhello.so.1.0 -------------------------------------------------------------------------------- /tests/testdata/x86_64/usr/lib/libhello.so.1.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncopa/lddtree/318c40861222540c624f010e2c16824f0c94ca3c/tests/testdata/x86_64/usr/lib/libhello.so.1.0 --------------------------------------------------------------------------------