前言
在Linux中,通过gcc编译成的可执行文件的格式是ELF格式。通过readelf命令可以用来查看elf格式文件的信息。
ELF文件类型
ELF文件有下面三种类型:
1、可重定位文件(目标文件)
可重定位对象文件中包含适合于与其他目标文件链接来创建可执行文件或者共享目标文件的代码和数据。一般包括如汇编器汇编生成的.o文件,例如:
gcc -c test.c
得到的test.o就是目标文件,目标文件通过链接可生成可执行文件。
静态库其实也算目标文件,静态库是通过ar命令将目标打包为.a文件。例如:
ar -rcs libtest.a test.o #库名一般以.a为扩展名,以lib开头
静态库的制作可以参考这一篇gcc 静态库制作之ar命令使用
2、可执行文件
用于生成进程映像,载入内存执行,例如编译好的可执行文件a.out。
在linux上编译成可执行文件为:
gcc test.c -o test
得到的test文件就是可执行的二进制文件。
3、 共享目标文件
用于和其他共享目标文件或者可重定位文件一起生成elf目标文件或者和执行文件一起创建进程映像,例如lib*.so文件。 例如:
gcc test.c -fPIC -shared -o libtest.so
得到的文件 libtest.so就是共享库。其中-fPIC用来产生和位置无关代码,-share用来生成动态共享库。
readelf调试工具
readelf参数较多,可直接通过readelf -h获取readelf的所有参数及用法,此处只对其中的几个常用参数以及数据详解。
readelf -h
readelf -h参数的作用是读取指定elf文件的头信息。
实例:
test.c
#include <stdio.h>
#include "test.h"
void test(){
printf("This is a static library\n");
}
test.h
#define __TEST_H__
#ifndef __TEST_H__
void test();
#endif
main.c
#include <stdio.h>
#include "test.h"
int main(int argc, char const *argv[])
{
test();
return 0;
}
编译成可重定位文件,即生成.o文件:
读取目标文件形式的elf文件头信息:
readelf -h test.o
这里,可见目标文件的elf文件,其类型为REL(可重定位文件)。
重要参数解释:
类别: 该elf文件的类型,这里是64位的elf格式
数据: 该参数指明了文件中数据的组织方式是大端规则还是小端规则,此处为二进制存储的小端规则
OS/ABI : 生成该文件的操作系统类型,ABI(Application Binary Interface)
类型: 当前文件的类型,EXEC(可执行文件), REL(可重定位文件),DYN(可被共享文件)
系统架构: 处理器类型
入口点地址 : 程序的虚拟地址入口点,可执行文件之外的类型该值为0x0
程序头起点: 程序头的开始处,从程序入口地址偏移地址开始。程序头table中记录elf文件中段的信息
Start of section headers : 段头的开始处,从程序入口地址偏移地址开始
读取静态库文件形式的elf文件头信息:
readelf -h libtest.a
这里,可见静态库文件的elf文件,其类型为REL(可重定位文件)。
读取可执行文件形式的elf文件头信息:
readelf -h main
这里,可见可执行文件的elf文件,其类型为EXEC(可执行文件)
读取动态库文件形式的elf文件头信息:
这里,可见动态库文件的elf文件,其类型为DYN(共享目标文件)。
总结
ELF文件中隐藏了丰富的信息,只要使用得当,将会帮助我们更好地进行开发或者问题的定位。
参考:Linux命令大全
(微信公众号【程序猿编码】)
(添加本人微信号,备注加群,进入程序猿编码交流群,领取学习资料,获取每日干货)
欢迎关注 微信公众号【程序猿编码】,专注于Linux c/c++ 、Python、Go语言、数据结构与算法、网络编程相关知识,常用的程序员工具。还有每日零点10分之前更新 新闻简报,即刻知晓天下事!