Linux 如何列出非本机二进制文件的库依赖项?

Linux 如何列出非本机二进制文件的库依赖项?,linux,gcc,shared-libraries,cross-compiling,binutils,Linux,Gcc,Shared Libraries,Cross Compiling,Binutils,在为本机平台开发时,我可以使用ldd列出所有共享库(.so文件),我构建的二进制可执行文件将在启动时尝试加载。但是当交叉编译时,我不知道如何获得相同的信息。ldd不像strip或ar那样是一个普通的binutils实用程序,它可以与gcc一起构建以进行交叉编译,但它是一个神秘的shell脚本,显然只能在本机平台上运行 那么,使用跨目标binutils工具,有没有办法获得一个动态链接的外来二进制文件的依赖项列表?您可以通过bash-x ldd/bin/ls了解ldd在做什么。ldd脚本没有那么“神

在为本机平台开发时,我可以使用ldd列出所有共享库(.so文件),我构建的二进制可执行文件将在启动时尝试加载。但是当交叉编译时,我不知道如何获得相同的信息。
ldd
不像
strip
ar
那样是一个普通的binutils实用程序,它可以与
gcc
一起构建以进行交叉编译,但它是一个神秘的shell脚本,显然只能在本机平台上运行


那么,使用跨目标binutils工具,有没有办法获得一个动态链接的外来二进制文件的依赖项列表?

您可以通过
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\u路径
和我自己的
libc.so.6
,这是个坏主意)

因此,您需要一个交叉变量
objdump

是否有任何方法可以获取外部二进制文件的动态链接依赖项列表

您可以很容易地列出二进制文件的直接依赖项:

readelf -d a.out | grep NEEDED

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

我不知道有什么方法可以递归地继续这个过程以获得完整的列表(正如
ldd
所做的那样)。您必须手动为每个所需的
库重复此过程。

要列出非本机二进制文件的共享库依赖项,您可以尝试以下工具:

我在SH4和MIPS上使用它。
正如在另一个答案中所报告的,您可以使用readelf输出和递归循环来实现同样的效果,但我从未亲自尝试过,因为存在交叉ldd。

而在
gdb
中,信息共享类似于
ldd
。它提供了可执行文件的完整的人类可读运行时信息。
readelf
丢失路径和其他库信息
readelf
是一个非常好的宿主研究工具。开发者可以选择工作

很抱歉创建了一个僵尸线程,但我正在为我的OpenWRT路由器做一些事情,希望它检查一些依赖项,看看我的jffs2分区上是否有足够的空间来复制
e2fsck
。简短回答:

总之,我制作了一个小脚本,它使用了加上一些(可能过于冗长的)
grep
调用,并伴随着一点挥手和一些独角兽的眼泪(不用担心,它们是快乐的眼泪!),我成功地编写了下面的脚本,为您提供了所有依赖项。我确信还有很多改进的空间,尤其是循环和递归,以及始终都是bashism(即索引数组)这一事实,但这至少在名义上对我有效:

#/bin/bash
声明-搜索路径
声明-已找到一个\u deps
查找依赖项(){
本地文件=“$1”
本地-a部门
本地-从一个部门到另一个部门的流程
deps=($(readelf-d“$file”| grep“NEEDED”|\
grep-o-E“\[^]*\]”“| grep-o-E”[^][]*]”)
本地add\u this\u dep=true
#始终假定我们已找到$file并将其添加到$found\u deps列表中
#如果它不在那里
对于“${found_deps[@]}”中的found_dep
做
如果[“$found\u dep”=“$(basename$file)”]
然后
将此添加到dep=false
打破
fi
完成
#如果$add_this_dep为true,请继续并添加到find_dep列表中
如果$add\u这个dep
然后
找到_deps+=(“$(basename$文件)”)
fi
#对于readelf找到的每个依赖项(无路径)
对于“${deps[@]}”中的dep
做
本地进程_dep=true
#如果传入函数的文件的basename为
#此dep将完全跳过处理
如果[“$dep”=“$(basename$file)”]
然后
打破
其他的
#否则,如果它是“已找到的deps”之一,请不要处理它
对于“${found_deps[@]}”中的found_dep
做
如果[“$dep”=“$found\u dep”]
然后
进程dep=false
打破
fi
完成
#这不是一个“找到的dep”,所以添加
#将其添加到已找到的deps列表中
如果$process\U dep
然后
已找到_deps+=($dep)
fi
fi
#如果我们要处理这个dep
如果$process\U dep
然后
本地文件路径=
#在每个搜索路径下检查名为$dep的文件
对于$search\u路径中的dir
做
文件路径=$(查找“$dir”-名称“$dep”|头-n1)
#如果$file_路径不是空的,那么我们找到了
#它的副本,所以打破循环
如果[-n“$file_path”];则break;fi;
完成
#如果$file_路径不是空的,那么我们找到了一个副本
#对于文件,将其放置在要处理的DEP列表中
如果[-n“$file\u path”]
然后
deps_to_进程+=($file_路径)
fi
fi
完成
#现在,通过我们所有的$deps\u-to\u流程(使用路径)
#并对其运行“查找依赖项”
对于“${deps_to_process[@]}”中的dep_to_进程
做
查找_依赖项“$dep_to_进程”
完成
}
argc=$#
如果[$argc-等式0]
然后
printf“%s:递归打印(可能)非本机elf可执行文件的依赖项\n
printf'\n'
printf'用法:\n'
printf'\t%s[--supressheader][…]\n'$(basename$0)
printf'\t此处\n'
printf'\t\t是要查找依赖项的文件名。\n'
printf'\t\t[…]是一个
    $ 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
objdump -p /path/to/program | grep NEEDED