#include <iostream> #include <fstream> #include "pin.H" ofstream OutFile; // The running count of instructions is kept here // make it static to help the compiler optimize docount static UINT64 icount = 0; // This function is called before every block VOID docount(UINT32 c) { icount += c; } // Pin calls this function every time a new basic block is encountered // It inserts a call to docount VOID Trace(TRACE trace, VOID *v) { // Visit every basic block in the trace for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { // Insert a call to docount before every bbl, passing the number of instructions BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)docount, IARG_UINT32, BBL_NumIns(bbl), IARG_END); } } KNOBKnobOutputFile(KNOB_MODE_WRITEONCE, "pintool", "o", "inscount.out", "specify output file name"); // This function is called when the application exits VOID Fini(INT32 code, VOID *v) { // Write to a file since cout and cerr maybe closed by the application OutFile.setf(ios::showbase); OutFile << "Count " << icount << endl; OutFile.close(); } /* ===================================================================== */ /* Print Help Message */ /* ===================================================================== */ INT32 Usage() { cerr << "This tool counts the number of dynamic instructions executed" << endl; cerr << endl << KNOB_BASE::StringKnobSummary() << endl; return -1; } /* ===================================================================== */ /* Main */ /* ===================================================================== */ int main(int argc, char * argv[]) { // Initialize pin if (PIN_Init(argc, argv)) return Usage(); OutFile.open(KnobOutputFile.Value().c_str()); // Register Instruction to be called to instrument instructions TRACE_AddInstrumentFunction(Trace, 0); // Register Fini to be called when the application exits PIN_AddFiniFunction(Fini, 0); // Start the program, never returns PIN_StartProgram(); return 0; }
여기서는 처음으로 TRACE_라는 것이 나온다.
pintool은 Instrumentation Granularity에 따라 4가지 방식으로 Binary Instrumentation(Just in time)이 가능하다.
1. Trace Instrumentation(TRACE_AddInstrumentFunction API호출)
:Trace 단위로 Instrument하는 모드이다. Trace는 일반적으로 Branch의 Target에서 시작하여 Call, Return을 포함하여 무조건 분기에서 끝이 난다.
2. Instruction Instrumentation(INS_AddInstrumentFunction API호출)
:하나의 Instruction 단위로 Instrument하는 모드이다. 즉, 모든 명령어 실행 시 호출하는 함수이다.
3. Image Instrumentation(IMG_AddInstrumentFunction API호출)
:실행 바이너리 또는 공용 라이브러리가 주소 공간에 올라올 때 Instrument하는 모드이다.
IMG Loding, Unloding 등 이 때 실행되는 함수이다.
4. Routine Instrumentation(RTN_AddInstrumentFunction API호출)
:특정 함수를 실행함수의 전후로 Instrument하는 모드이다. 모든 함수 실행과 관련해 호출하는 함수이다.
자 이제, TRACE_를 이용해보자
이제 또 bbl이라는 개념이 나온다. bbl은 basic block이라는 뜻으로 trace가 call/return으로 분기되는 블럭 단위라고 보면 bbl은 trace안에서 if문과 같은 조건문으로 나눠지는 basic block을 의미하는 것 같다. 하지만 이는 내 생각이지 확실하지는 않다.
BBL_InsertCall 이루어진다. 각 BBL마다 instruction의 수를 세서 docount함수를 돌린다.
결국 전체 instruction을 counting하는 것인데 앞에서 instuction을 세는 예제보다 효과적으로 count하는것이다. per instruction이 아닌 per BBL로 incrementing을 해줬기 때문이다.
질문) 이해가 안되는 부분은 앞선 예제도 그렇고 이번 예제도 그렇고 실행을 할 때마다 instruction의 수가 다르게 나온다는 점이다.
참고자료
http://woosunbi.tistory.com/171
'pintool' 카테고리의 다른 글
Using PIN_SafeCopy() (0) | 2018.09.18 |
---|---|
Procedure Instruction Count (Routine Instrumentation) *질문 (0) | 2018.09.14 |
Detecting the Loading and Unloading of Images (Image Instrumentation)+질문 (0) | 2018.09.14 |
Memory Reference Trace (Instruction Instrument) (0) | 2018.09.14 |
Instruction Address Trace(Instruction Instrumentation) (0) | 2018.09.11 |