在现代电子设备的开发中,JTAG(Joint Test Action Group)调试是一种重要的技术手段,它允许开发者对系统级芯片(SoC)和微处理器软件进行调试和测试。本文将介绍如何在基于Intel架构的系统中,使用JTAG调试工具来调试Android Linux内核中的异常错误。
JTAG是一种标准的测试访问端口和边界扫描架构,用于调试和测试SoC和微处理器软件。JTAG调试配置包括三个部分:主机机器上的JTAG调试软件、JTAG探针以及SoC上的片上调试(OCD)。
JTAG调试软件是安装在主机机器上的一个工具,它从JTAG探针获取地址和数据,并展示给用户。用户可以通过这个工具进行运行控制和源代码级调试,包括运行、停止、单步执行、设置断点以及访问内存等操作。Intel System Studio Ultimate Edition提供了名为XDB的Intel JTAG调试器,作为主机侧的JTAG调试软件。
JTAG探针是一个硬件盒子,它将JTAG信号转换为PC连接信号,如USB、并行、RS-232、以太网等。USB是最流行的连接方式,许多JTAG探针使用USB作为与主机PC的连接。尽管JTAG引脚有最小标准数量,但目标侧接口有许多变体,例如ARM 10针、ST 14针、OCDS 16针、ARM 20针。本文中使用的Intel JTAG调试器和MinnowBoard MAX配置具有60针连接到目标。Intel ITP-XDP3探针用作MinnowBoard MAX的JTAG探针。Intel JTAG调试器也兼容其他厂商的JTAG探针,如Macraigor Systems的usb2Demon、OpenOCD。
OCD的主要组件是TAP(测试访问点)和TDI(测试数据输入)/TDO(测试数据输出)。通过TAP,可以重置或读写寄存器、绕过,而JTAG的主要技术是边界扫描,通过TDI/TDO信号线实现。
异常是处理器在执行指令时检测到一个或多个预定义条件时生成的同步事件。IA-32架构规定了三类异常:故障、陷阱和中止。通常,故障和陷阱是可以恢复的,而中止不允许程序重新启动。当发生异常时,它的处理方式与中断处理相同,即在停止并保存当前进程后,系统切换到异常处理程序,一旦异常处理完成,系统就会返回。
需要设置MinnowBoard MAX,使其运行Android操作系统。有关如何设置/构建/下载MinnowBoard MAX中的Android操作系统的介绍,请参见“Intel(R) System Studio Developer Story: How to configure, build and profile the Linux Kernel of Android by using the VTune”文章。将MinnowBoard MAX通过lure(带有60针JTAG连接器的小PCB)连接到Intel ITP-XDP3 JTAG探针,并将Intel ITP-XDP3通过USB连接到主机PC。主机PC应已安装Intel System Studio Ultimate Edition,以获得Intel ITP-XDP3的USB驱动程序。
将逐步介绍如何使用Intel JTAG调试器来检查和调试内核中的异常。
转到安装目录并运行批处理文件(例如start_xdb_legacy_products.bat)。
转到Intel JTAG调试器菜单 - 文件 - 连接,并选择Intel ITP-XDP3和Z3680、Z37xx。
转到Intel JTAG调试器菜单 - 文件 - 加载/卸载符号,并设置符号文件。对于源文件,转到Intel JTAG调试器菜单 - 选项 - 源目录并设置规则和目录。规则是调整文件目录,使其在编译时记录的符号文件中的路径与当前源路径一致。
Intel JTAG调试器菜单 - 查看 - 源文件并打开entry_64.S文件。
转到包含错误代码的rax寄存器的ENTRY(error_entry),这是异常的入口点。每个异常处理程序都定义为zeroentry或errorentry宏,因此可以在error_entry或某个特定处理程序中设置断点。在本文中,使用“zeroentry invalid_op do_invalid_op”进行测试。
C++
ENTRY(error_entry)
XCPT_FRAME
CFI_ADJUST_CFA_OFFSET
15
*
8
/*
oldrax contains error code */
cld
movq_cfi rdi, RDI+8
movq_cfi rsi, RSI+8
movq_cfi rdx, RDX+8
movq_cfi rcx, RCX+8
movq_cfi rax, RAX+8
movq_cfi r8, R8+8
movq_cfi r9, R9+8
movq_cfi r10, R10+8
movq_cfi r11, R11+8
movq_cfi rbx, RBX+8
movq_cfi rbp, RBP+8
movq_cfi r12, R12+8
movq_cfi r13, R13+8
movq_cfi r14, R14+8
movq_cfi r15, R15+8
xorl %ebx,%ebx
testl $3,CS+8(%rsp)
je error_kernelspace
error_swapgs:
SWAPGS
error_sti:
TRACE_IRQS_OFF
ret
将断点设置在“zeroentry invalid_op do_invalid_op”,并调用BUG(),它通过ud2指令制造“无效操作码”故障。
C++
#define BUG() \
do \
{ \
asm volatile ( \
"ud2"; \
unreachable(); \
} \
while (0)
将BUG()宏添加到内核的测试代码中,以通过特殊按键输入序列制造异常。
一些异常是系统硬件和软件的关键错误,因此了解这些异常发生的原因、原因和位置非常重要。通过使用Intel JTAG调试器,可以轻松地检查并进行更深入的调查。因为Intel JTAG调试器提供了强大的功能,如轻松访问汇编代码和源代码、检查调用堆栈和寄存器。