1 问题背景
最近有个项目需要将libwebp这个库的source code移植到linux 平台下,因为只需要部分功能,所以对代码进行了精简。精简过后可以编译通过,so加载到开发板上却无法实现对应的功能,也没有报出明显的错误。因为之前有遇到过引用了没有声明或者没有实现的函数导致so不能使用的情况,所以怀疑精简的时候出了问题,导致误删除了一些函数。
百度了一下linux 平台上如何查看so依赖的函数或者lib 是否有缺失方法,出现了ldd 这个命令,执行以下shell命令即可查看目标so依赖了哪些lib或函数,同时可以查看依赖项是否有缺失。
ldd -r xxx.so
执行后输出如下log,发现移植libwebp的so有一些undefined symbol error,应该是没有定义、函数没有实现或者是头文件没有引用等。
[15:17:30.658]undefined symbol: WebPUnfilters (./xxx.so)
[15:17:30.658]undefined symbol: WebPRescalerExportRow (./xxx.so)
[15:17:30.658]undefined symbol: WebPRescalerDspInit (./xxx.so)
[15:17:30.658]undefined symbol: WebPRescalerImportRow (./xxx.so)
[15:17:30.658]undefined symbol: VP8FiltersInit (./xxx.so)
对照了error项所指的函数,逐一排查,最终完美解决该问题。鉴于该命令的强大之处,于是想再深入了解一下该命令的用法。
2 ldd命令的详细用法
linux平台下想要知道某个shell命令的方法很简单,用man + 命令就可以看到该命令的用法。
man ldd
摘出了一些有用的信息:
LDD(1) Linux Programmer's Manual LDD(1)
NAME
ldd - print shared object dependencies
SYNOPSIS
ldd [option]... file...
DESCRIPTION
ldd prints the shared objects (shared libraries) required by each program or shared object specified on the command line. An example of its use and output is the following:
$ ldd /bin/ls
linux-vdso.so.1 (0x00007ffcc3563000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f87e5459000)
libcap.so.2 => /lib64/libcap.so.2 (0x00007f87e5254000)
libc.so.6 => /lib64/libc.so.6 (0x00007f87e4e92000)
libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f87e4c22000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f87e4a1e000)
/lib64/ld-linux-x86-64.so.2 (0x00005574bf12e000)
libattr.so.1 => /lib64/libattr.so.1 (0x00007f87e4817000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f87e45fa000)
In the usual case, ldd invokes the standard dynamic linker (see ld.so(8)) with the LD_TRACE_LOADED_OBJECTS environment variable set to 1. This causes the dynamic linker to inspect the pro‐
gram's dynamic dependencies, and find (according to the rules described in ld.so(8)) and load the objects that satisfy those dependencies. For each dependency, ldd displays the location of
the matching object and the (hexadecimal) address at which it is loaded. (The linux-vdso and ld-linux shared dependencies are special; see vdso(7) and ld.so(8).)
OPTIONS
--version
Print the version number of ldd.
-v, --verbose
Print all information, including, for example, symbol versioning information.
-u, --unused
Print unused direct dependencies. (Since glibc 2.3.4.)
-d, --data-relocs
Perform relocations and report any missing objects (ELF only).
-r, --function-relocs
Perform relocations for both data objects and functions, and report any missing objects or functions (ELF only).
--help Usage information.
DESCRIPTION里说明了ldd命令用于打印指定的程序或so所需的so,并且有详细的示例。
OPTIONS里有一系列选项,含义分别如下所示:
--version:打印指令版本号;
-v:详细信息模式,打印所有相关信息;
-u:打印未使用的直接依赖;
-d:执行重定位和报告任何丢失的对象;
-r:对数据对象和函数执行重新定位,并报告任何缺少的对象或函数(仅限ELF)。;
--help:显示帮助信息。
可以看出,查看so的依赖是否有缺失使用-r参数即可。