【问题标题】:GDB symbols missing - libc claimed to be wrong library or version mismatch缺少 GDB 符号 - libc 声称库错误或版本不匹配
【发布时间】:2019-01-30 05:09:19
【问题描述】:

在使用 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 不能解决问题。

一种解决方法是链接-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 链接似乎表明它正在与预期的 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

链接器也找到了这个,但它没有被称为 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 显示它期望的库中的符号?我不希望静态链接。

【问题讨论】:

    标签: c linux debugging gdb cross-compiling


    【解决方案1】:

    请确保框中的 libc 与构建服务器中的相同。 对不起,这应该是一个cmets,但目前,我没有足够的声誉。

    【讨论】:

    • ARM 目标上的 libc.so.6 实际上略大于 /usr/local/oecore-x86_64 sysroot 之一 (1.3MB)。事实上,我看过的所有它旁边的共享库都比构建机器上的 sysroot 略大。确实很有趣,为什么 Yocto 会这样构建它……
    • 啊,如果你执行“b main, c”然后执行“set sysroot”,它会给出正确的符号。链接的答案说“我遇到的问题是 gdbserver 在 main 之前在动态加载器处停止,并且动态库此时尚未加载,因此 GDB 还不知道符号将在内存中的位置。GDB 出现有一些机制来自动加载共享库符号,如果我为主机编译,并在本地运行 gdbserver,则不需要运行到 main。但是在 ARM 目标上,这是最可靠的事情。但随后需要让 IDE 调试器来执行此操作...
    • 在你看到 ????您可以使用“nosharedlibrary”、“sharedlibrary”来取回符号,而不是符号。
    【解决方案2】:

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

    我遇到的问题是 gdbserver 在 main 之前在动态加载器处停止,此时动态库尚未加载,因此 GDB 还不知道符号将在内存中的位置。

    GDB 似乎有一些机制可以自动加载共享库符号,如果我为主机编译并在本地运行 gdbserver,则不需要运行到 main。但在 ARM 目标上,这是最可靠的做法。

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

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

    或者在你点击 main 之后重新加载符号。

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

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

    > set auto-solib-add off
    

    【讨论】:

      猜你喜欢
      • 2014-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-06
      • 2013-08-01
      • 2020-09-10
      • 1970-01-01
      相关资源
      最近更新 更多