一、使用gdb调试android app
1、先关闭SELinux (在真机(target)操作)
- stevenrao@android-ndk-r16b$ adb shell
- shell@hammerhead:/ $ su
- root@hammerhead:/ # setenforce 0
- root@hammerhead:/ # gete
- getenforce getevent
- root@hammerhead:/ # getenforce
- Permissive
2、获取被调试的app 进程pid (在真机(target)操作)
- root@hammerhead:/ # ps | grep test
- u0_a55 8821 177 454040 51184 ffffffff 4011b73c S com.example.stevenrao.test
进程pid 为 8821 状态是 S,关于ps的状态码如下
- D uninterruptible sleep (usually IO)
- R running or runnable (on run queue)
- S interruptible sleep (waiting for an event to complete)
- T stopped by job control signal
- t stopped by debugger during the tracing
- W paging (not valid since the 2.6.xx kernel)
- X dead (should never be seen)
- Z defunct ("zombie") process, terminated but not reaped by its parent
- 130|root@hammerhead:/system/xbin # cat /proc/8821/status | grep TracerPid
- TracerPid: 0
3、用gdbserver attach (在真机(target)操作)
- 我刷的是google原生系统,包里面含有gdbserver,如果没有,可以在网上下载
- root@hammerhead:/ # gdbserver remote:1234 --attach 8821
查看gdbserver pid
root@hammerhead:/ # ps |grep gdbserver
- root 12167 5873 628 216 c0278e0c 000342f4 S gdbserver
- 127|root@hammerhead:/ # cat /proc/8821/status | grep TracerPid
TracerPid: 12167
- root@hammerhead:/ # ps | grep test
- u0_a55 8821 177 454040 51184 ffffffff 4011b73c t com.example.stevenrao.test
4、使用gdb 客户端连上gdb server 调试(在PC机(host)操作)
这一节直接可以跳过,用来完善调试流程,和本文主题无关
- #端口映射,本机所有发给1234端口的tcp包,都转发给手机设备的1234端口上
- stevenrao@~$ adb forward tcp:1234 tcp:1234
- #我本就有arm-eabi-gdb 程序,没有的去网上下载
- stevenrao@~$ /data/code/aosp-4.4.4_r1/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7/bin/arm-eabi-gdb
- GNU gdb (GDB) 7.3.1-gg2
- Copyright (C) 2011 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 "--host=x86_64-linux-gnu --target=arm-linux-android".
- For bug reporting instructions, please see:
- <http://source.android.com/source/report-bugs.html>.
- #设置指令架构
- (gdb) set architecture arm
- #设置调试程序
- (gdb) file /data/code/aosp-4.4.4_r1/out/target/product/hammerhead/symbols/system/bin/app_process
- #设置带符号信息的lib查找路径
- (gdb) set solib-search-path /data/code/aosp-4.4.4_r1/out/target/product/hammerhead/symbols/system/lib/:/data/code/aosp-4.4.4_r1/out/target/product/hammerhead/symbols/system/bin:/data/code/aosp-4.4.4_r1/out/target/product/hammerhead/symbols/system/lib/drm/:/data/code/aosp-4.4.4_r1/out/target/product/hammerhead/symbols/system/lib/egl/:/data/code/aosp-4.4.4_r1/out/target/product/hammerhead/symbols/system/lib/hw/:/data/code/aosp-4.4.4_r1/out/target/product/hammerhead/symbols/system/lib/ssl/engines/:/data/code/aosp-4.4.4_r1/out/target/product/hammerhead/symbols/system/lib/soundfx/:/data/code/aosp-4.4.4_r1/out/target/product/hammerhead/symbols/system/vendor/lib/:/data/code/aosp-4.4.4_r1/out/target/product/hammerhead/system/vendor/lib/:/data/code/aosp-4.4.4_r1/out/target/product/hammerhead/system/vendor/lib/egl/
- #连接端口
- (gdb) target remote :1234
- Remote debugging using :1234
- #对于 32 位 ARM,如果您的指令中没有符号,gdb 就不清楚自己正在反汇编哪个指令集(ARM 或 Thumb)。要指定缺少符号信息时选为默认指令集的指令集,请设置以下属性:
- (gdb) set arm fallback-mode arm # or thumb
- #查看栈
- (gdb) bt
- #0 epoll_wait () at bionic/libc/arch-arm/syscalls/epoll_wait.S:10
- #1 0x40182642 in android::Looper::pollInner (this=0x475926e8, timeoutMillis=<optimized out>) at system/core/libutils/Looper.cpp:223
- #2 0x4018286c in android::Looper::pollOnce (this=0x475926e8, timeoutMillis=-1, outFd=0x0, outEvents=0x0, outData=0x0)
- at system/core/libutils/Looper.cpp:191
- #3 0x4022b5ac in pollOnce (timeoutMillis=<optimized out>, this=<optimized out>) at system/core/include/utils/Looper.h:176
- #4 android::NativeMessageQueue::pollOnce (this=0x4758f6f8, env=0x4179cbe0, timeoutMillis=<optimized out>)
- at frameworks/base/core/jni/android_os_MessageQueue.cpp:97
- Backtrace stopped: previous frame identical to this frame (corrupt stack?)
- (gdb) f 0
- #0 epoll_wait () at bionic/libc/arch-arm/syscalls/epoll_wait.S:10
- 10 mov r7, ip
- #汇编调试
- (gdb) ni
- 11 cmn r0, #(MAX_ERRNO + 1)
- #查看寄存器
- (gdb) info register
- r0 0xfffffffc 4294967292
- r1 0xbeb26080 3199361152
- r2 0x10 16
- r3 0x7fffffff 2147483647
二、修改内核代码, 使TracerPid始终为0
1、修改内核源代码
关于内核如何编译,请参考我的另一篇http://blog.chinaunix.net/uid-27105712-id-5785215.html
要修改的文件涉及到两个
kernel/msm/fs/proc/base.c
- static int proc_pid_wchan(struct task_struct *task, char *buffer)
- {
- unsigned long wchan;
- char symname[KSYM_NAME_LEN];
- wchan = get_wchan(task);
- if (lookup_symbol_name(wchan, symname) < 0)
- if (!ptrace_may_access(task, PTRACE_MODE_READ))
- return 0;
- else
- return sprintf(buffer, "%lu", wchan);
- else
- return sprintf(buffer, "%s", symname);
- }
改成
- static int proc_pid_wchan(struct task_struct *task, char *buffer)
- {
- unsigned long wchan;
- char symname[KSYM_NAME_LEN];
- wchan = get_wchan(task);
- if (lookup_symbol_name(wchan, symname) < 0)
- if (!ptrace_may_access(task, PTRACE_MODE_READ))
- return 0;
- else
- return sprintf(buffer, "%lu", wchan);
- else
- {
- if (strstr(symname, "trace")) {
- return sprintf(buffer, "%s", "sys_epoll_wait");
- }
- return sprintf(buffer, "%s", symname);
- }
- }
kernel/msm/fs/proc/array.c 134 行
- static const char * const task_state_array[] = {
- "R (running)", /* 0 */
- "S (sleeping)", /* 1 */
- "D (disk sleep)", /* 2 */
- "T (stopped)", /* 4 */
- "t (tracing stop)", /* 8 */
- "Z (zombie)", /* 16 */
- "X (dead)", /* 32 */
- "x (dead)", /* 64 */
- "K (wakekill)", /* 128 */
- "W (waking)", /* 256 */
- };
改成
- static const char * const task_state_array[] = {
- "R (running)", /* 0 */
- "S (sleeping)", /* 1 */
- "D (disk sleep)", /* 2 */
- "T (stopped)", /* 4 */
- // "t (tracing stop)", /* 8 */
- "S (sleeping)", /* 8 */
- "Z (zombie)", /* 16 */
- "X (dead)", /* 32 */
- "x (dead)", /* 64 */
- "K (wakekill)", /* 128 */
- "W (waking)", /* 256 */
- };
kernel/msm/fs/proc/array.c 134 行
- seq_printf(m,
- "State:\t%s\n"
- "Tgid:\t%d\n"
- "Pid:\t%d\n"
- "PPid:\t%d\n"
- "TracerPid:\t%d\n"
- "Uid:\t%d\t%d\t%d\t%d\n"
- "Gid:\t%d\t%d\t%d\t%d\n",
- get_task_state(p),
- task_tgid_nr_ns(p, ns),
- pid_nr_ns(pid, ns),
- ppid, tpid,
- cred->uid, cred->euid, cred->suid, cred->fsuid,
- cred->gid, cred->egid, cred->sgid, cred->fsgid);
改成
- seq_printf(m,
- "State:\t%s\n"
- "Tgid:\t%d\n"
- "Pid:\t%d\n"
- "PPid:\t%d\n"
- "TracerPid:\t%d\n"
- "Uid:\t%d\t%d\t%d\t%d\n"
- "Gid:\t%d\t%d\t%d\t%d\n",
- get_task_state(p),
- task_tgid_nr_ns(p, ns),
- pid_nr_ns(pid, ns),
- ppid, /*tpid*/0,
- cred->uid, cred->euid, cred->suid, cred->fsuid,
- cred->gid, cred->egid, cred->sgid, cred->fsgid);
2、重新编译内核,并刷入内核到真机上
参考我的另外一个文章http://blog.chinaunix.net/uid-27105712-id-5785215.html
3、测试
参考前面 一.3 节
- root@hammerhead:/ # cat /proc/1952/status | grep TracerPid
- TracerPid: 0
- root@hammerhead:/ # ps | grep test
- u0_a55 1952 179 451984 50920 ffffffff 4010373c S com.example.stevenrao.test