前言
X86 处理器支持最近分支记录(Last branch record),也就是记录CPU的跳转记录(jmp,jcc,call,ret等指令,中断和异常). 通过操作MSR寄存器(model specific register)来配置分支记录功能。
一、分支记录格式
有如下两个函数:
int add_fun(int a,int b)
{
return (a+b);
}
int main(void)
{
return add_func(1,2);
}
分支记录格式为from -> to 形式,上面两个函数调用,可以生成两条branch record:
main -> add_fun /* call 指令*/
add_fun->main /* ret指令*/
二、分支记录方式
X86提供LBR, BTM两种方式来记录分支信息, LBR把分支信息记录到特定模型寄存器(MSR),而BTM把分支记录通过消息的形式发送给系统总线或者写到内存中(Branch Trace Store)。
2.1 LBR(last branch record)
把分支信息保存在称为"LBR stack"的MSR寄存器组里面,且用栈顶指针寄存器(top-of-stack (TOS) pointer
)来记录当前index. 这种方式明显缺点就是寄存器组数量有限,也就是保存的记录有限.根据CPU型号不同,LBR stack大小也有差异,目前最多支持32组寄存器. 可以通过CPU的DisplayFamily和DisplayModel值来查询LBR Stack的地址和大小。
2.2 BTM(Branch Trace Messages)
目前LBR stack方式记录的分支记录条数最多为32组,通过BTM机制,CPU把分支信息通过消息的形式,发送到系统总线或者写到内存,发送到系统总线时,需要在总线上外接调试设备来接受BTM消息. 而我们更多采用写到内存的方式(BTS).BTS 把BTM消息保存在预先分配内存区(Debug Store)中,这样能够保存更多LBR条目.实际上DS区分为三部分:内存管理区,BTS内存区,PEBS区(性能检测)
注:除上述两种方式之外,还可以通过intel-pt来实时指令采集,intel-pt是intel 在2015推出的实时指令采集,功能上更强大,性能影响也较小(5%)