如何在QEMU上的GDB中单步ARM组装?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在QEMU上的GDB中单步ARM组装?相关的知识,希望对你有一定的参考价值。

我正在尝试使用GNU汇编程序学习ARM汇编程序编程。我用QEmu设置了我的PC,并拥有Debian ARM-HF chroot环境。

如果我汇编并链接我的测试程序:

.text
.global _start
_start:
        mov     r0, #6
        bx      lr

有:

as test.s -o test.o
ld test.o -o test

然后将文件加载到gdb并在_start上设置断点:

root@Latitude-E6420:/root# gdb test
GNU gdb (GDB) 7.6.1 (Debian 7.6.1-1)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
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 "arm-linux-gnueabihf".
For bug reporting instructions, please see:
...
Reading symbols from /root/test...(no debugging symbols found)...done.
(gdb) break _start
Breakpoint 1 at 0x8054
(gdb)

如何单步执行代码,显示汇编程序源代码并监视寄存器?我尝试了一些基本的命令,但它们不起作用:

(gdb) break _start
Breakpoint 1 at 0x8054
(gdb) info regi
The program has no registers now.
(gdb) stepi
The program is not being run.
(gdb) disas
No frame selected.
(gdb) r
Starting program: /root/test 
qemu: Unsupported syscall: 26
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
qemu: Unsupported syscall: 26
During startup program terminated with signal SIGSEGV, Segmentation fault.
(gdb) 
答案

这里的问题是你试图在QEMU的用户模式仿真下运行ARM gdb。 QEMU不支持ptrace系统调用(这就是系统调用号26),所以这永远不会起作用。

您需要做的是在QEMU下使用QEMU选项运行测试二进制文件,以启用QEMU自己的内置gdb存根,该存根将侦听TCP端口。然后,您可以运行编译为在主机系统上运行但支持ARM目标的gdb,并告诉它连接到TCP端口。

(在QEMU中模拟ptrace在技术上非常棘手,并且它不会提供许多你无法通过QEMU内置gdbstub实现的额外功能。它不太可能实现。)

另一答案

最小工作QEMU用户模式示例

我错过了-fno-pie -no-pie选项:

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 -fno-pie -ggdb3 -no-pie -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 
  -ex 'layout split'
;

由于main,这使我们在layout split处于拆分代码/反汇编视图中。您还会对以下内容感兴趣:

layout regs

它显示了寄存器。

然而,在一天结束时,GDB仪表板更加灵活可靠:gdb split view with code

-fno-pie -no-pie是必需的,因为打包的Ubuntu GCC默认使用-fpie -pie,而那些由于QEMU错误而失败:How to GDB step debug a dynamically linked executable in QEMU user mode?

QEMU 2.11上的QEMU GDB存根没有类似gdbserver --multi的功能:How to restart QEMU user mode programs from the GDB stub as in gdbserver --multi?

对于那些学习ARM程序集的人,我正在使用断言启动一些可运行的示例,并在以下位置使用C标准库:https://github.com/cirosantilli/arm-assembly-cheat

在Ubuntu 18.04上测试,gdb-multiarch 8.1,gcc-arm-linux-gnueabihf 7.3.0,qemu-user 2.11。

独立QEMU用户模式示例

这个类似的过程也适用于ARM独立(无标准库)示例:

printf '
.data
    msg:
        .ascii "hello world\n"
    len = . - msg
.text
.global _start
_start:
    /* write syscall */
    mov r0, #1     /* stdout */
    ldr r1, =msg   /* buffer */
    ldr r2, =len   /* len */
    mov r7, #4     /* Syscall ID. */
    swi #0

    /* exit syscall */
    mov r0, #0 /* Status. */
    mov r7, #1 /* Syscall ID. */
    swi #0
' >  hello_world.S
arm-linux-gnueabihf-gcc -ggdb3 -nostdlib -o hello_world -static hello_world.S
qemu-arm -g 1234 ./hello_world

在另一个终端:

gdb-multiarch -q --nh 
  -ex 'set architecture arm' 
  -ex 'file hello_world' 
  -ex 'target remote localhost:1234' 
  -ex 'layout split' 
;

我们现在离开了该计划的第一个指令。

QEMU完整的系统示例

另一答案

使用stepi完成汇编指令的单步操作。 disas将在当前的PC周围进行拆解。 info regi将显示当前的寄存器状态。我的博客上为我的ELLCC交叉开发工具链项目提供了各种处理器的示例。

另一答案

您还应该为组装添加-g选项。否则,不包括代码行信息。崩溃可能来自于在代码行之后运行一些垃圾。也许你应该添加退出系统调用:

mov eax, 1 ; exit
mov ebx, 0 ; returm value
int 0x80 ; system call

以上是关于如何在QEMU上的GDB中单步ARM组装?的主要内容,如果未能解决你的问题,请参考以下文章

使用 GDB + Qemu 调试 Linux 内核

gdb 远程qemu-arm调试

在 Chrome 中单步执行 JavaScript 断点时如何查看 DOM?

你好!我现在在学用Linux 的gdb。我想问一下,单步运行怎么看gdb运行到了

视频更新:代码分析8之单步调试ARM64启动汇编与重定位

结合Yocto Qemu与Eclipse单步调试开发Linux Kernel