在 Raspberry Pi 运行 Linux 的 64 位版本上使用 GDB 调试 32 位程序集 Hello world

Issue debugging a 32-bits assembly Hello world with GDB on a Raspberry Pi running a 64 bit version of Linux

我正在尝试设置我的 Raspberry Pi 以便我可以开始学习 ARM,但在调试 32 位 ARM 文件时遇到问题。首先,一些信息可能对我的问题有用:

$ uname -a
Linux raspberrypi 5.15.32-v8+ #1538 SMP PREEMPT Thu Mar 31 19:40:39 BST 2022 aarch64 GNU/Linux

$ cat /etc/os-release 
PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=debian

我可以为 ARM64 编写一个 hello world 程序(汇编),使用 asld 编译它,然后执行它并使用 gdb 毫无问题地调试它。对于 32 位 ARM,安装包 binutils-arm-linux-gnueabihf 后,我可以使用 arm-linux-gnueabihf-as/ld 编译我的文件并毫无问题地执行它们。但是,我在使用 gdb 调试它们时遇到问题。

我的 gdb 版本是:

$ gdb -v
GNU gdb (Debian 10.1-1.7) 10.1.90.20210103-git

并且我正在使用 GEF 扩展。 32 位文件的 file 命令给出:

$ file helloworld
helloworld: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, not stripped

输入 gdb helloworld 后,我可以 运行 使用 r 命令,它会打印 Hello world,但我无法逐步调试它:设置断点到入口点(在我的例子中,0x10074 - 通过 info file 获得 - 这似乎不是标准的)使程序无限期地 运行 ,就好像它处于无限循环中一样,并用 CTRL 停止它+C 给我:

$sp  : 0x798fdfb4
$lr  : 0xc6ac9670
$pc  : 0x20      
$cpsr: [negative ZERO CARRY OVERFLOW INTERRUPT FAST thumb]
────────────────────────────────────────────────────────────────────────────────────────── stack ────
[!] Unmapped address: '0x55798fdfb4'
─────────────────────────────────────────────────────────────────────────────────── code:arm:ARM ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x20
──────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "helloworld", stopped 0x20 in ?? (), reason: SIGINT

我不确定发生了什么。 Unmapped address: '0x55798fdfb4'里面的地址貌似是PIE+ASLR下的标准.text地址,但是不知道为什么会出现映射问题。我该如何解决这个问题?

这个答案更像是对“如何在我的 raspberry Pi 上学习 32 位汇编语言”这个问题的回答,而不是对你的问题的直接回答:

如果您的目标是在您的 raspberry Pi 上学习 Aarch32 T32 或 A32 汇编语言,我强烈建议您在 32 位发行版上这样做 - 我不确定在这个阶段您是否可以调试Aarch64 Linux 系统上的用户模式 ​​Aarch32 程序使用 Aarch64 多体系结构 GDB 或 GDB 的 Aarch32 版本,我自己的尝试没有成功,并且直到今天还没有找到具体如何执行此操作的示例。 这种方法的另一个好处是,您将能够专注于学习 32 位 Arm,而不是问自己您的程序是否因为错误而无法运行,或者因为您正在使用的工具中的潜在 problem/bug 运行 在你的 Aarch64 系统上 - 我的两分钱。

如果您有备用的 8GiB micro-SD 卡,您可以安装 32 bit version of Ubuntu Server 22.04 from here

已安装,这是我在系统上得到的:

cat /sys/firmware/devicetree/base/model
Raspberry Pi 3 Model B Rev 1.2
uname -a
Linux ubuntu 5.15.0-1005-raspi #5-Ubuntu SMP PREEMPT Mon Apr 4 12:25:49 UTC 2022 armv7l armv7l armv7l GNU/Linux

安装 gcc 和 gdb:

sudo-apt -get install gcc gdb

创建 hello-world.s,改编自 this example:

        .arch armv7a
        .file   "hello-world.s"
        .text
        .global main
        .syntax unified
        .thumb
        .thumb_func
        .type   main, %function
main:
         mov r0, #1                      @ 1 = stdout
         ldr r1, =hello_world            @ str pointer
         mov r2, #13                     @ str len
         mov r7, #4                      @ linux write syscall
         svc 0                           @ software interrupt call write
exit:
         mov r0, #0                      @ return code
         mov r7, #1                      @ linux exit syscall
         svc 0                           @ software interrupt call exit
        .data
hello_world:
        .ascii "Hello World!\n"
        .end

as -g -o hello-world.o hello-world.s
gcc  -g -o hello-world hello-world.o

./hello-world
Hello World!

GDB 调试会话:

gdb ./hello-world
GNU gdb (Ubuntu 12.0.90-0ubuntu1) 12.0.90
Copyright (C) 2022 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 "arm-linux-gnueabihf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
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 ./hello-world...
(gdb) b main
Breakpoint 1 at 0x4e0: file hello-world.s, line 10.
(gdb) run
Starting program: /home/ubuntu/hello-world
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".

Breakpoint 1, main () at hello-world.s:10
10               mov r0, #1                      @ 1 = stdout
(gdb) step
11               ldr r1, =hello_world            @ str pointer
(gdb)
12               mov r2, #13                     @ str len
(gdb)
13               mov r7, #4                      @ linux write syscall
(gdb)
14               svc 0                           @ software interrupt call write
(gdb)
Hello World!
exit () at hello-world.s:16
16               mov r0, #0                      @ return code
(gdb)
17               mov r7, #1                      @ linux exit syscall
(gdb)
18               svc 0                           @ software interrupt call exit
(gdb)
[Inferior 1 (process 3043) exited normally]
(gdb) quit