IT/Tips

gdb fork

싸후이 2009. 11. 27. 18:26
출처 : http://studyfoss.egloos.com/5120049
GDB에서는 fork/exec() 이후에도 프로그램을 계속 디버깅 할 수 있는 기능을 제공한다.
(GNU/Linux, HP-UX only)

기본적으로는 fork() 이후에는 parent process 만이 계속 디버깅되며
child에 breakpoint를 설정하면 SIGTRAP을 받고 종료되어 버린다.
이를 해결하기 위한 전통적인 방법은 child에 sleep을 걸고
ps 명령 등으로 child의 pid를 알아낸 후에 attach 하는 방식이 사용되었다.

하지만 Linux (커널 2.5.60 이상) 에서는 다음과 같이 GDB에서 직접 처리할 수 있다.

set follow-fork-mode child

위와 같이 설정하면 fork() 후에 child process를 디버깅 상태로 만들고 parent는 계속 실행시킨다.
follow-fork-mode의 기본값은 parent이며 이는 다음과 같이 확인할 수 있다.

show follow-fork-mode

만약 parent와 child process를 모두 디버깅해야한다면
이들을 모두 제어하기 위해 다음 명령을 이용할 수 있다.

set detach-on-fork off

만약 fork/vfork/exec와 같은 특정 이벤트 발생 시 실행을 중지시키고 싶다면
catchpoint를 설정할 수 있다.

catch exec

아니면 exec()가 수행된 후에도 gdb breakpoint 등은 그대로 남아있게 되므로
공통으로 사용되는 main() 등의 함수에 break를 걸어둘 수도 있다.

이를 이용하여 gcc를 디버깅하려면 다음과 같이 할 수 있다.
(물론 gcc 자체가 디버깅 심볼을 포함하도록 compile되어 있어야 한다!)

/usr/bin/gcc 파일은 compiler driver로 실제 컴파일은 cc1이 담당하는데
gcc는 vfork() + exec() 조합을 통해 cc1을 실행한다. (as, collect2 등도 마찬가지..)
(물론 cc1의 path를 알고있다면 바로 cc1을 호출하여 간단히 디버깅할 수도 있겠지만
그렇지 않거나 (spec 파일에 따른?) gcc와 연계된 동작을 알고싶다면 위의 방법을 이용하면 된다..)

다음과 같이 입력하면 cc1의 main() 함수에서 중지된 채로 남아있다.

$ gdb gcc-4.4
(gdb) b main       ;; gcc/cc1의 main에 breakpoint 생성
(gdb) set follow-fork-mode child
(gdb) r test.c     ;; gcc 실행 (gcc main()에서 중지)
(gdb) c            ;; 계속 실행 (cc1 main()에서 중지)

실제 실행 결과는 아래와 같다

namhyung@NHK-XNOTE:~/temp/prog$ gdb gcc-4.4
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) b main
Breakpoint 1 at 0x80531d0: file ../../srcdir/gcc/gcc.c, line 6217.
(gdb) set follow-fork-mode child
(gdb) r test.c
Starting program: /usr/local/bin/gcc-4.4 test.c

Breakpoint 1, main (argc=Cannot access memory at address 0x0
) at ../../srcdir/gcc/gcc.c:6217
6217    {
(gdb) c
Continuing.
Executing new program: /usr/local/libexec/gcc/i686-pc-linux-gnu/4.4.0/cc1
[Switching to process 19640]

Breakpoint 1, main (argc=11, argv=0xbfcc97f4) at ../../srcdir/gcc/main.c:35
35      return toplev_main (argc, (const char **) argv);
(gdb)

'IT > Tips' 카테고리의 다른 글

ubuntu 9.10 설정  (0) 2010.01.27
자료형 최소값,최대값  (0) 2009.12.02
install XBMC on Ubuntu 9.04 (한글/SVN Repo Installer)  (0) 2009.11.06
firfox 부가기능 추가  (0) 2009.11.02
mplayer 한글설정  (0) 2009.10.30