GNU 에서 만든 GDB 디버거의 사용방법에 대해서 설명하고 있다.
간단한 예제를 통해, 사용방법을 익히도록 하겠다.

설치하기

참고로 여기서 설명하고 있는 환경은 redhat9 이다. 설치시에 개발 패키지를 선택했다면, 자동으로 gdb 가 설치되어 있을 것이다.
버전은 5.3 이다. 물론 이것을 그대로 사용해도 거의 문제가 없다. 하지만 뒤에서 설명할 '멀티프로세스 프로그램 디버깅' 에서는 최소 6.2 버전 이상이 되어야 원활한 디버깅을 할 수 있다.
그래서 여기서는 간단하게 나마, gdb 를 컴파일하고 설치하는 방법에 대해 다루도록 하겠다.

#tar xzf gdb-6.2.tar.gz
#cd gdb-6.2
#./configure --prefix=/usr/local/program/gdb
#make
#make install

에러없이 수행이 되었다면, /usr/local/program/gdb/bin 아래에 실행파일이 복사되었을 것이다.

준비운동 하기

다음의 소스를 test.c 라는 파일로 저장한다.

#include <stdio.h>
 
struct time {
	int hour;
	int min;
	int sec;
} gtime = {1,2,3}, gtimes[4];
 
char *array[4] = {"one","two","three"};
 
int hello()
{
	int i = 10;
	while(i--);
		return 4;
}
 
int gethour(short sw)
{
	if (sw)
		return 2;
	else
		return hello();
}
 
int main()
{
	int lval = 2331, i;
	char *lstr = "I like you.";
	struct time *pt = &gtime;
 
	for(i=0; i<100; i++){
		printf("array[i] = %s\n", array[i]);
		gtime.hour += gethour(i % 2);
	}
 
	return 0;
}

이제 다음과 같이 컴파일을 한다.

#gcc -g test.c     /*-g 옵션을 주는 것은 심볼정보를 오브젝트 파일에 넣기 위함이다. -g 옵션이 없다면, 역 어셈브링해서 디버깅을 해야 한다*/

위의 프로그램은 컴파일은 정상적으로 되지만, 실행을 시켜보면, 'Segmentation fault' 가 발생한다.
이때가 바로 GDB 가 필요할 때다. 여기서는 이미 만들어진 ELF 형태의 오브젝트 파일을 이용해서 디버깅을 하지만, core 파일이나, 현재 실행중인 프로세스의 PID 를 가지고도 디버깅을 할 수 있다.

#gdb a.out
GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
Copyright 2003 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-gnu"...
(gdb)

GDB 를 실행시키면, 위와 같은 화면이 나타난다. GDB 프롬프트에서는 명령어 자동완성 기능과 히스토리 기능을 제공하기 때문에, 손쉽게 사용할 수 있다.

GDB 사용법

GDB 를 실행파일과 함께 실행시켰다면, 이제 본격적으로 사용 명령어를 통해 디버깅을 시작해야 한다.

명령어 사용예 설명
l(list) l main main 함수를 찾아 출력
l 10 10 행을 기준으로 출력
l - 출력된 행의 이전 행을 출력
l bug.c:main bug.c 파일의 main 함수를 출력
l bug.c:10 bug.c 파일의 10 행을 기준으로 출력

한번에 출력되는 행의 수를 20 으로 변경하려면,

(gdb) set listsize 20

입력하면 된다.

명령어 사용예 설명
b(break) b func func 함수의 시작부분에 breakpoint 설정
b 10 10 행에 breakpoint 설정
b +2 현재 행에서 2개 행 이후 지점에 breakpoint 설정
b *0x8049000 0x8049000 주소에 breakpoint 설정(어셈블리어로 디버깅시 사용)
b 10 if var == 0 10 행에 브레이크 포인트를 설정하는데 var 변수 값이 0 일때 작동

breakpoint 는 여러개를 지정해 줄 수 있고, 현재 잡은 breakpoint 의 정보를 보고 싶다면,

(gdb) info breakpoints

입력하면 된다. 잡은 breakpoint 를 삭제하는 명령어는 cl(clear) 이다.

명령어 사용예 설명
cl(clear) cl func func 함수의 시작 부분에 breakpoint 지움
cl 10 10 행의 breakpoint 지움
cl bug.c:28 bug.c 파일의 28 행의 breakpoint 지움
d 모든 breakpoint 지움

마지막으로 현재 설정한 breakpoint 를 임시로 비활성화 시키려면,

(gdb) disable 5

다시 활성화 시키려면,

(gdb) enable 5

한다. 여기서 5 는 breakpoint number 이다. 'info breakpoints' 를 통해 활성화 여부를 볼 수 있다.

명령어 사용예 설명
r r 프로그램 수행
r arg1 arg2 arg1 과 arg2 를 인자로 프로그램 수행
k k 프로그램 수행 종료
s s 현재 행 수행 후 정지, 함수 호출 시 함수 내부로 들어감
s 5 s를 5번 입력한 것과 동일
n n 현재 행 수행 후 정지, 함수 호출 시 함수 수행 후 다음 행으로 감
n 5 n을 5번 입력한 것과 동일
c c breakpoint 를 만날 때까지 계속 진행
u u 현재 루프를 빠져나감
finish finish 현재 함수를 수행하고 빠져 나감
return return 현재 함수를 수행하지 않고 빠져 나감
return 123 리턴값은 123
si si 현재의 인스트럭션을 수행, 함수 호출 시 함수 내부로 들어감
ni ni 현재의 인스트럭션을 수행, 함수 호출 시 함수 내부로 들어가지 않음

특정한 변수값을 보고 싶을 때, watchpoint 를 사용할 수 있다.

(gdb) watch [변수명]

지정한 변수값이 바뀔 때마다, 화면에 표시해준다.

명령어 설명
info locals 현재 지역변수들의 값을 출력
info variables 전역변수들의 리스트를 출력
p [변수명] 개별 변수의 값을 출력
p [함수명] 함수의 주소값을 출력
p [함수명]::[변수명] 함수에 있는 변수 값을 출력
display [변수명] 변수 값을 매번 화면에 디스플레이함
undisplay [디스플레이 번호] 디스플레이 설정을 없앰

printf 명령어를 사용해서 좀 더 다양한 포맷으로 출력할 수 있다.

(gdb)printf "l is %x\n", sdata.block_state
l is fffffffe

변수 sdata.block_state 의 값을 16 진수 형태로 출력한다.

명령어 설명
info f 또는 info frame 현재 스택 프레임 정보 출력
bt 현재 전체 스택 프레임 출력
frame [N] n번 스택 프레임으로 변경
up 상위 스택 프레임으로 이동
down 하위 스택 프레임으로 이동
info args 함수가 호출될 때 인자를 출력
info catch 함수의 예외 핸들러를 출력
명령어 사용예 설명
x/(범위)(출력형식)(범위의 단위) x/10i main main 함수의 시작부터 인스트럭션을 어셈블리로 변환해서 보임
set {타입}(주소) = (값) set {int}0x8048300 = 100 0x8048300 번지에 int 타입으로 100 입력
명령어 사용예 설명
call (함수명)(인자) call func(100) func 함수에 100 인자를 넣어서 실행
signal (info signals) signal SIGKILL 현재 디버깅 대상의 프로세스에 SIGKILL 시그널을 보냄

디버깅할 대상 프로그램이 인자값을 필요로 하는 경우가 있다. 이럴 때는 gdb 를 먼저 실행하고, 아래와 같이 실행한다.

(gdb) set args <인자들>
(gdb) run
  • computer/rtcclab/gdb_사용하기.txt
  • Last modified: 3 years ago
  • by likewind