GDB 符号丢失 - libc 声称是错误的库或版本不匹配

GDB symbols missing - libc claimed to be wrong library or version mismatch

在使用 Yocto 构建的 ARM 交叉编译系统中,我无法在 GDB 的回溯中显示正确的调试符号。

abc.c 是一个简单的 printf("Hello world\n"); C 中的程序(没什么棘手的)。在构建机器上:

> yocto-dir/build/tmp-angstrom-glibc/sysroots/x86_64-linux/usr/bin/arm-angstrom-linux-gnueabi/arm-angstrom-linux-gnueabi-gcc abc --sysroot=yocto-dir/build/tmp-angstrom-glibc/sysroots/imx28scm -g -O0 -o abc
> scp abc root@DEVICE-IP:~

在 ARM 目标上:

> gdbserver :2345 abc

在构建机器上启动 GDB(从安装的 Yocto SDK):

> /usr/local/oecore-x86_64/sysroots/x86_64-angstromsdk-linux/usr/bin/arm-angstrom-linux-gnueabi/arm-angstrom-linux-gnueabi-gdb abc
GNU gdb (Linaro GDB) 7.8-2014.09
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-angstromsdk-linux --target=arm-angstrom-linux-gnueabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://bugs.linaro.org>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from abc...done.
(gdb) target remote DEVICE-IP:2345
Remote debugging using DEVICE-IP:2345
warning: Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
Cannot access memory at address 0x0
0x4ae90a20 in ?? ()
(gdb) bt
#0  0x4ae90a20 in ?? ()
#1  0x00000000 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb) set sysroot yocto-dir/build/tmp-angstrom-glibc/sysroots/imx28scm
Reading symbols from yocto-dir/build/tmp-angstrom-glibc/sysroots/imx28scm/lib/ld-linux.so.3...done.
Loaded symbols for yocto-dir/build/tmp-angstrom-glibc/sysroots/imx28scm/lib/ld-linux.so.3
Cannot access memory at address 0x0

设置好sysroot后,还是不给符号

(gdb) bt
#0  0x4ae90a20 in ?? ()
#1  0x00000000 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb) b main
Breakpoint 1 at 0x84a8: file abc.c, line 5.
(gdb) c
Continuing.

Breakpoint 1, main () at abc.c:5
5      printf("Hello world\n");

好的,当它遇到断点时,它会显示符号。

(gdb) bt
Cannot access memory at address 0x0
#0  main () at abc.c:5

然而,越过那里就很奇怪了。

(gdb) n
Cannot access memory at address 0x1
0x4aea6ea0 in ?? ()
(gdb) bt
#0  0x4aea6ea0 in ?? ()
#1  0x0000a014 in do_lookup_unique (Cannot access memory at address 0x1
undef_map=0x1, ref=0x0, strtab=0x56ebb27 <error: Cannot access memory at address 0x56ebb27>, sym=0x84a0 <main>, type_class=-1224757248, result=0x1, map=<optimized out>, 
    new_hash=<optimized out>, undef_name=<optimized out>) at /usr/src/debug/glibc/2.24-r0/git/elf/dl-lookup.c:332
#2  do_lookup_x (undef_name=<optimized out>, new_hash=<optimized out>, old_hash=<optimized out>, ref=0x0, result=<optimized out>, scope=0x177ff8e, i=<optimized out>, version=<optimized out>, 
    flags=-1224757248, skip=0x1, type_class=100, undef_map=0x1) at /usr/src/debug/glibc/2.24-r0/git/elf/dl-lookup.c:544
#3  0x4aec0b10 in ?? ()
Cannot access memory at address 0x1
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

找不到合适的版本 libc.so.6.

(gdb) info sharedlibrary
warning: .dynamic section for "yocto-dir/build/tmp-angstrom-glibc/sysroots/imx28scm/lib/libc.so.6" is not at the expected address (wrong library or version mismatch?)
From        To          Syms Read   Shared Object Library
0x000007d0  0x0001bee0  Yes         yocto-dir/build/tmp-angstrom-glibc/sysroots/imx28scm/lib/ld-linux.so.3
0x4aee73c0  0x4afe2018  No          yocto-dir/build/tmp-angstrom-glibc/sysroots/imx28scm/lib/libc.so.6
(gdb) n
Cannot find bounds of current function

它没有提供理想的调试体验。

在 yocto-dir sysroot(如上所用)以及 /usr/local/oecore-x86_64 中有一个 gcc。它们的行为相同。 /usr/local/oecore-x86_64 SDK 是全新构建和安装的。

类似地,在 yocto-dir(如上所用)和 /usr/local/oecore-x86_64 中有一个 imx28scm sysroot,它们的行为相同。 然而,他们显然有不同版本的 libc.so.6 - yocto-dir 的是 14.8MB,而 /usr/local/oecore-x86_64 的是 1.3MB。 这是一个问题,但是将这些位置中的任何一个设置为 sysroot 都不能解决问题。

一种解决方法是 link 和 -static。在这种情况下,GDB 确实给出了符号:

(gdb) target remote DEVICE-IP:2345
Remote debugging using DEVICE-IP:2345
_start () at ../sysdeps/arm/start.S:79
79  ../sysdeps/arm/start.S: No such file or directory.
(gdb) set sysroot yocto-dir/build/tmp-angstrom-glibc/sysroots/imx28scm
(gdb) bt
#0  _start () at ../sysdeps/arm/start.S:79
(gdb) b main
Breakpoint 1 at 0x8480: file abc.c, line 5.
(gdb) c
Continuing.

Breakpoint 1, main () at abc.c:5
5      printf("Hello world\n");
(gdb) n
6      return 0;
(gdb) n
7   }

-Wl,--verbose 的链接似乎表明它正在 link 与预期 sysroot 中的库连接:

yocto-dir/build/tmp-angstrom-glibc/sysroots/x86_64-linux/usr/libexec/arm-angstrom-linux-gnueabi/gcc/arm-angstrom-linux-gnueabi/6.2.1/ld: Attempt to open yocto-dir/build/tmp-angstrom-glibc/sysroots/imx28scm/lib/libc.so.6 succeeded

linker 也找到了这个,但它没有被称为 libc.so.6,所以大概这不是干扰。

yocto-dir/build/tmp-angstrom-glibc/sysroots/x86_64-linux/usr/libexec/arm-angstrom-linux-gnueabi/gcc/arm-angstrom-linux-gnueabi/6.2.1/ld: Attempt to open yocto-dir/build/tmp-angstrom-glibc/sysroots/imx28scm/usr/lib/libc.so succeeded

为什么会出现库版本不匹配的情况?我怎样才能让 GDB 显示它期望的库中的符号? 我不想 link 静态地显示。

请确保框中的 libc 与您的构建服务器中的相同。 抱歉,这应该是一条评论,但目前,我没有足够的声誉。

显然,用于 ARM 目标的 GDB 在尝试加载 main() 之前的符号时遇到问题 (Debugging shared libraries with gdbserver):

The problem I had was that gdbserver stops at the dynamic loader, before main, and the dynamic libraries are not yet loaded at that point, and so GDB does not know where the symbols will go in memory yet.

GDB appears to have some mechanisms to automatically load shared library symbols, and if I compile for host, and run gdbserver locally, running to main is not needed. But on the ARM target, that is the most reliable thing to do.

因此,将其设置为在点击 main 后加载共享符号:

> b main
> c
  <breakpoint hit>
> set sysroot <sysroot>

或者点击主键后重新加载符号。

> set sysroot <sysroot>
...
> b main
> c
  <breakpoint hit>
> nosharedlibrary
> sharedlibrary

或者在与 IDE 调试器交互时将符号的自动加载设置为在 GDB 启动时关闭可能很有用:

> set auto-solib-add off