使用源代码
我喜欢回答您的问题的一种方法是查看来源。你没有说具体是哪个 linux 内核,所以看看 3.17.2 的源代码似乎至少有助于展示这种技术。
让我们从每个陷阱的递归 grep 开始...
寻找TRAP_BRANCH
$ grep -r TRAP_BRANCH .
./arch/ia64/kernel/brl_emu.c: siginfo.si_code = TRAP_BRANCH;
./arch/ia64/kernel/traps.c: case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break;
./arch/parisc/kernel/traps.c: handle_gdb_break(regs, TRAP_BRANCH);
./include/uapi/asm-generic/siginfo.h:#define TRAP_BRANCH (__SI_FAULT|3) /* process taken branch trap */
寻找TRAP_TRACE
$ grep -r TRAP_TRACE . | egrep -v HV
./arch/avr32/kernel/ptrace.c: code = TRAP_TRACE;
./arch/avr32/kernel/ptrace.c: code = TRAP_TRACE;
./arch/blackfin/include/uapi/asm/siginfo.h:#define TRAP_TRACEFLOW (__SI_FAULT|2) /* trace buffer overflow ************* */
./arch/blackfin/kernel/traps.c: info.si_code = TRAP_TRACEFLOW;
./arch/frv/kernel/traps.c: (__frame->__status & REG__STATUS_STEPPED) ? TRAP_TRACE : TRAP_BRKPT;
./arch/ia64/kernel/brl_emu.c: siginfo.si_code = TRAP_TRACE;
./arch/ia64/kernel/traps.c: case 36: siginfo.si_code = TRAP_TRACE; ifa = 0; break;
./arch/m68k/kernel/asm-offsets.c: DEFINE(LTRAP_TRACE, TRAP_TRACE);
./arch/m68k/kernel/traps.c: info.si_code = TRAP_TRACE;
./arch/m68k/math-emu/fp_entry.S: pea LTRAP_TRACE
./arch/mn10300/kernel/kgdb.c: si_code = TRAP_TRACE;
./arch/mn10300/kernel/traps.c: [EXCEP_ISTEP >> 3] = { SIGTRAP, TRAP_TRACE }, /* Monitor */
./arch/openrisc/kernel/traps.c: info.si_code = TRAP_TRACE;
./arch/parisc/kernel/ptrace.c: si.si_code = TRAP_TRACE;
./arch/parisc/kernel/traps.c: handle_gdb_break(regs, TRAP_TRACE);
./arch/powerpc/kernel/traps.c: info->si_code = TRAP_TRACE;
./arch/powerpc/kernel/traps.c: _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
./arch/powerpc/kernel/traps.c: _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
./arch/x86/include/asm/traps.h:#include <asm/siginfo.h> /* TRAP_TRACE, ... */
./arch/x86/include/asm/traps.h: return TRAP_TRACE;
./include/uapi/asm-generic/siginfo.h:#define TRAP_TRACE (__SI_FAULT|2) /* process trace trap */
比较 grep 结果
因此,至少相对而言,TRAP_TRACE 似乎比TRAP_BRANCH 更频繁地用于更多架构。更具体地说,TRAP_BRANCH 仅用于 2 个架构(ia64 和 parisc),而TRAP_TRACE 用于 10 个架构(avr32、blackfin、frv、ia64、@98765436 @、mn10300、openrisc、parisc、powerpc 和 x86)。
但是,我觉得仅仅注意到句法上的差异还不够令人满意。我也想了解语义差异。
检查代码
从 grep 输出中,我看到在 ./arch/*/kernel/traps.c 文件中最一致地找到匹配的模式。
然后看看./arch/parisc/kernel/traps.c,其中使用了两个陷阱,我看到它们都在handle_interruption 函数的上下文中使用。 TRAP_TRACE 是整数 code 的 3,TRAP_BRANCH 是整数 code 的 25。搜索 handle_interruption 的调用,我发现只有 ./arch/parisc/kernel/entry.S 调用了这个函数。
所以现在我们在硬件领域 (IMO) 陷入困境,是时候从源代码着手了。
查看技术手册
pa risc code for TRAP_BRANCH 的快速 google 提供 PA-RISC 1.1 Architecture and Instruction Set ... - PA-RISC Linux 作为热门搜索。
在此 PDF 中,搜索中断代码 25 会显示手册的 中断 部分,其中显示了两个代码。代码 3 根据优先级出现在中断类别的“组 2”中,其中指定为“恢复计数器陷阱”,而代码 25 出现在“组 4”中并称为“采取分支陷阱”。
接下来搜索“Taken branch”,我发现 PSW 禁用/启用位的 T 字段以及以下符号:
已启用分支陷阱。为 1 时,任何已采用的分支都会以已采用的分支陷阱终止。
然后:
与分支相关的陷阱
分支指令可能会根据 PSW 位的值引起各种陷阱。如果 PSW T 位为 1,并且采用分支,则发生采用分支陷阱。此陷阱可用于调试目的。如果 PSW H 位为 1,并且分支指令提升了特权级别,则会发生更高特权转移陷阱。如果 PSW L 位为 1,并且分支指令降低了特权级别,则会发生低特权转移陷阱。
“恢复计数器”的同时显示:
恢复计数器
恢复计数器 (CR 0) 是一个 32 位计数器,可用于在容错系统中提供硬件故障的软件恢复,也可用于调试目的。
文档后面有一条注释说:
恢复计数器可用于记录正常操作期间的中断,并模拟故障恢复期间的中断。
总结
据我所知(至少对于 PA RISC 架构)...
-
进程分支陷阱与
TRAP_BRANCH linux 代码相关联,可在某些架构上用于检测何时采用代码分支。
-
“进程陷阱”和“进程分支陷阱”的区别,假设“进程陷阱”是指
TRAP_TRACE linux 代码,前者用于调试中断处理,而后者用于调试所采用的分支。
我怀疑这些答案对于其他架构来说并不算太遥远,但我会将检查其他架构留给其他人去做。
希望这会有所帮助。