Binuitils 介绍
The GNU Binutils are a collection of binary tools. The main ones are:
ld
- the GNU linkeras
- the GNU assemblergold
- a new, faster, ELF only linker
But they also include
bin | discription |
---|---|
addr2line | Converts address into filenames and line numbers |
ar | A utility for creating, modifying and extracting from archives |
c++filt | Filter to demangle encoded C++ symbols |
dlltools | Creates files for building and using DLLs |
elfedit | Allows alteration of ELF format files |
gprof | Displays profiling information |
gprofng | Collects and displays application performance data |
nlmconv | Convert object code into an NLM |
nm | Lists symbols from object files |
objcopy | Copies and translates object files |
objdump | Displays information from object files |
ranlib | Generates an index to contents of an archieve |
readelf | Displays information from any ELF format object file |
size | Lists the section sizes of an object or archive file |
strings | Lists printable strings from files |
strip | Discards symbols |
windmc | A Windows compatible message compiler |
windres | A compiler for Windows resource files |
以上摘录自GNU官方网站。此外,/usr/inlcude/elf.h
文件也是一个参考。下面是一些个人的记录。
Binutils 使用简记
链接器ld(1)
和 动态链接器ld-liunx(8)
的小结
链接器ld
是编译系统的最后一环,能够编译出目标文件.o
或共享文件.so
,基本等同于静态库文件lib<name>.a
和共享库文件lib<name>.so.X.Y.Z
。平常使用的基本形式为:
ld [-static] [-L library_path] [-l library_name] [-soname...] [*.so] [*.o] -o <output>
动态链接器/lib[64]/ld-linux.so.*
是用来处理程序装载时的共享库文件,代替e_entry
作为依赖共享库的程序的入口点,并完成自身和共享库依赖的装载、符号解析工作。该文件也可以直接运行,形式上为:
/lib64/ld-linux.so.* [OPTIONS] [PROGRAM [ARGUMENTS]]
鉴于现在的默认编译方式为动态链接,有必要了解一下ld-linux
的相关内容。
ldconfig
是管理共享库的基本工具。较为正式的共享库形式为lib<name>.so.主版本号.次版本号.发布版本号
,而能够保持基本兼容性的形式为lib<name>.so.X
,两者通过软链接关联,该形式称为SO-NAME
,一般应用程序中.dymanic
节中对共享库依赖的声明也为为其SO-NAME
。一般情况下,在生成lib<name>.so.X.Y.Z
后并拷贝到库目录后,调用sudo ldconfig
就能更新SO-NAME
。(以前手动搞的确挺笨)- 影响
ld-linux
的一些环境变量,更多的参考手册。LD_LIBRARY_PATH
,对ld
也有影响LD_PRELOAD
强制提前装载的共享库,可以覆盖某些符号,例如printf
。LD_DEBUG
可以使ld-linux
打印装载信息
使用C++filt
处理name mangling
C++ 的Name mangling虽然规则明确,但形式比较复杂。
c++filt _ZN9wikipedia7article6formatE
> wikipedia::article::format
不同编译器的 mangle 方式可能不同,这里需要注意适用范围。
nm
查看符号表(.symtab)
nm hello.o
> U _GLOBAL_OFFSET_TABLE_
> 0000000000000000 T main
> U puts
默认包括符号值、符号类型、符号名三栏
objdump
/readelf
两者的功能有较大的重叠,不过objdump
也能够做dissamble、read raw bits。但两者的主要功能还是解析ELF文件的各个section的信息,主要包括elf header、section header table、section header string table、symbol table,以及.text、.data、.rodata等段。该部分与ELF文件格式紧密相关,可以参考《程序员的自我修养:链接、装载与库》第3章。
ar
查看archive的目标文件
ar -t /usr/lib/x86_64-linux-gnu/libc.a
>>>
init-first.o
libc-start.o
sysdep.o
version.o
check_fds.o
libc-tls.o
elf-init.o
dso_handle.o
errno.o
errno-loc.o
...
其他相关工具
ldd (1)
: list shared object dependencies
ldd /bin/bash
>>>
linux-vdso.so.1 (0x00007ffdb6c72000)
libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f4c3d5b0000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f4c3d5aa000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4c3d3b8000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4c3d722000
其中动态链接器ld
和libc
是典型的:
libc
implements both standard C functions like strcpy() and POSIX functions (which may be system calls) like getpid()
libdl
则是运行时用于加载动态库的库(以上的依赖是装载时的动态库依赖)。而liunx-vsdo实际并不是文件,其描述man 7 vsdo
:
The “vDSO” (virtual dynamic shared object) is a small shared
library that the kernel automatically maps into the address space
of all user-space applications.
一般也不需过于关心。
参考内容
- 俞甲子等《程序员的自我修养:链接、装载与库》