由于需要,最近一段时间在研究如何统计x86每条指令出现次数。经过请教得知pin可以动态统计指令数目及种类。
开始两周一直在研究pintools的使用文档(详见http://www.pintool.org/docs/33586/Pin/html/)。其中找到类似工具代码位置在pin/source/tools/SimpleExamples/opcodemix.cpp, 利用INS_Opcode(INS ins)可以得到不同的opcode的index,再利用OPCODE_StringShort(index)可得到助记符。但是可惜没有对应的寻址方式所以并不满足我的要求,然后查遍了pin的API都没有更为详细的分类。困扰了将近两周,最后发现yahoo group上有pin的讨论组,加入开始发问。实践证明团队的力量是无穷的,再次非常感谢pinheads讨论组特别是mark_charney 、tevi.devor and Lueck, Gregory M,他们几个的帮助使我找到了解决办法,顺利解决了困扰很久的问题。
最后的解决办法是使用另一个工具XED(文档http://www.pintool.org/docs/33586/Xed/html/),XED是X86 Encoder Decoder的缩写。xed已经和pintools连接起来,使用时只需在代码里添加如下头文件:
extern “C” {
#include “xed_interface.h”
}
XED里有个枚举类xed_iform_enum_t 详细定义了指令及寻址方式,const xed_decoded_inst_t* xedd = INS_XedDec(ins), 可以得到xedd, const int index=Xed_decoded_inst_get_iform_enum(xedd)得到index, const char* buff=Xed——iform_enum_t2str(index)即可得到助记符及寻址方式。如下:
26 ADD_GPR8_IMMb_80r0
27 ADD_GPR8_IMMb_82r0
28 ADD_GPR8_MEMb
29 ADD_GPRv_GPRv_01
30 ADD_GPRv_GPRv_03
31 ADD_GPRv_IMMb
32 ADD_GPRv_IMMz
33 ADD_GPRv_MEMv
34 ADD_MEMb_GPR8
35 ADD_MEMb_IMMb_80r0
36 ADD_MEMb_IMMb_82r0
37 ADD_MEMv_GPRv
39 ADD_MEMv_IMMz
40 ADD_OrAX_IMMz
注: opcodemix.cpp里使用TRACE_AddInstrumentFunction(Trace, 0),而没有使用INS_AddInstrumentFunction(Instruction,0),是为了执行效率问题,如果每条指令都插桩会导致执行效率低,而每个trace插桩执行效率会相应快很多。