背景
我正在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运行时启动代码的一个令人困惑的介绍…)