浅析Linux平台下的目标文件

4 篇文章 0 订阅

1. 使用到的工具

1.1 readelf

readelf是一个用于显示ELF文件信息的工具,可以通过不同选项来控制显示的内容。

1.2 objdump

objdump是一个用于显示目标文件信息的工具,可以通过不同的选项来控制显示的内容

2. 预备知识

2.1 ELF Header

Linux中目标文件的格式为ELF格式,ELF文件的开始是一个文件头(ELF Header),里面包含了整个文件的属性,包括文件是否可执行,静态链接/动态链接,入口地址(如果是可执行文件),目标硬件,目标操作系统和相关的信息等。段相关的信息包括section header的大小,数量和文件内偏移起始地址。

2.2 section header

section header用于描述每个section的属性,如名称,大小,类型等。

2.3 program header

program header用于描述segement的属性。目标文件(.o文件)不存在program header,因为它不能运行。可执行文件中,存在program header。一个segment包含一个或多个现有的section。

2. 测试代码

本文使用的测试代码如下:

/*
 * file: helloworld.c
 */

#include <stdio.h>

int global_init_var = 12;
int global_uninit_var;

void func1(int i)
{
	printf("%d\n", i);
}

int main(void)
{
	static int static_var = 100;
	static int static_var2;

	int a = 1;
	int b;

	func1(static_var + static_var2 + a + b);

	return 0;
}

使用gcc编译代码,分别编译出目标文件(不进行链接的.o文件)和可执行文件

gcc -c helloword.c -o helloword.o
gcc helloword.c -o helloword

3. 使用readelf查看目标文件结构信息

3.1 查看ELF Header信息

查看未链接的目标文件simpleSection.o的ELF header,结果如下:

readelf -h simpleSection.o

在这里插入图片描述
我们关注如下信息:

  1. Type:REL (Relocatable file),说明这是一个可重定位文件。
  2. Entry point address:说明了程序执行的入口地址,由于.o文件并不是最终的可执行文件,此处入口地址无意义。
  3. Start of program headers:Program Header在文件中的偏移位置
  4. Start of section headers:段表在文件中的偏移位置
  5. Size of this header:ELF Header的大小
  6. Size of program headers:Program Header的大小
  7. Number of program headers:Program Header的数量
  8. Size of section headers:Section Header的大小,即段表中每一项的大小
  9. Number of sections headers:Section Header的数量,即段表中有多少项
  10. Section header string table index:这个索引表明了段字符串表在段表中的索引,通过段字符串表可以获得每个段的名称

查看可执行文件的ELF Header,结果如下:

readelf -h simpleSection

在这里插入图片描述
对比之前未进行链接的目标文件的ELF Header,可以发现:可执行文件ELF Header中的Type字段为DYN (Position-Independent Executable file),表明这是一个可执行文件,并且Entry point address字段指明了入口地址。同时,该文件中还包含Program Header,其数量和大小不再是0。并且,和目标文件(.o文件)相比,可执行文件中的section数量要多一些。

3.2 查看section header信息

查看目标文件(simpleSection.o)的段表信息(section header):

readelf -S simpleSection.o

在这里插入图片描述
共显示有14个段,从0x408(十进制1032)字节处开始,与之前ELF Header显示的信息一致。Section Header中各字段的含义如下:

名称含义
Name段名。段名是一个字符串,位于一个叫“.shstrtab”的字符串表中,Name实际存储的是段名在“.shstrtab”中的偏移
Type段的类型
Address段虚拟地址。如果该段是可以加载的,则表示该段加载后在虚拟内存空间中的地址
Offset苏果该段存在于文件中,则表示该段在文件中的偏移。否则无意义,Offset字段对于.bss段来说就没有意义
Size段的大小
EntSize有些段包含了固定大小的项,比如符号表。EntSize则为这些包含固定大小的项的段中每一项的大小
Flag段的标志为
Link段的链接信息
Info段的链接信息
Align段地址对齐

常见的类型(Type)有如下几种:

名称含义
NULL无效段
PROGBITS程序段。代码段,数据段都为这种类型
NOBITS表示该段在文件中无内容。如.bss段
RELA重定位表。该段包含了重定位信息
DYNAMIC动态链接信息
SYMTAB表示该段的内容为符号表
STRTAB表示该段的内容为字符串表

3.3 小结:ELF文件结构

根据前面两小节中介绍的ELF文件中的相关信息,我们可以大致画出ELF文件的结构,如下图所示:
在这里插入图片描述

4. 使用objdump查看目标文件信息

4.1 查看目标文件结构和内容**

objdump -h SimpleSection.o

在这里插入图片描述
同样对于目标文件simpleSection.o,使用objdump查看段信息,只显示了8个段。这是因为,objdump只显示了部分主要的段,而忽略了部分段。

4.2 查看各个段的内容和汇编指令

objdump使用-s选项可以将各个段的内容以十六进制的方式显示出来,使用-d选项可以将包含指令的段反汇编。对目标文件simpleSection.o运行如下指令:

objdump -s -d simpleSection.o

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值