pintools的简单使用
2021/7/19 6:09:14
本文主要是介绍pintools的简单使用,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
目录
一、利用pintools分析bwa程序
(1)分析函数的调用次数,给出函数调用次序的排序
1. 将写好的插桩程序进行make ,参考Intel官网步骤
2. 下载bwa程序
3. 利用写好的pintools插桩程序来分析bwa的函数调用次数。
(2)分析函数的执行时间,按照执行时间排序。
1. 问题二的执行操作思路和上述相同。
2. 在pin的ManualExaples的目录下依次执行以下命令即可:
二、源代码
(1)分析函数的调用次数,给出函数调用次序的排序
(2)分析函数的执行时间,按照执行时间排序。
三、总结
一、利用pintools分析bwa程序
(1)分析函数的调用次数,给出函数调用次序的排序
1. 将写好的插桩程序进行make ,参考Intel官网步骤
(https://software.intel.com/sites/landingpage/pintool/docs/71313/Pin/html/index.html#ProcInstrCount)
执行如下命令
#make obj-intel64/proccount.so TARGET=intel64
2. 下载bwa程序
并按照GitHub上的提示执行,因为所给的资源文件是Ref_5.fa h和test40a.fq和test40b.fq所以在执行命令是需要替换。(https://github.com/lh3/bwa)
#make
# ./bwa mem Ref_5.fa test40a.fq | gzip -3 > aln-se.sam.gz
./bwa mem Ref_5.fa test40a.fq test40b.fq | gzip -3 > aln-pe.sam.gz
3. 利用写好的pintools插桩程序来分析bwa的函数调用次数。
因为pin 和proccount.so文件是在pin的相关目录下,因此需要进入对应的目录下,同时因为bwa是在bwa的相关目录下,因此也需要找到对应目录下的文件。执行以下命令:
#../../../pin -t obj-intel64/proccount.so -- ../../../../bwa/bwa mem ../../../../bwa/Ref_5.fa ../../../../bwa/test40a.fq | gzip -3 > aln-se.sam.gz
因为head proccount.out 显示条数较少,于是用cat查看,以下截图截取一部分。
执行命令:
# cat proccount.out
下面看第二个数据集test40b.fq。执行命令:
#../../../pin -t obj-intel64/proccount.so -- ../../../../bwa/bwa mem ../../../../bwa/Ref_5.fa ../../../../bwa/test40b.fq | gzip -3 > aln-se.sam.gz
(2)分析函数的执行时间,按照执行时间排序。
1. 问题二的执行操作思路和上述相同。
主要是protime.cpp文件的编译,和利用proctime.so和pin来分析bwa的函数执行时间。因为bwa程序已经编译过了,所以不用执行上述第二步骤。
2. 在pin的ManualExaples的目录下依次执行以下命令即可:
#make obj-intel64/proctime.so TARGET=intel64
#../../../pin -t obj-intel64/proccount.so -- ../../../../bwa/bwa mem ../../../../bwa/Ref_5.fa ../../../../bwa/test40.fq | gzip -3 > aln-se.sam.gz
#cat proctime.out
#../../../pin -t obj-intel64/proccount.so -- ../../../../bwa/bwa mem ../../../../bwa/Ref_5.fa ../../../../bwa/test40b.fq | gzip -3 > aln-se.sam.gz
#cat proctime.out
二、源代码
(1)分析函数的调用次数,给出函数调用次序的排序
分析函数的调用次数就是用在函数调用之前插桩,然后利用docount进行计数
RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)docount, IARG_PTR, &(rc->_rtnCount), IARG_END);
这是给指令插桩计数
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)docount, IARG_PTR, &(rc->_icount), IARG_END);
源代码: #include <fstream> #include <iomanip> #include <iostream> #include <string.h> #include <time.h> #include "pin.H" using std::ofstream; using std::string; using std::hex; using std::setw; using std::cerr; using std::dec; using std::endl; ofstream outFile; // Holds instruction count for a single procedure typedef struct RtnCount { string _name; string _image; ADDRINT _address; RTN _rtn; UINT64 _rtnCount; //记录calls的次数 UINT64 _icount; struct RtnCount * _next; } RTN_COUNT; // Linked list of instruction counts for each routine RTN_COUNT * RtnList = 0; // This function is called before every instruction is executed VOID docount(UINT64 * counter) { (*counter)++; } const char * StripPath(const char * path) { const char * file = strrchr(path,'/'); if (file) return file+1; else return path; } // Pin calls this function every time a new rtn is executed VOID Routine(RTN rtn, VOID *v) { // Allocate a counter for this routine RTN_COUNT * rc = new RTN_COUNT; // The RTN goes away when the _image is unloaded, so save it now // because we need it in the fini rc->_name = RTN_Name(rtn); rc->_image = StripPath(IMG_Name(SEC_Img(RTN_Sec(rtn))).c_str()); rc->_address = RTN_Address(rtn); rc->_icount = 0; rc->_rtnCount = 0; // Add to list of routines rc->_next = RtnList; RtnList = rc; RTN_Open(rtn); // Insert a call at the entry point of a routine to increment the call count RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)docount, IARG_PTR, &(rc->_rtnCount), IARG_END); // For each instruction of the routine for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { // Insert a call to docount to increment the instruction counter for this rtn INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)docount, IARG_PTR, &(rc->_icount), IARG_END); } RTN_Close(rtn); } // This function is called when the application exits // It prints the _name and count for each procedure VOID Fini(INT32 code, VOID *v) { outFile << setw(23) << "Procedure" << " " << setw(15) << "Image" << " " << setw(18) << "Address" << " " << setw(12) << "Calls" << " " << setw(12) << "Instructions" << endl; //sort call times RTN_COUNT *out, *temp1, *temp2 = NULL; RTN_COUNT temp; for(out = RtnList; out; out= out->_next) { temp1 = out; for(temp2 = temp1; temp2; temp2 = temp2->_next) { if(temp1->_rtnCount < temp2->_rtnCount) temp1 = temp2; } if(temp1 != NULL) { temp = *temp1; temp1->_name = out->_name; temp1->_image = out->_image; temp1->_address = out->_address; temp1->_rtnCount = out->_rtnCount; temp1->_icount = out->_icount; out->_name = temp._name; out->_image = temp._image; out->_address = temp._address; out->_rtnCount = temp._rtnCount; out->_icount = temp._icount; } } for (RTN_COUNT * rc = RtnList; rc; rc = rc->_next) { if (rc->_icount > 0) outFile << setw(23) << rc->_name << " " << setw(15) << rc->_image << " " << setw(18) << hex << rc->_address << dec <<" " << setw(12) << rc->_rtnCount << " " << setw(12) << rc->_icount << endl; } } /* ===================================================================== */ /* Print Help Message */ /* ===================================================================== */ INT32 Usage() { cerr << "This Pintool counts the number of times a routine is executed" << endl; cerr << "and the number of instructions executed in a routine" << endl; cerr << endl << KNOB_BASE::StringKnobSummary() << endl; return -1; } /* ===================================================================== */ /* Main */ /* ===================================================================== */ int main(int argc, char * argv[]) { // Initialize symbol table code, needed for rtn instrumentation PIN_InitSymbols(); outFile.open("proccount.out"); // Initialize pin if (PIN_Init(argc, argv)) return Usage(); // Register Routine to be called to instrument rtn RTN_AddInstrumentFunction(Routine, 0); // Register Fini to be called when the application exits PIN_AddFiniFunction(Fini, 0); // Start the program, never returns PIN_StartProgram(); return 0; }
(2)分析函数的执行时间,按照执行时间排序。
分析函数执行时间的主要思路是在函数执行前进行插桩和函数执行结束后插桩:
RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)getTime_now, IARG_PTR, rc, IARG_END);
RTN_InsertCall(rtn, IPOINT_AFTER, (AFUNPTR)getTime_end, IARG_PTR, rc, IARG_END);
然后将函数执行后的当前系统时间和函数执行结束后的系统时间相减便可得到函数的执行时间,每次插桩都如此统计函数执行的时间:
rc->_useTime += 1000000*(rc->_tv_end.tv_sec-rc->_tv_now.tv_sec)+(rc->_tv_end.tv_usec-rc->_tv_now.tv_usec);
源代码: #include <fstream> #include <iomanip> #include <iostream> #include <string.h> #include <sys/time.h> #include "pin.H" using std::ofstream; using std::string; using std::hex; using std::setw; using std::cerr; using std::dec; using std::endl; ofstream outFile; // Holds instruction count for a single procedure typedef struct RtnCount { string _name; string _image; ADDRINT _address; RTN _rtn; struct timeval _tv_now, _tv_end; //进入函数时的时间,和函数执行结束的时间 UINT64 _useTime; //函数执行的时间 struct RtnCount * _next; } RTN_COUNT; // Linked list of instruction counts for each routine RTN_COUNT * RtnList = 0; // This function is called before every instruction is executed VOID getTime_now(RTN_COUNT * rc) { gettimeofday(&(rc->_tv_now),NULL); } VOID getTime_end(RTN_COUNT *rc) { gettimeofday(&(rc->_tv_end), NULL); rc->_useTime += 1000000*(rc->_tv_end.tv_sec-rc->_tv_now.tv_sec)+(rc->_tv_end.tv_usec-rc->_tv_now.tv_usec); } const char * StripPath(const char * path) { const char * file = strrchr(path,'/'); if (file) return file+1; else return path; } // Pin calls this function every time a new rtn is executed VOID Routine(RTN rtn, VOID *v) { // Allocate a counter for this routine RTN_COUNT * rc = new RTN_COUNT; // The RTN goes away when the _image is unloaded, so save it now // because we need it in the fini rc->_name = RTN_Name(rtn); rc->_image = StripPath(IMG_Name(SEC_Img(RTN_Sec(rtn))).c_str()); rc->_address = RTN_Address(rtn); rc->_useTime = 0; // Add to list of routines rc->_next = RtnList; RtnList = rc; RTN_Open(rtn); // Insert a call at the entry point of a routine to increment the call count RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)getTime_now, IARG_PTR, rc, IARG_END); RTN_InsertCall(rtn, IPOINT_AFTER, (AFUNPTR)getTime_end, IARG_PTR, rc, IARG_END); RTN_Close(rtn); } // This function is called when the application exits // It prints the _name and count for each procedure VOID Fini(INT32 code, VOID *v) { outFile << setw(23) << "Procedure" << " " << setw(15) << "Image" << " " << setw(18) << "Address" << " " << setw(12) << "Usedtime" << endl; //sort call times RTN_COUNT *out, *temp1, *temp2 = NULL; RTN_COUNT temp; for(out = RtnList; out; out= out->_next) { temp1 = out; for(temp2 = temp1; temp2; temp2 = temp2->_next) { if(temp1->_useTime < temp2->_useTime) temp1 = temp2; } if(temp1 != NULL) { temp = *temp1; temp1->_name = out->_name; temp1->_image = out->_image; temp1->_address = out->_address; temp1->_useTime = out->_useTime; out->_name = temp._name; out->_image = temp._image; out->_address = temp._address; out->_useTime = temp._useTime; } } for (RTN_COUNT * rc = RtnList; rc; rc = rc->_next) { outFile << setw(23) << rc->_name << " " << setw(15) << rc->_image << " " << setw(18) << hex << rc->_address << dec <<" " << setw(12) << rc->_useTime << endl; } } /* ===================================================================== */ /* Print Help Message */ /* ===================================================================== */ INT32 Usage() { cerr << "This Pintool counts the number of times a routine is executed" << endl; cerr << "and the number of instructions executed in a routine" << endl; cerr << endl << KNOB_BASE::StringKnobSummary() << endl; return -1; } /* ===================================================================== */ /* Main */ /* ===================================================================== */ int main(int argc, char * argv[]) { // Initialize symbol table code, needed for rtn instrumentation PIN_InitSymbols(); outFile.open("proctime.out"); // Initialize pin if (PIN_Init(argc, argv)) return Usage(); // Register Routine to be called to instrument rtn RTN_AddInstrumentFunction(Routine, 0); // Register Fini to be called when the application exits PIN_AddFiniFunction(Fini, 0); // Start the program, never returns PIN_StartProgram(); return 0; }
三、总结
pintool确实是挺好用的,比起DECAF,Pin适合简单上手,DECAF适合更低层的系统级的分析。
Pin的拓展工具在github有很多,例如JonathanSalwan这位大牛整合的Pin的工具,并且还提供了相关的文档文档,十分的方便。
这篇关于pintools的简单使用的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-23线下车企门店如何实现线上线下融合?
- 2024-12-23鸿蒙Next ArkTS编程规范总结
- 2024-12-23物流团队冬至高效运转,哪款办公软件可助力风险评估?
- 2024-12-23优化库存,提升效率:医药企业如何借助看板软件实现仓库智能化
- 2024-12-23项目管理零负担!轻量化看板工具如何助力团队协作
- 2024-12-23电商活动复盘,为何是团队成长的核心环节?
- 2024-12-23鸿蒙Next ArkTS高性能编程实战
- 2024-12-23数据驱动:电商复盘从基础到进阶!
- 2024-12-23从数据到客户:跨境电商如何通过销售跟踪工具提升营销精准度?
- 2024-12-23汽车4S店运营效率提升的核心工具