当前位置:首页 > 智能硬件 > 智能硬件
[导读]c编译器在c程序编写过程中发挥着不可替代的作用,对于c编译器,相关人员应当给予足够重视。前文中,小编曾介绍过基于gcc c编译器的程序插装技术,但这并非c编译器插装技术的全面貌。本文,为基于gcc c编译器程序插装技术下篇,一起继续来了解这项技术吧。

c编译器在c程序编写过程中发挥着不可替代的作用,对于c编译器,相关人员应当给予足够重视。前文中,小编曾介绍过基于gcc c编译器的程序插装技术,但这并非c编译器插装技术的全面貌。本文,为基于gcc c编译器程序插装技术下篇,一起继续来了解这项技术吧。

一、基于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的主要代码:

二、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的完整代码:

三、实例

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

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

四、结语

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

以上便是小编此次为大家带来的所有内容,希望大家喜欢,have a nice day!

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

如果你是在Linux下做开发,你就必须知道Makefile是什么东西,如果不知道那就可以说你不是一个合格的Linux开发工程师,因为Makefile是必备的一项技能。那么,Makefile到底有什么作用呢?首先,gcc大...

关键字: Linux Makefile gcc

众所周知,LLVM的Clang C / C ++编译器比GCC提供更快的编译速度。 但是,新版本的GCC中的编译速度有所提高。

关键字: gcc Linux llvm

上篇文章中,小编对Turbo c编译器已做部分介绍。本文中,小编将对Turbo c编译器余下内容加以讲解。如果你对c编译器具有兴趣,不妨继续往下阅读哦。

关键字: c编译器 turbo 指数

为增进大家对c编译器的认识,本文将对Turbo C c编译器予以讲解。如果你对c编译器具有兴趣,不妨继续往下阅读哦。

关键字: c编译器 turbo 指数

本文中,小编将对c编译器和c编辑器的区别予以介绍。如果你对c编译器具有兴趣,不妨继续往下阅读哦。

关键字: c编译器 指数 c编辑器

最近发布的 GCC 10 编译器已对 C++20 的主要功能协程(Co-Routines)进行了初始支持,但是除非显式地开启该选项,否则并不会启用此功能。当 GCC 10 在 C++20 模式(std

关键字: gcc

许多朋友经常混淆c编译器和c编辑器,注意,c编译器的作用在于编译,而c编辑器在于编写代码。对于c编译器,小编曾带来诸多文章。但有网友提问,有没有较为推荐的c编译器。为解决大家的疑问,本文将对6款c编译器予以介绍,大家可以...

关键字: c编译器 指数 编译器

c编译器每天都在被使用,但对c编译器十分了解的人却不多,而对c编译器编译过程有所认知的朋友更是少之又少。在上篇文章中,小编对c编译器的工作过程有所讲解。本文中,为继续增进大家对c编译器的讲解,将对编译器工作过程的余下步骤...

关键字: c编译器 指数 编译器

c编译器的问世是程序界的里程碑之一,没有c编译器,c程序将无法运行。由此可见,c编译器尤为重要。为增进大家对c编译器的了解,本文将带来c编译器的通识篇,以使大家能够了解编译器的运行过程。此外,本文仅为上篇,剩余内容将在后...

关键字: c编译器 指数 编译器

对于c编译器,很多朋友均有所了解。往期文章中,小编为大家带来过诸多c编译器文章。在这篇c编译器相关文章中,小编将介绍如何基于SDCC c编译器开发微控制器。如果你对c编译器的应用同样存在兴趣,不妨继续往下阅读哦。

关键字: c编译器 sdcc 微控制器 指数
关闭
关闭