调试链接警告“符号类型与原始声明不匹配”

ugo*_*ren 5 c gcc linkage lto

我正在尝试系统地调试以下问题:

% gcc -fPIC -flto -o try1.o -c try1.c
% gcc -fPIC -flto -o try2.o -c try2.c
% gcc -shared -flto -fPIC -o try.so try1.o try2.o
try2.c:1:14: warning: type of 'aaaaaaaa' does not match original declaration [enabled by default]
try1.c:1:5: note: previously declared here
Run Code Online (Sandbox Code Playgroud)

在这个综合测试中,我确切地知道了问题所在- 在这里aaaaaaaa定义int,但是short在那里。在我真正的问题中,链接组合了许多对象,这些对象是复杂的构建过程的结果,而且我不知道哪两个对象包含冲突的定义。

我想通过检查每个链接的目标文件来解决它,看看每个文件中如何定义符号,并找到一对定义不匹配的文件。然后,我将跟踪构建过程,以了解它们是如何构建的,并找到根本原因。但是我不知道查看对象定义方式的方法。

我尝试了nm -Aobjdump -t,但是它们没有显示符号类型/大小:

% nm -A try1.o
try1.o:00000001 C __gnu_lto_v1
try1.o:00000000 D aaaaaaaa
% nm -A try2.o
try2.o:00000001 C __gnu_lto_v1
try2.o:         U aaaaaaaa
try2.o:00000000 T foo
% objdump -t try1.o | grep aaa
00000000 g     O .data  00000004 aaaaaaaa
% objdump -t try2.o | grep aaa
00000000         *UND*  00000000 aaaaaaaa
Run Code Online (Sandbox Code Playgroud)

我的编译器:

% gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Run Code Online (Sandbox Code Playgroud)

a3f*_*a3f 2

使用nm --print-size。GNUnm默认为 BSD 格式,仅显示值。这不会显示未定义符号的大小,因为链接不需要此信息,并且不会存储在任何地方。

使用 进行编译时-flto,GCC 添加了几个.gnu.lto_.section,其中包含未定义符号的预期大小。我不知道是否有任何现成的工具可以解析它们。

您可以使用以下命令显示十六进制转储:

F=try2.o; objdump -h $F | grep -o '\.gnu.lto_\S*' | xargs -I% readelf -x % $F
Run Code Online (Sandbox Code Playgroud)