'gdb'에 해당되는 글 2건

[펌글]gdb 디버깅하기 :: 2008/06/17 11:07

이 글은 maniacs님 블로그에서 퍼온 글입니다.
원본은 http://psyoblade.egloos.com/2653919  에서 확인하실 수 있습니가.
감사합니다. maniacs님

gdb 를 통한 디버깅 따라하기
참고서적 : 유닉스 리눅스 프로그래밍 필수 유틸리티 : vi, make, gcc, gdb, cvs, rpm


1. 우선 컴파일 시에 디버깅 정보를 담아야 한다.
 gcc -g -o [프로그램명] [소스파일명]
 디버깅 옵션인 -g 으로 컴파일하며, 최적화 옵션인 -O 은 주지 않도록 한다.

2. 실행방법
 gdb [프로그램명]
 gdb [프로그램명] [core파일명]
 gdb [프로그램명] [실행중인프로세스pid]


3. 종료방법
 q
 Ctrl + d

4. 소스 찾아가기 (list)
 l   : main 함수를 기점으로 소스의 내용이 출력된다
 l 10  : 10 행 주변의 소스가 출력되는데 10 - 5 행부터 10 + 5행까지 총 10행이 출려된다.
 l func  : func 함수의 소스를 출력
 l -5  : 기본값으로 10줄이 출력된다고 가정하고, 다음에 출력될 라인이 11라인이라면, 10(마지막라인) - 5 라인을 중심으로 출력된다. 즉, 그대로 1~10라인이 출력된다.
 l a.c:func : a.c 파일의 func 함수부분을 출력
 l a.c:10 : a.c 파일의 10행을 기준으로 출력

5. 옵션
 set listsize 20 : 한번에 출력하는 행의 갯수를 20개로 늘린다.
 Enter  : 마지막으로 수행한 명령어를 다시 수행한다

6. 프로그램 실행, 종료 (run, kill)
 r   : 프로그램 수행 (재시작)
 r arg1 arg2 : arg1과 arg2를 인자로 프로그램 수행
 k   : 프로그램 수행종료

7. 역추적하기 (backtrace)
 bt   : 오류가 발생한 함수를 역으로 찾아간다.

8. 중단점 사용하기 (breakpoint, temporary breakpoint)
 b func  : func 함수에 브레이크 포인트 설정
 b 10  : 10행에 브레이크 포인트 설정
 b a.c:func : a.c파일의 func함수에 브레이크 포인트 설정
 b a.c:10 : a.c파일의 10행에 브레이크 포인트 설정
 b +2  : 현재 행에서 2개 행 이후 지점에 브레이크 포인트 설정
 b -2  : 현재 행에서 2개 행 이전 지점에 브레이크 포인트 설정
 b *0x8049000 : 0x8049000 주소에 브레이크 포인트 설정 (어셈블리로 디버깅 시 사용)
 b 10 if var == 0 : 10행에 브레이크 포인트를 설정해되, var 변수 값이 0일 때 작동
 tb   : 임시 중단점을 사용하는 것으로 한번만 설정되며, 그 이후에는 삭제된다.

9. 중단점 설정하기 (condition)
 condition 2 var == 0 : 고유번호가 2번인 브레이크포인트에 var변수가 0일 때 동작하라고 설정

10. 중단점 삭제하기 (clear, delete)
 cl func  : func 함수의 시작 부분에 브레이크 포인트 지움
 cl 10  : 10행의 브레이크 포인트 지움
 delete 1 : 고유번호 1번의 브레이크 포인트를 지운
 cl a.c:func : a.c 파일의 func함수의 브레이크 포인트 지움
 cl a.c:10 : a.c 파일의 10행의 브레이크 포인트 지움
 cl   : 모든 브레이크 포인트 지움

11. 중단점 정보보기 (information)
 info b  : 현재 설정된 브레이크 포인트의 정보를 보여준다
 방향키Up/Down : 방향키 Up/Down을 누르면 히스토리 기능을 제공한다
 info br + TAB : info br 로 시작하는 키워드가 히스토리에 있다면 뿌려준다
 info TAB + TAB : info 뒤에 올 수 있는 인자 리스트를 보여준다
 TAB + TAB  : 현재 사용가능한 모든 명령어 리스트를 보여준다

12. 중단점 비활성화, 활성화 하기 (enable, disable)
 disable 2 : 고유번호 2번인 브레이크 포인트 비활성화
 enable 2 : 고유번호 2번인 브레이크 포인트 활성화

13. 디버깅 하기 (step, next, continue, until, finish, return, step instruction, next instruction)
 s  : 현재 출력된 행을 수행하고 멈추지만, 함수의 경우 함수의 내부로 들어가서 수행된다
 s 5  : s를 5번 입력한 것과 동일
 n  : 현재 행을 수행하고 멈추지만, 함수의 경우 함수를 수행하고 넘어간다
 n 5  : n을 5번 입력한 것과 동일
 c  : 다음 브레이크 포인트를 만날때 까지 계속 수행한다
 u  : for 문에서 빠져나와서 다음 브레이크 포인트까지 수행한다.
 finish : 현재 함수를 수행하고 빠져나감
 return : 현재 함수를 수행하지 않고 빠져나감
 return 123 : 현재 함수를 수행하지 않고 빠져나감, 단, 리턴값은 123
 si  : 현재의 인스트럭션을 수행, 함수 호출 시 내부로 들어간다.
 ni  : 현재의 인스트럭션을 수행, 함수 호출 시 내부로 들어가지 않는다.

14. 감시점 설정 (watch)
 watch i : i변수에 와치포인트를 설정하고 i변수가 바뀔 때마다 브레이크가 걸리면서 이전값과 현재값을 출력한다.

15. 변수 정보보기 (info, print)
 info locals : 현재 상태에서 어떤 지역변수들이 있으며, 값은 어떠한지를 알 수 있다.
 info variables : 현재 상태에서의 전역변수 리스트를 확인할 수 있다.
 p lval  : lval 값을 확인한다.
 p func  : func 함수의 주소값을 확인한다.
 p pt  : pt가 구조체라면 구조체의 주소를 확인한다
 p *pt  : pt가 구조체라면 구조체의 값을 확인한다.
 p **pt  : *pt가 구조체라면 구조체의 값을 확인한다.
 info registers : 레지스트 값 전체를 한번에 확인한다.

16. 레지스트 값 및 포인터가 가리키는 구조체의 배열을 출력 (info, print)
 info all-registers : MMX 레지스트를포함하여 거의 대부분의 레지스트 값을 확인한다.
 p $eax  : eax 레지스트의 값을 확인한다. ( ex_ eax, ebx, ecx, edx, eip )
 p *pt@4  : 4크기의 배열로 gdb가 알 수 있으므로 4개의 크기만큼 가져와서 확인할 수 있다.

17. 중복된 변수명이 있는 경우 특정 변수를 지정해서 출력 (print)
 p 'main.c'::var : main.c 파일에 있는 전역변수인 var 변수의 값을 출력
 p hello::var : hello 함수에 포함된 static 변수인 var 변수의 값을 출력

18. 출력 형식의 지정
 p/t var : var 변수를 2진수로 출력
 p/o var : var 변수를 8진수로 출력
 p/d var : var 변수를 부호가 있는 10진수로 출력 (int)
 p/u var : var 변수를 부호가 없는 10진수로 출력 (unsigned int)
 p/x var : var 변수를 16진수로 출력
 p/c var : var 변수를 최초 1바이트 값을 문자형으로 출력
 p/f var : var 변수를 부동 소수점 값 형식으로 출력
 p/a addr : addr주소와 가장 가까운 심볼의 오프셋을 출력 ( ex_ main + 15 )

19. 타입이 틀릴 경우 타입을 변환하여 출력
 p (char*)vstr : 실제 컴파일 시에 (void *)형으로 되어있었다고 하더라도 (char *)로 캐스팅 하여 보여줌

20. 특정한 위치 지정
 p lstr + 4 : 예를 들어 lstr = "I like you." 라는 문자열은 "ke you."가 출력된다.

21. 변수 값 설정
 p lval = 1000 : 변수값 확인 이외에는 설정도 가능하다.

22. 출력명령 요약 (print)
 p [변수명]    : 변수 값을 출력
 p [함수명]    : 함수의 주소를 출력
 p/[출력형식] [변수명] : 변수 값을 출력 형식으로 출력
 p '[파일명]'::[변수명] : 파일명에 있는 전역변수 값을 출력
 p [함수명]::[변수명] : 함수에 있는 변수 값을 출력
 p [변수명]@[배열크기] : 변수의 내용을 변수 배열의 크기 형태로 출력

23. 디스플레이 명령 (display, undisplay)
 display [변수명]  : 변수 값을 매번 화면에 디스플레이
 display/[출력형식] [변수명] : 변수 값을 출력 형식으로 디스플레이
 undisplay [디스플레이번호] : 디스플레이 설정을 없앤다
 disable display [디스플레이번호] : 디스플레이를 일시 중단한다.
 enable display [디스플레이번호] : 디스플레이를 다시 활성화한다.

24. 스택이란
 스택의 경우는 상위 1기가는 커널에서 사용하며, 그 바로 아래 공간인 상위 0xBFFFFFFF 부터 하위로 늘어나게된다.
 상세한 디버깅을 위해서는 -g 옵션으로 디버깅 정보와 --save-temps 옵션을 통해 어셈블리 코드를 얻어낼 수 있다.
 상위 프레임으로 갈 수록 메인 함수에 가까워 지는 것이다.

25. 스택 프레임 관련 명령 (frame, up, down, info)
 frame [N] : n번 스택 프레임으로 변경
 up   : 상위 프레임으로 이동
 up [N]  : n번 상위 스택 프레임으로 이동
 down  : 하위 프레임으로 이동
 down [N] : n번 하위 스택 프레임으로 이동
 info frame : 현재 스택 프레임 정보를 출력
 info args : 현재 스택 프레임의 함수가 호출될 때 인자를 출력
 info locals : 현재 스택 프레임의 함수내의 지역변수를 출력
 info catch : 현재 스택 프레임의 함수내의 예외 핸들러를 출력

26. 스택 트레이스 하는법
 b main 또는 원하는 곳에 브레이크 포인트를 잡고
 오류가 발생할 때 까지 c를 통해 진행하면, 세그먼트 폴트 등의 오류가 발생하고 디버그가 멈추는데
 여기서 bt 를 통해서 전체 스택 프레임을 확인하고 어떤 함수에서 호출시에 문제가 발생하였는지 확인
 단, 일반적인 라이브러리에서는 오류발생 확률이 없다고 보고, 그 함수를 호출시에 문제를 의심한다.
 다시 프레임을 이동하면서, 로컬변수와 전역변수 등을 확인하면서 디버깅이 가능하다.

27. 메모리 상태 검사 (x)
 x/[범위][출력 형식][범위의 단위] : 메모리의 특정 범위의 값들을 확인할 수 있다.
 이렇게 메모리를 직접 읽어보는 일은 -g 옵션을 가지고 컴파일 되지 않은 실행파일을 디버깅 할때에 자주 사용된다.
 즉, x/10i main 과 같이 역 어셈블하여 해당 코드를 추측하는 것이다.

28. 출력형식
 x/10 main : main 함수 시작부터 40바이트를 출력한다. 출력형식은 다음과 같다.
 x/10t main : main 함수 시작부터 40바이트를 2진수로 출력
 x/10o main : main 함수 시작부터 40바이트를 8진수로 출력
 x/10d main : main 함수 시작부터 40바이트를 부호가 있는 10진수로 출력 (int)
 x/10u main : main 함수 시작부터 40바이트를 부호가 없는 10진수로 출력 (unsigned int)
 x/10x main : main 함수 시작부터 40바이트를 16진수로 출력
 x/10c main : main 함수 시작부터 40바이트를 최초 1바이트 값을 문자형으로 출력
 x/10f main : main 함수 시작부터 40바이트를 부동 소수점 값 형식으로 출력
 x/10a main : 가장 가까운 심볼의 오프셋을 출력
 x/10s main : 문자열로 출력
 x/10i main : 어셈블리 형식으로 출력

29. 범위의 단위 (기본 word - 4바이트)
 x/10b main : byte - 1바이트 단위 - 10바이트 출력
 x/10h main : halfword - 2바이트 단위 - 20바이트 출력
 x/10w main : word - 4바이트 단위 - 40바이트 출력
 x/10g main : giant word - 8바이트 단위 - 80바이트 출력

30. 디스어셈블링 (disas)
 disas func : 어셈블리 코드를 좀 보편적으로 보기 위한 명령어
 disas 0x8048300 0x8048400 : 특정 주소 범위사이의 어셈블리 코드를 보기

31. 함수호출 (call)
 call func(arg1, arg2) : 특정함수 func를 arg1, arg2 파라메터를 포함하여 호출하고, 반환값은 출력

32. 점프 (jump)
 jump *0x08048321 : 해당 주소로 무조건 분기하여 인스트럭션을 계속 수행한다.
 jump 10  : 무조건 10행으로 분기하여 수행한다.
 jump func : func 함수로 무조건 분기하여 수행한다.

33. 시그널 전송 (signal)
 info signals : 보낼 수 있는 시그널의 종류를 확인할 수 있다.
 signal SIGKILL : 디버깅 대상의 프로세스에게 KILL 시그널을 보낼 수 있다.

34. 메모리의 특정 영역에 값을 설정 ( set )
 set {타입}[주소] = [값] : p 명령 대신에 set 을 통해서 메모리의 특정 주소에 저장하는 것이 더 일반적이다
 set {int}0x8048300 = 100 : 해당 주소에 100의 값을 입력한다.

35. gdb 환경설정 (set)
 info set : 변경 가능한 환경설정 정보를 출력한다.
 info functions : 함수들의 리스트를 출력
 info types  : 선언된 타입에 대한 리스트를 출력
 set prompt psyoblade: : 프롬프트를 psyoblade: 로 변경할 수 있다.
 set print array on : 배열을 출력할 때 한 행에 출력하는 것이 아니라 여러 행에 출력한다.

36. 기타 info 를 통해 알 수 있는 정보들
 address         catch           extensions      handle          objects         set             stack           tracepoints
 all-registers   common          files           heap            program         sharedlibrary   symbol          types
 architecture    copying         float           leaks           registers       signals         target          variables
 args            dcache          frame           line            remote-process  source          terminal        warranty
 breakpoints     display         functions       locals          scope           sources         threads         watchpoints
 
이올린에 북마크하기(0) 이올린에 추천하기(0)

2008/06/17 11:07 2008/06/17 11:07
Trackback Address :: http://zemy.net/tc/zemyblue/trackback/96
[로그인][오픈아이디란?]
Name
Password
Homepage

Secret

[스크랩]GDB 사용법 :: 2008/06/02 17:21

출처 : http://natural.chonnam.ac.kr/asm/lecture/gdb-1.txt 

GNU DeBugger(gdb) 사용법(1)

1 gdb에서 프로그램 실행

- 디버깅할 프로그램을 매개변수로 주고 gdb 실행

[1 gdb]# gdb ./toycat
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...(no debugging symbols found)...

- 프로그램 매개변수를 주고 프로그램 시작

(gdb) run /etc/resolv.conf
Starting program: /home/jhyou/asm/work/gdb/toycat /etc/resolv.conf
search chonnam.ac.kr
nameserver 168.131.33.5
nameserver 168.131.33.6

Program exited normally.

- gdb 종료

(gdb) quit
[1 gdb]#


2 프로그램 코드 보기

2.1 디스어셈블

- disassemble 주소
  disas 주소

(gdb) disassemble _start
Dump of assembler code for function _start:
0x8048080 <_start>:     cmpl   $0x2,(%esp,1)
0x8048087 <_start+7>:   je     0x80480ab <_start.argc_ok>
0x8048089 <_start+9>:   mov    $0x4,%eax
0x804808e <_start+14>:  mov    $0x2,%ebx
0x8048093 <_start+19>:  mov    $0x8049130,%ecx
0x8048098 <_start+24>:  mov    $0x17,%edx
0x804809d <_start+29>:  int    $0x80
0x804809f <_start+31>:  mov    $0x1,%eax
0x80480a4 <_start+36>:  mov    $0x1,%ebx
0x80480a9 <_start+41>:  int    $0x80
End of assembler dump.

- x/<명령수>i

(gdb) x/5i _start
0x8048080 <_start>:     cmpl   $0x2,(%esp,1)
0x8048087 <_start+7>:   je     0x80480ab <_start.argc_ok>
0x8048089 <_start+9>:   mov    $0x4,%eax
0x804808e <_start+14>:  mov    $0x2,%ebx
0x8048093 <_start+19>:  mov    $0x8049130,%ecx

(gdb) x/5i 0x8048080
0x8048080 <_start>:     cmpl   $0x2,(%esp,1)
0x8048087 <_start+7>:   je     0x80480ab <_start.argc_ok>
0x8048089 <_start+9>:   mov    $0x4,%eax
0x804808e <_start+14>:  mov    $0x2,%ebx
0x8048093 <_start+19>:  mov    $0x8049130,%ecx

(gdb) x (_start + 2)
0x8048082 <_start+2>:   and    $0x2,%al


2.2 AT&T 문법과 Intel 문법 선택

* 명령 형식: set disassembly-flavor <att|intel>

(gdb) set disassembly-flavor intel

(gdb) show disassembly-flavor
The disassembly flavor is "intel".

(gdb) disassemble _start
Dump of assembler code for function _start:
0x8048080 <_start>:     cmp    DWORD PTR [esp],0x2
0x8048087 <_start+7>:   je     0x80480ab <_start.argc_ok>
0x8048089 <_start+9>:   mov    eax,0x4
0x804808e <_start+14>:  mov    ebx,0x2
0x8048093 <_start+19>:  mov    ecx,0x8049130
0x8048098 <_start+24>:  mov    edx,0x17
0x804809d <_start+29>:  int    0x80
0x804809f <_start+31>:  mov    eax,0x1
0x80480a4 <_start+36>:  mov    ebx,0x1
0x80480a9 <_start+41>:  int    0x80
End of assembler dump.

(gdb) x/5i _start
0x8048080 <_start>:     cmp    DWORD PTR [esp],0x2
0x8048087 <_start+7>:   je     0x80480ab <_start.argc_ok>
0x8048089 <_start+9>:   mov    eax,0x4
0x804808e <_start+14>:  mov    ebx,0x2
0x8048093 <_start+19>:  mov    ecx,0x8049130


3 프로그램 실행 추적하기

3.1 프로그램 추적 시작

프로그램을 추적하기 위해서는 먼저 추적을 시작할 코드 위치에 breakpoint를 설정한
후 run 명령을 실행한다.

[1 gdb]# gdb toycat
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...(no debugging symbols found)...

(gdb) set disassembly-flavor intel

(gdb) x/2i _start
0x8048080 <_start>:     cmp    DWORD PTR [esp],0x2
0x8048087 <_start+7>:   je     0x80480ab <_start.argc_ok>

- _start 코드의 두번째 명령어의 위치인 _start + 7 주소에 breakpoint를
  설정한다.
  ***주의***: gdb의 버그때문인지 프로그램 시작위치인 _start 주소에 대한
              breakpoint는 작동하지 않는다.

(gdb) break *(_start + 7)
Breakpoint 1 at 0x8048087

- 프로그램 실행을 시작하면, breakpoint에서 멈춘다.
  (breakpoint를 만나지 않으면 프로그램이 종료될 때까지 멈추지 않는다.)

(gdb) run /etc/resolv.conf
Starting program: /home/jhyou/asm/work/gdb/toycat /etc/resolv.conf

Breakpoint 1, 0x08048087 in _start ()


- 현재 명령코드 위치(eip 레지스터)의 코드 보기

(gdb) x $eip
0x8048087 <_start+7>:   je     0x80480ab <_start.argc_ok>
(gdb)


3.2 명령 코드 따라가기

- 준비 작업

[1 gdb]# gdb toycat
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...(no debugging symbols found)...
(gdb) set disassembly-flavor intel
(gdb) x/2i _start
0x8048080 <_start>:     cmp    DWORD PTR [esp],0x2
0x8048087 <_start+7>:   je     0x80480ab <_start.argc_ok>
(gdb) break *(_start+7)
Breakpoint 1 at 0x8048087

(gdb) run /etc/resolv.conf
Starting program: /home/jhyou/asm/work/gdb/toycat /etc/resolv.conf

Breakpoint 1, 0x08048087 in _start ()


3.2.1 nexti, stepi

nexti(단축명령: ni), stepi(단축명령: si)

(gdb) x $eip
0x8048087 <_start+7>:   je     0x80480ab <_start.argc_ok>

(gdb) stepi
0x080480ab in _start.argc_ok ()
(gdb) x $eip
0x80480ab <_start.argc_ok>:     mov    eax,0x5

(gdb) si
0x080480b0 in _start.argc_ok ()
(gdb) x $eip
0x80480b0 <_start.argc_ok+5>:   mov    ebx,DWORD PTR [esp+8]

(gdb) nexti
0x080480b4 in _start.argc_ok ()
(gdb) x $eip
0x80480b4 <_start.argc_ok+9>:   mov    ecx,0x0

(gdb) ni
0x080480b9 in _start.argc_ok ()
(gdb) x $eip
0x80480b9 <_start.argc_ok+14>:  int    0x80

(gdb) ni
0x080480c0 in _start.argc_ok ()
(gdb) x $eip
0x80480c0 <_start.argc_ok+21>:  cmp    eax,0x0
(gdb)

- stepi와 nexti의 차이점

  stepi는 "call <주소>" 명령(서브프로그램, 함수 호출 명령)을 실행하면,
  <주소>위치 위치에서 멈춘다. 즉, stepi는 서브프로그램 코드를 추적하는데 사용한다.

  nexti는 call 명령과 관계없이 현재 명령의 다음 명령코드에서 멈춘다.

  그외, 명령 코드에 대해서는 stepi와 nexti는 동일한 기능을 한다.

- 참고: nexti 명령 후 x $eip 명령이 실행되도록 하는 설정 방법을
        4.4절 display와 @.1 사용자 정의 명령 설정 참고


3.2 추적 도중 프로그램 멈추기: kill(k)

(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/jhyou/asm/work/gdb/toycat /etc/resolv.conf

Breakpoint 1, 0x08048087 in _start ()

(gdb) kill
Kill the program being debugged? (y or n) y

(gdb) run
Starting program: /home/jhyou/asm/work/gdb/toycat /etc/resolv.conf

Breakpoint 1, 0x08048087 in _start ()

(gdb) k
Kill the program being debugged? (y or n) y
(gdb)


3.3 다음 breakpoint까지 연속 실행: continue(c)

breakpoint를 프로그램 실행 경로 중 군데군데에 breakpoint를 설정해두고
각 breakpoint 위치에서 nexti 등 명령으로 상세히 추적을 하다가
다음 breakpoint 위치로 이동할 때 쓰는 명령이다.

반복문 또는 특정 함수의 디버깅 때에도 break/continue를 조합하여 사용한다.

[1 gdb]# gdb toycat
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...(no debugging symbols found)...

(gdb) set disassembly-flavor intel
(gdb) x/10i _start
0x8048080 <_start>:     cmp    DWORD PTR [esp],0x2
0x8048087 <_start+7>:   je     0x80480ab <_start.argc_ok>
0x8048089 <_start+9>:   mov    eax,0x4
0x804808e <_start+14>:  mov    ebx,0x2
0x8048093 <_start+19>:  mov    ecx,0x8049130
0x8048098 <_start+24>:  mov    edx,0x17
0x804809d <_start+29>:  int    0x80
0x804809f <_start+31>:  mov    eax,0x1
0x80480a4 <_start+36>:  mov    ebx,0x1
0x80480a9 <_start+41>:  int    0x80

(gdb) break *(_start + 7)
Breakpoint 1 at 0x8048087
(gdb) break *0x8048089
Breakpoint 2 at 0x8048089
(gdb) break *0x804809f
Breakpoint 3 at 0x804809f

(gdb) run
Starting program: /home/jhyou/asm/work/gdb/toycat

Breakpoint 1, 0x08048087 in _start ()

(gdb) continue
Continuing.

Breakpoint 2, 0x08048089 in _start ()

(gdb) c
Continuing.
usage: toycat filename

Breakpoint 3, 0x0804809f in _start ()
(gdb) c
Continuing.

Program exited with code 01.
(gdb)


4 데이터 보기

- 준비작업

[1 gdb]# gdb toycat
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...(no debugging symbols found)...

(gdb) x/2i _start
0x8048080 <_start>:     cmpl   $0x2,(%esp,1)
0x8048087 <_start+7>:   je     0x80480ab <_start.argc_ok>

(gdb) break *(_start+7)
Breakpoint 1 at 0x8048087

(gdb) run /etc/resolv.conf
Starting program: /home/jhyou/asm/work/gdb/toycat

Breakpoint 1, 0x08048087 in _start ()
(gdb)


4.1 레지스터 보기

(gdb) info reg
eax            0x0      0
ecx            0x0      0
edx            0x0      0
ebx            0x0      0
esp            0xbffff480       0xbffff480
ebp            0x0      0x0
esi            0x0      0
edi            0x0      0
eip            0x8048087        0x8048087
eflags         0x297    663
cs             0x23     35
ss             0x2b     43
ds             0x2b     43
es             0x2b     43
fs             0x0      0
gs             0x0      0
fctrl          0x37f    895
fstat          0x0      0
---Type <return> to continue, or q <return> to quit---
ftag           0xffff   65535
fiseg          0x0      0
fioff          0x0      0
foseg          0x0      0
fooff          0x0      0
fop            0x0      0
xmm0           {f = {0x0, 0x0, 0x0, 0x0}}       {f = {0, 0, 0, 0}}
xmm1           {f = {0x0, 0x0, 0x0, 0x0}}       {f = {0, 0, 0, 0}}
xmm2           {f = {0x0, 0x0, 0x0, 0x0}}       {f = {0, 0, 0, 0}}
xmm3           {f = {0x0, 0x0, 0x0, 0x0}}       {f = {0, 0, 0, 0}}
xmm4           {f = {0x0, 0x0, 0x0, 0x0}}       {f = {0, 0, 0, 0}}
xmm5           {f = {0x0, 0x0, 0x0, 0x0}}       {f = {0, 0, 0, 0}}
xmm6           {f = {0x0, 0x0, 0x0, 0x0}}       {f = {0, 0, 0, 0}}
xmm7           {f = {0x0, 0x0, 0x0, 0x0}}       {f = {0, 0, 0, 0}}
mxcsr          0x1f80   8064
orig_eax       0xffffffff       -1

(gdb) info reg esp
esp            0xbffff480       0xbffff480

(gdb) info reg eax ebx ecx
eax            0x0      0
ebx            0x0      0
ecx            0x0      0

(gdb) print $esp
$1 = (void *) 0xbffff480


4.2 메모리 내용 보기: x

- 명령 형식
  (gdb) x/nfu 주소
  n : 반복 갯수
  f : 출력 양식(format)
      i(명령코드)
      x(16진수), o(8진수), t(2진수), d(부호있는 10진수), u(부호없는 10진수)
      s(문자열,string)
   
  u : 단위(unit)
      b(바이트), h(2바이트), w(4바이트)

  * 참고: f와 u 지정없이 x 명령만 실행하면, 앞에서 지정한 f와 u 형식이 적용된다.


- 명령 예

(gdb) x/10xw $esp
0xbffff470:     0x00000002      0xbffff5ad      0xbffff5cd      0x00000000
                                ----(A)---
0xbffff480:     0xbffff5de      0xbffff5fb      0xbffff612      0xbffff64f
0xbffff490:     0xbffff661      0xbffff684

(gdb) x/s 0xbffff5ad   <== 이 값은 바로 위 줄의 밑줄쳐진 부분(A)의 값이다.
0xbffff5ad:      "/home/jhyou/asm/work/gdb/toycat"

  * 참고: $esp + 4의 주소에는 0번째 프로그램 매개변수(argv[0], 프로그램 이름)
         문자열의 주소가 들어있다.

(gdb) x/40xb 0xbffff5ad
0xbffff5ad:     0x2f    0x68    0x6f    0x6d    0x65    0x2f    0x6a    0x68
0xbffff5b5:     0x79    0x6f    0x75    0x2f    0x61    0x73    0x6d    0x2f
0xbffff5bd:     0x77    0x6f    0x72    0x6b    0x2f    0x67    0x64    0x62
0xbffff5c5:     0x2f    0x74    0x6f    0x79    0x63    0x61    0x74    0x00
0xbffff5cd:     0x2f    0x65    0x74    0x63    0x2f    0x72    0x65    0x73

(gdb) x/5i _start
0x8048080 <_start>:     cmp    DWORD PTR [esp],0x2
0x8048087 <_start+7>:   je     0x80480ab <_start.argc_ok>
0x8048089 <_start+9>:   mov    eax,0x4
0x804808e <_start+14>:  mov    ebx,0x2
0x8048093 <_start+19>:  mov    ecx,0x8049130

(gdb) x/24xb _start
0x8048080 <_start>:     0x81    0x3c    0x24    0x02    0x00    0x00    0x00 0x74
0x8048088 <_start+8>:   0x22    0xb8    0x04    0x00    0x00    0x00    0xbb 0x02
0x8048090 <_start+16>:  0x00    0x00    0x00    0xb9    0x30    0x91    0x04 0x08
(gdb)

- C언어 문법에 따른 수식으로 주소를 표현할 수 있다.

* 예: 프로그램 매개변수 보기

(gdb) x/s ((char**)((int)$esp + 4))[0]
0xbffff5ad:      "/home/jhyou/asm/work/gdb/toycat"

(gdb) x/s ((char**)((int)$esp + 4))[1]
0xbffff5cd:      "/etc/resolv.conf"

* 참고: 변수를 이용하여 프로그램 매개변수 포인터를 간략하게 나타내기

(gdb) set $argv = ((char**)((int)$esp + 4))

(gdb) x/s $argv[0]
0xbffff5ad:      "/home/jhyou/asm/work/gdb/toycat"

(gdb) x/s $argv[1]
0xbffff5cd:      "/etc/resolv.conf"


4.3 데이터 보기: print

- 명령형식
  print   수식
  print/f 수식
          f : 출력양식
              x(16진수), o(8진수), t(이진수),
              d(부호있는 10진수), u(부호없는 10진수),
              c(문자)
              a(주소)
              f(실수)

- 예

(gdb) print/t 37
$12 = 100101

(gdb) print 1 + 2 * 3
$13 = 7

(gdb) print/a (int)$esp + 4
$14 = 0xbffff474  <== (B)

(gdb) print/a *0xbffff474    <== 이 값은 (B)에 표시된 값
$15 = 0xbffff5ad  <== (C)

(gdb) print (char*)0xbffff5ad    <== 이 값은 (C)에 표시된 값
$16 = 0xbffff5ad "/home/jhyou/asm/work/gdb/toycat"

(gdb) print *(char*)0xbffff5ad
$17 = 47 '/'

* 배열주소@갯수 형식의 지정으로 배열의 원소 갯수를 지정할 수 있다.

(gdb) print *(char*)0xbffff5ad@10
$18 = "/home/jhyo"

(gdb) print/c *(char*)0xbffff5ad@10
$19 = {47 '/', 104 'h', 111 'o', 109 'm', 101 'e', 47 '/', 106 'j', 104 'h',
121 'y', 111 'o'}

(gdb) print *(char**)((int)$esp+4)@5
$29 = {0xbffff5ad "/home/jhyou/asm/work/gdb/toycat", 0xbffff5cd "/etc/resolv.conf", 0x0,
  0xbffff5de "PWD=/home/jhyou/asm/work/gdb", 0xbffff5fb "STY=8051.pts-5.loafers"}
(gdb)


4.4 자동 데이터 출력 설정하기

디버깅시 프로그램 실행이 멈출 때(stepi, nexti, breakpoint)마다 보고 싶은
데이터를 등록한다.

- 준비 작업

[1 gdb]# gdb toycat
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...(no debugging symbols
found)...
(gdb) set disassembly-flavor intel
(gdb) break *(_start+7)
Breakpoint 1 at 0x8048087
(gdb) run /etc/resolv.conf
Starting program: /home/jhyou/asm/work/gdb/toycat /etc/resolv.conf

Breakpoint 1, 0x08048087 in _start ()


- 프로그램 실행을 멈출 때마다 다음 명령코드 보기

(gdb) display/i $eip
1: x/i $eip  0x8048087 <_start+7>:      je     0x80480ab <_start.argc_ok>

(gdb) stepi
0x080480ab in _start.argc_ok ()
1: x/i $eip  0x80480ab <_start.argc_ok>:        mov    eax,0x5

(gdb) stepi
0x080480b0 in _start.argc_ok ()
1: x/i $eip  0x80480b0 <_start.argc_ok+5>:      mov    ebx,DWORD PTR [esp+8]

- $eip, $eax 레지스터, 변수 fd 값 보기

(gdb) display $eip
2: $eip = (void *) 0x80480b0
(gdb) display $eax
3: $eax = 5
(gdb) display fd
4: {<data variable, no debug info>} 134517116 = 0

(gdb) stepi
0x080480b4 in _start.argc_ok ()
4: /x {<data variable, no debug info>} 134517116 = 0x0
3: $eax = 5
2: $eip = (void *) 0x80480b4
1: x/i $eip  0x80480b4 <_start.argc_ok+9>:      mov    ecx,0x0

(gdb) stepi
0x080480b9 in _start.argc_ok ()
4: /x {<data variable, no debug info>} 134517116 = 0x0
3: $eax = 5
2: $eip = (void *) 0x80480b9
1: x/i $eip  0x80480b9 <_start.argc_ok+14>:     int    0x80

- display 항목 제거하기: undisplay <display 번호>

(gdb) undisplay 4
(gdb) undisplay 3

(gdb) stepi
0x080480c0 in _start.argc_ok ()
2: $eip = (void *) 0x80480c0
1: x/i $eip  0x80480c0 <_start.argc_ok+21>:     cmp    eax,0x0
(gdb)


4.5 symbol에 대한 정보 보기

- 함수 이름

(gdb) info functions
All defined functions:

Non-debugging symbols:
0x08048080  _start
0x080480ab  _start.argc_ok
0x080480e9  _start.open_success
0x080480e9  _start.read_loop
0x08048117  _start.read_end

- 변수 이름

(gdb) info variables
All defined variables:

Non-debugging symbols:
0x08049130  usage_msg
0x08049147  open_err_msg
0x0804915c  buffer
0x0804917c  fd


5 기타

5.1 도움말 보기

- 전체 도움말 목록 보기

(gdb) help
List of classes of commands:

aliases -- Aliases of other commands
breakpoints -- Making program stop at certain points
data -- Examining data
files -- Specifying and examining files
internals -- Maintenance commands
obscure -- Obscure features
running -- Running the program
stack -- Examining the stack
status -- Status inquiries
support -- Support facilities
tracepoints -- Tracing of program execution without stopping the program
user-defined -- User-defined commands

Type "help" followed by a class name for a list of commands in that class.
Type "help" followed by command name for full documentation.
Command name abbreviations are allowed if unambiguous.

- break 항목에 대한 도움말 보기

(gdb) help break
Set breakpoint at specified line or function.
Argument may be line number, function name, or "*" and an address.
If line number is specified, break at start of code for that line.
If function is specified, break at start of code for that function.
If an address is specified, break at that exact address.
With no arg, uses current execution address of selected stack frame.
This is useful for breaking on return to a stack frame.

Multiple breakpoints at one place are permitted, and useful if conditional.

Do "help breakpoints" for info on other commands dealing with breakpoints.
(gdb)


5.2 사용자 정의 명령 설정

- x/i $eip 명령을 ci로 축약 설정

(gdb) define ci
Type commands for definition of "ci".
End with a line saying just "end".
>x/i $eip
>end 

(gdb) ci
0x80483da <main+38>:    pushl  0x8049674
(gdb) ci
0x80483da <main+38>:    pushl  0x8049674

- nexti 명령 후 x $eip 명령이 자동 실행되도록 설정

(gdb) define hookpost-nexti  
Type commands for definition of "hookpost-nexti".
End with a line saying just "end".
>x/i $eip
>end

(gdb) nexti
0x080483ca in main ()
0x80483ca <main+22>:    push   $0x8048510
(gdb) nexti
0x080483cf in main ()
0x80483cf <main+27>:    call   0x80482f4 <printf>
(gdb) ni
0x080483d4 in main ()
0x80483d4 <main+32>:    add    $0x10,%esp

- 사용자 명령 정의 보기
   
(gdb) show user ci           
User command ci:
  x/i $eip

(gdb) show user hookpost-nexti
User command hookpost-nexti:
  x/i $eip


5.3 gdb 사용자 기본 설정 파일: ~/.gdbinit

~/.gdbinit 파일에 gdb 설정 명령들을 저장해두면 gdb가 실행될 때마다
~/.gdbinit 파일의 명령들을 읽어 각종 설정을 자동으로 초기화한다.

- 실습

* 아래와 같이 출력되도록 ~/.gdbinit 파일을 작성한다.

[1 gdb]# cat ~/.gdbinit
set disassembly-flavor intel

define ci
x/i $eip
end

* gdb toycat을 실행한다.

[1 gdb]# gdb toycat
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...(no debugging symbols found)...

(gdb) break *(_start+7)
Breakpoint 1 at 0x8048087
(gdb) run
Starting program: /home/jhyou/asm/work/gdb/toycat

Breakpoint 1, 0x08048087 in _start ()

* disassembly-flavor 설정이 intel로 설정되어있다.

(gdb) show disassembly-flavor
The disassembly flavor is "intel".

(gdb) x/5i _start
0x8048080 <_start>:     cmp    DWORD PTR [esp],0x2
0x8048087 <_start+7>:   je     0x80480ab <_start.argc_ok>
0x8048089 <_start+9>:   mov    eax,0x4
0x804808e <_start+14>:  mov    ebx,0x2
0x8048093 <_start+19>:  mov    ecx,0x8049130

* ci 명령이 등록되어 있다.

(gdb) show user
User command ci:
  x/i $eip

(gdb) ci
0x8048087 <_start+7>:   je     0x80480ab <_start.argc_ok>



6 부록: 예제 프로그램: toycat.asm

6.1 toycat.asm 프로그램 소스

;; toycat.asm
;;
;; To build:
;; nasm -f elf toycat.asm
;; ld -o toycat toycat.o
;; To execute:
;; ./toycat /etc/passwd
;;

BITS 32

segment .text
global _start

_start:
                ; if (argc != 2) {
                ;    write(STDERR, usage_msg, usage_msg_len);
                ;    exit(1);
                ; }
                cmp dword [esp], 2
                je .argc_ok

                mov eax, 4                   
                mov ebx, 2
                mov ecx, usage_msg
                mov edx, usage_len
                int 0x80

                mov eax, 1                   
                mov ebx, 1
                int 0x80

.argc_ok:
                ; fd = open(argv[1], O_RDONLY);
                mov eax, 5
                mov ebx, [esp + 8]
                mov ecx, 00q
                int 0x80
                mov [fd], eax

                ; if (fd < 0) {
                ;     write(STDERR, open_err_msg, open_err_len);
                ;     exit(2);
                ; }
                cmp eax, 0
                jge .open_success

                mov eax, 4
                mov ebx, 2
                mov ecx, open_err_msg
                mov edx, open_err_len
                int 0x80

                mov eax, 1
                mov ebx, 2
                int 0x80
.open_success: 

                ; while ((nread = read(fd, buffer, buffer_len) > 0) {
                ;    write(STDOUT, buffer, nread);
                ; }
.read_loop:     mov eax, 3
                mov ebx, [fd]
                mov ecx, buffer
                mov edx, buffer_len
                int 0x80

                cmp eax, 0         ; eax == nread
                jng .read_end

                mov edx, eax       ; write(STDOUT, buffer, nread);
                mov eax, 4        
                mov ebx, 1
                int 0x80

                jmp .read_loop
.read_end:

                ; close(fd);
                mov eax, 6
                mov ebx, [fd]
                int 0x80

                ; exit(0);
                mov eax, 1
                mov ebx, 0
                int 0x80

segment .data
usage_msg       db  "usage: toycat filename", 10
usage_len       equ $ - usage_msg

open_err_msg    db  "cannot open file!", 10
open_err_len    equ $ - open_err_msg

segment         .bss
buffer          resb 32
buffer_len      equ  $ - buffer

fd              resd 1

@.2 toycat.asm의 실행 예

- 컴파일

[1 gdb]# nasm -f elf toycat.asm
[1 gdb]# ld -o toycat toycat.o

- 실행 1

[1 gdb]# ./toycat
usage: toycat filename

- 실행 2

[1 gdb]# ./toycat /etc/resolv.conf
search chonnam.ac.kr
nameserver 168.131.33.5
nameserver 168.131.33.6

이올린에 북마크하기(0) 이올린에 추천하기(0)

2008/06/02 17:21 2008/06/02 17:21
Trackback Address :: http://zemy.net/tc/zemyblue/trackback/83
[로그인][오픈아이디란?]
Name
Password
Homepage

Secret