2013년 9월 30일 월요일

stack frame 해석하기

GDB에서 출력되는 frame 정보 해석

Sample Program
------------------------------------------------------------------------------------------------------
1  #include <stdio.h>
2
3  int func1(int arg1, int arg2);
4  int func2(int a1,int a2);
5
6  int func1(int arg1, int arg2)   //시작주소는 0x804841C, gdb에서 x func1명령으로 확인 가능
7  {
8      int temp=3;
9      temp = func2(arg1, arg2); // 이 명령 위치는 0x0804843b, 본문 참조
10    return temp;
11 }
12
13
14 int func2(int a1, int a2)   //시작주소는 0x8048443, gdb에서 x func2명령으로 확인 가능
15 {
16     int tmp=9;
17     return a1+a2+tmp;
18 }
19
20 int main(void)   //시작주소는 0x804845f, gdb에서 x main명령으로 확인 가능
21 {
22     int a=10, b=40,c=0;
23  
24     c = func1 (a,b); //이 명령의 위치는  0x08048494, 본문 참조
25
26     printf(" c = %d\n");
27
28     return 0;
29 }
30
------------------------------------------------------------------------------------------------------
(gdb) bt
#0 func2 (a1=10,a2=40) at a.c:17
#1 0x0804843b in func1 (arg1=10,arg2=40) at a.c:9
#2 0x08048494 in main ( ) at a.c:24
------------------------------------------------------------------------------------------------------

#0 func2 (a1=10,a2=40) at a.c:17 
   - 현재 sample program의 파일 이름이 a.c
   - program이 a.c파일의 17번째 라인이 실행 될 차례임.
   - func2가 호출될 때 a1=10, a2=40으로 호출되었음  위 내용은 frame 명령으로 재확인 가능
----------------------------------------------
(gdb) frame
 #0 func2(a1=10, a2=40) at a.c:17
17                       return a1+a2+tmp;
----------------------------------------------

#1 0x0804843b in func1 (arg1=10,arg2=40) at a.c:9
   - func2는 func1에서 호출되었고 이는 a.c파일 Line 9에서 호출됨

#2 0x08048494 in main ( ) at a.c:24
   - func1은 a.c파일에 있는 main 함수의 Line 24 에서 호출됨

------------------------------------------------------------------------------------------------------
(gdb) info frame 1
Stack frame at 0xbffff160
  eip = 0x804843b in func1 (a.c:9); saved eip 0x8048494
  called by frame at 0xbffff190, caller of frame at 0xbffff130
  source language c.
  Arglist at 0xbffff158, args: arg1=10, arg2=40
  Locals at 0xbffff158, Previous frame's sp is 0xbffff160
  Saved registers:
    ebp at 0xbffff158, eip at 0xbffff15c
------------------------------------------------------------------------------------------------------

(gdb) info frame 1
   - func1번의 stack frame 정보 요청

Stack frame at 0xbffff160
   - func1의 stack frame은 0xbffff160부터 아래쪽(낮은 주소)임.
   - 0xbffff160 - 4 부터 낮은 주소쪽으로 func1의 stack frame임.  (stack은 높은 주소에서 낮은 주소 방향으로 자라남)

eip = 0x804843b in func1 (a.c:9); saved eip 0x8048494
   - func1에서 func2를 호출한 func1의 코드 위치는 a.c파일의 9라인이며 이 주소는 0x0804843b(eip)임.  stack frame상의 최하위 프레임(주소가 낮은)의 경우 이 값이 현재의 cpu의 instruction pointer값임.
   - saved eip는 func1이 호출된 후 실행되어야 할 명령이 있는 main함수상에서 func1호출 다음에 있는 명령의 주소임.

called by frame at 0xbffff190, caller of frame at 0xbffff130
   - func1를 호출한 함수(main)의 stack frame은 0xbffff190이며, func1이 호출한 함수(func2)의 stack fame은 0xbffff130임.  호출할수록 stack frame의 주소가 작아짐.

source language c.
    
Arglist at 0xbffff158, args: arg1=10, arg2=40
    - func2의 argument는 2개 이며 각각 10, 40의 값을 가지고 호출 되었음.
    - 0xbffff158은 func2의 bp이며 arg1은 bp +8, arg2는 bp+12
    - bp(base pointer)과 arg1사이(bf+4)에는 return address가 있음.

Locals at 0xbffff158, Previous frame's sp is 0xbffff160
     
Saved registers:
    ebp at 0xbffff158, eip at 0xbffff15c
   - func2의 ebp는 0xbffff158임.  ebp의 역할은 해당k 함수에서 기준 위치로 첫번째 변수는 ebp-4, 두번째 변수는 ebp-8등으로 stack상의 지역변수를 ebp로 부터의 offset으로 표시함.  (꼭 첫번째 변수가 ebp - 4가 되는 것은 아님)
   - func2의 eip는 0xbffff15C에  저장되어있으며 이는 func1에서 func2를 호출한 다음 명령의 주소임. 이 값은 위에 saved eip값으로 확인 할 수 있음.
    
0xBFFFF190 : 이 아래부터 main의 stack frame
------------------------------------------------------------
0xBFFFF18C : main의 return address
0xBFFFF188 : main의 bp
...
0xBFFFF17C : main의 변수 c  =>  -12(%ebp)와 같이 표시됨 bp로 부터 12바이트 아래 있음.
0xBFFFF178  : main의 변수 b =>  -16(%ebp)
0xBFFFF174  : main의 변수 a
...
0xBFFFF164  : arg2 = 40
0xBFFFF160  : arg1 = 10  : 이 아래부터 func1의 stack frame
------------------------------------------------------------
0xBFFFF15C : func1의 return address : main함수에서 func1이 return되면 다음에 실행할 명령의 주소(ip:instruction pointer)
0xBFFFF158 : func1의 bp
...
0xBFFFF14c : func1의 변수 temp  => -12(%ebp)와 같이 표시됨 bp로 부터 12바이트 아래 있음.
..
0xBFFFF134 : a2 = 40
0xBFFFF130 : a1 = 10 : 이 아래부터 func2의 stack frame
------------------------------------------------------------
0xBFFFF12C: func2의 return address
0xBFFFF128: func2의 bp
0xBFFFF124: func2의 첫번째 변수 tmp  -4(%ebp)k


각 함수의 시작 주소는 아래와 같이 확인 가능
------------------------------------------------------------------------------------------------------
(gdb) x func1
0x804841C
(gdb) x func2
0x8048443
(gdb) x main
0x804845f

------------------------------------------------------------------------------------------------------
(gdb) x/20i func2
  ==>  func2시작부터 20줄의 역어셈블 코드가 출력됨  i는 역 어셈블하라는 뜻