Chinaunix首页 | 论坛 | 博客
  • 博客访问: 145955
  • 博文数量: 40
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 410
  • 用 户 组: 普通用户
  • 注册时间: 2014-02-11 09:11
文章分类

全部博文(40)

文章存档

2020年(1)

2017年(36)

2014年(3)

我的朋友

分类: LINUX

2017-03-17 18:35:07

虚拟机环境:vmware

第一步 配置串口互联,左侧为调试端,右侧为被调试端


检验是否配置成功,首先在被调试机上运行如下命令
# cat /dev/ttyS0
然后在调试机上运行如下命令
# echo 123 &> /dev/ttyS0
被调试机上可以看到


第二步 准备要调试的内核
配置内核选项
[cpp@dark linux-2.6.34]$ make menucofnig
# Kernel hacking  --->
#       [*] Compile the kernel with debug info
#       [*] KGDB: kernel debugging with remote gdb  --->
本人使用rpmbuild构建的内核rpm包,内核配置文件的在/root/rpmbuild/SOURCES/*.config目录下,直接编辑这些文件修改即可,内核源码中的.config文件在build的时候会被覆盖
内核一般在调试端编译,因为最好在进行编译的内核源码目录下使用GBD加载vmlinux
执行如下命令编译内核并声称rpm包
rpmbuild -bb SPECS/kernel.spec

调试内核请使用带debug的rpm包

第三步 在被调试机上安装内核并修改启动项

在目标Linux内核启动选项append命令 ro kgdboc=ttyS0,115200 kgdbwait,如此目标机器启动到一定时机停止,出现kgdb: Waiting for connection from remote gdb…的字句,这样对于目标机器的配置已经完成,再来看主机配置,启动gdb配置串口:

第四步 加载vmlinux,设置波特率,target到被调试端
# 加载 vmlinux
gdb vmlinuxd
# 设置远程端口 波特率
(gdb) set remotebaud 115200
# 连接远程串口
(gdb) target remote /dev/ttyS0


常用调试技巧

>> 加载module符号
首先在被调试机上查看模块的加载地址
# cat /proc/modules | grep vsec
然后再调试机上加载对应的模块符号
(gdb) add-symbol-file ./vsecdce_module.ko 0xffffffffa00b1000

>> 通过ESP找task_struct
# 读取栈顶寄存器的值
rsp 0xffff88007a3e1a98    0xffff88007a3e1a98
# 获取thread_info地址
(gdb) x 0xffff88007a3e1a98 & 0xFFFFFFFFFFFFC000
   0xffff88007a3e0000:    rex push rdx
# 获取task_struct结构地址
(gdb) p *(struct thread_info*)0xffff88007a3e0000
$2 = {task = 0xffff88007a525240, exec_domain = 0xffffffff8189f200, flags = 128, status = 1, cpu = 0, preempt_count = 1, addr_limit = {seg = 18446744073709551615}, restart_block = {
    fn = 0xffffffff8108bc00 , {{arg0 = 0, arg1 = 0, arg2 = 0, arg3 = 0}, futex = {uaddr = 0x0, val = 0, flags = 0, bitset = 0, time = 0, uaddr2 = 0x0}, nanosleep = {
        index = 0, rmtp = 0x0, compat_rmtp = 0x0, expires = 0}, poll = {ufds = 0x0, nfds = 0, has_timeout = 0, tv_sec = 0, tv_nsec = 0}}}, sysenter_return = 0x0, uaccess_err = 0}
# 打印task_struct结构
(gdb) p *(struct task_struct*)0xffff88007a525240
# 设置条件断点
b sys_kill if 666 == $rdi

>> LINUX64函数传参
func3 (a1=1, a2=2, a3=3, a4=4, a5=5, a6=6, a7=7, a8=8, a9=9, a10=10, a11=11, a12=12)
前6个参数:rdi rsi rdx rcx r8 r9
后面的参数:rbp[oldrbp funcaddr a7 a8 a9 a10 a11 a12]
那么在函数执行过程中,这些参数以及局部变量存放在哪里呢?
a7-ax那些放在rbp后面原本就通过栈传递的参数,位置不动
a1-a6那些通过寄存器传递的参数,由于函数执行过程中要各种使用这些寄存器,所以要把寄存器中的参数拷贝到栈


阅读(2184) | 评论(0) | 转发(0) |
0

上一篇:QT国际化

下一篇:WINDOWS PE文件格式

给主人留下些什么吧!~~