QEMU 调试 TF-A开发环境建立(使用 QEMU 调试 TF-A (Trusted Firmware-A) 之二)


前言

QEMU 是一款开源的模拟器,可以模拟多种不同的处理器和硬件架构,包括 ARMv7ARMv8 等。在 TF-A 开发过程中,使用 QEMU 可以将 ARMv8 软件在 x86 平台上运行,从而实现快速、灵活和低成本的开发和调试。
通过使用 QEMU 调试 TF-A,开发者可以运行TF-A固件的ELF文件,可以停止和启动运行,可以单步运行,还可以在运行时检查和修改变量和寄存器状态。这种调试方式,比使用硬件调试器便宜许多,也更加方便一些。
我们计划使用QEMU模拟Cortex-A57处理器来运行和调试TF-A。由于TF-A本身就是一个引导程序,在调试时我们只需加载TF-A二进制文件,并不需要加载任何其他软件或固件。
本文介绍如何建立一个开发环境,用来使用QEMU模拟Cortex-A57处理器运行和调试TF-A。


1 TF-A (Trusted Firmware-A)概述

TF-A(Trusted Firmware-A)是一个用于 ARMv8-A 架构(包括 AArch64 和 AArch32)的开源固件项目。TF-A 提供了一个安全和可信赖的基础,用于开发功能强大的 ARMv8-A 体系结构的系统。
TF-A 的主要功能包括:
提供了一个安全的引导过程,确保系统启动时加载的固件和操作系统是可信的。
安全监视器:为操作系统提供了一种运行在更高权限级别的软件环境,可以用于处理安全相关的任务,如访问保护硬件资源、安全服务等。
异常处理:在发生异常(如系统错误、中断等)时,TF-A 可以提供适当的处理程序。
Power State Coordination Interface (PSCI):PSCI 是 ARM 推出的一种用于多核处理器的功耗管理规范,TF-A 提供了 PSCI 的实现,以实现低功耗和休眠状态。
TF-A 通常与其他固件、引导加载程序和操作系统组件一起使用,以实现一个完整的系统引导和运行过程。

2 Cortex-A57

ARM Cortex-A57 是 ARM Holdings 设计的一款高性能、能效出色的 64 位处理器核心,基于 ARMv8-A 架构。Cortex-A57 作为 ARM 大小核心(big.LITTLE)配置的大核(big core)而设计,与能效更高的 Cortex-A53 小核(LITTLE core)配合使用,实现性能与功耗的平衡。Cortex-A57 处理器在高端移动设备、网络基础设施、嵌入式系统以及其他高性能计算领域广泛应用。
Cortex-A57 的主要特点如下:

  • 高性能:Cortex-A57 提供了比前代 Cortex-A15 更高的性能,性能提升约 25%-50%。它采用了先进的流水线和指令调度策略,以提高执行效率。
  • 节能:Cortex-A57 设计上更注重能效,相较于 Cortex-A15 在同等性能下功耗更低。这得益于更高的指令级并行性(ILP)和更高的时钟频率,以及更高效的电源管理技术。
  • ARMv8-A 架构:Cortex-A57 基于 ARMv8-A 架构,支持 64 位(AArch64)和 32 位(AArch32)指令集。ARMv8-A 还引入了新的寄存器、指令和异常处理模型,提高了性能和安全性。
  • 大小核心(big.LITTLE):Cortex-A57 可以与 Cortex-A53(节能小核)组合形成大大小小核心配置。大核用于处理高性能任务,而小核用于处理低功耗任务。这种组合实现了在不同场景下的性能与功耗平衡。
  • 高度可扩展:Cortex-A57 支持多核(最多 4 个核心)配置,允许在更高性能要求的场景中部署多核处理器。它还支持高速缓存一致性、硬件虚拟化扩展和高性能浮点运算等特性。
  • 安全性:Cortex-A57 支持 ARM TrustZone 技术,实现安全和非安全世界的隔离,可用于实现各种安全应用,如移动支付、数字版权保护等。

3 ARM FVP基板

ARM FVPFixed Virtual Platform)基板是一种仿真和测试ARM处理器的开发板,它可以在一个虚拟的环境中运行ARM处理器架构的软件。 它由ARM公司提供,主要用于ARM处理器的开发和调试。
ARM FVP基板内置了多个ARM处理器核心,并提供多种不同的配置,包括不同版本的ARM处理器架构、不同的内存配置、不同的外设等。基板通过仿真器将在虚拟平台上模拟执行ARM架构的软件,并提供了一系列调试工具和性能分析工具,方便软件开发人员进行开发和调试。
使用ARM FVP基板可以大大简化ARM处理器软件的开发和测试,减少硬件依赖和测试成本,提高软件的开发效率和质量。同时,ARM FVP基板还可以用于云端虚拟化和物联网等场景,实现低成本和低风险的软件开发和测试。

QEMU-System-Arm是一款开源的虚拟机软件,可以模拟各种架构的处理器,其中包括ARM架构的处理器。而ARM FVP基板是一种硬件开发板,可以帮助开发者在硬件上进行ARM架构的软件移植和测试。
它们的关系在于,QEMU-System-Arm可以模拟ARM FVP基板上的处理器,并通过模拟运行ARM架构的操作系统和应用程序,来验证ARM FVP基板的软件设计、移植和测试。这种模拟环境可以更快速、更便捷地进行软件验证,从而提高软件开发的效率。
此外,ARM FVP基板还可以作为QEMU-System-Arm的物理板卡,用于在真实的硬件环境中验证ARM架构的软件。

4 GDB调试环境介绍

4.1 GDB简介

GDB(GNU调试器)是一个功能强大的、跨平台的源代码调试器。它支持多种编程语言(如C、C++、Go等)和许多处理器架构。GDB允许开发人员对程序执行进行深入了解,以查找并修复错误。GDB调试环境通常包括以下组件:

  • GDB调试器:这是GDB的核心组件,它与目标程序进行交互,控制程序的执行,并收集关于程序状态的信息。您需要根据目标处理器架构(例如ARM、x86、MIPS等)安装合适的GDB版本。
  • 目标程序:您希望调试的程序。在我们之前的例子中,这是TF-A(Trusted Firmware-A)。确保目标程序是使用调试信息编译的,这样GDB才能获取有关源代码和符号的详细信息。
  • 调试服务器:在某些情况下,我们需要一个调试服务器与目标程序进行通信。例如,在远程调试或使用QEMU进行硬件仿真。当前我们计划让QEMU充当调试服务器,使用GDB连接到它以控制目标程序。
  • 源代码和符号:为了方便调试,我们需要访问目标程序的源代码和符号。这些信息包含在目标程序的ELF文件中。在我们当前的例子中,就是TF-A源代码经过编译生成的bl31.elf文件。
  • 终端/控制台:用于与GDB进行交互的界面。我们可以使用命令行终端中运行GDB,或者使用支持GDB的集成开发环境(IDE)。

4.2 设置GDB调试环境

要设置GDB调试环境,请按照以下步骤操作:

  • 安装GDB:根据目标处理器架构安装合适的GDB版本。在许多Linux发行版中,您可以使用包管理器来安装GDB。
sudo apt-get update
sudo apt-get install gdb-multiarch
  • 编译目标程序:确保目标程序是使用调试信息编译的。编译时,使用-g选项告诉编译器生成带有调试符号的ELF文件
  • 运行目标程序:在适当的环境中运行目标程序,以便可以使用GDB对其进行调试。在我们当前的例子中,意味着启动QEMU并加载TF-A。
  • 启动GDB并连接到目标程序:在终端中启动GDB,并连接到目标程序。这可能涉及连接到调试服务器(例如,在QEMU示例中)或直接连接到运行在本地的程序。

4.3 使用GDB

现在,您的GDB调试环境已准备就绪。您可以使用GDB的各种功能,例如,设置断点、单步执行、检查和修改变量、寄存器和内存等,以调试目标程序。以下是一些常用的GDB调试命令:
(1)设置断点:使用break命令在特定的源代码行或函数上设置断点。

break main.c:42
break my_function

(2)控制执行:使用以下命令控制目标程序的执行:

  • run:启动程序执行。
  • continue:从当前断点处继续执行。
  • next:执行下一行源代码(不进入函数)。
  • step:执行下一行源代码(进入函数)。
  • finish:继续执行,直到当前函数返回。

(3)检查变量和寄存器:使用print命令查看变量和寄存器的值。

print my_variable
print $rax

(4)修改变量和寄存器:使用set命令修改变量和寄存器的值。

set my_variable = 42
set $rax = 0xdeadbeef

(5)检查内存:使用x命令检查内存。例如,要检查以16进制表示的地址0x1000处的4个字(32位),可以执行:

x/4x 0x1000

(6)修改内存:使用set命令修改内存。例如,要将以16进制表示的地址0x1000处的一个字设置为0xdeadbeef,可以执行:

set *(unsigned int *)0x1000 = 0xdeadbeef

(7)添加监视点:使用watch命令在特定变量或内存地址上设置监视点。当变量或内存地址的值发生更改时,程序将停止执行。例如:

watch my_variable

(8)查看堆栈跟踪:使用backtrace命令查看当前的堆栈跟踪。

backtrace

(9)切换堆栈帧:使用frame命令切换到不同的堆栈帧。例如:

frame 5

(10)退出GDB:使用quit命令退出GDB。

通过熟练掌握这些命令,您可以更有效地使用GDB调试环境找到并解决程序中的问题。

5、配置 QEMU 调试 TF-A开发环境

5.1 安装交叉工具链

QEMU是一个通用的开源处理器模拟器和虚拟机,可以用于在本地机器上模拟其他体系结构。要配置QEMU以使用交叉工具链,Ubuntu 20.04虚拟机上安装ARM交叉工具链,按照以下步骤操作:

sudo apt-get update
sudo apt-get install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu

安装完gcc-aarch64-linux-gnu工具链之后,可以使用以下命令来查找其位置:

dpkg -L gcc-aarch64-linux-gnu

会显示已安装软件包的文件列表,其中应包括工具链所在的文件路径。在大多数情况下,它应该位于/usr/bin目录下,并使用类似于aarch64-linux-gnu-gcc的名称。

5.2 安装其他必需的依赖项

TF-A的编译需要安装device-tree-compiler和python3-pyelftools。

sudo apt-get install device-tree-compiler python3-pyelftools

5.3 克隆TF-A源代码

从GitHub上克隆TF-A源代码仓库:

git clone https://github.com/ARM-software/arm-trusted-firmware.git
cd arm-trusted-firmware

5.4 编译TF-A(Trusted Firmware-A)

在源代码目录下,执行以下命令以针对Cortex-A53编译TF-A:

make CROSS_COMPILE=aarch64-linux-gnu- PLAT=<platform> TARGET=<target>

其中是目标硬件平台,例如fvp(Fixed Virtual Platform),是编译目标,例如all。

以下是一个示例命令,用于编译针对ARM FVP基板的所有TF-A组件:

make CROSS_COMPILE=aarch64-linux-gnu- PLAT=fvp CPU=cortex-a57 TARGET=all DEBUG=1

编译成功后,可以在build目录下找到相应的二进制文件。

注意:具体的平台和目标可能因硬件而异,请根据您的需求选择合适的选项。可以在TF-A文档中找到更多关于编译选项的信息:
TF-A User Guide
TF-A Build System

6、仿真调试过程

下面是QEMU仿真Armv8-A FVP运行TF-A并使用gdb-multiarch调试过程说明。

(1)使用QEMU仿真Armv8-A FVP并运行TF-A,同时启用GDB调试服务器。在这个例子中,我们使用-s选项启用GDB服务器,监听端口1234,您可以根据需要更改端口号:

qemu-system-aarch64 -M virt -cpu cortex-a57 -s -S -kernel path/to/bl31.elf

请将path/to/bl31.elf替换为实际的TF-A BL31 ELF文件路径。-S选项会让QEMU在启动时暂停执行,以便您可以在GDB中设置断点。-s选项告诉QEMU启用默认GDB服务器。QEMU默认将在IP=127.0.0.1,端口1234上监听GDB客户端的连接。

如果希望设置特定的IP地址和端口(例如,IP地址为192.168.5.2,端口为1024),可以使用-gdb tcp::port选项,指令改为:

qemu-system-aarch64 -M virt -cpu cortex-a57 -S -kernel path/to/bl31.elf -gdb tcp:192.168.5.2:1024

这里我们用-gdb tcp:192.168.5.2:1024选项替换了-s选项。这将启动一个GDB服务器,监听在IP地址192.168.5.2和端口1024上。

(2)在另一个终端中,启动gdb-multiarch并加载TF-A BL31的符号:

gdb-multiarch -ex "file path/to/bl31.elf"

同样,请将path/to/bl31.elf替换为实际的TF-A BL31 ELF文件路径。

(3)连接到QEMU GDB服务器:

(gdb) target remote :1234

如果按照刚才(1)中设置了IP和端口,则指令改为:

(gdb) target remote 192.168.5.2:1024

(4)在bl31_entrypoint.S中设置断点。例如,假设bl31_entrypoint.S文件中有一个名为_bl31_entrypoint的标签,您可以在此处设置断点:

(gdb) break bl31_entrypoint

(5)继续执行程序:

(gdb) continue

现在,程序将在_bl31_entrypoint处暂停执行。您可以使用step(或si)命令单步执行汇编指令,并使用其他GDB命令(如info registers查看寄存器状态,x命令检查内存等)进行调试。

在实际调试过程中,可能需要根据您的环境和目标硬件进行一些调整。但是,这个示例提供了一个基本的框架,说明了如何使用QEMU和GDB调试TF-A的入口点。

7、实际调试过程举例

下面用实际调试的例子,再次说明仿真调试过程

第一步:启动GDB调试服务器

qemu-system-aarch64 -M virt -cpu cortex-a57 -s -S -kernel /mnt/hgfs/ccc/arm-trusted-firmware/build/fvp/debug/bl1/bl1.elf

qemu-system-aarch64 命令用于启动 QEMU 虚拟机,它是一个流行的开源硬件模拟器和虚拟化工具。在这个特定的命令中,QEMU 用于模拟一个基于 ARMv8 架构的 64 位系统(AArch64),具体来说是使用 Cortex-A57 处理器的虚拟硬件。

以下是命令中每个参数的简要说明:

  • M virt:指定虚拟硬件模型为 “virt”,即 QEMU 的通用 ARM 虚拟机,适用于大多数场景。
  • cpu cortex-a57:设置虚拟 CPU 为 ARM Cortex-A57 处理器。
  • s:表示在启动 QEMU 时启用 GDB 调试服务器。这允许您通过 GDB 连接到 QEMU 实例并进行调试。
  • S:告诉 QEMU 在启动时暂停执行,等待 GDB 连接。一旦 GDB 连接并发出“continue”命令,模拟执行将继续。
  • kernel /mnt/hgfs/ccc/arm-trusted-firmware/build/fvp/debug/bl1/bl1.elf:指定要加载并执行的内核映像文件(在这种情况下为 BL1 可执行文件)。

通过这个命令,可以在 QEMU 虚拟环境中运行和调试 ARM Trusted Firmware(可信固件)的 BL1 部分。可以通过 GDB 连接到 QEMU 实例以设置断点、单步执行代码、检查寄存器和内存等,这对于开发和调试固件代码非常有用。

QEMU 启动成功后,会打开一个用于与虚拟机进行交互的终端界面,该终端使用主机的标准输入/输出来与用户进行交互,如下图所示。
在这里插入图片描述
终端提供一系列命令,用于控制和查询虚拟机的状态,可以输入help,获得可用指令的详细信息。

第二步:启动gdb-multiarch
在另一个终端中,启动gdb-multiarch并加载TF-A BL1的符号:

gdb-multiarch -ex "file /mnt/hgfs/ccc/arm-trusted-firmware/build/fvp/debug/bl1/bl1.elf"

GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
Reading symbols from /mnt/hgfs/ccc/arm-trusted-firmware/build/fvp/debug/bl1/bl1.elf...done.
(gdb) 

第三步:加断点(这一步可选)

(gdb) break bl1_entrypoint

Breakpoint 1 at 0x0: file bl1/aarch64/bl1_entrypoint.S, line 86.
(gdb) 

第四步:连接到QEMU GDB服务器

(gdb) target remote :1234

Remote debugging using :1234
bl1_entrypoint () at bl1/aarch64/bl1_entrypoint.S:86
86		adrp	x20, bl2_ep_info
(gdb) 

至此,使用 QEMU 调试 TF-A开发环境建立完成。
文章中所有的指令,都在本作者自己的设备上测试通过。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值