gdb
원본 사이트
좋은 정보를 블로그에 올려주신 분에게 감사를...^^;
http://blog.daum.net/joell/11772014
native gdb
localhost opt # tar xvzf termcap-1.3.1.tar.gz
localhost opt # cd termcap-1.3.1
localhost termcap-1.3.1# CC=arm-linux-gcc ./configure --build=i686-linux --host=arm-linux --prefix=$PWD/build
localhost termcap-1.3.1# make && make install
localhost termcap-1.3.1# cd ..
localhost opt # wget ftp://ftp.jaist.ac.jp/pub/GNU/gdb/gdb-6.6.tar.gz
localhost opt # tar xvzf gdb-6.6.tar.gz
localhost opt # cd gdb-6.6
localhost gdb-6.6 # CFLAGS=-L/opt/termcap-1.3.1 ./configure --build=i686-linux --host=arm-linux --target=arm-linux --prefix=/nfsroot/gdb
localhost gdb-6.6 # make && make install
확인 필요
ptrace: bogus breakpoint trap 메세지가 너무 많이 나옴
gdb & gdbserver
localhost opt # tar xvzf gdb-6.6.tar.gz
localhost opt # cd gdb-6.6
localhost gdb-6.6 # ./configure --build=i686-linux --host=i686-linux --target=arm-linux --prefix=$PWD/build
localhost gdb-6.6 # make && make install
localhost gdb-6.6 # cp build/bin/arm-linux-gdb /nfsroot/
localhost gdb-6.6 # cd gdb/gdbserver
localhost gdbserver # CC=arm-linux-gcc ./configure --build=i686-linux --host=arm-linux --target=arm-linux
localhost gdbserver # cp gdbserver /nfsroot/
태스트
태스트 할 프로그램을 ARM용으로 컴파일 한다. 디버깅 옵션( -g )가 빠지지 않도록 주의해야 한다.
태스트를 하기 전에 컴파일결과 만들어진 파일들을 확인해보자.
a.out: ELF 32-bit LSB executable, ARM, version 1, for GNU/Linux 2.0.0, dynamically linked (uses shared libs), not stripped
localhost nfsroot # file arm-linux-gdb
arm-linux-gdb: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), not stripped
localhost nfsroot # file gdbserver
gdbserver: ELF 32-bit LSB executable, ARM, version 1, for GNU/Linux 2.0.0, dynamically linked (uses shared libs), not stripped
타겟보드에서 nfs로 pc에 마운트하여 태스트를 진행한다. 주의할 점은 PC와 타겟 모두 동일한 실행파일(a.out)과 소스코드(gdb_test.c)를 가지고 있어야 한다.
우선 minicom을 실행시키다.
타겟보드에서 pc에 nfs 마운트한다. 타겟의 IP는 192.168.1.166, host pc의 IP는 192.168.1.167로 설정하였다.
# route add default gw 192.168.1.1
# mount -t nfs 192.168.1.167:/nfsroot /nfsroot -o nolock,rsize=1024,wsize=1024
타겟보드에서 컴파일한 실행파일을 실행 시켜 보자. 허용되지 않은 메모리를 접근하려고 해서 segmentation fault 에러가 난 것을 확인 할 수 있다.
# ./a.out
debug test
pc : [<4007a174>] lr : [<40082994>] Not tainted
sp : bffffdb0 ip : 4012b068 fp : 0000000a
r10: 4012cce0 r9 : 00000000 r8 : 4012b01c
r7 : 000003ff r6 : 00000400 r5 : 00000000 r4 : 00000000
r3 : 40015001 r2 : 00000064 r1 : 40015000 r0 : 00000064
Flags: nzCv IRQs on FIQs on Mode USER_32 Segment user
Control: 397F Table: A7CB8000 DAC: 00000015
Segmentation fault
타겟보드에서 자신의 IP와 임의의 포트번호, 디버깅할 실행파일 이름을 인자로 하여 gdbserver를 실행한다.
Process a.out created; pid = 61
Listening on port 10000
PC에서 디버깅할 실행파일을 인자로 하여 gdb를 실행한다.
/nfsroot
localhost nfsroot # ./arm-linux-gdb a.out
GNU gdb 6.6
Copyright (C) 2006 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 "--host=i686-linux --target=arm-linux"...
(gdb)
우선 디버거에서 사용할 라이브러리 위치를 알려주기 위해서 툴체인의 라이브러리 상위폴더를 지정해주어야 한다.
pc에서 타겟보드로 연결 하자.
Remote debugging using 192.168.1.166:10000
0x40001c80 in _start () at rtld.c:-1
-1 rtld.c: No such file or directory.
in rtld.c
타겟보드에서 다음 메세지를 확인 할 수 있다.
우선 실행을 시켜보자. PC에서 continue 또는 c를 입력하자
Continuing.
그리고 나서 보드에서 test라고 입력한 후 엔터를 친다.
pc : [<4007a174>] lr : [<40082994>] Not tainted
sp : bffffdb0 ip : 4012b068 fp : 0000000a
r10: 4012cce0 r9 : 00000000 r8 : 4012b01c
r7 : 000003ff r6 : 00000400 r5 : 00000000 r4 : 00000000
r3 : 40015001 r2 : 00000074 r1 : 40015000 r0 : 00000074
Flags: nzCv IRQs on FIQs on Mode USER_32 Segment user
Control: 397F Table: A7AC0000 DAC: 00000015
PC를 확인 해보면 Segmentation fault가 난 것을 알 수 있다. 잘못된 메모리 주소를 접근했기 때문에 난 에러이다.
0x4007a174 in ?? ()
gdb 명령 backtrace를 사용해보자. main함수 소스코드 라인 10줄에서 fgets함수를 호출 한 후, getline_info에서 실행이 멈춘것을 알 수 있다. fgets의 인자로 받은 buf주소가 0x0=NULL 이어서 문제가 생긴 것이다.
#0 _IO_getline_info (fp=0x4012b01c, buf=0x0, n=1023, delim=10, extract_delim=1, eof=0x0) at iogetline.c:87
#1 0x4007a05c in _IO_getline (fp=0x74, buf=0x40015000 "test\n", n=116, delim=1073827841, extract_delim=1) at iogetline.c:41
#2 0x40079274 in _IO_fgets (buf=0x0, n=1024, fp=0x4012b01c) at iofgets.c:50
#3 0x00008478 in main (argc=1, argv=0xbffffe64) at debug_test.c:10
소스코드를 확인 해 보면 10번째 라인에 fgets함수를 볼 수 있다. 인자로 buf 를 사용하고 있다
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main( int argc, char **argv )
5 {
6 char *buf;
7
8 buf = malloc( 1<<31 );
9
10 fgets( buf, 1024, stdin );
(gdb) list +
11 printf( "%s\n", buf );
12
13 return 1;
14 }
(gdb)
스택 프레임을 main함수로 바꾸자
#3 0x00008478 in main (argc=1, argv=0xbffffe64) at debug_test.c:10
10 fgets( buf, 1024, stdin );
현재 스택 프레임에 대한 정보를 자세히 보려면
Stack level 3, frame at 0xbffffe38:
pc = 0x8478 in main (debug_test.c:10); saved pc 0x400381e0
caller of frame at 0xbffffe1c
source language c.
Arglist at 0xbffffe34, args: argc=1, argv=0xbffffe64
Locals at 0xbffffe34, Previous frame's sp at 0xbffffe2c
Saved registers:
r11 at 0xbffffe28, lr at 0xbffffe30, pc at 0xbffffe30
지역번수의 내용을 확인하면 buf의 주소가 NULL인 것을 볼 수 있다.
buf = 0x0
아규먼트는 메인함수 호출시 사용된 것이 나온다.
argc = 1
argv = (char **) 0xbffffe64
print명령을 사용하면 포인터 변수인 buf의 내용과 가리키는 곳의 내용을 출력할 수 있다. 역시 여기서도 가리키는 곳을 접근 할수 없다는 메세지가 나온다.
$1 = 0x0
(gdb) print *buf
Cannot access memory at address 0x0
현재 디버그 중인 프로그램을 중지 시키려면 kill명령을 사용하면 된다.
타겟보드에서 실행중인 gdbserver를 중지시키게 된다.
Kill the program being debugged? (y or n) y
타겟보드에서 디버깅이 종료된 것을 확인 할 수 있다.
#
디버깅을 다시 시작 하기 위해 타겟보드에서 gdbserver를 다시 실행시킨다.
process id가 실행 할 때 마다 변하는 것을 볼 수 있다.
Process a.out created; pid = 69
Listening on port 10000
PC에서도 다시 gdbserver에 접속한다.
Remote debugging using 192.168.1.166:10000
0x40001c80 in _start () at rtld.c:-1
-1 rtld.c: No such file or directory.
in rtld.c
breakpoint를 8번째 라인으로 설정한다.
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main( int argc, char **argv )
5 {
6 char *buf;
7
8 buf = malloc( 1<<31 );
9
10 fgets( buf, 1024, stdin );
(gdb) list +
11 printf( "%s\n", buf );
12
13 return 1;
14 }
(gdb) break 8
Breakpoint 1 at 0x8454: file debug_test.c, line 8.
Continuing.
Breakpoint 1, main (argc=1, argv=0xbffffe64) at debug_test.c:8
8 buf = malloc( 1<<31 );
(gdb) print buf
$1 = 0x0
(gdb) print *buf
Cannot access memory at address 0x0
10 fgets( buf, 1024, stdin );
(gdb) print buf
$2 = 0x0
(gdb) print *buf
Cannot access memory at address 0x0
출처:http://webnautes.tistory.com/entry/gdb-gdb-server-cross-compile-for-arm