C语言 Debugging qemu-arm SIGSEGV



背景

我正在Docker for Mac上的Docker容器中运行qemu-arm用户空间模拟器。

我正在开发一个在cortex-m4处理器上运行的代码库。我希望能够交叉编译docker容器中的代码,以针对cortex-m4处理器,并在qemu-arm用户空间模拟器上运行该代码。

为了测试这一点,我有一个简单的C程序(/tmp/program.c):

int main() {
return 0;
}

我使用debian:稳定的docker图像作为基础。

我用GNUarm工具链编译程序,如下所示:

arm-none-eabi-gcc -mcpu=cortex-m4 --specs=nosys.specs /tmp/program.c

然后,我尝试在docker容器中使用qemu-arm运行此操作:

qemu-arm -cpu cortex-m4 -strace ./a.out

但我得到以下错误:

--- SIGSEGV {si_signo=SIGSEGV, si_code=1, si_addr=0x0007fff0} ---
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault

据我所知,SIGSEGV发生在几种情况下,这里唯一有意义的是,当我试图在qemu-arm用户空间中运行二进制文件时,我正在访问我无法访问的内存。

似乎si_addr=0x0007fff0是我正在访问的地址,而我不应该访问。

由于我的程序做得很少,我假设这个不可访问的地址可能是qemu-arm试图存储二进制文件以运行的地方?但我在qemu-arm中看不到指定这一点的选项。

问题

所以我的问题是:

  • 如何验证是什么试图访问该无法访问的地址
  • 如果我的想法是正确的(qemu-arm正试图在这里存储要运行的二进制文件),有办法改变吗?我在任何命令行选项中都没有看到

更多信息

Docker version 20.10.6, build 370c289

Dockerfile复制:

FROM debian:stable
RUN apt-get update
RUN apt-get install -y gcc-arm-none-eabi qemu-user gcc
RUN echo 'int main() {return 0;}' > /tmp/program.c
# running the program on the docker container exits successfully
RUN gcc /tmp/program.c
RUN ./a.out
# running the program in `qemu-arm` errors
RUN arm-none-eabi-gcc -mcpu=cortex-m4 --specs=nosys.specs /tmp/program.c
RUN qemu-arm -cpu cortex-m4 -strace ./a.out

qemu-arm是Linux用户空间二进制文件的模拟器。您正在编译的程序似乎是用裸金属工具链构建的。编译一个裸机二进制文件,使其也能作为Linux用户空间程序运行,这并非不可能,但必须采取特定步骤才能使其以这种方式工作。

你可能应该考虑一下你真正想要的是不是:

  • 构建一个针对Cortex-M4的Linux二进制文件,并在qemu arm上运行
  • 构建一个裸机二进制文件,并在qemu系统arm上运行
  • 其他的东西

例如,您希望程序如何产生输出?程序是想直接与(模拟的)硬件(如串行端口)通话,还是与其他设备通话?程序是否需要运行中断处理程序?

调试正在发生的事情的最好方法是让QEMU启动它的gdbsub,并将一个arm感知的gdb连接到它。(这可能是对工具链的C运行时启动代码的一个令人困惑的介绍…)

最新更新