kdb 已经和 kgdb 合入到内核的同一个模块,代码已经合并
CONFIG_KGDB_KDB=y
kgdboc=ttyS0,115200
在启动过程中会自动进入
在 挂载 procfs后手动 "echo g > /proc/sysrq-trigger" 进入
kdb>
进入 kdb 交互式 shell 之后,可以使用 help 命令查看 kdb 支持的调试功能,并尝试使用之。
前面说过 kdb 和 kgdb 可通过交互 shell 自己切换,
kdb 交互式shell下 可以通过 键入kgdb 进入 kgdb
kgdb 非交互式shell下 可以通过 键入$3#33 进入 kdb
| JTAG | KGDB | KDB |
---|
框架 | JTAG+JLINK+JLinkGDBServer+GDB | KGDB+串口+GDB | KDB+串口(只要是输入就可以,例如lcd) |
可以调试的对象 | 裸机(包括u-boot) rtos linux | linux | linux |
需要的硬件 | JLINK | 串口 | 串口(只要可以输入就可以,不一定是串口) |
需要的软件 | JLinkGDBServer+GDB | KGDB+GDB | KDB |
调试linux启动的范围 | 大(在stext时,就可以调试) | 小(必须等待KGDB建立后) | 小(必须等待KDB建立后,与KGDB一同建立) |
linux启动后是否可以调试 | 可以 | 可以 | 可以 |
可否调试裸机 | 可以 | 不可以 | 不可以 |
用户接口 | GDB | GDB | KDB命令行 |
底层实现机制 | 外部JLINK通过JTAG通过DAP访问debug APB总线上的coresight组件 | 代码通过寄存器从系统总线访问 debug APB总线上的coresight组件 | 同KGDB |
实现原理
kdb_init
kdb_inittab
kdb_register_flags("go", kdb_go, "[<vaddr>]", "Continue Execution", 1, KDB_ENABLE_REG_WRITE | KDB_ENABLE_ALWAYS_SAFE_NO_ARGS);
---
kgdb_arch_init
register_undef_hook(&kgdb_brkpt_hook);
register_undef_hook(&kgdb_compiled_brkpt_hook);
static struct undef_hook kgdb_brkpt_hook = {
.instr_mask = 0xffffffff,
.instr_val = KGDB_BREAKINST,
.cpsr_mask = MODE_MASK,
.cpsr_val = SVC_MODE,
.fn = kgdb_brk_fn
};
static struct undef_hook kgdb_compiled_brkpt_hook = {
.instr_mask = 0xffffffff,
.instr_val = KGDB_COMPILED_BREAK,
.cpsr_mask = MODE_MASK,
.cpsr_val = SVC_MODE,
.fn = kgdb_compiled_brk_fn
};
----------------------------------
device_initcall(sysrq_init);
sysrq_init_procfs
proc_create("sysrq-trigger", S_IWUSR, NULL, &sysrq_trigger_proc_ops)
-------------------------------
console_initcall(kgdboc_earlycon_late_init);
kgdboc_earlycon_init(kgdboc_earlycon_param);
early_param("kgdboc_earlycon", kgdboc_earlycon_init);
kgdboc_earlycon_init
kgdb_register_io_module
kgdb_register_callbacks
register_sysrq_key
__sysrq_swap_key_ops
__sysrq_put_key_op
static struct platform_driver kgdboc_platform_driver = {
.probe = kgdboc_probe,
.driver = {
.name = "kgdboc",
kgdboc_probe
configure_kgdboc
kgdb_register_io_module
kgdb_register_callbacks
register_sysrq_key
__sysrq_swap_key_ops
__sysrq_put_key_op
三种初始化相关的 ops
static const struct sysrq_key_op sysrq_dbg_op = {
.handler = sysrq_handle_dbg,
.help_msg = "debug(g)",
.action_msg = "DEBUG",
};
sysrq_handle_dbg
if (!kgdb_connected) {
#ifdef CONFIG_KGDB_KDB
if (!dbg_kdb_mode)
pr_crit("KGDB or $3#33 for KDB\n");
#else
pr_crit("Entering KGDB\n");
#endif
}
kgdb_breakpoint();
asm(__inst_arm(0xe7ffdeff));
drivers/tty/sysrq.c
static const struct proc_ops sysrq_trigger_proc_ops = {
.proc_write = write_sysrq_trigger
write_sysrq_trigger/
__handle_sysrq
sysrq_key_table[16]/即sysrq_handle_dbg
kgdb_breakpoint
asm(__inst_arm(0xe7ffdeff));
_und_svc:
...
__und_svc_fault:
bl __und_fault
__und_fault:
ldr r2, [r0, #S_PC]
sub r2, r2, r1
str r2, [r0, #S_PC]
b do_undefinstr
比较 产生异常的指令码 是不是 (0xe7ffdeff或0xe7ffdefe)
如果是,调用 do_undefinstr
如果不是,正常 未定义指令异常 流程
do_undefinstr
call_undef_hook(regs, instr)
list_for_each_entry(hook, &undef_hook, node) fn = hook->fn;
fn ? fn(regs, instr) : 1;/即 kgdb_compiled_brk_fn
kgdb_handle_exception
kgdb_cpu_enter
kdb_stub
kdb_main_loop
kdb_local
while(1){
kdb_getstr
diag = kdb_parse(cmdbuf);
if (diag == KDB_CMD_GO)
break;
}
或
gdb_serial_stub