Intel x86提供的Branch Trace Store的功能

本文介绍了Intel x86架构中的Branch Trace Store(BTS)功能,及其在Win32环境下的启用和应用。BTS能够记录CPU执行的分支指令信息,帮助进行性能分析。文章详细阐述了BTS的工作框架,包括Last Branch Record、Branch Trace Messages和Branch Trace Store,并着重讲解了在Windows环境下开启BTS、设置DS_BUFFER_MGR_BLOCK、编写中断服务程序以及管理Performance Mon. Counter寄存器的步骤。此外,还提到了多核环境下和线程分析的相关问题。

写给转载者:

转载请保留作者信息

来源: http://www.csksoft.net/blog

作者:陈士凯

介绍

Branch Trace Store(BTS)是目前广泛被intel CPU所提供的一种硬件辅助调试功能,因为在MSRA项目需要,所以作了一些基于它的应用。虽然Intel的CPU开发手册[1]提供了比较详细的使用方法,但是由于比较笼统,且缺少win32下的相关资料。所以我打算把其中的一些tricky的事情和大家分享下。这些内容当然也是我自己查找公开资料得到的,因此也不算什么秘密吧 :-)

 

BTS简单的说就是允许CPU将自己实际执行到的分支指令(jmp/jxx/call/int/etc.)的相关信息保存下来的功能。一般CPU都会保存每个分支指令的源地址和目标地址,该地址在保护模式下是虚拟地址形式表示的。利用这个功能,可以实时地了解当前CPU正在执行代码的实际流程情况,很多分析软件,如Intel的Vtune或者profiling库,如*nix平台下的perfmon[2]都用它来做一些程序性能分析。当然,还可以做很多其他有趣的事,比如逆向工程,具体我就不说了。

 

不过目前很少有资料具体介绍如何在win32下开启该功能并实现一个可用的BTS捕捉引擎。当然可以参考perfmon的代码,但BTS在其中只是很小一个部分,同时为了实现跨平台,对于新手来说难度较大。因此我这里重点介绍对于单核心的NetBurst构架的CPU(通俗地说就是P4这类)在win32下的具体实现细节。其他的构架,比如现在的Core Due,大家可以参考intel的开发手册举一反三。

 

工作框架

实际上,上面所说的BTS只是intel对于分支指令信息捕获机制的一个分支,就P4而言,大致提供了下列几种分支指令的捕获手段

Last Branch Record(LBR)

故名思意,该方式将记录最后几个分支信息,实际上NetBurst CPU中内建了若干个MSR寄存器用于记录Last Branch Record,称为LBR Stack。在该模式下运行的CPU会采用Round Robin的方式循环填充那几个MSR寄存器。

该方式常用在调试器的Call Stack分析上,我们这里就不涉及了

 

Branch Trace Messages

该方式和我们将介绍的Branch Trace Store大致类似,与LBR不同的是,CPU会把分支信息发送到系统总线上供第三方硬件在总线上接收数据。而BTS则直接将数据保存到由程序制定的内存单元中。我们这里也不讨论该方式。

 

Branch Trace Store

简单的说,BTS就是将分支信息保存到了有程序(实际就是我们)制定的一块内存空间中。而当这块内存用尽时,CPU可以采用Round Robin的方式循环填充,这就和LBR类似,但可以指定内存块的大小来决定最大捕捉量。另一种处理方式是在内存快用尽的时候,一个事先由我们设定的处理中断将触发来完成对当前内存块中BTS数据的保存工作。这样就可以记录任意多的分支信息了。我们这里主要考虑的就是这种方式的BTS。

 

 

按照intel开发手册的描述,BTS开启后的CPU执行模式如下图所示:

 

每当CPU执行到一个分支指令后,它就会产生一个如上左图的BTS记录项。这里举个例子:

0x80001234   mov eax,[esp]

0x80001238   or eax,eax

0x80001240   jnz 0x80002000

0x80001245   nop

...

 

当执行上面这段执行,其中遇到了jnz指令,如果他的跳转条件成立,那么将产生一个从0x80001240到0x80002000的跳转,那么产生的BTS记录项就是{From:0x80001240,To:0x80002000,...}

 

对于P4的CPU,这个BTS记录项的结构如下:

struct BTS_ITEM_BLOCK_P4{     ULONG   dwBranchFrom;     ULONG   dwBranchTo;     ULONG   dwFlags; };

每次CPU执行到分支指令的时候,只要BTS开启,它就会产生一个如上结构得数据块,然后把它存储到事先定义好的一块内存当中去。而这块内存是比较灵活的,如上图所示,CPU需要知道这块内存的起始地址、结束地址、以及当记录到第几个记录时候需要触发一个中断程序来负责将现有的BTS记录保存下来防止内存溢出。当BTS记录存储到图中那个灰底色的“BTS记录#m”时,就会触发中断,可以发现它往往并不是整块记录内存

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值