EABI(Application Binary Interface)或EABI(Extend ABI)通常是处理器体系结构的一部分,它与平台是紧密相连的。我们可以把ABI理解为一套规则,这套规则一般包括定义了以下内容:
1) 应用程序如何发出系统调用来trap到内核态。
2) 如何使用机器的寄存器。比如,RISC处理器的ABI就要规定用那个通用寄存器来作 stackpointer和frame pointer。
3) 规定如何进行procedure call。
2)和3)是最重要的。而且特定于那个平台的编译器和链接器实现都要遵循这些约定。
一、EABI
Embedded application binary interface, 即嵌入式应用二进制接口,是描述可连接目标代码,库目标代码,可执行文件影像,如何连接,执行和调试,以及目标代码生成过程,和c, c++语言接口的规范,是编译连接工具的基础规范,也是研究它们工作原理的基础,可惜arm的EABI迄今为止没有完全订好。作为EABI的组成部分有过程调用规范,可执行文件格式规范,c/c++ ABI规范和调试格式规范。
二、ATPCS
ATPCS即arm-thumb procedure call standard,PCS即procedure call standard.
PCS规定了应用程序的函数可以如何分开地写,分开地编译,最后将它们连接在一起,所以它实际上定义了一套有关过程(函数)调用者与被调用者之间的协议。PCS规范强制实现如下约定:调用函数如何传参(即压栈方法,以何种方式存放参数),被调用函数如何获取参数,以何种方式传递函数返回值。PCS 规范的制订是一系列指标的“tradeoff”(因为很大程度上涉及系统的一些性能),如会涉及生成代码的大小,调试功能的支持,函数调用上下文处理速度以及内存消耗。当然,通过编译器的支持可以让生成的代码有不同的特性,如gcc编译选项可以支持或不支持framepointer来支持深入调试功能或提高程序运行性能。
PCS是体系结构密切相关的,直接涉及编译器如何使用处理器提供的应用寄存器,如编译器使用什么寄存器作为栈指针,利用哪些寄存器作直接传参等。值得注意的是,没有谁规定说ATPCS是必须这样而不是那样的,它是应用相关的,任何一个操作系统和应用可以处于它自身的考虑定义自己的PCS,当然,如果那样,也必须有自己的编译器,而实际上,在一个处理器设计时,都会有某种假设,所以PCS某种程度上应该是一样的。
ATPCS是基于arm指令集和thumb指令集过程调用的规范。
三、BFD
Binary format descriptor, 即二进制文件格式描述符,它是连接工具(ld)和二进制文件操作工具(bin-util)实现对于目标文件操作的标准接口,ld和bin-util通过调用实现BFD接口的库libbfd
来实现它们的目标文件操作功能。
BFD的结构
BFD整体上简单地可分为前端和后端(就象gcc一样),这样做的目的主要出于可移植性的考虑,前端向应用层提供统一的调用接口,是目标文件格式无关的,后端实现目标格式相关的部分,前端通过调用后端的相关函数实现真正的具体目标文件格式操作功能。所以如果要支持一种新嵌入式目标文件格式(就象 uclinux支持的简化类coff文件格式BFLT)就只要修改BFD的后端就行了。
BFD的结构
前端的结构和一些主要的功能是:段操作,符号表处理,重定位管理,库操作,及其为了方便用的函数。后端涉及具体的文件格式操作方法的支持,典型的是a.out,coff,和elf.
BFD工作过程简述
每当bin-util工具如(objdump)打开一个目标文件时,工具通过调用BFD库里相关目标文件格式的信息判定该文件的二进制格式。然后抽取库里相关例程的信息建立对应的二进制格式操作描述符表(实际上诗歌函数指针表,有点象COM的VTABLE),利用这些指针,工具读取分析和操作该目标文件。我们利用objcopy(操作),objdump(读取、分析),readelf(读取),就是全仰仗BFD的功能。我刚才讲了现成目标文件的工作过程,那么目标文件的形成过程又是怎样的呢?如上所述,编译器/连接器在处理目标文件符号表等时先会调用前端函数(前端是统一和抽象的过程),然后通过后端处理具体文件格式的操作函数将符号表等相关信息写到输出文件, 这些任务的就是通过调用内存中的BFD描述符的函数实现的。
如果觉得《ABI/EABI简介》对你有帮助,请点赞、收藏,并留下你的观点哦!