【问题标题】:How to GDB step debug a dynamically linked executable in QEMU user mode?如何在 QEMU 用户模式下 GDB 逐步调试动态链接的可执行文件?
【发布时间】:2018-12-20 23:41:03
【问题描述】:

例如对于 ARM,如果我静态编译,一切正常:

sudo apt-get install gdb-multiarch gcc-arm-linux-gnueabihf qemu-user
printf '
#include <stdio.h>
#include <stdlib.h>

int main() {
    puts("hello world");
    return EXIT_SUCCESS;
}
' >  hello_world.c
arm-linux-gnueabihf-gcc -ggdb3 -static -o hello_world hello_world.c
qemu-arm -L /usr/arm-linux-gnueabihf -g 1234 ./hello_world

在另一个终端上:

gdb-multiarch -q --nh \
  -ex 'set architecture arm' \
  -ex 'set sysroot /usr/arm-linux-gnueabihf' \
  -ex 'file hello_world' \
  -ex 'target remote localhost:1234' \
  -ex 'break main' \
  -ex continue \
;

这让我留在main,我可以像往常一样查看源代码和单步调试。

但是,如果我删除 -static 并保持其他所有内容不变,我的断点将永远不会被命中,程序会一直运行到完成:

The target architecture is assumed to be arm
Reading symbols from hello_world...done.
Remote debugging using localhost:1234
Reading symbols from /usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3...(no debugging symbols found)...done.
0xff7b3b80 in ?? () from /usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3
Breakpoint 1 at 0x50c: file hello_world.c, line 5.
Continuing.
[Inferior 1 (Remote target) exited normally]

可执行文件本身确实可以正常工作:

qemu-arm -L /usr/arm-linux-gnueabihf ./hello_world

打印:

hello world

我见过:How to single step ARM assembler in GDB on Qemu?,但它并没有具体涵盖动态链接可执行文件的情况。

在 Ubuntu 18.04、gdb-multiarch 8.1-0ubuntu3、gcc-arm-linux-gnueabihf 4:7.3.0-3ubuntu2、qemu-user 1:2.11+dfsg-1ubuntu7.3 上测试。

编辑:工作原始 crosstool-ng 设置

作为健全性检查,我尝试使用 crosstool-ng 获得一个干净的工具链,并且它有效:

git clone https://github.com/crosstool-ng/crosstool-ng
cd crosstool-ng
git checkout d5900debd397b8909d9cafeb9a1093fb7a5dc6e6
export CT_PREFIX="$(pwd)/.build/ct_prefix"
./bootstrap
./configure --enable-local
./ct-ng arm-cortex_a15-linux-gnueabihf
# Has to be older than host kernel, which is 4.15.
printf "
CT_LINUX_V_4_14=y
CT_LINUX_VERSION=\"4.14.0\"
" >> .config
./ct-ng oldconfig
env -u LD_LIBRARY_PATH time ./ct-ng build -j`nproc`
cd ..
crosstool-ng/.build/ct_prefix/arm-cortex_a15-linux-gnueabihf/bin/arm-cortex_a15-linux-gnueabihf-gcc -ggdb3 -o hello_world hello_world.c -ggdb3 -static -o hello_world hello_world.c
qemu-arm -L crosstool-ng/.build/ct_prefix/arm-cortex_a15-linux-gnueabihf/arm-cortex_a15-linux-gnueabihf/sysroot -g 1234 ./hello_world

在另一个外壳上:

./.build/ct_prefix/arm-cortex_a15-linux-gnueabihf/bin/arm-cortex_a15-linux-gnueabihf-gdb \
  -q --nh \
  -ex 'set architecture arm' \
  -ex 'set sysroot crosstool-ng/.build/ct_prefix/arm-cortex_a15-linux-gnueabihf/arm-cortex_a15-linux-gnueabihf/sysroot' \
  -ex 'file hello_world' \
  -ex 'target remote localhost:1234' \
  -ex 'break main' \
  -ex continue \
;

它也适用于gdb-multiarch提供的发行版。

【问题讨论】:

    标签: gdb qemu


    【解决方案1】:

    失败是由于-pie -fpie,并且有一个错误报告在:https://bugs.launchpad.net/qemu/+bug/1528239

    显式设置 -no-pie -fno-pie 使其在 crosstool-ng 和 Ubuntu 主机上都可以工作。

    不同之处在于 Ubuntu 的 GCC 默认使用 -fpie,而我的 crosstool-ng 版本没有。

    这可以通过以下方式检查:

    gcc -v
    

    主机 GCC 包含的内容:

    --enable-default-pie
    

    但不在 crosstool-ng 构建中。

    我是如何发现这一点的:前几天我在玩-fpie,我注意到.text 地址在这种情况下非常小:What is the -fPIE option for position-independent executables in gcc and ld?

    然后用打包的工具链看到break地址很小,就做了链接。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-23
      • 2011-06-07
      • 1970-01-01
      • 2018-06-23
      • 1970-01-01
      • 2011-06-09
      • 1970-01-01
      • 2019-09-12
      相关资源
      最近更新 更多