之前2天时间弄了个框架
以为这个STUB能很快完成
搞了一周后才发现GDB的难度超出了我的预期
好在有其他的代码可以参考
由于自己缺少汇编的编写经验
在异常向量的处理上花了太多的时间
现在看看我用的undef入口代码
.globl vector_undef
vector_undef:
sub sp, sp, #72
stmia sp, {r0 - r12} @/* Calling r0-r12 */
add r8, sp, #60
mrs r1, cpsr
msr cpsr_c, #I_Bit|F_Bit|Mode_SVC
mov r0, r0
@mov r2, lr @ Save old lr
stmdb r8, {sp, lr} @/* Calling SP, LR */
msr cpsr_c, r1 @/* return to Undefined Instruction mode */
str lr, [r8, #0] @/* Save calling PC */
mrs r6, spsr
str r6, [r8, #4] @/* Save CPSR */
str r0, [r8, #8] @/* Save OLD_R0 */
mov r0, sp
bl rt_hw_trap_udef
ldmia sp, {r0 - r12} @ Calling r0 - r2
mov r0, r0
ldr lr, [sp, #60] @ Get PC
add sp, sp, #72
movs pc,lr
代码在bl rt_hw_trap_udef前部分和RTT原本的差不多,都是将寄存器值压入栈供函数使用
有的一点区别就是我们的SP,LR寄存器是先恢复到SVC模式再压栈
因为GDB需要的是sp,lr 而不是sp_udef lr_udef
后半部分主要就是把存入的寄存器覆盖回去.恢复现场
要注意的是这里使用movs pc,lr
因为在undef里 lr_udef寄存器保存的是PC+4的值,我们这里把lr_udef当做了PC传递给函数
但函数修改出来后的值是PC
所以不能用subs 而是直接movs
还有这周主要的工作就是完善了单步执行
大部分的arm架构都是没有支持单步执行的调试单元的
也就是说我们必须用断点来模拟单步执行
= =不过很纠结我的一点就是kgdb将单步执行视为普通的continue
让模拟单步的环节交给GDB
但我找不到是kgdb是如何告诉gdb让他来模拟的.....
所以我只能自己去模拟单步
if (ins_will_execute(curins)) {
// Decode instruction to decide what the next PC will be
addr = (unsigned long) target_ins((unsigned long*)pc,
curins);
} else {
// The current instruction will not execute (the conditions
// don't hold)
addr = pc+4;
}
模拟单步的基本过程就是这样
addr是要设置断点的位置
先是解析当前的指令,看是否需要跳转
如果不需要,那就将断点设置为pc+4
不然 就要对命令作解析
比如 bx lr
那我们就要设置ADDR为lr
大致计划上BeagleBone的工作就差不多了,只剩下大量测试了
多核支持也只能等以后RTT多核完善后再说
接下来是准备去实现对cortexM的支持
一开始是准备对所有的arm使用同一套arch
这套arch同时实现软件断点,硬件断点
但现在看来cortexM带有非常完善的调试单元
而且cortexM大多混用thumb指令
差异较大
所以准备分开实现
cortexA系列.ARM9等等不再去实现硬件断点,因为软件断点已经足够好哟你
cortexM只实现硬件断点
虽然我找不到对cortexM做GDB支持的理由
廉价便宜的各种JTAG,SWD调试器完全满足了需要