x86 kgdb deug调试分析

news2024/11/15 18:28:20

本文主要是收集,以下文章写得很好,我二次整理一下。

如果要手动livedb.

1.  call kdbg_arch_late()

2. kgd_set_hw_break(addr,8,1);

3. kgdb_correct_hw_break();// enable bp to cpu regs

-------------------------------分割线---------------------------------------

为KGDB 增加watchpoint断点支持 on x86

为KGDB 增加watchpoint断点支持 on x86 – linux kgdb gdb debug

前言

前面我们在《gdb 和 watchpoint》 文章
里讨论了在gdb的watchpoint,这次我们来讨论下如何让kgdb也支持watchpoint特性。

KGDB 相当于一个gdb server,只是这个server是跑在内核里面。所以KGDB支持watchpoint实现和
gdb server的实现如出一辙,即通过GDB远程串行协议里的Stop-Reply-Packets来传达
watchpoint信息给gdb,让gdb知道那个watchpoint击中了。

其运行的大致流程为:

1
2
3
4
5
6
7
8
9
10
11
A:using gdb to set a watchpoint 
 
B:send out a set watchpoint protocol packet to kgdb from gdb
 
C:kgdb receive/parse the protocol packet
 
D:kgdb set a watchpoint hardware breakpoint on kernel
 
E:Once kernel hit a watchpoint breakpoint, kgdb will collect the 
    watchpoint breakpoint info, fill them to a Stop-Reply-Packets with 
    watchpoint format, and send out to gdb

1: 设置watchpoint 断点 in kgdb

在gdb敲入watch命令后,会将发送一个设置watchpoint的数据包给kgdb,kgdb收该数据包后就执行设置断点动作.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 (gdb) watch xxx  (假设我们要监视断点地址为 xxx)
 
 gdb发送数据包"Z2,xxx,4" 给kgdb
 
 kgdb 收到协议数据包后,调用gdb_cmd_break()(kernel/debug/gdbstub.c)
 来解析设置断点协议数据
 
gdb_cmd_break()
------------------------------------------
parsing  "Z2,xxx,4"
--> 'Z'      设置断点
--> '2'      断点类型为write watchpoint
--> 'xxx'  断点地址为 xxx
--> '4'      断点长度为 4
------------------------------------------
 
--> arch_kgdb_ops.set_hw_breakpoint(xxx, 4, BP_WRITE_WATCHPOINT)
--> kgdb_set_hw_break(xxx, 4, BP_WRITE_WATCHPOINT) (arch/x86/kernel/kgdb.c)
    这个函数完成了将断点信息加入到breakinfo[HBP_NUM]数组里和设置其enabled标志为1,
    真正的断点使能是在kgdb退出,让系统正常运行时,调用kgdb_correct_hw_break()函数
    来每个cpu上使能硬件断点.

2: watchpoint触发捕获

watchpoint 断点隶属于硬件断点,所以我们先来谈谈硬件断点的触发的整个流程和细节。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
硬件断点的触发后,会产生一个调试异常,因此会进入do_debug异常的
处理程序(arch/x86/kernel/traps.c).
 
do_debug() {
 
unsigned long dr6;
get_debugreg(dr6, 6); //保持dr6寄存器值到dr6变量
 
 /* DR6 may or may not be cleared by the CPU */
set_debugreg(0, 6); //手动清除dr6寄存器
 
//通过notify_die通知链告诉大家"debug"异常发生了,同时把dr6寄存器值作为参数传递出去。
notify_die(DIE_DEBUG, "debug", regs, PTR_ERR(&dr6), error_code,
                            SIGTRAP)
}

如果kgdb处于早期调试模式(那时候Hardware Breakpoint Layer还没初始化),则是由kgdb自己处理
DIE_DEBUG的notify通知,如果是普通模式,即硬件断点管理都是从Hardware Breakpoint Layer获取的,
则是由Hardware Breakpoint Layer处理,然后通过回调函数kgdb_hw_overflow_handler()进入kgdb.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Hardware Breakpoint Layer处理流程:
 
static struct notifier_block hw_breakpoint_exceptions_nb = {
    .notifier_call = hw_breakpoint_exceptions_notify,
    /* we need to be notified first */
    .priority = 0x7fffffff
};
register_die_notifier(&hw_breakpoint_exceptions_nb);
 
触发硬件断点:
do_debug() -- notify_die(DIE_DEBUG)->
arch/x86/kernel/hw_breakpoint.c
hw_breakpoint_exceptions_notify() -> 
hw_breakpoint_handler() {
for (i = 0; i < HBP_NUM; ++i) {
        if (likely(!(dr6 & (DR_TRAP0 << i))))
            continue;
        perf_bp_event(bp, args->regs); -->
           perf_swevent_overflow(event)->
             event->overflow_handler(event, nmi, data, regs);-->
                kgdb_hw_overflow_handler(). 这里最终跑到kgdb的代码里了.
}/* end of for()*/
}

3: watchpoint 断点信息获取

kgdb只需要知道是哪个watchpoint断点被踩中了,并把它的地址传递给gdb就可以了。

如果kgdb处于早期调试模式,则可以挨个判断dr6寄存器值的bit位来看哪个watchpoint击中了。
但是普通模式的Hardware Breakpoint Layer回调函数并没有传递dr6值给我们,不过还好,它传
递struct perf_event的event对象给我们,通过这个对象,我们可以得到发生硬断点的地址,然后
根据地址和kgdb里保存的硬断点数组对比,相同的,则是踩中的断点..

1
2
3
4
5
6
7
8
9
static void kgdb_hw_overflow_handler(struct perf_event *event, int nmi,
        struct perf_sample_data *data, struct pt_regs *regs) {
 for (i = 0; i < HBP_NUM; i++) {
        if (!breakinfo[i].enabled)
            continue;
        if (breakinfo[i].addr == event->attr.bp_addr) //查找和判断踩中断点信息
            break;
    }
}

在得到是哪个breakinfo[i]被触发后,在查看下breakinfo[i].type,如果是
X86_BREAKPOINT_WRITE/X86_BREAKPOINT_RW 就可以认定是watchpoint断点了,
而断点地址则保存在breakinfo[i].addr.

4: 填充Stop-Reply-Packets来通知gdb踩中watchpoint断点了
根据watchpoint断点的类型,返回给gdb的Stop-Reply-Packets可以有如下格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
type = breakinfo[i].type;
addr = breakinfo[i].addr;
            switch (type) {
            case KST_READ_WATCHPOINT:
                ptr += strlen(strcpy(ptr, "rwatch:"));
                break;
            case KST_ACCESS_WATCHPOINT:
                ptr += strlen(strcpy(ptr, "awatch:"));
                break;
            case KST_WRITE_WATCHPOINT:
                ptr += strlen(strcpy(ptr, "watch:"));
                break;
            }
            ptr += kgdb_long2hex(addr, ptr);
            *ptr++ = ';';

具体packgets包格式,可以阅读 Stop-Reply-Packets

5: test watchpoint support on x86

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
After gdb connect successly to kgdb, setting a watchpoint
at softlockup_thresh address.
 
(gdb) watch softlockup_thresh
 
Then change the watchdog_thresh value to 24 on target:
# echo "24" > /proc/sys/kernel/watchdog_thresh
 
Then the gdb will stop and show:
----------------------------------------------------------
Old value = 60
New value = 24
0xffffffff810481f2 in do_proc_dointvec_minmax_conv (negp=0xffff88066cbb9e17,
lvalp=0xffffffff8190e718, 
    valp=0xffffffff8190e718, write=<value optimized out>,
data=0xffff88066cbb9e68) at kernel/sysctl.c:2408
2408			*valp = val;
(gdb)
----------------------------------------------------------
 
Change the watchdog_thresh value to 24 on target again:
# echo "24" > /proc/sys/kernel/watchdog_thresh
 
As the previous watchdog_thresh value is 24, thus gdb will not stop..

6: 扩展阅读

更多有关kgdb和Hardware Breakpoint Layer的内容,可阅读:《抓虫日记之 kgdb 和 删除硬断点 》
更多有关x86硬件调试寄存器信息,可阅读:《x86 调试寄存器》

x86 调试寄存器 – linux kgdb gdb debug

英文官方介绍《Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3A: System Programming Guide》第16章-- DEBUGGING, PROFILING BRANCHES AND TIME-STAMP COUNTER

本文内容转载自
==============================
调试寄存器(DRx)理论与实践
By Hume/冷雨飘心 Humewen@21cn.com.
==============================

有8个调试寄存器供处理器操作,其中有2个被保留,所以真正可用的寄存器只有6个Dr0,Dr1,Dr2,Dr3,Dr6和Dr7。这些寄存器全是32位,如下图所示:

Dr0~3 用于设置硬件断点,即在调试器中经常使用的bpm断点,由于只有4个断点寄存器,所以最多只能设置4个bpm断点。Dr7是一些控制位,用于控制断点的方式,Dr6用于显示是哪些引起断点的原因,如果是Dr0~3或单步(EFLAGS的TF)或由于GD置位时访问调试寄存器引起1号调试陷阱的话,则相应设置对应的位。下面对Dr6和Dr7的对应位做一些详细介绍:

调试控制寄存器Dr7:

位0 L0和位1 G0:用于控制Dr0是全局断点还是局部断点,如果G0置位则是全局断点,L0置位则是局部断点。
G1L1~G3L3用于控制D1~Dr3,其功能同上。

LEN0:占两个位,开始于位15,用于控制Dr0的断点长度,可能取值:
00 1字节
01 2字节
10 保留
11 4字节
RWE0:从第17位开始,占两个位,控制Dr0的断点是读、写还是执行断点或是I/O端口断点:
00 只执行
01 写入数据断点
10 I/O端口断点(只用于pentium+,需设置CR4的DE位)
11 读或写数据断点
RWE1~3,LEN1~3分别用于控制Dr1~3的断点方式,含义如上。

还有一个GD位:用于保护DRx,如果GD位为1,则对Drx的任何访问都会导致进入1号调试陷阱。即IDT的对应入口,这样可以保证调试器在必要的时候完全控制Drx。

调试状态寄存器Dr6:

该寄存器用于表示进入陷阱1的原因,各个位的含义如下:
B0~B3,如果其中任何一个位置位,则表示是相应的Dr0~3断点引发的调试陷阱。但还需注意的是,有时候不管GiLi如何设置,只要是遇到Drx指定的断点,总会设置Bi,如果看到多个Bi置位,则可以通过GiLi的情况判断究竟是哪个Dr寄存器引发的调试陷阱。
BD置位表示是GD位置位情况下访问调试寄存器引发的陷阱。
BT置位表示是因为TS置位即任务切换时TSS中TS位置1时切到第二个任务时第一条指令时引发的。
BS置位表示是单步中断引发的断点。。。。即EFLAGS的TF置位时引发的调试陷阱。

注意I/O端口断点是586+以上CPU才有的功能,受CR4的DE位的控制,DE为1才有效。(DE是CR4的第3位)。

其它相关链接

【总结】调试寄存器 原理与使用:DR0-DR7

DDD的博客:抓虫日记之 kgdb 和 删除硬断点 - 哲思

为避免硬/软断点影响kgdb,在kgdb主程序kgdb_cpu_enter运行过程中,所有的断点是被disable的。
对于硬件断点来说,它会显示的调用kgdb_disable_hw_debug()来disable所有的硬件断点,
在kgdb离开时,调用kgdb_correct_hw_break()来使能/增加需要激活的硬件断点。

A: 前言

自从Prasad Krishnan兄(也许该叫大叔)引入Hardware Breakpoint统一管理机制后,
结束了各个内核模块中对Hardware Breakpoint处理各自为政的状态,一统Hardware
Breakpoint的天下.

KGDB也无例外,为了对别人负责,也需要迁移到Hardware Breakpoint Layer, 其实
kgdb对使用Hardware Breakpoint Layer是很不爽的。为避免大家心里暗怨我瞎说,
特举例如下:

 1: 使用Hardware Breakpoint Layer,增加了kgdb对系统的依赖性,这潜在的影响
 

 kgdb的稳定性。
 

  
 

 2: 当kgdb用于早期调试时(如系统初始化阶段),Hardware Breakpoint Layer有
 

 可能还没有初始化,那时候还是得kgdb自己来管理硬件断点。从这个角度来说kgdb支持
 

 Hardware Breakpoint Layer确实比较鸡肋。
 

  
 

 3: Hardware Breakpoint Layer依赖notifier_chain来实现的,有时候kgdb会避免
 

 使用notifier_chain的(这样就可以单步调试notifier的相关代码),一旦使用了Hardware
 

 Breakpoint Layer,就不能调试notifier的相关代码时,应该kgdb依赖它,kgdb是不能自己
 

 调自己的。
 

 

迫于像大家看齐的压力,kgdb还是忍痛接受了Hardware Breakpoint Layer,反正
Hardware Breakpoint Layer还是有一个好处的,就是not evil,不会破坏别人的硬件断点设置,
这样别人不会来抱怨你冲掉他们的硬断点设置。

为了让kgdb这个怪物支持Hardware Breakpoint Layer,Hardware Breakpoint Layer
还是给予了一定的协助的,如提供一些无锁操作函数等等.如为原来有锁的release_bp_slot提供
一个无锁的dbg_release_bp_slot.
kgdb由于使用了NMI这个强大的DD,如果调用一些持锁的函数,基本有概率会”无理由”的把你
给锁住,哭都不知道找谁去。同样,在Jason大牛的一番艰苦奋战下,kgdb基本把Hardware
Breakpoint Layer给摆平了.

B: 问题和现象

但在某天某时某分(秒就算了),我发现在对硬断点增/减多次操作后,在操作就再也不成功了。
经过多次重启机器的麻木实验后,发现规律如下:
前四次是肯定可以成功,而后面的操作是肯定不可以成功。

而四正好是X86的硬件断点最大数,也就是Hardware Breakpoint Layer定义的最大操作数。
从这个表象上看,很可能是删除断点的时候没有删掉,于是开始dig kgdb硬断点相关代码.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/855045.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第5讲:如何构建类的方法

【分享成果&#xff0c;随喜正能量】在这个社会上&#xff0c;对别人好一点&#xff0c;多站在别人的角度考虑&#xff0c;不要为小事争执&#xff0c;不要取笑他人&#xff0c;不要在别人背后嚼舌根&#xff0c;更不能逼人太甚。凡事退一步&#xff0c;对你有好处。。 《VBA中…

前沿分享-无创检测血糖RF波

非侵入性血糖仪&#xff0c;利用射频 (RF) 波连续测量血液中的葡萄糖水平。利用射频波技术连续实时监测血液中的葡萄糖水平&#xff0c;使用的辐射要比手机少得多。 大概原理是血液中的葡萄糖是具有介电特性&#xff0c;一般来说就是介电常数。 电磁波波幅的衰减反映了介质对电…

电脑文件丢失如何找回?使用这个方法轻松找回!

电脑文件丢失怎么办&#xff1f;有没有免费的电脑文件恢复软件&#xff1f;相信很多人在日常办公中也都经常会遇到这种现象&#xff0c;不管是在学习中&#xff0c;还是日常的办公&#xff0c;往往也都会在电脑上存储大量的数据文件&#xff0c;那么如果我们在日常办公操作过程…

忆恒创源发布PBlaze7 7940系列PCIe 5.0企业级NVMe SSD

今天&#xff0c;国内知名企业级SSD产品和解决方案供应商——北京忆恒创源科技股份有限公司&#xff08;Memblaze&#xff0c;以下简称“忆恒创源”&#xff09;全新一代PCIe 5.0企业级NVMe SSD PBlaze7 7940正式发布。与主流PCIe 4.0产品相比&#xff0c;PBlaze7 7940有着2.5倍…

1.利用matlab建立符号表达式(matlab程序)

1.简述 、 1. 使用sym命令创建符号变量和表达式 语法&#xff1a; sym(‘变量’,参数) %把变量定义为符号对象 说明&#xff1a;参数用来设置限定符号变量的数学特性&#xff0c;可以选择为’positive’、’real’和’unreal’&#xff0c; ’positive’ 表示为“正、实”符…

【C++】位图|布隆过滤器|海量数据处理面试题

文章目录 一.位图1. 位图的概念2. 位图的使用3. 位图的实现 二.布隆过滤器1. 布隆过滤器2. 布隆过滤器的实现 三.海量数据处理面试题1.位图2.布隆过滤器3.哈希切割 一.位图 1. 位图的概念 所谓位图&#xff0c;就是用每一位来存放某种状态&#xff0c;适用于海量数据&#xf…

沁恒ch32V208处理器开发(一)开发环境

目录 简介&#xff1a;开发环境开发界面自定义风格 烧录工具支持范围烧录界面 简介&#xff1a; CH32V2x 系列是南京沁恒基于 32 位 RISC-V 指令集及架构设计的工业级通用微控制器。采用青稞 V4 内核&#xff0c;支持硬件中断堆栈&#xff0c;提升中断响应效率&#xff1b;CH3…

PyCharm新手入门指南

安装好Pycharm后&#xff0c;就可以开始编写第一个函数&#xff1a;Hello World啦~我们就先来学习一些基本的操作&#xff0c;主要包含新建Python文件&#xff0c;运行代码&#xff0c;查看结果等等。 文章主要包含五个部分&#xff1a; 一、界面介绍 主要分为菜单栏、项目目录…

3.2用互斥元保护共享数据

概述 于是&#xff0c;你有一个类似于上一节中链表那样的共享数据结构&#xff0c;你想要保护它免于竞争条件以及可能因此产生的不变量损坏。如果你可以将所有访问该数据结构的代码块标记为互斥的&#xff08;mutually exclusive)&#xff0c;岂不是很好&#xff1f;如果任何线…

flutter 没有open android module in Android studio 插件代码爆红

参考 1.结论 其实就是缺少这个文件 2.解决方案有两个 2.1 方案一 手动创建一个,命名规则是项目名字‘_android’‘.iml’ 内容如下: <?xml version"1.0" encoding"UTF-8"?> <module type"JAVA_MODULE" version"4">&l…

Python小白入门:类和面向对象思想的超详细知识点总结

目录 一、创建和使用类1.1 创建类1.2 根据类创建实例1.2.1访问属性1.2.2 调用方法1.2.3 创建多个实例 练习题 二、使用类和实例2.1 创建一个类2.2 给属性指定默认值2.3 修改属性值2.3.1 直接通过实例进行修改2.3.2通过方法进行设置2.2.3 通过方法对属性值进行递增 练习题 三、继…

【第一阶段】kotlin中反引号中的函数名特点

在kotlin中可以直接中文定义函数&#xff0c;使用反引号进行调用 eg: fun main() {2023年8月9日定义的函数(5) }private fun 2023年8月9日定义的函数(num:Int){println("反引号的用法$num") }执行结果 在Java中is,in可以定义方法&#xff0c;但是在kotlin中is,in是…

基于亚奈奎斯特采样和SOMP算法的平板脉冲响应空间插值matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ...................................................................... %fine regular gr…

RobotFramework的安装过程及应用举例

一、安装python3.8.0 二、安装wxPython C:\>pip install -U wxPython Collecting wxPythonObtaining dependency information for wxPython from https://files.pythonhosted.org/packages/00/78/b11f255451f7a46fce2c96a0abe6aa8b31493c739ade197730511d9ba81a/wxPython-…

flutter开发实战-实现marquee根据文本长度显示文本跑马灯效果

flutter开发实战-实现marquee文本跑马灯效果 最近开发过程中需要marquee文本跑马灯效果&#xff0c;这里使用到了flutter的插件marquee 效果图如下 一、marquee 1.1 引入marquee 在pubspec.yaml中引入marquee # 跑马灯效果marquee: ^2.2.31.2 marquee使用 marquee使用也是…

k8s 自身原理 1

咱们从 pod 一直分享到最近的 Statefulset 资源&#xff0c;到现在好像我们只是知道如何使用 k8s&#xff0c;如何按照 k8s 设计好的规则去应用&#xff0c;去玩 k8s 仔细想想&#xff0c;对于 k8s 自身的内在原理&#xff0c;我们好像还不是很清楚&#xff0c;对于每一个资源…

【linux】-进程概念之环境变量的详解(命令行参数的介绍)

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

介绍另外一个容器技术, Apptainer

一说到容器&#xff0c;我们往往会脱口而出&#xff0c; Docker&#xff0c; 实际上Docker 仅仅是Linux 容器化的一种&#xff0c; 今天介绍的Apptainer 就是另外一种容器技术。 那么Apptainer 具体是一个什么东西呢&#xff1f; 跟Docker 有什么区别呢&#xff1f; 首先&#…

剑指 Offer !!56 - II. 数组中数字出现的次数 II

剑指 Offer 56 - II. 数组中数字出现的次数 II 在一个数组 nums 中除一个数字只出现一次之外&#xff0c;其他数字都出现了三次。请找出那个只出现一次的数字。示例 1&#xff1a;输入&#xff1a;nums [3,4,3,3] 输出&#xff1a;4 示例 2&#xff1a;输入&#xff1a;nums …