ldd、objdump、nm、strings、strip 等工具介绍
最近在做 Docker 镜像的时候发现镜像文件非常大,需要找出程序的依赖库,减少程序的大小,所以整理了一下相关的工具。基本上这些工具都在 GNU Binutils 中。
GNU Binary Utilities 或 binutils 是一整套的编程语言工具程序,用来处理许多格式的目标文件。当前的版本原本由在 Cygnus Solutions 的程序员以 Binary File Descriptor library(libbfd)所撰写。这个工具程序通常搭配 GCC、make、和 GDB 这些程序来使用。
它包含 20 个左右的工具,本文介绍了我在创建 Docker 镜像的时候的使用的几种工具。
ldd
ldd 不是 GNU Binutils 工具集中的一个工具,但是却是一个非常有用的工具, 它可以显示程序或者共享库所需的共享库。
# ldd main linux-vdso.so.1 => (0x00007ffc88fd4000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007faee13b8000) libc.so.6 => /lib64/libc.so.6 (0x00007faee0feb000) /lib64/ld-linux-x86-64.so.2 (0x00007faee15d4000)
依照 ldd 得手册, 有时候 ldd 会通过执行程序来获取依赖信息,对于来源不明的程序,执行这些程序可能会带来风险,所以对于来源不明的程序,可以使用 objdump
来分析。
objdump
onjdump 可以显示目标文件的信息,可以通过参数控制要显示的内容。
比如 -p
可以显示文件头内容, 通过 grep
可以查看依赖的库。
# objdump -p main|grep GLIBC 0x09691a75 0x00 02 GLIBC_2.2.5 0x09691972 0x00 03 GLIBC_2.3.2 0x09691a75 0x00 04 GLIBC_2.2.5
甚至可以查看 -T
可以查看动态符号表的内容:
# objdump -T main|grep GLIBC 0000000000000000 DO *UND* 0000000000000000 GLIBC_2.2.5 stderr 0000000000000000 DO *UND* 0000000000000000 GLIBC_2.2.5 fwrite 0000000000000000 DO *UND* 0000000000000000 GLIBC_2.2.5 vfprintf 0000000000000000 DO *UND* 0000000000000000 GLIBC_2.2.5 fputc 0000000000000000 DO *UND* 0000000000000000 GLIBC_2.2.5 abort 0000000000000000 DO *UND* 0000000000000000 GLIBC_2.2.5 pthread_mutex_lock 0000000000000000 DO *UND* 0000000000000000 GLIBC_2.3.2 pthread_cond_wait 0000000000000000 DO *UND* 0000000000000000 GLIBC_2.2.5 pthread_mutex_unlock 0000000000000000 DO *UND* 0000000000000000 GLIBC_2.3.2 pthread_cond_broadcast 0000000000000000 DO *UND* 0000000000000000 GLIBC_2.2.5 pthread_create 0000000000000000 DO *UND* 0000000000000000 GLIBC_2.2.5 nanosleep 0000000000000000 DO *UND* 0000000000000000 GLIBC_2.2.5 pthread_detach ......
nm
nm 显示目标文件的符号。
# nm go/bin/glide |more 0000000000908680 r andMask 0000000000901d00 r bswapMask 00000000009036c0 r BSWAP_SHUFB_CTL 0000000000b000e0 B bufio.ErrAdvanceTooFar 0000000000b000f0 B bufio.ErrBufferFull 0000000000b00100 B bufio.ErrFinalToken 0000000000b00110 B bufio.ErrInvalidUnreadByte 0000000000b00120 B bufio.ErrInvalidUnreadRune 0000000000b00130 B bufio.ErrNegativeAdvance 0000000000b00140 B bufio.ErrNegativeCount 0000000000b00160 B bufio.errNegativeRead 0000000000b00170 B bufio.errNegativeWrite 0000000000b00150 B bufio.ErrTooLong 00000000004d9140 T bufio.init 0000000000b21120 B bufio.initdone. 00000000004d6510 T bufio.(*Reader).Buffered 00000000004d59d0 T bufio.(*Reader).Discard 00000000004d5590 T bufio.(*Reader).fill 00000000004d57c0 T bufio.(*Reader).Peek 00000000004d5b70 T bufio.(*Reader).Read ......
strings
strings 显示文件中的可打印字符。
# strings main|grep GLIBC GLIBC_2.2.5 GLIBC_2.3.2 GLIBC_2.2.5
strip
通过上面的工具,可以分析出文件的依赖库,创建 Docker 镜像的时候只需把所需的依赖库加进去即可。
如果程序本身比较大,可以将程序压缩,去掉不需要的一些数据, 比如使用 strip
进行裁剪。
你可以通过参数控制要丢掉的哪些符号。比如去除符号表和行号信息:
strip main
libtool
Linux 下的 GNU Libtool 是一种属于 GNU 建构系统的 GNU 程序设计工具,用来产生便携式的库。这里引用 libtool 手册的说明:
libtool --mode=compile gcc -g -O -c foo.c
MacOS 下的 libtool 时另外一个工具,可以用来创建库:
libtool -dynamic -o c.dylib a.o b.o libtool -static -o c.a a.o b.o
ar
可以对静态库做创建、修改和提取的操作。
ar rv libNAME.a file1.o file2.o ar -d lib.a conflict.o ar -x lib.a
otool
比 nm 更强大,mac 还有一个对应的图形化工具——MachOView。
查看依赖动态库:
otool -L a.out
查看反汇编代码段:
otool -v -t a.out
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论