GCC 4.8 在编译单元 header 中插入版本 4,即使使用 -gdwarf-2
GCC 4.8 inserts version 4 in a compilation unit header even with -gdwarf-2
我用 GCC 4.8 编译了一个应用程序,我试图在没有 GDB 7.5+(据说增加了对 DWARF-4 的支持)的旧系统上调试它。在该系统上升级 GDB 不是一个选项。我无法调试它,因为 GDB 输出以下消息:
Dwarf Error: wrong version in compilation unit header (is 4, should be 2) [in module a.out]
我尝试按照其他问题中的建议使用 -gdwarf-2 -gstrict-dwarf 进行编译,但编译器不断插入几个编译单元 headers 版本 4:
/tmp> readelf --debug-dump=info a.out | grep -A2 'Compilation Unit @'
readelf: Warning: CU at offset 6b contains corrupt or unsupported version number: 4.
readelf: Warning: CU at offset 1eb contains corrupt or unsupported version number: 4.
Compilation Unit @ offset 0x0:
Length: 0x67 (32-bit)
Version: 2
--
Compilation Unit @ offset 0x6b:
Length: 0x84 (32-bit)
Version: 4
--
Compilation Unit @ offset 0xf3:
Length: 0x62 (32-bit)
Version: 2
--
Compilation Unit @ offset 0x159:
Length: 0x8e (32-bit)
Version: 2
--
Compilation Unit @ offset 0x1eb:
Length: 0x136 (32-bit)
Version: 4
--
Compilation Unit @ offset 0x325:
Length: 0x62 (32-bit)
Version: 2
即使您按如下方式编译最小的 C 程序,也会发生这种情况:
/home/MuchToLearn/src> cat main.c
int main(void)
{
return 0;
}
/home/MuchToLearn/src> gcc -gdwarf-2 -gstrict-dwarf main.c
我是不是漏掉了什么?如果 -gdwarf-2 选项不会生成可由仅支持 DWARF-2 的旧 GDB 版本调试的二进制文件,那么它有什么意义?
编辑: Employed Russian 的回答是正确的。版本 4 编译单元来自 /usr/lib/crt1.o
和 /usr/lib/libc_nonshared.a
。为了解决这个问题,我将它们复制到本地目录并使用 strip -g
删除了它们的调试符号。然后,我按如下方式链接可执行文件:
ld -o main -dynamic-linker /lib/ld-linux.so.2 crt1.o /usr/lib/crti.o main.o /lib/libc.so.6 libc_nonshared.a /usr/lib/crtn.o
生成的可执行文件不包含任何第 4 版编译单元,GDB 不再对此抱怨。
This happens even if you compile a minimal C program as follows:
即使这个最小的程序也会静态 link 部分 libc(即 crt1.o
、crtbegin.o
等)。
您应该确认具有版本 4 的编译单元确实来自您的程序,而不是来自库(只需查看它们的 DW_AT_name
和 DW_AT_comp_dir
)。
我的 gcc-4.8:gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
在我要求时生成版本 2:
gcc -g -c t.c
readelf -wi t.o | grep -A2 'Compilation Unit'
Compilation Unit @ offset 0x0:
Length: 0x4e (32-bit)
Version: 4
gcc -gdwarf-2 -c t.c
readelf -wi t.o | grep -A2 'Compilation Unit'
Compilation Unit @ offset 0x0:
Length: 0x52 (32-bit)
Version: 2
如果版本 4 对象真的只是 crt1.o
或类似对象,请注意您可以安全地 运行 strip -g
这些对象——您不会损失太多(除非您有调试 libc 启动问题,这不太可能)。
我用 GCC 4.8 编译了一个应用程序,我试图在没有 GDB 7.5+(据说增加了对 DWARF-4 的支持)的旧系统上调试它。在该系统上升级 GDB 不是一个选项。我无法调试它,因为 GDB 输出以下消息:
Dwarf Error: wrong version in compilation unit header (is 4, should be 2) [in module a.out]
我尝试按照其他问题中的建议使用 -gdwarf-2 -gstrict-dwarf 进行编译,但编译器不断插入几个编译单元 headers 版本 4:
/tmp> readelf --debug-dump=info a.out | grep -A2 'Compilation Unit @'
readelf: Warning: CU at offset 6b contains corrupt or unsupported version number: 4.
readelf: Warning: CU at offset 1eb contains corrupt or unsupported version number: 4.
Compilation Unit @ offset 0x0:
Length: 0x67 (32-bit)
Version: 2
--
Compilation Unit @ offset 0x6b:
Length: 0x84 (32-bit)
Version: 4
--
Compilation Unit @ offset 0xf3:
Length: 0x62 (32-bit)
Version: 2
--
Compilation Unit @ offset 0x159:
Length: 0x8e (32-bit)
Version: 2
--
Compilation Unit @ offset 0x1eb:
Length: 0x136 (32-bit)
Version: 4
--
Compilation Unit @ offset 0x325:
Length: 0x62 (32-bit)
Version: 2
即使您按如下方式编译最小的 C 程序,也会发生这种情况:
/home/MuchToLearn/src> cat main.c
int main(void)
{
return 0;
}
/home/MuchToLearn/src> gcc -gdwarf-2 -gstrict-dwarf main.c
我是不是漏掉了什么?如果 -gdwarf-2 选项不会生成可由仅支持 DWARF-2 的旧 GDB 版本调试的二进制文件,那么它有什么意义?
编辑: Employed Russian 的回答是正确的。版本 4 编译单元来自 /usr/lib/crt1.o
和 /usr/lib/libc_nonshared.a
。为了解决这个问题,我将它们复制到本地目录并使用 strip -g
删除了它们的调试符号。然后,我按如下方式链接可执行文件:
ld -o main -dynamic-linker /lib/ld-linux.so.2 crt1.o /usr/lib/crti.o main.o /lib/libc.so.6 libc_nonshared.a /usr/lib/crtn.o
生成的可执行文件不包含任何第 4 版编译单元,GDB 不再对此抱怨。
This happens even if you compile a minimal C program as follows:
即使这个最小的程序也会静态 link 部分 libc(即 crt1.o
、crtbegin.o
等)。
您应该确认具有版本 4 的编译单元确实来自您的程序,而不是来自库(只需查看它们的 DW_AT_name
和 DW_AT_comp_dir
)。
我的 gcc-4.8:gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
在我要求时生成版本 2:
gcc -g -c t.c
readelf -wi t.o | grep -A2 'Compilation Unit'
Compilation Unit @ offset 0x0:
Length: 0x4e (32-bit)
Version: 4
gcc -gdwarf-2 -c t.c
readelf -wi t.o | grep -A2 'Compilation Unit'
Compilation Unit @ offset 0x0:
Length: 0x52 (32-bit)
Version: 2
如果版本 4 对象真的只是 crt1.o
或类似对象,请注意您可以安全地 运行 strip -g
这些对象——您不会损失太多(除非您有调试 libc 启动问题,这不太可能)。