请阅读【嵌入式开发学习必备专栏 】
文章目录
- ARMv8/v8 软件设置段带你
- 断点地址软件配置流程
- 代码实现
ARMv8/v8 软件设置段带你
在ARMv8/9架构中,可以通过寄存器 DBGBVR0_EL1
设置断点。这个寄存器是一系列调试断点值寄存器中的第一个DBGBVRn_EL1
,其中n表示寄存器编号,对于ARMv8/9,通常可以有多个这样的寄存器,具体数量取决于实现:
• DBGBCR0_EL1 and DBGBVR0_EL1 are for breakpoint number zero.
• DBGBCR1_EL1 and DBGBVR1_EL1 are for breakpoint number one.
• DBGBCR2_EL1 and DBGBVR2_EL1 are for breakpoint number two.
• …
• …
• DBGBCR<n-1>_EL1 and DBGBVR<n-1>_EL1 are for breakpoint number (n-1).
DBGBVR0_EL1
允许在EL1(异常级别1,通常是操作系统级别)控制下设置断点,从而帮助开发人员进行代码调试。
DBGBVR0_EL1
寄存器通常在软件调试过程中使用,它使得调试器能够指定程序中的一个地址,当处理器执行到这个地址时自动触发一个调试事件(如断点异常)。这对于调试复杂的软件问题非常有用,尤其是在需要理解程序流程或识别特定代码执行路径时。
此外,DBGBVR0_EL1
可以进行下面内容匹配:
— An instruction virtual address.
— A Context ID.
— A VMID value.
— A concatenation of both a Context ID value and a VMID value.
为了方便测试,在PC执行到设置的断点地址之后让CPU停下来,这里需要配置下系统debug 寄存器 EDSCR.HDE
: Halting debug enable
位,EDSCR
寄存器的内容如下:
STATUS, bits [5:0]
: debug 状态的 flag, 具体含义如下:
0b000001
PE is restarting, exiting Debug state.0b000010
PE is in Non-debug state.0b000111
Breakpoint.0b010011
External debug request.0b011011
Halting step, normal.0b011111
Halting step, exclusive.0b100011
OS Unlock Catch.0b100111
Reset Catch.0b101011
Watchpoint.0b101111
HLT instruction.0b110011
Software access to debug register.0b110111
Exception Catch.0b111011
Halting step, no syndrome
其它位的含义这里就不再过多介绍
注意:为了使软件可以配置对breakpoint 相关寄存器进行配置,还需要对寄存器oslar_el1
配置,进行解锁操作。
在断点地址配置好之后,如还需配置具体的触发方式及断点使能配置,需要对寄存器DBGBCR<n>
:Debug Breakpoint Control Registers, n = 0 - 15
:
Bit[13] (HMC) - 1'b1 - State matching (match all states)
Bits[8:5] (BAS) - 4'b1111 - Match A32/A64 instructions
Bits[2:1] (PMC) - 2'b11 - State matching (match all states)
Bit[0] (E) - 1'b1 - Enable this breakpoint
断点地址软件配置流程
- 设置断点地址:将你希望断点触发的代码地址写入
DBGBVR0_EL1
。 - 配置断点控制寄存器(DBGBCR0_EL1):与
DBGBVR0_EL1
一起使用的还有控制寄存器(例如DBGBCR0_EL1
),它用于配置断点的类型(如硬件断点)和行为(如断点触发条件)。你需要根据需求配置这些控制寄存器,以确保断点以正确的方式被触发。 - 运行调试会话:当程序执行到达
DBGBVR0_EL1
指定的地址时,将触发断点,此时可以通过调试器查看程序状态,包括寄存器、内存和其他有用的调试信息。 - 处理断点触发:一旦断点触发,你可以使用调试器来检查程序的状态、修改变量或寄存器的值,或是单步执行程序来进一步调试。
代码实现
cpu_bkpt_test:
stp x0, x1, [sp, #-0x10]!
mrs x0, mdscr_el1
orr x0, x0, #(0x1 << 14)
msr mdscr_el1, x0
mov x0, #0
msr oslar_el1, x0
isb
adr x0, bkpt0
msr dbgbvr0_el1, x0
mov x0, #0x21E7
msr dbgbcr0_el1, x0
isb
bkpt0:
bl bkpt_test
ldp x0, x1, [sp], #0x10
ret
为了方便观察测试,在汇编代码中调用一个打印函数,如果测试不成功,会进行打印,具体实现如下:
void bkpt_test(void)
{
log_info("-------------\n");
}
在执行到上面断点函数bkpt0
之后,可以通过trace32观察到 trace32 状态改变: