新闻中心

EEPW首页>嵌入式系统>设计应用> 解析基于ELF的嵌入式软件源码级交叉调试技术

解析基于ELF的嵌入式软件源码级交叉调试技术

作者: 时间:2012-08-10 来源:网络 收藏

三、器实现的要点

在设计器JDBG时,首先完成与目标文件无关的部分:连接目标机,查看修改目标机寄存器和内存;然后实现与目标文件有关的部分:下载目标文件到目标机,功能,包括断点控制、执行控制、变量观察等,以下重点讨论各项功能的设计与实现。

1、 下载目标文件

目标文件中包含多种类型的内容,目标程序在目标机上运行时只需要程序的二进制指令代码与相关数据,这些内容包含在文件中的可执行程序段中。下载目标文件时在宿主机上提取目标文件中的代码与数据段,根据其地址映射关系利用remote协议中写内存的功能在目标机上建立程序的远程映像。

2、 断点

断点是调试器控制程序执行的基本手段。各种机器有其特殊的断点指令(如X86的int3指令),设置断点就是将机器断点指令替换所指定程序单元中的指令,使得程序运行到断点指令处时,产生“断点异常”,用户程序不再继续执行下去,目标机向宿主机返回断点停止信号,由宿主机调试器接管对用户程序的控制。

断点分为逻辑断点与物理断点,两者是多对一的关系。逻辑断点与源代码对应,提供源级断点信息(源文件名+行号或物理地址等);物理断点与目标码对应,提供断点的目标码地址及断点处的指令内容。插入一个断点即根据逻辑断点信息确定物理断点地址,将该地址对应指令用机器断点指令替代;删除断点即恢复断点指令处预先保存的原指令,使得程序可继续执行。

检查点是一种条件断点,使程序在条件满足时停止执行。通常条件都涉及表达式的值变化,利用写内存保护来检查表达式的值是最常用的方法,但这种方法不适用于不具备MMU功能的处理器。某些处理器(如i386)提供了专门的调试控制寄存器,通过在调试控制寄存器中设置相应线性地址及中止条件(读或写)即可中止程序的运行。通过查询方式检查表达式的值也是一种可行的方法,其效率相对较低。当检查点的条件满足时,检查点的操作与普通断点类似。

对一个断点应具有基本的插入、删除、使能、使不能等基本操作功能。在设计中采用双向链表结构作为断点的数据结构,使得断点控制更加方便高效。

3、 启动程序运行

启动程序运行首先从目标文件的头中得到应用程序的入口,将目标机的PC寄存器置为该入口地址,从入口处开始执行程序指令。如果程序中没有设置任何断点或检查点,则程序一直运行到结束;如果程序中有断点,则程序运行到第一个断点处停止并返回其停止位置。

4、级单步调试

源码级单步以行为单位,一行源代码对应多条机器指令,因此一个源语句的单步执行需要多个机器指令的单步执行。最简单的实现方法就是从源语句对应目标代码的起始地址开始逐条单步执行机器指令。显然这种方法效率很低,尤其调试需要大量宿主机/目标机间的通讯,而且有的处理器自身并不提供机器单步执行指令。因此,更有效的方法是用“内部临时断点+连续执行”的方式来实现。

用机器单步执行时,每执行完一条机器指令立即读取当前PC,判断程序停止位置。调试器对程序的控制是即时交互的,当单步执行结束、跳转或进入函数调用时,调试器都会即时得知。不采用机器单步,则不具有这种即时掌握程序运行状态的便利,需要在运行前反汇编目标代码,通过分析汇编指令预测程序单步执行可能的出口位置,并在该处设上断点。可能的出口位置包括该行指令的终止地址、跳转、分枝跳转、函数调用等指令。对于跳转指令,能得到绝对地址则直接在跳转地址处设断点,不能得到跳转地址则在指令处设断点,再执行跳转指令由当前PC值确定程序停止的位置。对于函数调用指令,如果采用单步跳过(stepover)方式,则将其作为普通指令看待,直接执行调用函数;如果采用单步进入(stepinto)方式,则需在指令处设断点,再执行调用指令,以进入函数内部让用户继续跟踪程序的执行。

以单步跳出方式(stepout)执行程序时,以子程序为单位,需执行完当前子程序的所有代码,在调用该子程序的下一条语句处停止。通过反汇编当前子程序的所有指令,可得到该子程序所有可能的函数返回出口,在这些函数返回指令处设临时断点,程序运行到断点处再执行该返回指令跳出当前子程序,处理调用该子程序的语句行的后继信息,最终确定程序停止位置。

5、数据浏览

数据与指令同样是构成程序的根本。数据类型繁多,不同的类型处理起来有所不同,其基本原理是由数据名找到存放该数据的地址,再从地址中取出数据的值。关键在于找到名与地址的映射关系。这些信息可从.debug,.symtab等节中得到。全局变量一般可得到直接的地址信息,而局部变量采用堆栈方式存放在内存中,需根据从.debug中得到的该变量在堆栈中的位置信息来确定地址。采用表结构来管理变量,将每个变量的名、地址等信息登记在表中,将对数据值的操作转化为对相应地址的内存单元操作,如查看变量即为读取该变量所在内存单元的内容。

四、调试器JDBG简述

JDBG采用图形用户界面,相应的命令提供图形按钮或菜单,并提供快捷键。进入调试之前,先连接目标机,在连接时设置连接参数并保存,在以后的连接中可直接使用已保存的设置参数。当宿主机/目标机处于连接状态时,下载目标文件,启动调试器。调试器启动后,用户可在打开的源文件中设置断点,运行下载的目标程序,查看/修改寄存器、内存的内容。当运行的目标程序停止后,返回停止点源码信息,用户可以观察数据,添加新的断点或删除已设断点,控制程序的单步执行或连续执行,或退出调试状态。

linux操作系统文章专题:linux操作系统详解(linux不再难懂)

上一页 1 2 下一页

评论


相关推荐

技术专区

关闭