- 看异常类型(错误原因提示)
在内核中访问地址必须是c开头以上的,其他的肯定是非法的 //内核访问地址范围从0xc0000000开始 - 调用栈backtrace(对照反汇编代码)反汇编查找相应的出错点
- 寄存器 PC和LR 根据位置和反汇编代码找到相应的出错位置,进行修改即可
- EIP is at list_del+0xa/0x61 list_del函数有0x61这么大,而Oops发生在0xa处
- 添加调试信息
fprintf(stdout, "[WARNNING] {%s %s(Line %d)}: \r\n", __FILE__,__FUNCTION__,__LINE__);
- gdb常用命令
set print pretty on #友好地显示结构体
up/down #函数帧移动
set print element 0 #显示完整字符串
cd #改变当前工作目录
run #执行该程序
backtrace #显示程序中的当前位置和表示如何到达当前位置的栈跟踪
breakpoint #设置断点
watch #在程序中设置一个监测点或数据断点
commands #命中断点时列出将要执行的命令
continue #从断点开始继续执行
delete #删除一个断点或监测点
clear #删除刚才停止处的断点
print #显示变量或表达式的值
display/undisplay #程序停止时显示变量和表达式
type #显示一个数据结构的内容
whatis #显示变量或函数类型
info #显示与该程序有关的各种信息
jump #在源程序中的另一点开始运行
kill #异常终止在gdb 控制下运行的程序
list #列出相应于正在执行的程序的源文件内容
next #执行下一条指令但不进入函数
step #执行下一个源程序行必要时进入下一个函数
pwd #显示当前工作目录
reverse-search/search #在源文件中搜索正规表达式
set variable #设置变量
signal #将一个信号发送到正在运行的进程
until #结束当前循环
finish #结束当前函数
quit #退出gdb
查看当前程序栈的内容:
x/10x $sp –> 打印stack的前10个元素
查看当前程序栈的信息:
info frame –> list general info about the frame
查看当前程序栈的参数:
info args –> lists arguments to the function
查看当前程序栈的局部变量:
info locals –> list variables stored in the frame
查看当前寄存器的值:
info registers(不包括浮点寄存器) info all-registers(包括浮点寄存器)
查看当前栈帧中的异常处理器:
info catch(exception handlers)
宏调试
在全局的Makefile中添加新的编译参数-g3,就可以支持整个工程代码中所有的宏的调试 macro exp MACRO3(3)。
当然这个方法也有一个缺点,就是g3的调试信息会比默认的g2的调试信息要大
反汇编篇
1、set disassembly-flavor intel:设置反汇编的代码为intel格式
2、disassemble 函数名/起始地址[,结束地址]:将内存中的机器码程序以指令助记符的形式显示出来
3、info line 函数名/*内存地址:查看某个line的相关信息,即在源文件中的行号及在内存中的起始地址和结束地址
4、ni 单步步过,si 单步步入
5、 display 显示某寄存器的值
为什么用EAX寄存器保存函数返回值?
这是由操作系统的ABI(Application Binary Interface)来决定的