KDB调试

KDB内核调试器

   KDB 内核调试器始终加载到固定内存的特殊区域中,其中有效地址空间等于实际地址空间。KDB 内核调试器在关闭内存转换的情况下运行。这允许它运行,即使 VMM 子系统尚未初始化或关键 VMM 结构已损坏。但是,KDB 内核调试器可以执行处理器通常执行的相同地址转换。这允许用户在处理器关闭其内存转换时按有效地址查看数据。

   当 KDB 内核调试器由条件调用时,它是唯一正在运行的程序。将停止所有其他进程,并禁用处理器中断。其中一个处理器被指定为调试处理器,该处理器运行 KDB 内核调试器。这通常是发生异常活动(例如,未处理的异常)的处理器。

   如果 KDB 内核调试器由用户手动调用,则任意选择调试处理器。KDB 内核调试器通过向每个处理器发送进程间中断 (IPI) 来停止系统中的所有其他处理器。如果无法停止这些处理器中的任何一个,KDB 内核调试器将打印一条警告消息。例如,如果处理器在锁上旋转并禁用中断,则无法处理 KDB 内核调试器发送的 IPI。

   KDB 内核调试器大多是自包含的,不依赖于其他内核组件,如网络和视频驱动程序。KDB 内核调试器使用自己的计算机状态保存区域 (mst) 和特殊堆栈运行。这要求在 KDB 内核调试器中复制某些内核代码。复制允许开发人员从内核代码中的几乎任何位置进行调试。除非通过系统暂停进入 KDB 内核调试器,否则处理器将恢复正常操作,并在开发人员退出 KDB 内核调试器时重新启用中断。

kdb的基本法

 记住常用的即可。

  安装新内核后,使用新内核重新启动机器,现在,内核已经有kdb支持了。那么如何进入调试环境呢?如果在配置内核时,没有选择kdb-off by default,那么在内核启动后,按下“pause”键即可进入kdb调试环境。如果在配置内核时选择了kdb-off by default,那么有两种办法:一种是在启动时加入“kdb=on”,另一种方式是在proc文件系统加载后,输入如下命令:

  #echo 1”>/proc/sys/kernel/kdb。

  然后就可以按“pause”键进入调试环境了。按“pause”键后,出现提示符kdb,同时键盘上Caps和Scroll两指示灯不停闪烁,提示现在处于kdb调试环境中。
  kdb提供丰富的命令实现运行控制、内存操纵、寄存器操纵、断点设置、堆栈跟踪等许多功能,总共有33条命令,下面分别进行介绍。
  运行控制类
  包括go、ss和ssb三个命令,提供对程序执行的控制。具体用法如下:

    go:继续程序执行

  格式:go
  该命令使内核继续执行,直到遇到一个断点才停止。如果没有设置断点,该命令将离开kdb调试器,系统回到正常运行状态。Caps和Scroll指示灯恢复到原来的状态。

  ss:单步执行程序

  格式:ss
  该命令仅仅执行下一条指令,执行完后停止。这在进行跟踪时是必不可少的。

  ssb:执行到分支或者函数调用时停止

  格式:ssb
  该命令与ss的区别是,ss只执行一条语句,而ssb执行一组语句,它使指令继续执行,在遇到一个分支语句,或者遇到一个函数调用语句时停止。
  断点类
  kdb提供强大的断点功能,包括设置断点、清除断点、激活断点、使断点失效,kdb也可以设置硬件断点。断点指令包括bp、bl、bpa、bph、bpha、bc、be和bd。

  bp:设置或者显示断点

  格式:bp [vaddr]
  该命令设置一个新的断点,其中vaddr是要设置的断点的地址。如果不带参数,运行bp将显示当前设置的所有断点。

  bl:设置或者显示断点

  格式:bl [vaddr]
  该命令的操作与bp命令相同。

  bpa:设置或者显示全局断点

  格式:bpa []
  该命令设置一个全局断点,或者显示所有全局断点,用法同上。

  bph:设置硬件断点或者显示所有断点

  格式:bph [vaddr [datar|dataw|io [length]]]
  如果不带参数,则显示所有断点。如果带参数,那么设置断点。其中vaddr为要设置硬件断点的地址,datar表示对该内存区进行读操作,dataw表示写操作,io表示对该内存区进行io输入输出操作。length指明读写io操作的数据长度。

  bpha:设置硬件断点或者显示所有断点

  格式和用法同bph。

  bc:清除断点

  格式:bc
  清除标号为bpnum的断点。如果断点号为“*”,将清除所有断点。

  bd:使断点无效

  格式:bd
  使标号为bpnum的断点无效,如果标号为“*”,表示使所有断点无效。

  be:激活断点

  格式:be
  激活标号为bpnum的断点。如果标号为“*”,将激活所有无效的断点。
  内存操作类
  内存操作类命令包括对内存进行显示和修改的md、mdr、mds、mm四条命令。

  md:显示内存内容

  格式1:md [vaddr [line-count [output-radix]] ]
  显示地址为vaddr的内存的内容。line-count为要显示的内存的行数,output-radix指定以8进制、10进制或者16进制显示。如果省略line-count和output-radix,那么将以设置的环境变量MDCOUNT和RADIX方式显示。如果不带任何参数,md命令将接着上次md命令的后续地址显示内存内容
格式2:mdWcn
  在缺省情况下,md以当前环境变量BYTESPERWORD的值读取数据,在读取硬件寄存器的时候,需要指定数据的宽度。这是可以使用mdWcn来进行读取,W是读取的宽度,单位是字节,cn为要读取的数目。

  mdr:显示原始内存的内容

  格式:mdr
  从指定地址vaddr开始显示count长度的内存,它打印一连串的内存数据。这个命令是留给外部的调试器使用的,一般很少使用。

  mds:以符号的方式显示内存的内容

  格式:mds [vaddr [line-count [output-radix]]]
  从指定地址vaddr开始显示内存的内容,与md的区别是每行仅显示一个字,并且它试图将该地址与符号表进行匹配,如果找到,那么它将显示相应的符号名以及偏移值。如果不带参数,它将从上次mds的末尾开始显示。

  mm:修改内存内容

  格式1:mm
  将指定地址vaddr开始的数据修改为新的数据。修改的数据的长度为一个机器字。
  格式2:mmW
  意义同上,区别在于它改变W字节的内容。
  堆栈跟踪类
  该类指令实现对堆栈的跟踪,包括bt、btp和bta三条命令。

  bt:显示调用堆栈

  格式:bt []
  如果不指定参数,它根据当前寄存器的内容显示堆栈,提供当前活动线程的完整的堆栈跟踪。如果指定stack-frame addr参数,它将从该地址开始跟踪。

  btp:显示进程的堆栈

  格式:btp
  显示由pid指定的进程的堆栈。

  bta:显示所有进程的堆栈

  格式:bta
  寄存器类
  寄存器类命令包括对寄存器内容进行显示和修改的rd和rm指令,以及异常帧显示指令ef。

  rd:显示寄存器内容

  格式:rd [c|d|u]
  如果不带任何参数,rd显示所有进入kdb调试器时该点所设置的所有通用寄存器的值。如果带c参数,它将显示控制寄存器cr0、cr1、cr2、cr4 寄存器的内容。如果带d参数,它显示调试寄存器的内容。如果带u参数,它显示当进入kdb调试器时当前任务的所有寄存器。

  rm:修改寄存器的内容

  格式:rm
  该命令修改register-name指定的寄存器的内容为register-content。其中register-name 为%eax、%ebx、%ecx、%edx、%esi、%edi、%esp、%eip或%ebp。如果参数为%%,由rd u指定的寄存器将被修改。当前rm命令不允许修改控制寄存器,也不允许显示和修改Pentium和Pentium Pro系列的特定寄存器。

  ef:显示异常帧

  格式: ef
  显示vaddr地址处的异常帧。
  环境变量类
  这类指令对kdb调试器环境变量进行显示和设置。包括set和env命令。

  set:设置环境变量

  格式:set <env-var=value>
  将环境变量env-var的值设置为value。最多有33个环境变量,每个环境变量最大512字节。kdb的主要环境变量有:
  PROMPT:kdb调试器提示符,缺省为kdb。
  MOREPROMPT:在一屏显示不下的情况下,系统的提示符,缺省为more。
  RADIX:显示数据时所使用的数制,缺省为16进制。
  LINES:kdb调试器显示行数。缺省为24行。
  COLUMNS:kdb调试器显示的列数。缺省为80列。
  MDCOUNT:执行md指令时显示的内存行数,缺省为8行。
  BTARGS:执行bt跟踪时,指定任一函数在打印时所使用参数最大个数。
  SSCOUNT:该环境变量规定在执行ssb命令时,如果显示超过此数,执行将停止。缺省为20。
  IDMODE:反汇编时所使用的指令格式。缺省为x86。
  BYTESPERWORD:指定字的长度,缺省为4个字节。
  IDCOUNT:反汇编时,一次反汇编的指令长度,缺省为16条指令。
  env:显示环境变量
  格式:env
  显示所有环境变量的值。
  

杂项

  id:指令反汇编

  格式:id
  从vaddr开始的地址反汇编指令。

  cpu:切换到另一个CPU

  格式:cpu
  这条命令仅仅在SMP结构下有用,它切换到由cpunum指定的CPU。

  ps:显示所有活动的进程

  显示当前的活动的进程。包括pid、父进程pid、CPU号、当前状态,以及对应的线程。

  reboot:重新启动机器

  格式:reboot
  在某些情况下,内核无法返回到正常工作状态,这时可以利用reboot重新启动机器。注意在重启机器前,它不进行任何状态保存的工作。

  sections:列出内核中所有已知的段的信息

  格式:sections
  列出模块和内核的所有已知的段的信息。首先是模块信息,最后是内核信息。包括模块名和一个或者多个段的信息。段信息包括段名、段起始地址、段结束地址和段标识。本命令仅仅是为外部调试器而设立的。

  sr:激活SysRq代码,也就是调用MAGIC_SYSRQ函数

  格式:sr
  将sysrq key字符作为参数传递给SysRq函数进行处理,就像你已经键入了SysRq键和该字符一样。如果要使用这个命令,需要在配置内核时,选择Magic SysRq Key。然后在新内核启动后,使用如下命令激活SysRq功能。

  #echo “1” > /proc/sys/kernel/sysrq

  这是一个功能强大的命令,它使得在kdb中可以使用操作系统提供的SysRq处理函数。
  lsmod:列出内核中加载的所有模块

  格式:lsmod

  显示所有模块的信息。包括模块名、模块大小、模块结构地址、引用计数,以及被哪个模块所引用。

  rmmod:卸载一个模块

  格式:rmmod
  将由modname指定的模块从内核中卸载。
  ll:对链表中的每个元素重复执行命令
  格式:ll
  它对以地址addr开头的链表的头link-offset个元素,重复执行cmd命令。
  help和?:显示帮助信息。
  格式:help 或者?
  显示kdb的命令以及简单的用法。

常用的一些内核模块操作
查看加载模块用lsmod或者cat /proc/modules(这个还可以查看模块加载地址)
卸载模块用rmmod,有时加上-f强行卸载
加载模块用modprobe或者insmod,区别转载如下:
"
insmod 与 modprobe 都是载入 kernel module,不过一般差别于 modprobe 能够处理 module 载入的相依问题。
比方你要载入 a module,但是 a module 要求系统先载入 b module 时,直接用 insmod 挂入通常都会出现错误讯息,不过 modprobe 倒是能够知道先载入 b module 后才载入 a module,如此相依性就会满足。
不过 modprobe 并不是大神,不会厉害到知道 module 之间的相依性为何,该程式是读取 /lib/modules/2.6.xx/modules.dep 档案得知相依性的。而该档案是透过 depmod 程式所建立。
modprobe:
modprobe可载入指定的个别模块,或是载入一组相依的模块。modprobe会根据depmod所产生的相依关系,决定要载入哪些模块。若在载入过程中发生错误,在modprobe会卸载整组的模块。
-a或--all  载入全部的模块。
-c或--show-conf  显示所有模块的设置信息。
-d或--debug  使用排错模式。
-l或--list  显示可用的模块。
-r, --remove //若在命令指定模块,则删除指定模块,否则,指定"自动清除"模式
-t或--type  指定模块类型。
-v或--verbose  执行时显示详细的信息。
-V或--version  显示版本信息。
-help  显示帮助。
-C, --config configfile //指定配置文件.默认使用/etc/modules.conf文件为配置文件
modprobe -r ip_vs # 删除ip_vs模块
modprobe -l | grep ip_vs # 查看ip_vs模块是否编译进内核
lsmod -l | grep ip_vs # 查看ip_vs模块是否载入进内核
"

posted @   心亘久  阅读(960)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示