尽管每天都在调用linux的elf文件做各种事,但却很少去了解他,最近尝试在orangepi上编译个elf到android手机上运行,因为两个CPU都是ARMv8的.结果运行失败了.遂查找原因.结果挖出这玩意...
以下内容大部分为摘抄整理:
关于ABI,EABI,OABI:
ABI(application binary interface)
应用程序二进制接口
一般应用程序是要分各种CPU架构的,ABI用于对接.
而ABI的不同则是linux内核和glibc的升级导致的规范变化导致的。不同的ABI程序和库在不同的环境下很高概率是不能运行的,除非是低版本最原始的ABI在现代系统上跑一般都可以向下兼容。而这种不兼容主要发生在C++身上,因为C++近几年的特性改变速度相对较快,管理困难。X86上常见的elf ABI有:
OS/ABI: UNIX - Linux
OS/ABI: UNIX - System V
OS/ABI: UNIX - GNU
其中GNU和Linux两种是相同的,只是使用不同版本的readelf会现实不同的结果。而system v则是最古老的,也是兼容性最好的。有的老一些的系统上只识别system v的ABI。但是system v ABI for x86_64却是比linux还要先进的ABI。因为这个ABI把大部分的参数转由寄存器传递,而不是由栈传递,对栈的使用减少就增加了以往的缓存溢出的难度。还有x32上的return to libc等攻击的手法也得变通,难度提高。
OABI 的O表示Old,旧的ABI
EABI的E表示Embedded 嵌入式,是描述可连接目标代码,库目标代码,可执行文件映像,如何连接,执行和调试,以及目标代码生成过程,和c, c++语言接口的规范,是编译连接工具的基础规范,也是研究它们工作原理的基础,可惜arm的EABI迄今为止没有完全订好。
EABI的好处 / 为何要用EABI
支持软件浮点和硬件实现浮点功能混用
系统调用的效率更高
后今后的工具更兼容
软件浮点的情况下,EABI的软件浮点的效率要比OABI高很多。
OABI和EABI的区别
两种ABI在如下方面有区别:
调用规则(包括参数如何传递及如何获得返回值)
系统调用的数目以及应用程序应该如何去做系统调用
目标文件的二进制格式,程序库等
结构体中的 填充(padding/packing)和对齐。
还有
OABI:
* ABI flags passed to binutils: -mabi=apcs-gnu -mfpu=fpa
* gcc -dumpmachine: arm-unknown-linux
* objdump -x for compiled binary:
private flags = 2: [APCS-32] [FPA float format] [has entry point]
* "file" on compiled Debian binary:
ELF 32-bit LSB executable, ARM, version 1 (ARM), for GNU/Linux 2.2.0, dynamically linked (uses shared libs), for GNU/Linux 2.2.0, stripped
* "readelf -h | grep Flags""
Flags: 0x0
EABI:
* ABI flags passed by gcc to binutils: -mabi=aapcs-linux -mfloat-abi=soft -meabi=4
* gcc -dumpmachine: arm-unknown-linux-gnueabi
* objdump -x for compiled binary:
private flags = 4000002: [Version4 EABI] [has entry point]
* "file" on compiled binary (under Debian):
ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.4.17, dynamically linked (uses shared libs), for GNU/Linux 2.4.17, stripped
* "readelf -h | grep Flags""
Flags: 0x4000002, has entry point, Version4 EABI