ㅈㅅㄹ

스크립트를 사용하여 좀 더 편하게 작업하려면 안드로이드 GDB 디버깅 ver 2를 참고하기 바란다.

Java단에서의 디버그는 eclipse를 통해서 손쉽게 할 수 있지만 안드로이드 소스 자체를 수정하여 디버그하고 싶거나, NDK를 사용하여 개발한 앱의 Native단을 디버그 하기 위해선 GDB를 이용해야 한다. 안드로이드 PDK 사이트에 Debugging with GDB 문서를 보면 여러가지 방법들이 나오는데 개인적으론 터미널 세개 띄워 놓고 수동으로 디버그 하는게 제일 편한 것 같다.



아래에서 # 문자는 디바이스의 쉘을 나타내고 $ 는 컴퓨터의 쉘을 나타낸다.

일단 안드로이드 디바이스를 구동한다. eclipse에서 run 버튼을 눌러 아예 원하는 app을 실행시켜도 상관 없다. 디바이스가 정상적으로 구동 된 후 adb shell 명령어를 통해 접속하여 디바이스에서 쉘을 띄우고 난 후 ps 명령어를 실행하여 디버그를 원하는 App의 process id를 알아 낸 후 다음의 명령어를 실행하자.

# gdbserver :[PORT] --attach [PID]

[PORT]에는 적당한 포트 번호를 입력하고 [PID]에는 ps를 통해 알아낸 process id를 입력한다. 이후 리눅스 터미널에서 다음을 입력하여 위의 [PORT]란에 입력한 포트를 포워드 하자.

$ adb forward tcp:[PORT] tcp:[PORT]

이 후 android 소스트리에 있는 arm-eabi-gdb를 실행하여 디버그를 해야 한다. prebuilt/linux-x86/toolchain에 여러 버전의 arm-eabi가 들어 있는데, 이 중에서 가장 최신 버전을 이용하면 된다.

$ prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi-gdb out/target/product/generic/symbols/system/bin/app_process

gdb가 실행되면 심볼 정보를 gdb에 알려줘야 한다. gdb 창에서 다음을 입력하자

(gdb) set solib-absolute-prefix /absolute-source-path/out/target/product/product-name/symbols
(gdb) set solib-search-path /absolute-source-path/out/target/product/product-name/symbols/system/lib

매 번 이걸 입력하는게 귀찮으니 $HOME/.gdbinit이라는 파일을 만들고 위의 두 라인을 입력해 놓으면 알아서 실행 된다.

마지막으로 gdbserver에 연결하면 된다.

(gdb) target remote:[PORT]

이러면 gdb가 심볼 정보를 로딩하고 나서 __futex_wait()에 브레이크 포인트를 잡아서 gdb 입력창을 띄워 줄 것이다. 여기서 실제 디버그할 곳의 브레이크 포인트를 잡고 cont를 실행해 주면 되겠다.

__futex_wait () at bionic/libc/arch-arm/bionic/atomics_arm.S:159
159    ldmia   sp!, {r4, r7}
Current language:  auto; currently asm
(gdb) b filename/where/to/set/breakpoint:[LINENO]
Breakpoint 1 at 0xXXXXXXX: file filename/where/to/set/breakpoint, line [LINENO].
(gdb) cont
Continuing.