基于GCC的嵌入式程序插装技术

发布者:化羽2015最新更新时间:2012-03-29 来源: 单片机与嵌入式系统应用 关键字:GCC  ARM  嵌入式程序 手机看文章 扫描二维码
随时随地手机看文章

引 言
   程序插装(Program Instrumentation)概念最先是由J.G.Huang教授提出,是借助往被测程序中插入操作(称为“探针”),以便获取程序的控制流和数据流信息,从而实现测试目的的方法。在软件动态测试中,程序插装是一种基本的测试手段,应用广泛,是覆盖率测试、软件故障注入和动态性能分析的基础技术。
    GCC(GNU Compiler Collection)是一个高度优化,高度可移植,广泛使用的编译系统。它能处理多种语言,包括C/C++、Fortran、Java和Pascal等多种语言前端,而且后端支持几乎所有的处理器结构。GCC作为源码开放的软件,人们可以自由修改和使用;加入插装模块后,在GCC所支持的语言中都可插入相应的测试代码(这里只介绍C语言的插装模块)。本文将详细叙述如何修改GCC,使其在编译每个C函数时,分别将各个形式参数连同该函数名传递给一个指定函数。该指定函数的返回值赋予原来的形式参数,从而可以人为控制被插装函数的每个参数实际值,进而完成各种规则下的测试。

1 GCC编译流程分析
    编译器的工作是将源代码(通常使用高级语言编写)翻译成目标代码(通常是低级的目标代码或者机器语言)。在现代编译器的实现中,这个工作一般是分为两个阶段来实现的:
    第一阶段,编译器的前端接收输入的源代码,经过词法、语法和语义分析等得到源程序的某种中间表示方式。
    第二阶段,编译器的后端将前端处理生成的中间表示方式进行一些优化,并最终生成在目标机器上可运行的代码。
    GCC编译器以一个函数为单位对经过预处理的输入源文件进行编译处理。根据GNU Bison(一个类似YACC但功能更强大的文法分析工具)生成的语法分析程序,前端完成语法、语义分析,建立语法树,并转换成中间代码。GCC内部使用了一种能对实际的体系结构做一种抽象的,与硬件平台无关的语言,这个中间语言就是RTL(Register Ttansfer Language)。通过修改源程序的RTL,可以改变、删除源程序,包括插入所需要的代码,由GCC后端处理并最终输出对应硬件平台的汇编码,源程序无需手工修改便可实现插装功能。
    GCC的入口点main函数在文件main.c中。此函数非常简单,只有一条直接调用toplev_main函数的语句。toplev_main函数是在 toplev.c文件中定义的,以下我们只关心与编译有关的源码,其他的暂时忽略。toplev_main中最重要的是调用了do_complile函数,这个函数从名字看就是做编译工作的;而在此之后,toplev_main函数就返回了。dD_compile函数也是在tokv.c中定义的,其中真正进行编译工作的是调用compilte_file函数。compik_file函数最终调用了一个钩子函数来分析(parse)整个输入文件:
    (*lang_hooks.parse_file)(set_yydebug);
    这里的lang_hooks是一个全局变量,不同语言的前端对此赋以不同的值。对C语言来说,这条语句相当于调用了c-opts.c中的 c_common_parse_file函数。c_com-mon_parse_file中调用了c-parse.c中的c_parse_file函数;在此函数中又调用了同文件中的yyparse函数,该函数负责解析C语言源文件,并转化为特殊的语法树结构。该函数是GNU bison将YACC转变为C语言而自动生成的,所以这段代码阅读起来比较困难,但我们并不关心语法分析的细节。在完成函数体的分析后,利用已经建立的 tree结构生成RTL,优化后最终输出汇编码;自此C函数的编译就算结束了,这些是由yyparse调用finish_function函数完成的。 finish_function函数中最重要的函数是tree_rest_of_compilation(定义在tree_optimize.c中),它是真正实现上述功能的函数。为了说明它所做的具体事情,我们将该函数做了删减,保留了关键的地方。


    将函数各个部分展开成RTL形式后,调用函数rest_of_compilation将RTL输出为汇编码。至此,得到了一张清晰的GCC编译时的函数调用路线,如表1所列。[page]

2 基于GCC的程序插装技术
   根据插装测试的要求,需要在函数开始时为每个参数调用钩子函数,并用钩子函数的返回值更新参数的值;同时,将被插装函数的名称压入函数本地栈内,作为该函数的一个匿名本地变量,只用于传递给钩子函数。从上面列出的 tree_rest_of_compilation函数源码得知,负责建立被编译函数参数和返回值的函数是expand_function_start,定义是在文件function.c中。expand_function_start中处理函数参数和返回值的函数是assign_parms,这是需要特别关注的函数。以下是该函数简化的伪码:


    斜体加粗的部分是增加的代码。在for循环前,获得当前编译的函数名(见源码中①位置);但暂时不能输出到函数的RTL链中,因为本地栈要在所有参数传递完毕才完全建立起来。在for循环体结束前,记录下函数参数的一份拷贝(见②),最后调用。insert_function_name_local函数,将当前函数名插入本地栈,并且修正栈指针(见③)。经过以上修改,得到了插装所需的所有信息,包括函数参数和函数名称的RTX表示。GCC将函数编译后生成的RTX表示以链表形式组织,最后一次性把这个RTX链表输出为后端平台的汇编码。完成这项工作的是rest_of_compilation函数,所以在调用rest_of_complilation函数前插入我们的RTX,最终完成插装,由函数inject_rtl负责完成。下面是 inject_rtl的主要代码:[page]

3 APCS与程序插装实现
   编译器必须以一套统一的方法编译函数的定义和调用过程,才能确保不同语言编写的函数能相互调用。规定这些细节的便叫作“函数调用规范(Procedure Call Stand-ard)”。ARM体系结构定义了自己的函数调用规范——ARM函数调用标准(ARM Procedure Call Standard,APCS)。虽然APCS不是强制性的,但实现APCS并不困难,而且可获得统一的二进制兼容的好处,所以大部分的编译器都实现了 APCS,其中包括GCC。
    APCS中函数传递参数的定义如下:
    ◇前4个整数实参(或者更少)被装载到r0~r3。前4个整数实参(或者更少)被装载到r0~r3。
    ◇前4个浮点实参(或者更少)被装载到f0~f3。
    ◇如果参数为双字(8字节),就必须从偶数寄存器开始放置。
    ◇如果一个参数不能完全放入寄存器中,则超过的那部分拷贝到栈中。
    其他任何实参(如果有的话)存储在内存中,用进入函数时紧接在sp值上面的字来指向。换句话说,其余的参数被压入栈顶。所以,要想简单,最好定义接受4个或更少的整数参数的函数。
    本文所述的插入函数只有两个整型形参,所以调用时只需将两个实参分别传入ro和rl。GCC提供emit_li-brary_call函数用来生成函数调用的RTL码,GCC将按照APCS产生正确的函数调用汇编码。函数定义在calls.c中,原型为:


    插入所需函数后,需要将返回值赋值给对应的被插装函数的形参。以下是插入函数insert_parms_test_function的完整代码:

[page]
4 实 例
    为便于检查插装效果,用经过修改的GCC编译一段简单的C语言程序。该程序为一个独立函数foo,接受两个整数类型的参数。具体代码如下:

   

    从GCC输出的汇编码可以看到,foo函数的两个参数都经过钩子函数pt_hook_partns的处理更新;在pt_hook_parms函数内,可以根据测试算法返回不同的边界值,从而达到测试的目的。依照此方法,一个实际程序经过插装后,在ARM模拟器上顺利运行,并取得预期的测试效果。

结语
    本文详细地论述了修改GCC增加插装功能的实现方法。按照这样的思路,成功地实现了基于ARM7芯片的嵌入式系统的动态参数边界测试,达到了预期的效果。本文所述的插装函数比较简单,没有区分参数的类型,所有参数均按照一个字大小来处理;下一步的工作是细分参数不同类型,插装不同的处理函数。作为一种通用的插装方法,在此摹础上.通过识别不同的插装点和插装不同的函数,可以实现函数调用栈检查,程序覆盖率测试,获取函数实际执行时间等需要插装技术作为基础的功能。

关键字:GCC  ARM  嵌入式程序 引用地址:基于GCC的嵌入式程序插装技术

上一篇:调节多核处理器硬件适应软件设计方法
下一篇:基于PowerPC440GP型微控制器的嵌入式系统设计

推荐阅读最新更新时间:2024-03-16 12:56

ARM应用系统开发详解 第2章 ARM微处理器的编程模型
本章简介ARM微处理器编程模型的一些基本概念,包括工作状态切换、数据的存储格式、处理器异常等,通过对本章的阅读,希望读者能了解ARM微处理器的基本工作原理和一些与程序设计相关的基本技术细节,为以后的程序设计打下基础。 本章的主要内容: - ARM微处理器的工作状态 - ARM体系结构的存储器格式 - ARM微处理器的工作模式 - ARM体系结构的寄存器组织 - ARM微处理器的异常状态 在开始本章之前,首先对字(Word)、半字(Half-Word)、字节(Byte)的概念作一个说明: 字(Word):在ARM体系结构中,字的长度为32位,而在8位/16位处理器体系结构中,字的长度一般为16位,请读者在阅
[单片机]
<font color='red'>ARM</font>应用系统开发详解 第2章 <font color='red'>ARM</font>微处理器的编程模型
keil(MDK-ARM)的调试使用
现在软件的模拟功能都是非常强大,但是有时候会用不好。 原文地址: 那就看这里吧:http://www.cnblogs.com/strongerHuang/p/5596355.html 1.编译+调试 打开软件工程 - 编译 - 调试 这里的编译建议使用Build Target(第2个按钮)编译工程(如下图动画),也就是使用快捷键F7。Translate(第1个按钮)是编译当前活动文件。Rebuild all Target files(第3个按钮)是重新编译所有目标文件。 在线调试分类:软件在线调试和硬件在线调试;由于现在硬件成本比较便宜,一般我们都使用硬件在线调试,也就是软件直接下载到芯片,我们查看运行状态。 2.复位+全
[单片机]
keil(MDK-<font color='red'>ARM</font>)的调试使用
S3C2440-裸机篇-02 | 安装和使用arm-linux-gcc交叉编译工具链
1.为什么需要交叉编译工具 宿主机运行的是标准Linux操作系统,编译出的程序却需要在目标机的Linux上跑,这就叫交叉编译,编译器叫做交叉编译器。 之前我们已经使用过gcc编译Linux本地主机的程序(Linux C语言编程(上篇) | gcc的使用),而我们现在需要的这个编译器的目标系统是ARM,不运行操作系统,仅运行裸机程序,需要在Linux主机上编译出可以运行在S3C2440@ARM920T芯片上跑的程序,所以不能使用这个编译器,需要使用arm-linux-gcc交叉编译器。 2.arm-linux-gcc的安装 arm-linux-gcc是ARM官方基于Linux平台的arm编译器,其特点有: 开源免费 支持
[单片机]
S3C2440-裸机篇-02 | 安装和使用<font color='red'>arm</font>-linux-<font color='red'>gcc</font>交叉编译工具链
基于ARM的LCD触摸屏系统设计
引言 随着嵌入式系统技术的飞速发展,工业设备产品也越来越现代化,普遍要求可视化操作。LCD触摸屏低耗能.散热小,成本低,纤薄轻巧,外形尺寸小,安装容易。使用LCD触摸屏作为工业设备的输入输出设备既能达到可视化的要求,方便现场操作,又能降低产品的成本。而在产品的整体设计过程中,人机交互界面的设计往往占据着很大一部分工作,这样,不但极大地增加了产品的开发成本瓶且延长了产品的上市周期。本文设计的基于S3C44BOX的人机交互界面是一种可定制、简单易用、性能优良的通用型人机交互界面,能很好地解决上述问题。 1 系统结构 系统主要包括三个部分,分别为PC机、S3C4480X微处理器和LCD触摸屏模块。系统结构框图如图1所示
[家用电子]
基于<font color='red'>ARM</font>的LCD触摸屏系统设计
arm-linux,arm-elf-交叉编译环境下载地址
最常用的编译版本是arm-linux-gcc-3.4.1 和 arm-linux-3.3.2 的,现在的嵌入式开发基本上用的是这些,3.4.1的用于编译2.6的内核,而3.3.2的常用于编译busybox,和bootloader(u- boot),编译的版本配合不好的话就会出错,所以要选择好编译版本,如果这个版本不行的话,可以试试其他的版本,在uclinux上用的多的就是 arm-elf-tools-20030314 http://www.handhelds.org/download/projects/toolchain/arm-linux-gcc-3.4.1.tar.bz2 http://www.handhelds.org/do
[单片机]
HI3531ARM调试printf的实现
void UART_Putc(char c) { if (c == 'n') *(unsigned int *)(UART0_ADDR + 0X00) = 'r'; delay_x(0x800); *(unsigned int *)(UART0_ADDR + 0X00) = c; } unsigned int val_i=0; void UART_Print(const char *str,...) { va_list unnamed_p; char *sval; unsigned int tmp=0; va_start( unnamed_p, str); whil
[单片机]
ARM公司发布了RealView ICE 3.3版本
英国 ARM 公司发布了 RealView ® ICE 3.3版本,该版本可支持对CortexTM-A9 处理器 的调试。该版本同时也支持TI OMAP3和TI DaVinci 平台 ,以及 ARM 1176JZF-S ® 平台 ,同时还支持Freescale i.MX31应用 处理器 ,进一步增强了 RealView 调试工具的优势。   新功能    RealView ICE 3.3版本固件具有许多新的功能,包括:   ·对 ARM Cortex-A9 处理器 的全面调试支持   ·支持TI OMAP 34xx、TI OMAP 35xx、TI OMAP 1710、TI DaVinci、Freescale i.MX31
[嵌入式]
基于ARM与MEMS器件的微惯性测量装置设计
   摘要 开发一种生物运动微惯性测量装置,以基于ARM7的LPC2129为核心处理单元,采用MEMS陀螺和MEMS加速度计为测量传感器。该装置实现了对SPC-III机器鱼尾鳍拍动参数的精确测量,为活体鱼尾鳍拍动参数测量实验打下了基础。    关键词 微惯性测量 LPC2129 MEMS器件 尾鳍拍动   在仿生推进机理的研究中,精确测量鱼类尾鳍拍动参数对于鱼类仿生推进机理研究及工程应用具有重要的意义;然而,目前研究者大多采用分析高速摄像机拍摄的图像获得参数的观测方法。这种方法受到环境与设备的限制,结果精确度较差。本设计是一种基于MEMS器件的生物运动微惯性测量装置。利用该装置实现了对SPC-III机器鱼尾鳍拍动参数的精确测量
[工业控制]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved