不,没有分支监视器陷阱标志。
英特尔可能会制造一个,但还没有。
细节
让我们首先浏览并定义术语:
[请注意,所有这些仅与 Intel x86 有关]
陷阱标志 (TF)
如问题中所述,在执行指令后导致#DBG(通过异常0x1陷阱)。使用 RFLAGS 的第 8 位进行控制。
分支陷阱标志 (BTF)
TLDR:BTF 将 TF 的行为修改为仅在分支上触发异常。
从 2016 年 4 月版的英特尔 SDM 开始:
当软件同时设置 IA32_DEBUGCTL MSR 中的 BTF 标志(位 1)和 EFLAGS 寄存器中的 TF 标志时,处理器仅在导致分支的指令之后生成单步调试异常。 [1] 这种机制允许调试器单步执行由分支引起的控制传输。这种“分支单步”有助于在指令单步进一步缩小搜索范围之前将错误隔离到特定代码块。处理器在生成调试异常时清除 BTF 标志。调试器必须在恢复程序执行之前设置 BTF 标志以继续单步执行分支。
[1] 导致任务切换的 CALL、IRET 和 JMP 的执行永远不会导致单步调试异常(无论 BTF 标志的值如何)。调试器希望在切换到任务时出现调试异常,应在该任务的 TSS 中设置 T 标志(调试陷阱标志)。请参阅第 7.2.1 节,“任务状态段 (TSS)”。</p>
监控陷阱标志 (MTF)
MTF 是 VMCS 中的一个位,它在来宾中时在某些指令边界上触发 Monitor Trap Flag VMEXIT。
一般来说,只要客户机向前推进,就会发生退出,主机端不会发生任何比 MTF VMEXIT 优先级更高的事情。有一些奇怪的边缘情况,比如 REP MOV(可以中断的指令)和 SMI(对主机操作系统不可见的中断)。有关详细信息,请参阅 SDM 的 Monitor Trap Flag 部分(2016 年 4 月的 25.5.2)。
回应
当架构中已经存在这样的标志(EFLAG)时,为什么我们需要在 VMCS(虚拟 Macine 控制结构)中使用单独的标志?
Host 和 Guest State 需要分开。如果您正在调试运行 GDB 的客户机,主机需要能够触发 VMEXIT,而不是客户机内的异常。请注意,当设置了陷阱标志时,默认情况下会在当前上下文中触发异常(如果您在来宾中运行,则为来宾,如果您在主机中运行,则为主机)。
主机可以尝试在不使用 MTF 的情况下进行调试,方法是强制设置来宾的 TF 并使用 VMCS 中的异常位图在调试异常上配置 VMEXIT。不幸的是,如果来宾也启用了调试异常,那么主机就无法清楚地知道调试异常属于谁(如果我没记错的话,没有办法退出对 RFLAGS 的写入)。MTF 的存在使得调试运行调试器的 VM 成为可能。
...任何人都可以让我知道是否有某种方法可以使用其他方式做同样的事情?
没有分支监视器陷阱标志。您可以通过查看来宾 RIP(应该在 VMCS 中)上的解码指令来实现等效的东西,但这需要一堆额外的 VMEXITS。显然,这并不理想。
如果你在进入客人之前设置 BTF,事情会很快变得一团糟。它将被视为访客的 BTF,而不是与主机相关的 BTF。如果你还在 VMCS 中设置了 MTF,BTF 将不会延迟 MTF VMEXIT。另一方面,它会延迟客人的下一次调试陷阱。
每当客户机 VMEXIT 下一个时,如果 BTF 尚未被调试异常清除(退出时清除 IA32_DEBUGCTL),它将被破坏。您可以使用 MSR LOAD/STORE 列表保存该值,但这并没有多大作用。