如何查看哪些 .o 文件构成了 .so 文件?
意味着如何从 .so 文件中注意到用于构建 .so 文件的目标文件是什么(如果我只有 .so 文件).
意味着如何从 .so 文件中注意到用于构建 .so 文件的目标文件是什么(如果我只有 .so 文件).
仅从一个共享库中无法确定编译成它的目标文件。如果幸运的话,您可能能够做出合理的猜测。
共享库是由链接器从目标文件和其他共享库制作而成的,但它并不包含用于构建它的目标文件或共享库。相反,静态库由存档程序ar
制作,它包含目标文件:它只是目标文件的ar
归档。
如果共享库未被剥离调试信息,则为了调试目的,其符号表将包含链接到共享库中的那些目标文件所编译的源文件的名称——至少是那些使用调试信息编译的源文件。通过那些源文件的名称,您可以推断出目标文件的名称,但不能确定。
例如,在这里我们从源文件foo.c
和bar.c
制作一个共享库。
将源文件编译为目标文件:
$ gcc -Wall -fPIC -c -o foo.o foo.c
$ gcc -Wall -fPIC -c -o bar.o bar.c
将目标文件链接起来以创建共享库:
$ gcc -shared -o libfoobar.so foo.o bar.o
然后:
$ readelf -s libfoobar.so | grep FILE
26: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
35: 0000000000000000 0 FILE LOCAL DEFAULT ABS foo.c
37: 0000000000000000 0 FILE LOCAL DEFAULT ABS bar.c
39: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
42: 0000000000000000 0 FILE LOCAL DEFAULT ABS
这句话的意思是三个源文件都为该库提供了调试信息,因此我们可以推断它们编译的目标文件可能是:
crtstuff.o
foo.o
bar.o
crtstuff.c
不是我们编译的源文件之一。它实际上包含了 C 运行库的初始化和结束代码,并且这些代码是从默认链接的 C 运行对象文件中被添加到我们的库中的。$ gcc -Wall -fPIC -c -o abc.o foo.c
$ gcc -Wall -fPIC -c -o xyz.o bar.c
$ gcc -shared -o libfoobar.so abc.o xyz.o
这也是一种完全可行的编译和链接库的方式。
如果库中已经去除了调试信息:
$ strip -g libfoobar.so
$ readelf -s libfoobar.so | grep FILE
$
不再使用FILE
符号。