Android Native Framework gdb Tool

脚本使用方法

  • gdb_native.sh 228 adb1
  • gdb_native.sh 228
    • 其中228代表要调试进程的pid,必须指定;
    • adb1 指定你想使用的adb工具,也可以不指定adb。
#!/bin/bash
  PROJECT_ROOT=$(dirname $_)
  #set -x
  BIN_BIT=64   # BIN_BIT=64 when bin is 64bit version
  GDB=$PROJECT_ROOT/prebuilts/gdb/linux-x86/bin/gdb
  # GDB=$PROJECT_ROOT/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi-gdb
  # maybe gdbserver64, if process is 64bit version
  GDB_SERVER=gdbserver$BIN_BIT
  OUT=$PROJECT_ROOT/out/target/product/flounder

  usage () {
    echo -e "\033[;35m Usage : $0 228\033[0m"
    echo -e "\033[;35m Usage : $0 228 adb1 \033[0m"
  }
  if [ -n "$2" ] ;then
    aadb=$2
  else
    aadb=/usr/bin/adb
  fi
  if [ -n "$1" ] ;then
    process_pid=$1
  else
    process_pid=0
  fi
  ADB=$aadb
  GDB_PORT=5028

  # 0: setenforce 0
  $ADB root
  $ADB remount
  $ADB shell setenforce 0
  sleep 1

  if [[ $process_pid = 0 ]]; then
      echo -e "\033[;31merror: Process id must designated!!!\033[0m"
      usage
      exit 0
  else
      process_name=$($ADB shell ps $process_pid | grep $process_pid | awk -F '\/' '{print $4}')
  fi
  TARGET_NAME=$process_name  # process name
  TARGET_PID=$process_pid  # process id
  GDB_PARAMETER=/tmp/gdbinit.`whoami`
  echo -e "\033[;33m check target name($TARGET_NAME) pid($TARGET_PID) \033[0m"
  # kill old gdbserver
  oldgdbserver=`$ADB shell ps | grep "gdbserver" | awk '{ print $2 }'`
  if [[ 0$oldgdbserver != 0 ]]; then
      $ADB shell kill -9 $oldgdbserver
  fi

  # 1: bringup gdbserver and attach to host process for wait clent to connet me
  echo "1: $ADB shell $GDB_SERVER :$GDB_PORT --attach $TARGET_PID"
  $ADB shell $GDB_SERVER :$GDB_PORT --attach $TARGET_PID &

  # 2: 设置端口转发
  # 表示通过adb映射tcp端口1234,命令中前面的是local的端口,后面的是remote的端口。
  echo "2: $ADB forward tcp:$GDB_PORT tcp:$GDB_PORT"
  $ADB forward tcp:$GDB_PORT tcp:$GDB_PORT
  sleep 3

  # 3: 启动gdb,并传入参数
  # echo "target remote:$GDB_PORT" > $GDB_PARAMETER
  # echo "file $OUT/system/bin/$TARGET_NAME" >> $GDB_PARAMETER
  # echo "set sysroot $OUT/symbols/" >> $GDB_PARAMETER
  # echo "set dir $PROJECT_ROOT" >> $GDB_PARAMETER

  echo "set solib-absolute-prefix $OUT/symbols/system/lib$BIN_BIT" > $GDB_PARAMETER
  echo "set sysroot $OUT/symbols/" >> $GDB_PARAMETER
  echo "set solib-search-path $OUT/symbols/system/lib$BIN_BIT/" >> $GDB_PARAMETER
  echo "target extended-remote :$GDB_PORT" >> $GDB_PARAMETER
  echo "3: $GDB -x $GDB_PARAMETER $OUT/symbols/system/bin/$TARGET_NAME"
  $GDB -x $GDB_PARAMETER $OUT/symbols/system/bin/$TARGET_NAME

扩展功能

到这里对于刚接触gdb调试同学也有了入门的知识,对于gdb老手估计是要玩飞的节奏

但是这里要说一下,如果要调试的是framework相关的进程的native代码,可能会受到system server的watchdog的影响,1分钟没有及时响应操作就会触发watchdog而kill到system server进程,zygote也会跟着挂掉,这里有个小技巧可以用一下,就是在调试的过程中,如果需要耗时查看一些运行时状态,可以先执行
adb shell am hang
防止超时重启,查看完毕想要继续执行,就Ctrl+c终止掉am hang即可继续执行,后面就重复这个过程即可。
另外还有一种方式就是用Android Studio在线调试,把断点加在watchdog里面,配置gdb native调试。

gdb命令说明

  • 显示gdb命令帮助信息
help            显示gdb命令种类
help subcommand      显示subcommand的帮助信息
apropos word       搜索与word相关的命令
  • 显示调试界面
ctrl + X + A
  • 设置断点
b(break)     在函数或某一行处设置断点 
如果只记得部分函的前缀,可以这样:(gdb) b make_ <按TAB键>。 
break filename:linenum       在源文件filename的linenum行处停住 
break filename:function       在源文件filename的function函数的入口处停住 
break *address                       在程序运行的内存地址处停住 
break       break命令没有参数时,指在下一条指令处停住 
break  …  If …           在条件成立时程序停住 
break thread threadnum       定义在线程threadnum上的断点,如break BootAnimation.cpp:364 thread 28 if bartab > lim
  • 设置观察点
watch expr       设置观察点,当表达式expr的值变化时,程序停住
rwatch expr       设置观察点,当表达式expr的值被读时,程序停住
awatch expr       设置观察点,当表达式expr的值被读或写时,程序停住
  • 设置捕捉点
catch       设置被调试程序捕捉点,当event发生时,程序停住 
catch catch [args]       捕捉一个C++捕捉到的异常 
catch throw [args]       捕捉一个C++抛出的异常 
catch syscall [args]       捕捉系统调用
  • 维护被调试程序断点

condition N COND       修改断点号为N的停止条件为COND

ignore N COUNT       忽略断点号为N的停止条件COUNT次

clear [linenum|funname|*]       清除指定的行或函数断点

d(delete) [breakpoints][range]          清除指定的断点

disable [breakpoints] [range…]        禁用指定的断点

enable [breakpoints] [range…]         启用指定的断点

  • 为停止点设定运行命令

commands N       调试程序在断点号为N的断点处停止后,执行命令 

执行命令 

end

  • 显示被调试程序的信息
info subcommand       显示被调试程序的某些信息,可用help info查看子命令。如: 

info breakpoints    [n]       显示所有断点(或断点n)信息 

info watchpoints [n]       显示所有观察点(或观察点n)信息 

info program       查看被调试程序的执行状态 

info args          打印出当前函数的参数名及其值 

info locals       打印出当前函数中所有局部变量及其值 

info display       查看display设置的自动显示的信息 

info frame       查看栈帧信息,包括程序语言

  • 运行及查看被调试信息

r(run)       运行被调试程序

c(continue)       从断点出开始继续执行直到结束或下一个断点

s(step)       单步跟踪,如果有函数调用,他会进入该函数。进入函数的前提是此函数被编译有debug信息

n(next)       单步跟踪,如果有函数调用,他不会进入该函数

p(print)       打印表达式的值 

可以查看全局变量(所有文件可见)、静态全局变量(当前文件可见)、局部变量(当前Scope可见) 

p file::var       查看文件file中的变量var 

p func::var       查看函数file中的变量var 

p start@len       查看一段连续的内存空间的值,“@”的左边是第一个内存的地址的值,“@”的右边则你你想查看内存的长度,如: 

int array = (int ) malloc (len * sizeof (int)); 

p *array@len 

p/format expr       按指定的格式显示表达式expr(format:x, d, f, c, u, o, t, a)

display[/fmt] expr       程序停下来后就会显示expr的值

undisplay/delete displaynum/disable displaynum/enable displaynum

bt          查看当前函数调用堆栈信息

f(frame)       查看当前栈层信息,包括栈的层编号、当前的函数名、函数参数值、函数所在文件及行号和函数执行到的语句

finish       运行程序,直到当前函数完成返回

u(until)       运行程序直到退出循环体

  • 显示源代码

l(list)       列出具体的函数或代码行 

list       显示当前行后面的源程序 

list -         显示当前行前面的源程序 

list +       显示当前行后面的源程序 

list linenum       显示程序第linenum行的周围的源程序 

list file:filenum       显示文件file中的filenum行 

list file:func       显示文件file中的函数func 

list funcname       显示函数名为function的函数的源程序,如list android::BootAnimation::movie

  • 搜索源代码

forward-search reg       利用正则表达式前向搜索源码

search reg       利用正则表达式前向搜索源码

reverse-search reg       利用正则表达式在全部源码中进行搜索

  • 设置被调试程序参数/gdb配置

set subcommand       设置gdb环境变量,可以使用help set查看set子命令。如: 

set args       设置被调试程序运行参数 

set directories       设置源文件搜索路径,多个使用“:”分割 

set solib-search-path       设置符号表搜索路径 

set environment varname [=value]       设置环境变量。如:set env USER=llj 

set listsize num       设置一次显示源代码的行数 

set step-mode on       打开step-mode模式,于是,在进行单步跟踪时,程序不会因为没有debug信息而不停住。这个参数有很利于查看机器码 

set print address on       打开地址输出, 当程序显示函数信息时,GDB会显出函数的参数地址 

set print array on       打开数组显示,打开后当数组显示时,每个元素占一行,如果不打开的话,每个元素则以逗号分隔 

set print elements num       设置显示数组元素的最大个数 

set print null-stop on/off       如果打开了这个选项,那么当显示字符串时,遇到结束符则停止显示 

set print pretty on/off       打开后gdb显示结构体时会比较漂亮 

set print sevenbit-strings       设置字符显示,是否按“/nnn”的格式显示 

set print union on/off       设置显示结构体时,是否显式其内的联合体数据

show subcommand       显示调试器的信息,使用help show查看子命令。如: 

show environment [varname]       查看环境变量 

show listsize       显示当前listsize的设置 

show directories       显示定义了的源文件搜索路径 

show language       查看gdb当前的语言环境

  • 其他

q(quit)       退出gdb

handle          处理信号

  • shell命令

此外gdb中可以执行shell命令,使用SHELL环境变量定义的可执行程序来执行shell命令,常用的命令如下:

show environment SHELL       查看shell执行程序

make       重新编译程序,相当于shell make

cd       必变工作目录,相当于shell cd

pwd       查看当前工具目录,相当于shell pwd

  • 调整程序线路

     一旦使用GDB挂上被调试程序,当程序运行起来后,你可以根据自己的调试思路来动态地在GDB中更改当前被调试程序的运行线路或是其变量的值,这个强大的功能能够让你更好的调试你的程序,比如,你可以在程序的一次运行中走遍程序的所有分支。
    
  • 修改变量的值


print x = 4       C/C++语法,把变量x的值修改为4 

set var width=10       用gdb命令将参数width值修改为10

  • 跳转执行

jump +num       当前运行点向下偏移num行开始执行 

jump linenum       从当前调试文件的linenum行开始执行 

jump file:linenum       从file的linenum行开始执行

-产生信号量


singal SIGNAL       发送信号SINGAL给被调试程序

-强制函数返回


return       强制函数返回,忽略未执行的语句 

return result       强制函数返回结果result,忽略未执行的语句

-强制调用函数


call func       调用当前程序中的函数 

print func       调用当前程序中的函数

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,398评论 25 707
  • 时光流转,愿你安好。
    庄德坤阅读 160评论 0 0
  • 模块与包 控制模块被全部导入的内容 在模块中以下划线命名的变量或函数是不会被导入的 在模块中使用all来控制导入的...
    buildbody_coder阅读 372评论 0 0
  • 每日必读:轻熟原则 早起仪式=反思回顾+想做事情列表 晚间仪式=陪家人闲话+反思+坐享 日省——每日复盘,a Ti...
    wenzi2507阅读 162评论 0 0