OK6410A 开发板 (八) 85 linux-5.11 OK6410A kdb 调试 linux

kdb 已经和 kgdb 合入到内核的同一个模块,代码已经合并
CONFIG_KGDB_KDB=y

kgdboc=ttyS0,115200

在启动过程中会自动进入
在 挂载 procfs后手动 "echo g  >  /proc/sysrq-trigger" 进入

// 默认进入kdb
kdb> 
	进入 kdb 交互式 shell 之后,可以使用 help 命令查看 kdb 支持的调试功能,并尝试使用之。
	前面说过 kdb 和 kgdb 可通过交互 shell 自己切换,

kdb 	交互式shell下 可以通过 键入kgdb 进入 kgdb // 进入之后就开始等待gdb的连接
kgdb 	非交互式shell下 可以通过 键入$3#33 进入 kdb
  • 几种调试手段的区别
JTAGKGDBKDB
框架JTAG+JLINK+JLinkGDBServer+GDBKGDB+串口+GDBKDB+串口(只要是输入就可以,例如lcd)
可以调试的对象裸机(包括u-boot) rtos linuxlinuxlinux
需要的硬件JLINK串口串口(只要可以输入就可以,不一定是串口)
需要的软件JLinkGDBServer+GDBKGDB+GDBKDB
调试linux启动的范围大(在stext时,就可以调试)小(必须等待KGDB建立后)小(必须等待KDB建立后,与KGDB一同建立)
linux启动后是否可以调试可以可以可以
可否调试裸机可以不可以不可以
用户接口GDBGDBKDB命令行
底层实现机制外部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); // drivers/tty/serial/kgdboc.c
kgdboc_earlycon_init
	kgdb_register_io_module		// kernel/debug/debug_core.c
		kgdb_register_callbacks
			register_sysrq_key 	// drivers/tty/sysrq.c
				__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 // drivers/tty/serial/kgdboc.c
		kgdb_register_io_module		// kernel/debug/debug_core.c
			kgdb_register_callbacks
				register_sysrq_key 	// drivers/tty/sysrq.c
					__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)); // arch/arm/include/asm/kgdb.h
    		// #define KGDB_COMPILED_BREAK 0xe7ffdeff 非arm定义指令, kgdb会将其视为 断点指令
    		// #define KGDB_BREAKINST      0xe7ffdefe 非arm定义指令, kgdb会将其视为 下一条指令
  • 发生时

drivers/tty/sysrq.c
static const struct proc_ops sysrq_trigger_proc_ops = {
	.proc_write = write_sysrq_trigger

	write_sysrq_trigger/
		__handle_sysrq // sysrq键 调用 __sysrq_swap_key_ops->__handle_sysrq 
			sysrq_key_table[16]/即sysrq_handle_dbg
				kgdb_breakpoint
					asm(__inst_arm(0xe7ffdeff)); // 非定义指令,产生非定义指令异常,进入 __und_svc
					
_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
		
	比较 产生异常的指令码 是不是  (0xe7ffdeff0xe7ffdefe)
	如果是,调用 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 // kernel/debug/debug_core.c
					kdb_stub // kernel/debug/kdb/kdb_debugger.c
						kdb_main_loop  // kernel/debug/kdb/kdb_main.c
							kdb_local
								while(1){
									kdb_getstr // 获取用户输入的字符串
									diag = kdb_parse(cmdbuf); // 解析字符串
									if (diag == KDB_CMD_GO)
										break;
								}
														
					或
					
					gdb_serial_stub				

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值