Linux基础(03)gdb调试
1. 安装GDB增强工具 (gef) * GDB的版本大于7.7 * wget -q -O- https://github.com/hugsy/gef/raw/master/scripts/gef.sh | sh * 确保网络连通 并且成功更新ubuntu (更新source.list 使用apt-get update) 2. GDB安装插件(在root权限安装,用户权限使用不了需要在用户权限下安装) git clone https://github.com/gatieme/GdbPlugins.git ~/GdbPlugins (安装gdb的Python脚本插件) 切换gdb模式 : echo "source ~/GdbPlugins/peda/peda.py" > ~/.gdbinit (默认打开gdb插件是pada) 倾向于破解和逆向 echo "source ~/GdbPlugins/gef/gef.py" > ~/.gdbinit 倾向于debug?逆向 echo "source ~/GdbPlugins/gdbinit/gdbinit" > ~/.gdbinit 个人定制 3.Linux程序发布流程 * 确定程序是否存在符号表 readelf -s test-1 * 生成符号表 objcopy --only-keep-debug test-1 test-1.symbol * 生成发布程序 objcopy --strip-debug test-1 test-release * 使用符号表进行程序debug gdb -q --symbol=test-1.symbol --exec=test-release 4.gdb语法的使用 set listsize num 设置 l 的显示行数 list/l (code/num) 查看某个函数代码或者查看某行代码. 查看其它文件的代码 l xxx.c:(code/num) break/b num 打断点 条件断点 b num if var== 也可以断到某个函数上b func continue/c 跳到下一个断点 disable num 使断点失效 enable num 使断点重新有效 run/r 运行程序 调试已运行的程序 info breakpoints 查看断点 delete/d num 删除断点列表的某个断点 print/p code 调试时打印某个变量的值 也可以选择打印的方式 如: p/d code 打印十进制的结果 p/s 打印字符串的结果 p var=100 修改内存 step/s 执行下一句代码有函数进入函数 next/n 执行下一句代码有函数也跳过 until/u 跳出当前循环 finish 退出当前函数 info locals 查看当前函数中的全部局部变量 bt 查看函数调用栈 如: 进入某个函数时bt一下可以知道哪个函数调用了当前进入的函数 或者 可以查看处在哪个函数中 info frame 打印当前栈里所以的信息 x &code 查看某个变量的内存地址 #观察点 watch var/add 观察内存是否被改变如果改变则自动断点 gdb就近原则 如果有变量重名 想查看任意函数内 的变量 watch func::var info watchpoints 查看观察点列表 rwatch var/add 观察内存是否被读取如果被读取则断点 #设置捕捉点 catch event/throw throw 抛出一个C++的异常 catch throw catch 捕捉一个C++的异常 catch catch exec 调用系统调用exev时停止 catch exec exec 在一个进程中启动另外一个程序 fork 调用系统调用fork时停止 catch fork load/load libname 载入动态链接库时 catch load / catch load libname unload #搜索源代码 search var/func 内存搜索 只有调用了函数或存在于内存才能搜索到 reverse-search var/func 全文搜索 不占用内存也能搜索只要在代码段 #查看内存 x/nfu n是一个正整数表示内存的长度配合u n代表数量u代表单位(字节) f代表显示格式和print占位符相同 x 十六进制格式显示 d 十进制格式显示 u 十六进制格式显示无符号整型 o 八进制格式显示 t 二进制格式显示 a 十六进制格式显示 c 按字符格式显示 f 按浮点数格式显示 u可以用下面的字符来代替: b 表示单字节 h 表示双字节 w 表示四字 节 g 表示八字节 十六进制两位数一个字节 如:x/3uh 0x80494a4 往后的三个无符号的十六进制只显示两个字节的地址 x/3uh 0x80494a4 1 0 16 x/3xh 0x80494a4 0x0001 0x0000 0x0010 查看数组地址 p*[email?protected] #插入命令 在触发某些断点是执行插入的命令并不是真的在源代码上插入 conmades bnum ... ... end 一般都是没有gef等脚本时使用的 ? ################################################################################ 5.gdb多进程多线程调试 1 int main() 2 3 { 4 pid_t pid = fork();//创建子进程 5 if(pid == -1) 6 { 7 perror("fork error"); 8 return -1; 9 } 10 else if(pid == 0)//child 11 { 12 printf("i am a child:my pid is %d,my father is%dn",getpid(),getppid()); 13 } 14 else//father 15 { 16 printf("i am a father:my pid is %dn",getpid()); 17 wait(NULL);//等待子进程 18 } 19 return 0; 20 } ##################进程间是完全独立互不影响的但可以通信 fork创建一个完全和父进程一样的子进程,两个进程并行执行,执行先后随机看CPU的调度 父进程的fork返回值是子进程的pid号 子进程的fork返回值是0 wait阻塞函数 等待子进程退出后 父进程才退出 ##确定gdb中的进程跟踪模式 show/set follow-fork-mode parent/child 跟踪的父子进程间的切换 detach-on-fork show detach-on-fork和跟踪的进程有关,只负责on和off,跟踪父进程则负责父进程的on/off,跟踪子进程则负责子进程的on/off parent on 只调试父进程,子进程正常运行 child on 只调试子进程,父进程正常运行 parent off 同时调试两个进程,子进程暂停在fork位置 child off 同时调试两个进程,父进程暂停在fork位置 shell ps -ef | grep num/programName 查看指定pid或程序名的进程 shell ps -A查看所有进程 ##进程间的切换 在detach off 的时候使用切换调试的进程 info inferiors 查看调试的进程 inferiors num 切换调试的进程 #进程的管理 add-inferior [-copies n] 复制一个进程 -copies + 进程列表num [-exec executable] 新开一个进程 + 程序的路径 detach kill remove-inferior 删除进程 ###########多线程 show/set scheduler-locking off不锁定任何线程 on锁定其他线程只有当前线程执行 step只有被调试线程运行 gdb版本过低不一定能锁定 info thread 查看所有线程 threads num 切换到指定线程
1 int main() 2 { 3 pthread_t tid1,tid2; 4 pthread_create(&tid1,NULL,thread1,NULL);//创建线程1 5 pthread_create(&tid2,thread2,NULL);//创建线程2 6 pthread_join(tid1,NULL);//等待线程1 7 pthread_join(tid2,NULL);//等待线程2 8 return 0; 9 } 切换到指定线程后调试,断点打在线程函数上不妨碍主线程main的执行所以会有三个线程 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |