Programing

네이티브가 아닌 바이너리의 라이브러리 종속성을 나열하는 방법은 무엇입니까?

crosscheck 2020. 12. 30. 19:01
반응형

네이티브가 아닌 바이너리의 라이브러리 종속성을 나열하는 방법은 무엇입니까?


네이티브 플랫폼 용으로 개발할 때 ldd를 사용하여 내가 빌드 한 바이너리 실행 파일이 시작시로드하려고 시도하는 모든 공유 라이브러리 (.so 파일)를 나열 할 수 있습니다. 그러나 크로스 컴파일을 할 때 동일한 정보를 얻는 방법을 모릅니다. ldd같은 일반 바이너리 유틸리티 유틸리티 아닙니다 strip또는 ar함께 구축 할 수있는, gcc크로스 컴파일, 대신, 그것은 분명히 네이티브 플랫폼에서 실행 할 수있는 비밀 쉘 스크립트입니다.

그렇다면 교차 대상 binutils 도구를 사용하여 외부 바이너리에 대한 동적으로 연결된 종속성 목록을 얻을 수있는 방법이 있습니까?


외부 바이너리에 대한 동적으로 연결된 종속성 목록을 얻는 방법이 있습니까?

바이너리의 직접적인 종속성을 쉽게 나열 할 수 있습니다 .

readelf -d a.out | grep NEEDED

 0x0000000000000001 (NEEDED)             Shared library: [librt.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

전체 목록을 얻기 위해 재귀 적으로 계속할 방법이 없습니다 ldd. 모든 NEEDED라이브러리에 대해 수동으로 프로세스를 반복해야합니다 .


bash -x ldd /bin/ls무엇을하고 있는지 이해하기 위해 할 수 있습니다 ldd. ldd스크립트는 "비밀"이 아니다. 기본적으로 실행됩니다.

LD_TRACE_LOADED_OBJECTS=1 /lib64/ld-linux-x86-64.so.2 /bin/ls

따라서 시스템의 동적 로더를 사용합니다 (결과는 ldd실제 환경과 시스템 따라 달라 지기 때문입니다 !). 그러나 objdump -x /bin/ls실행 파일의 동적 섹션으로 검사 할 수 있습니다.

% objdump -x /bin/ls
  /bin/ls:     file format elf64-x86-64
  /bin/ls
  architecture: i386:x86-64, flags 0x00000112:
  EXEC_P, HAS_SYMS, D_PAGED
  start address 0x00000000004046d4

  Program Header:
      PHDR off    0x0000000000000040 vaddr 0x0000000000400040 paddr 0x0000000000400040 align 2**3
           filesz 0x00000000000001c0 memsz 0x00000000000001c0 flags r-x
    INTERP off    0x0000000000000200 vaddr 0x0000000000400200 paddr 0x0000000000400200 align 2**0
           filesz 0x000000000000001c memsz 0x000000000000001c flags r--
      LOAD off    0x0000000000000000 vaddr 0x0000000000400000 paddr 0x0000000000400000 align 2**21
           filesz 0x0000000000019ef4 memsz 0x0000000000019ef4 flags r-x
      LOAD off    0x000000000001a000 vaddr 0x000000000061a000 paddr 0x000000000061a000 align 2**21
           filesz 0x000000000000077c memsz 0x0000000000001500 flags rw-
   DYNAMIC off    0x000000000001a028 vaddr 0x000000000061a028 paddr 0x000000000061a028 align 2**3
           filesz 0x00000000000001d0 memsz 0x00000000000001d0 flags rw-
      NOTE off    0x000000000000021c vaddr 0x000000000040021c paddr 0x000000000040021c align 2**2
           filesz 0x0000000000000044 memsz 0x0000000000000044 flags r--
  EH_FRAME off    0x0000000000017768 vaddr 0x0000000000417768 paddr 0x0000000000417768 align 2**2
           filesz 0x00000000000006fc memsz 0x00000000000006fc flags r--
     STACK off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**3
           filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-

  Dynamic Section:
    NEEDED               libselinux.so.1
    NEEDED               librt.so.1
    NEEDED               libacl.so.1
    NEEDED               libc.so.6
    INIT                 0x0000000000402148
    FINI                 0x00000000004125f8
    HASH                 0x0000000000400260
    GNU_HASH             0x00000000004005c0
    STRTAB               0x0000000000401100
    SYMTAB               0x0000000000400620
    STRSZ                0x00000000000004d7
    SYMENT               0x0000000000000018
    DEBUG                0x0000000000000000
    PLTGOT               0x000000000061a208
    PLTRELSZ             0x0000000000000990
    PLTREL               0x0000000000000007
    JMPREL               0x00000000004017b8
    RELA                 0x0000000000401740
    RELASZ               0x0000000000000078
    RELAENT              0x0000000000000018
    VERNEED              0x00000000004016c0
    VERNEEDNUM           0x0000000000000003
    VERSYM               0x00000000004015d8

  Version References:
    required from librt.so.1:
      0x09691a75 0x00 05 GLIBC_2.2.5
    required from libacl.so.1:
      0x05822452 0x00 06 ACL_1.2
      0x05822450 0x00 04 ACL_1.0
    required from libc.so.6:
      0x09691a75 0x00 03 GLIBC_2.2.5
      0x0d696913 0x00 02 GLIBC_2.3

다시 말하지만, 실제 종속성은 바이너리가 실행되는 시스템에 따라 다릅니다 (예 : 어딘가에 LD_LIBRARY_PATH내 자신의 것을 가질 수 있기 때문에 libc.so.6나쁜 생각이 될 것입니다).

따라서 교차 변형이 필요합니다. objdump


에있는 동안 gdb, 공유 정보는 유사하다 ldd. 사람이 읽을 수있는 실행 파일의 런타임 정보를 제공합니다.
readelf경로와 다른 라이브러리 정보를 그리워 .
readelf호스트 연구에 아주 좋은 도구입니다. 개발자는 작동하는 것을 선택할 수 있습니다.


이것은 나를 도왔다

objdump -p /path/to/program | grep NEEDED 

좀비 스레드를 만들어서 미안하지만 OpenWRT 라우터에 대한 몇 가지 작업을 진행 중이며 jffs2 파티션에 복사 할 충분한 공간이 있는지 확인하기 위해 종속성을 확인하기를 원했습니다 e2fsck. 짧은 대답 : nope.avi .

Anyhoo, 나는 받아 들인 대답 과 약간의 (아마 지나치게 장황한) grep전화를 사용하고 약간의 손을 흔들고 약간의 유니콘 눈물 을 사용하는 작은 스크립트를 만들었습니다 (걱정하지 마십시오, 그들은 행복한 눈물이었습니다!). 나는 다음과 같은 스크립트를 작성했습니다. 당신은 모든 종속성. 특히 RE : 루프와 재귀, 그리고 항상 모든 바 시즘 (즉, 인덱스 배열)이라는 사실뿐만 아니라 개선의 여지가 많이 있다고 확신합니다. 그러나 이것은 적어도 명목상으로는 저에게 효과적입니다.

#!/bin/bash

declare -a search_path
declare -a found_deps

find_dependencies() {
    local file="$1"
    local -a deps
    local -a deps_to_process

    deps=( $( readelf -d "$file" | grep "NEEDED" | \
        grep -o -E "\[[^]]*\]" | grep -o -E "[^][]*" ) )

    local add_this_dep=true

    # always assume we've found $file and add it to the $found_deps list
    # if it's not there
    for found_dep in "${found_deps[@]}"
    do
        if [ "$found_dep" = "$(basename $file)" ]
        then
            add_this_dep=false
            break
        fi
    done

    # if $add_this_dep is true, go ahead and add to the found_deps list
    if $add_this_dep
    then
        found_deps+=("$(basename $file)")
    fi

    # for every dependency found by readelf (no path)
    for dep in "${deps[@]}"
    do
        local process_dep=true

        # if the basename of the file passed into the function is
        # this dep, skip processing altogether
        if [ "$dep" = "$(basename $file)" ]
        then
            break
        else
            # otherwise, if it's one of the 'found deps' don't process it
            for found_dep in "${found_deps[@]}"
            do
                if [ "$dep" = "$found_dep" ]
                then
                    process_dep=false
                    break
                fi
            done

            # it wasn't one of the 'found deps' so add 
            # it to the found_deps list
            if $process_dep
            then
                found_deps+=($dep)
            fi
        fi

        # if we are supposed to process this dep
        if $process_dep
        then
            local file_path=

            # check each search path for a file named $dep underneath it
            for dir in $search_path
            do
                file_path=$( find "$dir" -name "$dep" | head -n 1 )

                # if the $file_path is not empty, then we found
                # a copy of it, so break out of the loop
                if [ -n "$file_path" ]; then break; fi;
            done

            # if the $file_path is not empty, then we found a copy
            # of the file, place it the list of deps to be processed
            if [ -n "$file_path" ]
            then
                deps_to_process+=($file_path)
            fi
        fi
    done

    # now, go through all of our $deps_to_process (with path)
    # and run "find_dependencies" on them
    for dep_to_process in "${deps_to_process[@]}"
    do
        find_dependencies "$dep_to_process"
    done
}

argc=$#

if [ $argc -eq 0 ]
then
    printf '%s: prints dependencies of a (potentially) non-native elf executable, recursively\n'
    printf '\n'
    printf 'usage:\n'
    printf '\t%s <non-native elf executable> [ --supress-header ] [ <path> ... ]\n' "$(basename $0)"
    printf '\twhere\n'
    printf '\t\t<non-native elf executable> is the name of a file to find the dependencies of.\n'
    printf '\t\t[ <path> ... ] is an optional list of directories under which to search for libraries.\n'
    printf '\t\t[ --supress-header ] is an optional flag that prints nothing other than the list of files to stdout.\n'
    printf '\t\t\t(without the parameter a banner is sent to stderr)'
    printf '\n'
else
    file="$1"
    shift 1

    show_header=true

    if [ "$1" = "--supress-header" ]; then show_header=false; shift 1; fi;

    if $show_header
    then
        printf ' -------------------------------------------------------------------------------------------------------------\n' 1>&2
        printf '  ldd-nonnative: find all dependencies of a (potentially) non-native binary %s\n' "$file" 1>&2
        printf ' -------------------------------------------------------------------------------------------------------------\n' 1>&2
    fi

    search_path="$@"
    find_dependencies $file

    printf '\t%s\n' "${found_deps[@]}"
fi

# ❤ copyheart, shelleybutterfly, 2014
# love is never subject to the low; please copy and share with love :)

# contact information:
# shelleybutterfly@mojoprocode.com

# I hereby dedicate this software to the public domain in all jurisdictions
# where possible. In other jurisdictions, I license it to you under your
# choice of permissive license, as defined by the Open Source Institute (OSI),
# found at URL http://opensource.org. Should such a license be unavailable in
# your jurisdiection, you may use any copyleft open source license, again as
# defined by OSI; and if that too is unavailable, then you are licensed this
# software under the least restrictive possible terms allowed in your
# jurisdiction.

# I request but do not require that you give credit to me, shelleybutterfly,
# which I will accept in cases of licensing other than the public domain as
# valuable consideration for your use of my software. (I love to know that 
# my name is plastered all over some obscure piece of code that's at least
# appreciated by those who do see it, and I consider that more than enough
# consideration. :D) This software is provided completely as-is, and I take
# absolutely no responsibility for any damages that it may cause. It has
# not been fully tested and should be considered pre-alpha release quality,
# (that is to say, it is likely unstable and unsafe to use without your own
# validation to ensure that it meets some or any your needs without: among
# other things: melting your computer, calling your grandma at midnight,
# telling your girlfriend she's fat, and throwing your computer in the
# dishwasher to make sure it's clean, and you take full responsibility for
# doing your own testing to ensure that it suits your needs, and operates 
# properly int the conditions under which you intend to use it.

# Should you not be willing to take this risk, it is highly recommended
# that you do not use this software at all, ever, and that you instead find
# a real commercial piece of software, or other warranted piece of software,
# as I can not and do not and shall not provide any warranty of fitness for
# any purpose whatsoever, even to scrub your toilet, and it's provided with
# the understanding that it will be used primarily as an educational tool
# rather than any sort of production code. I disclaim any responsibility for
# anything that may happen to you due to your use of software, even if it
# causes huge zits, a rash under your boobs that wont go away, or a burning
# sensation when you pee. Sorry, **especially** for a burning sensation when
# you pee.

# Your use of this software implies acceptance of these terms as well as 
# any painful urination or other issues it may cause in your life.

# [deep breath] 

# my love to you all; I hope this software was useful to you in some way; if
# you end up using it despite the dire warnings against doing so, feel free
# to drop me a note at shelleybutterfly@mojoprocode.com, as I imagine it
# will be rare enough to make my day, every time. ♥

그래서, 간다. 누군가에게 도움이되기를 바랍니다. 예를 들어, 쉘 스크립팅을 충분히 사용하여 이와 같은 작업을 수행 할 수있을만큼 충분히 좋은 결과를 얻기까지 오랜 시간이 걸렸습니다. 예상보다 훨씬 오래 걸린다는 사실을 신경 쓰지 마십시오. 여러분 중 일부를 흔들었을 가능성이있는 것을 용서하십시오. 당신 존재의 핵심에 스크립트 전문가. :)


이 추가에 조금 늦었지만 누군가가 이익을 얻거나 명확히 할 수 있습니다. readelf에 대한 -A 플래그가 ldd와 동일한 결과를 제공하지 않습니까?

    $ readelf -AW /bin/vi

Library list section '.gnu.liblist' contains 8 entries:
     Library              Time Stamp          Checksum   Version Flags
  0: libselinux.so.1      2011-07-25T08:02:58 0x17a7d5f7 0       0
  1: libtermcap.so.2      2011-07-25T08:02:59 0x29ae9ff7 0       0
  2: libacl.so.1          2011-07-25T08:02:58 0x60748842 0       0
  3: libc.so.6            2011-07-25T08:02:58 0x0c2c7eeb 0       0
  4: libdl.so.2           2011-07-25T08:02:58 0xdfbfc467 0       0
  5: libsepol.so.1        2011-07-25T08:02:58 0x857499cb 0       0
  6: /lib64/ld-linux-x86-64.so.2 2011-07-25T08:02:58 0x9e6549b7 0       0
  7: libattr.so.1         2011-07-25T08:02:58 0x862f1546 0       0

여기서 누락 된 유일한 정보는 해당 라이브러리가있는 전체 경로 인 것 같습니다.

반면에 지금까지 언급 한 도구는 설치가 작동하는 것으로 알려진 경우에만 유용합니다. 가장 일반적인 문제는 다음과 같습니다.

  1. Installing a program (mostly via rpm) that then fails to start or crashes during start up. Somehow I think this is related to library incompatibilities but I haven't found an easy way of checking these thing before installing a program (nor indeed after)
  2. In an attemtp to overcome (1), sometimes I have resorted to downloading the sources and compiling locally. The typical configure script is partially helpful because it tells you which libraries you are missing. However, it fails to tell you what the lowest version of such libraries are required

Can anyone shed some light on these issues? BTW, I have tried reading installation instructions and release notes but they are almost always nowhere near sufficient.

A beefy example may put everything into context, so please try compiling Cinelerra.


By design ldd can only been executed on target. However, it is possible to mimic ldd behavior using readelf. A script called `xldd' was developed in crosstool-ng project. An independent version of this script is available here:

https://gist.github.com/jerome-pouiller/c403786c1394f53f44a3b61214489e6f


To list shared libraries dependency of a non-native binary, you can try the following tool: http://www.mathembedded.com/component/k2/item/1-cross-ldd.html

I use it on SH4 and MIPS. As reported in other answer, you can achieve the same using readelf output and a recursive loop, but I have never try by myself since cross-ldd exist.


some depends idiot just uploaded this. i'm sure it shows things LDD doesn't but it's not well tested yet. a small bit of output is shown below.

http://sourceforge.net/p/dep-trace/

http://sourceforge.net/projects/dep-trace/files/libdeps

should show total dependancy table of what ldconfig(1) will load (or has already loaded) and show which libs are NOT_FOUND (ie, no version or file) and then also what is effected.

try it, enjoy. it's very new so don't say i didn't tell you. it did just find some things below i didn't know about my lib system - i'm just about to go fix that.

# libdeps objdump -h
Experimental - see help
libdeps [objdump | ldd] [-l | file]
       -l  use find *.so is used on ldconfig dirs
     file  one file.so per line
snip...

# libdeps objdump -d

LIBTABLE

ld-linux.so.2(file)

ld-linux.so.2(GLIBC_2.0)(file)

ld-linux.so.2(GLIBC_2.1)(file)

ld-linux.so.2(GLIBC_2.0)(file)

ld-linux.so.2(GLIBC_2.3)(file)

ld-linux.so.2(GLIBC_2.1)(file)

ld-linux.so.2(GLIBC_PRIVATE)(file)

ld-linux.so.2(GLIBC_2.3)(file)

libBrokenLocale.so.1(file)

snip ...

libc.so.6 libc.so.6(file) ld-linux.so.2 ld-linux.so.2(GLIBC_2.0) ld-linux.so.2(GLIBC_2.1) ld-linux.so.2(GLIBC_PRIVATE)

snip ...

libanl.so.1 libanl.so.1(file) ld-linux.so.2 ld-linux.so.2(GLIBC_2.0) ld-linux.so.2(GLIBC_2.1) ld-linux.so.2(GLIBC_PRIVATE) libc.so.6(GLIBC_2.1.3) libc.so.6(GLIBC_2.0) libc.so.6 libc.so.6(GLIBC_2.1) libc.so.6(GLIBC_2.3) libc.so.6(GLIBC_2.2) libc.so.6(GLIBC_PRIVATE) libc.so.6(GLIBC_2.3.2) libc.so.6(GLIBC_2.1.2) libpthread.so.0(GLIBC_2.1) libpthread.so.0


libnss_db.so.2 libnss_db.so.2(file) ld-linux.so.2 ld-linux.so.2(GLIBC_2.0) ld-linux.so.2(GLIBC_2.1) ld-linux.so.2(GLIBC_PRIVATE) libc.so.6(GLIBC_2.1.3) libc.so.6(GLIBC_2.0) libc.so.6 libc.so.6(GLIBC_2.1) libc.so.6(GLIBC_2.3) libc.so.6(GLIBC_2.2) libc.so.6(GLIBC_PRIVATE) libnss_files.so.2 libnss_files.so.2(GLIBC_PRIVATE) libdb3.so.3(NOT_FOUND) libdb3.so.3(DB3_2)(NOT_FOUND)

snip...

NOT_FOUND
libctutils.so.0

libdb3.so.3

libdb3.so.3(DB3_2)

EFFECTED
libctutils.so.0 libconsole.so.0

libdb3.so.3 libnss_db.so.2

libdb3.so.3(DB3_2) libnss_db.so.2

libconsole.so.0

libnss_db.so.2

12/04/14  21:56  -0500     Thursday,  December  04,  2014,  09:56:35 PM  EST

ReferenceURL : https://stackoverflow.com/questions/10052041/how-to-list-library-dependencies-of-a-non-native-binary

반응형