How to single step ARM assembly in GDB on QEMU?

前端 未结 4 1726
死守一世寂寞
死守一世寂寞 2020-11-30 11:47

I\'m trying to learn about ARM assembler programming using the GNU assembler. I\'ve setup my PC with QEmu and have a Debian ARM-HF chroot environment.

If I assemble

相关标签:
4条回答
  • 2020-11-30 12:05

    You should add the -g option too to the assembling. Otherwise the codeline info is not included. That crash probably comes from running some garbage after the code lines. Maybe you should add the exit system call:

    mov eax, 1 ; exit
    mov ebx, 0 ; returm value
    int 0x80 ; system call
    
    0 讨论(0)
  • 2020-11-30 12:13

    Your problem here is that you're trying to run an ARM gdb under QEMU's user-mode emulation. QEMU doesn't support the ptrace syscall (that's what syscall number 26 is), so this is never going to work.

    What you need to do is run your test binary under QEMU with the QEMU options to enable QEMU's own builtin gdb stub which will listen on a TCP port. Then you can run a gdb compiled to run on your host system but with support for ARM targets, and tell that to connect to the TCP port.

    (Emulating ptrace within QEMU is technically very tricky, and it would not provide much extra functionality that you can't already achieve via the QEMU builtin gdbstub. It's very unlikely it'll ever be implemented.)

    0 讨论(0)
  • 2020-11-30 12:14

    Single step of an assembly instruction is done with stepi. disas will disassemble around the current PC. info regi will display the current register state. There are some examples for various processors on my blog for my ELLCC cross development tool chain project.

    0 讨论(0)
  • 2020-11-30 12:21

    Minimal working QEMU user mode example

    I was missing the -fno-pie -no-pie options:

    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
    

    On another terminal:

    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'
    ;
    

    This leaves us at main, in a split code / disassembly view due to layout split. You will also interested in:

    layout regs
    

    which shows the registers.

    At the end of the day however, GDB Dashboard is more flexible and reliable: gdb split view with code

    -fno-pie -no-pie is required because the packaged Ubuntu GCC uses -fpie -pie by default, and those fail due to a QEMU bug: How to GDB step debug a dynamically linked executable in QEMU user mode?

    There was no gdbserver --multi-like functionality for the QEMU GDB stub on QEMU 2.11: How to restart QEMU user mode programs from the GDB stub as in gdbserver --multi?

    For those learning ARM assembly, I am starting some runnable examples with assertions and using the C standard library for IO at: https://github.com/cirosantilli/arm-assembly-cheat

    Tested on Ubuntu 18.04, gdb-multiarch 8.1, gcc-arm-linux-gnueabihf 7.3.0, qemu-user 2.11.

    Freestanding QEMU user mode example

    This analogous procedure also works on an ARM freestanding (no standard library) example:

    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
    

    On another terminal:

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

    We are now left at the first instruction of the program.

    QEMU full system examples

    • Linux kernel: How to debug the Linux kernel with GDB and QEMU?
    • Bare metal: https://github.com/cirosantilli/newlib-examples/tree/f70f8a33f8b727422bd6f0b2975c4455d0b33efa#gdb
    0 讨论(0)
提交回复
热议问题