카테고리 없음

Pin 툴 매뉴얼 [작성중]

진모씨 2013. 8. 14. 11:38


DBI(Dynamic Binary Instrumentation)

동적(실행 중) 바이너리(기계어) 재편성(구성)

Intel Pin은 x86, x64 CPU를 지원하고 윈도랑 리눅스를 지원하고 맥 OS도 지원해요!

엄청나죠?


Pin: 간접 실행 및 응용 가능한 프로그램

뜬금없이 말했군요.

이 도구는 동적으로 모든 실행되는 기계어들을 다 추적할수 있게 하는 프레임워크라고 볼수 있죠!

프레임워크라고 하는 이유는..

제가 C 코드를 짜서 이 기능을 활용하게 해주어요!


===============================

용어:

프레임워크: 찾아보세요..

Pin: Intel Pin이라고 검색하세요. 프로그램이에요.

Pin Tool: 곧 나와요.

===============================

pin tool은 pin이라는 프로그램에 '플러그인'이 되어 제가 짠 기능을 수행해주죠.


Pin: 이벤트 반응자

pin에는 프로그램의 동작에 반응하는 '이벤트 반응자'를 달수 있어요.

각 동작의 종류에 따라 다른 함수가 호출이 되죠.


pin에 달수 있는 '이벤트 반응자'는 3가지에요.


INS

RTN

IMG


각각 함수들이 있죠. 이벤트 등록, 그리고 각각에 관련된 '조건' 함수들, '처리' 함수들 등이 있죠. 그냥 분류에요.


INS_~ 함수들

명령어 추적

INS는.. 모든 명령어 실행 시 호출할 함수들이에요.

명령어 관련 함수들이 여기 있죠.


RTN_~ 함수들

루틴 추적

RTN은.. 모든 함수 실행 시 호출할 함수들이에요.

함수 관련 함수들이 여기 있죠.


IMG_~ 함수들

이미지 로딩, 언로딩 등등.. 추적함

IMG는.. 모든 이미지 로딩, 언로딩 시 실행되는 함수들이죠.

엄청나죠? 이미지라 함은, dll파일같은 공용 라이브러리들을 말하죠!


TRACE_~ 함수들

'기록 단계에서 호출되며 추적 가능'

이건 나중에 배워요.


이제 시작해보아요.

Pin은 아래와 같이 나누어져있어요.

pin.exe

source/

 tools/

  SimpleExamples/

  ...

  MyPinTool/


하하, MyPinTool을 주목하라구.


source\tools 폴더는말이죠.

pin tool들이 모여있는 장소에요.

소스 코드들을 컴파일해서 OS에 맞게 쓸수 있죠.

pin.exe같은 경우 컴파일되어 배포되어요. 그냥 실행하면 된다구요!


Visual Studio 2010을 저는 쓰는데요, Express버전으로 쓴답니다. C++가 필요해요.


시작프로그램에서 검색하면.. Visual 이라고 검색해보아요.

Visual Studio 명령 프롬프트 라는것을 찾아서 실행해요.

x64 비트일 경우에는요, Windows (버전) SDK를 설치하신 후 sdk 프롬프트로 들어가셔요. sdk 프롬프트 라고 치면 나오나.. 안깔아봐서요.

왜냐하면 Visual Studio의 C++ 컴파일러는 보통 CLR과 C가 되거든요.


근데 32비트에요..

x64비트용으로 컴파일하려면 SDK의 컴파일러들이 필요하죠. SDK를 깔면 32비트에서 64비트 프로그램을 컴파일할수도 있답니다.


그리고 그 명령 프롬프트로 그 source\tools 폴더에 들어가죠.

물론 pin설치폴더 하위 폴더 말이죠.. 킄.


그다음 make 툴이름 을 하면 툴이 dll로 만들어져요.

make SimpleExamples

이렇게 하면 간단한 예제 코드들이 컴파일되죠. 근데 의외로 유용한 도구들이 많아요.


메모리 접근을 모두 기록하는 'pinatrace'

등등.. 나머지는 별로 안썼음..


make 라고만 하면

그냥 모든 툴들이 dll로 컴파일되죠.


pin 설치폴더의 pin.exe를 실행하죠.

pin -t 툴이름 -- 실행파일exe


pin -t pinatrace -- myProgram.exe

myProgram.exe에 pinatrace라는 플러그인을 달아서 실행해요.



이게 된 후..

pinatrace.out에 뭔가 기록이 되거든요.

근데 너무 파일이 크니, more pinatrace.out 명령어로 봐줘요.



접근한 주소: 읽기/쓰기(R 또는 W) 접근한 메모리 주소    접근한 크기     (읽거나 쓴 결과)


형식으로 출력되구요.


일단 처음에는 쉬운 것을 짜봐야겠죠? 그 전에..

이제 실제 코드 예제에요. 결과는 '실행된 기계어 명령어 수'에요.


#include <iostream> #include <fstream> #include "pin.H" ofstream OutFile; // 명령어들의 실행 횟수는 이 변수에 저장됩니다. // 컴파일러가 docount 함수를 최적화하게 icount를 static으로 놓습니다. static UINT64 icount = 0; // 이 함수는 어떤 명령어가 실행될 때 마다 호출됩니다 VOID docount() { icount++; } // 새로운 명령어가 인식될 때 실행됩니다. VOID Instruction(INS ins, VOID *v) { // 모든 명령어가 실행되기 전에 docount 함수를 인수 없이 실행합니다. INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)docount, IARG_END); } KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool", "o", "inscount.out", "출력 파일을 설정하세요"); // 응용프로그램이 종료될 때 호출됩니다. VOID Fini(INT32 code, VOID *v) { // cout과 cerr이 응용프로그램에 의해 닫혔을 수 있으므로 파일에 저장합니다. OutFile.setf(ios::showbase); OutFile << "명령어 수 " << icount << endl; OutFile.close(); } /* ===================================================================== */ /* 도움말을 출력함 */ /* ===================================================================== */ INT32 Usage() { cerr << "실행된 동적 명령어들의 수를 셉니다." << endl; cerr << endl << KNOB_BASE::StringKnobSummary() << endl; return -1; } /* ===================================================================== */ /* Main */ /* ===================================================================== */ /* argc, argv 는 전체 명령줄입니다 : pin -t <toolname> -- ... */ /* ===================================================================== */ int main(int argc, char * argv[]) { // pin 시작 if (PIN_Init(argc, argv)) return Usage(); OutFile.open(KnobOutputFile.Value().c_str()); // 명령어 구성을 위해 호출될 함수를 등록합니다. INS_AddInstrumentFunction(Instruction, 0); // 응용 프로그램이 종료되었을 때 호출될 함수를 등록합니다. PIN_AddFiniFunction(Fini, 0); // 프로그램을 시작하고, 리턴하지 않습니다. PIN_StartProgram(); return 0; }


아참, 모든 명령어 실행 시 함수가 호출되게 한다면 프로그램이 느려지겠죠?

Pin Tool의 단점이지만, 다른 프로그램도 마찬가지일거에요, 아직은.