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