英特尔(R) System Studio 开发者故事:使用英特尔® JTAG 调试器和 MinnowBoard MAX,如何调试 Android-Linux-Kernel 中的异常错误。





0/5 (0投票)
在本文中,我们将介绍如何在基于英特尔® 架构的系统上,使用英特尔® JTAG 调试器(该工具是英特尔 System Studio® Ultimate Edition 的一部分),调试和检查 Android Linux 内核中的异常错误。
英特尔® 开发者专区提供跨平台应用开发的工具和操作指南、平台和技术信息、代码示例以及同行专家经验,以帮助开发者创新和成功。加入我们的Android、物联网、英特尔® 实感™ 技术和Windows社区,下载工具,获取开发套件,与志同道合的开发者分享想法,并参与黑客马拉松、竞赛、路演和本地活动。
英特尔(R) System Studio 开发者故事:使用 XDB 和 MinnowBoard MAX,如何调试 Android-Linux-Kernel 中的异常错误。
在本文中,我们将介绍如何在基于英特尔® 架构的系统上,使用英特尔® JTAG 调试器(该工具是英特尔 System Studio® Ultimate Edition 的一部分),调试和检查 Android Linux 内核中的异常错误。在此过程中,我们还将了解 JTAG 和英特尔® JTAG 调试器是什么,以及一些关于基于英特尔® 架构系统异常处理的信息。我们将使用 MinnowBoard MAX 作为基于英特尔® 架构的目标系统。
1. JTAG 概述
JTAG 是 Joint Test Action Group 的缩写,通常读作 jay-tag,但它通常指 IEEE std 1149.1-1990 IEEE 标准测试访问端口和边界扫描架构。该标准用于调试和测试 SoC(片上系统)和微处理器软件。
JTAG 调试的配置由三部分组成:主机中的 JTAG 调试器软件、JTAG 探针和 SoC 中的片上调试 (OCD)。
1.1 JTAG 调试器软件
JTAG 调试器是主机中的一款软件工具。它从 JTAG 探针获取地址和数据并显示给用户,用户可以通过 USB 或其他 PC 连接方式向 JTAG 探针发送数据和地址,反之亦然。通过使用此工具,用户可以进行运行控制和源代码行调试,并加载映像的符号(二进制映像下载到目标系统),例如运行、停止、单步进入、单步跳过、设置断点,以及访问内存。因此,用户可以轻松调试目标系统的软件,并检查系统内存和寄存器。英特尔 System Studio® Ultimate Edition 包含英特尔® JTAG 调试器(又称 XDB),用于主机端的 JTAG 调试器软件。
1.2 JTAG 探针(或 JTAG 适配器)
JTAG 探针是将 JTAG 信号转换为 PC 连接信号(如 USB、并行、RS-232、以太网)的硬件盒。USB 是最常用的一种,许多 JTAG 探针都使用 USB 连接到主机 PC。尽管 JTAG 引脚数量有最小标准,但目标端接口有许多变体,例如 ARM 10 引脚、ST 14 引脚、OCDS 16 引脚、ARM 20 引脚。本文中使用的英特尔® JTAG 调试器和 MinnowBoard MAX 配置与目标系统采用 60 引脚连接。英特尔® ITP-XDP3 探针用作 MinnowBoard MAX 的 JTAG 探针。英特尔® JTAG 调试器还兼容来自其他供应商的 JTAG 探针,例如 Macraigor® Systems usb2Demon®、OpenOCD。
1.3 片上调试 (目标 SoC)
OCD 的主要组成部分是 TAP(测试访问点)和 TDI(测试数据输入)/ TDO(测试数据输出)。通过使用 TAP,我们可以复位或读/写寄存器和旁路,JTAG 的主要技术是通过 TDI/TDO 信号线实现的边界扫描(点击获取更多详细信息和图片)。
2. 英特尔架构中的异常概述
异常是在处理器执行指令时检测到一个或多个预定义条件时生成的同步事件。
IA-32 架构规定了三类异常:故障、陷阱和中止。
通常,故障和陷阱是可恢复的,而中止不允许程序重新启动。发生异常时,其处理方式与中断处理相同。这意味着,在暂停并保存当前进程后,系统会切换到异常处理程序,并在异常处理完成后再次返回。
3. 准备 MinnowBoard MAX 和英特尔® ITP-XDP3,并通过 USB 连接到主机 PC
您需要使用 Android 操作系统设置 MinnowBoard MAX。为此,请参阅“英特尔(R) System Studio 开发者故事:如何使用 VTune 配置、构建和分析 Android 的 Linux 内核”一文(请点击)。其中介绍了 MinnowBoard MAX 以及如何在 MinnowBoard MAX 中设置/构建/下载 Android 操作系统。
将 MinnowBoard MAX 与 Lure(带有 60 针 JTAG 连接器的小型 PCB)连接到英特尔® ITP-XDP3 JTAG 探针,并将英特尔® ITP-XDP3 通过 USB 连接到主机 PC。主机 PC 应已安装英特尔® System Studio Ultimate Edition,以便为英特尔® ITP-XDP3 提供 USB 驱动程序。
4. 使用英特尔® JTAG 调试器 (XDB) 调试 MinnowBoard MAX 上的 Android 内核异常。
我们将逐步介绍如何使用英特尔® JTAG 调试器检查和调试内核中的异常。
(1) 运行英特尔® JTAG 调试器:转到安装目录并运行批处理文件。(例如 start_xdb_legacy_products.bat)。
(2) 连接到目标:转到英特尔® JTAG 调试器菜单 - 文件 - 连接,然后选择英特尔® ITP-XDP3 和 Z3680, Z37xx。
(3) 加载符号文件并设置源文件目录。转到英特尔® JTAG 调试器菜单 - 文件 - 加载/卸载符号并设置符号文件。对于源文件,转到英特尔® JTAG 调试器菜单 - 选项 - 源目录并设置规则和目录。规则用于调整编译时记录在符号文件中的当前源路径和路径之间的文件目录。
(4) 浏览到包含异常处理程序的入口文件:英特尔® JTAG 调试器菜单 - 视图 - 源文件并打开 entry_64.S 文件。
(5) 在异常入口点设置断点:找到 `ENTRY(error_entry)`,它是带有 rax 寄存器中错误代码的异常入口点。每个异常处理程序都定义为 zeroentry 或 errorentry 宏,因此您可以在 error_entry 或某些特定的处理程序中设置断点。在本文中,我们使用 "`zeroentry invalid_op do_invalid_op`" 进行测试。
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 divide_error do_divide_error
zeroentry overflow do_overflow
zeroentry bounds do_bounds
zeroentry invalid_op do_invalid_op
zeroentry device_not_available do_device_not_available
paranoiderrorentry double_fault do_double_fault
zeroentry coprocessor_segment_overrun do_coprocessor_segment_overrun
errorentry invalid_TSS do_invalid_TSS
errorentry segment_not_present do_segment_not_present
zeroentry spurious_interrupt_bug do_spurious_interrupt_bug
zeroentry coprocessor_error do_coprocessor_error
errorentry alignment_check do_alignment_check
zeroentry simd_coprocessor_error do_simd_coprocessor_error
(6) 示例:制造一个异常,并在设置断点时检查处理程序是否捕获到它:将断点设置为 "`zeroentry invalid_op do_invalid_op`" 并调用 `BUG()`,它会通过 ud2 指令生成“无效操作码”故障。
#define BUG() \
do { \
asm volatile("ud2"); \
unreachable(); \
} while (0)
<调用 BUG()>
您在内核测试代码中添加 `BUG()` 宏以制造异常。(在此示例中,我将其添加到 keyboard.c 中,以通过特殊的按键输入序列制造异常。
<在 Invalid_op 断点处停止>
您将断点设置为无效操作码的异常处理程序或异常处理程序的入口。然后您可以看到并调试此异常的来源。
5. 结论
有些异常是系统硬件和软件的严重错误,因此了解这些异常的类型、原因和发生位置非常重要。通过使用英特尔® JTAG 调试器,您可以轻松检查并进一步调查这些问题。因为英特尔® JTAG 调试器提供了强大的功能,例如轻松访问汇编代码和源代码,以及检查调用堆栈和寄存器。