【问题标题】:The difference between 'singlestep' and 'singlestep_enabled' variables in QEMUQEMU 中 'singlestep' 和 'singlestep_enabled' 变量的区别
【发布时间】:2015-09-10 08:41:23
【问题描述】:

所以,我将一个新的特定拱门集成到 QEMU 仿真器中(QEMU 中的实现类似于 OpenRISC 拱门,因此您在回答时可以依赖这个拱门),并且我正在运行一些测试。
QEMU 是 2.0.93 版本

  1. 当我在正常模式下运行测试时,QEMU 以错误答案结束
  2. 当我在 -singlestep 模式下运行时,QEMU 失败,我的断言是在单步运行时将超过 1 个命令放入 TargetBlock
  3. 当我使用 GDB 运行 QEMU 时,它提供 singlestep_enabled 模式,var 等于 7(意思是 SSTEP_ENABLE|SSTEP_NOIRQ|SSTEP_NOTIMER),我得到了测试的正确答案。

问题是,为什么会这样,这两种模式之间的实际执行差异是什么? 到目前为止,我在网上没有找到太多关于 QEMU 的文档

【问题讨论】:

  • @Peter Teoh 曾经说过,singlestep_enabled 启用了“硬件单步仿真”(stackoverflow.com/a/23847965/2238032),但是如果有人告诉我为什么不允许用户使用这种模式,并且gdb 是,我将不胜感激
  • 有用! 另外,我不得不说 GDB 基本上每 TB 刷新 (tb_flush() func) 所以它把每一束代码放到同一个 TB每次。另外,如果 qemu 在某个先前生成的 Tb 中找到与某些代码相等的代码,它会从其页表(确切地说是 Page Descs)中加载它,而不是将其重新生成到新的 TB

标签: gdb qemu processor emulation


【解决方案1】:

这两个标志执行不同的功能。

'singlestep' 是一个布尔值,指示是否给出了命令行 '-singlestep' 选项。这基本上使 QEMU 进入了一种模式,它在每​​个 TB 中只放置一条客户指令。我们实际上并没有在每条指令后停下来。

'singlestep_enabled' 是每个 CPU 的,并且在 gdb 存根想要执行单步时设置(通过 cpu_single_step() 函数)。然后目标前端将发出执行单个指令并引发调试异常的代码。 (然后 gdb 存根将处理该异常并将控制权返回给调试器。)

您可能在代码中看到的第三种单步是模拟目标 CPU 的内置调试单步行为,我们至少在 x86 和 ARM 上实现了这种行为。这通常以特定于目标的方式处理,以提供客户 CPU 所需的步进语义。

如果您的代码为单步操作和正常操作生成了不同的答案,这可能意味着您在生成 TCG 代码的方式上存在错误:可能在辅助函数上没有正确的标志,或者错误处理 TCG 本地变量。或者,当发生加载/存储异常时,您可能无法正确恢复状态。

旁注:2.0.93 是 QEMU 的旧版本,甚至不是发布版本(它是 2.1 的候选发布版本)。如果你正在开发一个新的目标前端,你应该使用当前的 git master。

【讨论】:

  • 非常感谢您的回答。但实际上,我的拱门做错的只是在-singlestep 模式下将超过 1 个命令放入 TB,并因此提高断言。我假设我的翻译功能不能正常工作。如果我说某事,请标记我。错了
  • 并告诉我更多关于“第三种单步”的信息。我刚刚检查了 ARM arch 的翻译源,我没有发现与常见的单步有任何重大差异。它位于哪里?
  • ARM 体系结构单步是通过 pstate_ss 和 ss_active 标志处理的。关于这些在 translate.c 中的工作方式有一个很大的评论。 (这比 2.0.93 更新;正如我所说,如果您正在为其编写新功能,则应该使用最新的 QEMU。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-13
  • 2012-05-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多