如何从使用 Qemu 运行的裸机程序获取 UART 输出?
这是我一直在使用的命令行调用:
qemu-system-arm -M xilinx-zynq-a9 -cpu cortex-a9 -nographic -kernel $BUILD_DIR/mm.elf -m 512M -s -S
Run Code Online (Sandbox Code Playgroud)
xilinx-zynq-a9cortex-a9-m 512M表示平台有 512 MiB RAM-s是一个快捷方式-gdb tcp::1234-S意味着启动时冻结CPU我使用的ELF文件(mm.elf)执行一个简单的矩阵乘法运算,然后打印它是成功还是失败,以及运行了多长时间。ELF 是使用 Xilinx ARM 工具链编译的。我用它来进行软件故障注入。目前我使用 GDB 来询问应该打印的变量的值。然而,由于在故障注入的情况下打印可能会出现很多问题,因此最好看看通过 UART 实际发送的内容。
这有一些我尝试过的建议,但它不适用,因为问题是关于在主机终端窗口中获取 Linux 启动消息。
这是一个不太相关的问题,因为它仍然假设用户拥有某种引导加载程序。虽然从技术上讲必须有一个引导加载程序才能运行应用程序,但 Xilinx 在boot.S等文件中提供了此系统代码,然后将其编译到 ELF 文件中,作为之前运行的代码main。
我尝试将这些添加到当前 Qemu 命令的末尾。结果遵循尝试的参数。
-serial mon:stdio
-serial null …Qemu版本 4.2.0于 2019 年 12 月发布,包含一项称为TCG 插件的新功能。他们在test/plugins目录中有一些示例,并且 API 或多或少在qemu-plugin.h中定义。
该文件定义了两个枚举类型qemu_plugin_cb_flags和qemu_plugin_mem_rw,它们被传递到注册回调的函数中。这些枚举似乎表明回调是否会读取或写入 CPU 寄存器或内存。但是,所有示例插件都使用QEMU_PLUGIN_CB_NO_REGS,并且只有 2 个插件使用内存访问枚举。 hotpages.c并mem.c用作QEMU_PLUGIN_MEM_RW注册内存回调的默认值 ( qemu_plugin_register_vcpu_mem_cb)。 mem.c当插件加载时有一个参数来选择是读还是写,但是,它似乎在回调函数中没有任何区别。
我的问题是,如何从插件回调函数访问来宾内存和寄存器?API 似乎表明这是可能的,因为回调注册要求您说明是否要访问它们,以及它是 RW 还是只是读取。
有没有使用这部分 API 的示例?我意识到这是 Qemu 功能的一个非常新的部分。
当您在指令上注册回调时(例如insn.c中),您可以获得指令的虚拟地址。
uint64_t insn_vaddr = qemu_plugin_insn_vaddr(insn);
Run Code Online (Sandbox Code Playgroud)
我正在运行一个裸机ARM程序,这个虚拟地址似乎与ELF文件中指令的地址相关。
在内存回调函数内部,您可以调用qemu_plugin_get_hwaddr来获取内存访问的硬件地址,但我不确定该结构到底代表什么。
这个答案已有 7 年历史了,建议使用 GDB 接口。我的问题与使用 TCG 插件功能特别相关。