gdb获取进程的全局变量

2019-07-13 08:02发布

0、前言         在程序运行过程中,我们经常需要查看一些变量的情况以此来判断当前程序的运行情况,对于嵌入式Linux设备而言,最常见的就是填加相应的打印信息至控制台或是写入到日志文件中,这两种方式在本质上可以认为是类似的,只不过前者是将控制台作为输出,而后者是以日志文件作为输出。         因为增加打印查看变量,需要重新对程序进行编译处理,有时候这样的操作会比较繁琐和耗时,而我们可能又需要查看未加入打印信息处理的某些变量,这时候我们可以采用gdb处理来进行。
1、gdb         GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。此处不作具体介绍,大家可以参考《软件调试的艺术》一书以及《Debug Hacks 中文版 ---深入调试的技术和工具》一书,这两本书对GDB工具的使用有比较详细的介绍,个人认为这两本书算比较经典的。
2、shell中去执行子命令
        Shell中通常将EOF与 << 结合使用,表示后续的输入作为子命令或子Shell的输入,直到遇到EOF为止,再返回到主调Shell。可以把EOF替换成其他东西,意思是把内容当作标准输入传给程序。         当shell看到<<的时候,它就会知道下一个词是一个分界符。在该分界符以后的内容都被当作输入,直到shell又看到该分界符(位于单独的一行)。这个分界符可以是你所定义的任何字符串。
3、脚本实现         在进行脚本编写时,我们需要知道我们所需要查看获取的程序中全局变量的名称,注意,此处必须是全局变量,因全局变量存放在静态存储区,位置是固定的,而局部变量在栈空间,栈地址是不固定的,并且可能随时释放。只有固定地址的变量我们才能通过gdb的方式去查看其值。        编写 of_state.sh脚本,内容如下
#!/bin/bash

PNAME=of
PARAMETER=v_ofp_shared->connect_of_ok

PID=`ps -ef | grep ${PNAME} | grep -v "grep" | awk '{print $2}'`

gdb -p ${PID} < log.txt
p v_ofp_shared->connect_of_ok
quit
SHIT

state=$(cat log.txt | grep -r "(gdb) $1" | awk '{print $4}')
echo ""
echo "========== The State =========="

if [ ${state} -eq 1 ]; then
    echo OpenFlow OK!
else
    echo OpenFlow FAIL!
fi

具体的分析:
    首先,我们依据进程名来获取到进程的PID; PID=`ps -ef | grep ${PNAME} | grep -v "grep" | awk '{print $2}'`
    其次 ,执行 “gdb -p 进程PID ”,以进入gdb模式;   gdb -p ${PID}     接着,在gdb模式下,我们采用 " p 变量名" 的方式,来查看到变量的值 p v_ofp_shared->connect_of_ok
    注意此处我们是在shell脚本下进入到gdb模式,gdb模式下的命令处理就需要用到上述第2步中所提及的shell中去执行子命令的处理 gdb -p ${PID} < log.txt
..........
SHIT
    此处分界符我们使用的是“SHIT”,使用"EOF"或其他的字符串作为分界符是一样的。为了获取到所需变量的值,我们需要将gdb的调试信息先存起来,就是上述中的 >log.txt 来讲gdb的所有调试信息重定向到log.txt文件中     最后,我们从log.txt文件,去提取出我们所需要的变量的值信息     log.txt文件的内容类似于上图所示,我们需要从中提取出“$1 = ”后的值     cat log.txt | grep -r "(gdb) $1" | awk '{print $4}'
获取到所需全局变量的值后,我们可以进行相应的echo打印以及或许的判定处理