文档章节

Linux下ELF文件的格式(3)

谁染霜林醉
 谁染霜林醉
发布于 2014/08/20 22:41
字数 1604
阅读 132
收藏 0

【说明】本文章从本人的CSDN博客搬过来的,因个人感觉CSDN的博客系统太差,so,搬到这里。

在上一篇文章中,主要介绍了几个重要的段以及这几个段中存放的信息。这里将重点介绍目标文件中的 ELF文件头 和 段表(Section Header Table)。


关于ELF文件头,它主要包含了描述整个文件的基本属性,比如ELF文件版本,目标机器型号,程序入口地址等。

关于段表,它描述了ELF文件包含的所有段的信息,比如每个段的段名,长度,在文件中的偏移,读写权限以及其他的属性。


1.再看文件头

再来看整个头文件结构

那么对于系统来讲,这个结构是怎么存储的,按什么格式存储呢?

/user/include/elf.h中,可以找到描述这个头文件的结构体,如下所示:

对比实际的内容跟这个结构体,发现从Type (e_type)开始往下是一一对应的,而前面几条信息就对应于 e_ident[16],即e_ident中存放着前几条的信息。

现在将几个重要的字段解释一下:

e_type : ELF文件类型,主要有3种,ET_REL 可重定位,ET_EXEC可执行,ET_DYN共享目标文件,一般为.so文件

e_machine : 机器类型,如EM_386,intel的x86架构,EM_68K摩托罗拉的68000系列等

e_entry : 入口地址,可执行文件被加载后,会从这个虚拟地址开始执行指令。目标文件不会执行,所以地址为0

e_shoff : 段表在文件中的偏移,即段表所在的地址,这个很重要

e_ehsize : 头文件本身的大小

e_shentsize : 段表描述符的大小,即sizeof(Elf32_Endr),一般为40

e_shnum : 段表描述符的数量,即该文件总共有多少个段

e_shstrndx : 段表字符串表所在的段在段表中的下标,很绕口,后面再讲。


2.段表

ELF文件的段结构就是由段表决定的,编译器,连接器和装载器都是靠段表来定位和访问各个段的属性的。

现在我们来仔细看看目标文件中的各个段:

这里列出来的就是段表的信息,可以看到第一个是无效的,它的类型是NULL,共有13个有效的段。其中包括上篇里我们自定义的 special段。

那么,描述段表的结构又是怎样的呢?

段表其实是一个Elf32_Shdr的数组,每一个数组元素都是一个结构体,来描述一个段。

sh_name : 段名

sh_type : 段的类型

    比如:SHT_NULL 表示无效段

                SHT_PROGBITS 表示程序段 代码段 数据段

                SHT_SYMTAB 表示该段的内容为符号表  

                 等等


sh_flags : 段的标志

    比如:SHF_WRITE 该段在进程空间中可以写

                SHF_ALLOC 表示需要在进程空间中分配信息,代码段 数据段等,注意:bss段也是这个标志,虽然是在文件中没有,但是会在进程中分配 空间

                SHF_EXECINSTR 表示可执行 像代码段


例如:.text段的类型是 SHT_PROGBITS,标志是SHF_ALLOC + SHF_EXECINSTR


sh_addr : 如果该文件被加载,表示该段在进程虚拟地址空间中的位置,否则为0

sh_offset : 段偏移,如果该段在文件中,则表示偏移,否则无意义。比如对于BSS段来讲,这个值是没有意义的

sh_size : 段的长度

sh_link sh_info : 段的链接信息


参照下表:

sh_addralign : 段地址对齐 段地址对齐于 2的sh_addralign次方,前面说过,2**2是2的2次方,即对齐4个字节,不够4的,也要占满。如果sh_addralign为1或者0,则不限制对齐。

sh_entsize :   项的长度,有些段包含了一些固定大小的项,如符号表,它的每一项占得空间都是相同的,这是该字段表示的是每个项的大小。为0则表示不含有相同大小的项。


每个段描述符的大小为sizeof(Elf32_Shdr),大小为40个字节,到文件最后结束时,大小为0x0570,即1392个字节,跟ll命令查看的大小是相同的。下面让我们看看ELF文件格式的真实存储情况:

(程序就是前面文章中用到的,环境是Ubuntu14.04 64位)


因为字节对齐的原因,中间有的段之间有一个或两个字节的空位。


3.重定位表

首先,重定位过程发生在链接时,简单的讲重定位的任务就是将编译时无法确定的地址,确定下来。

在hello.o中,有一个段,.rel.text,他的类型是SHT_REL,说明它是一个记录.text段的重定位信息的段。这个段的sh_link表示符号表的下标【为12】,sh_info表示作用于哪个段【为1,说明是 .text段】。

比如:printf函数,这个一个外部定义的函数,在编译期间是不会知道它的地址的,所以需要依靠连接器来决定它的真是运行地址(后面的文章会说到)。


4.字符串表

前面提及的几个表结构都是用固定大小的结构体来存储的,但是,字符串的大小是不固定的,不能用固定的结构来表示的。所以ELF采用了一种依赖结束符的存储结构。

从0地址取,是空串,

从1地址取,是NIHAO,

从3地址取,是HAO

这样就不用考虑字符串的长度了。

字符串表也已段的形式保存在ELF文件中,名为.strtab或.shstrtab。前者是字符串表,后者是段表字符串表。前者保存的是普通的字符串,而后者保存的则是段表用到的字符串,比如表名。

前面讲到,Elf32_Ehdr最后一个成员是e_shstrndx,他表示 段表字符串表 (.shstrtab)在 段表中的下标。在文件头里看到,最后一个成员的值是11,再查看段表11位置上的值正好是.shstrtab,即段表字符串表。


下一篇文章,将介绍ELF文件的符号,马上就会很清晰的认识这个文件格式了。

© 著作权归作者所有

谁染霜林醉
粉丝 3
博文 15
码字总数 18432
作品 0
济南
程序员
私信 提问
随想:从down掉系统看操作系统设计

如果一个文件被打开,那么试着删除这个文件会怎么样?在windows下会弹出可恶的对话框,说不让删除,而linux或者unix下默认就真的被删除了。 记得以前刚上大学的时候不懂电脑,就知道c盘有着重...

晨曦之光
2012/04/10
43
0
linux中的可执行文件

linux下的可以直接执行的文件很多,它继承了unix的对可执行文件格式很开放的优势。unix或者linux中,对于程序的执行实际上并没有由内核 负责,就是说内核并不管哪些文件格式可以执行哪些不可...

晨曦之光
2012/04/10
1K
0
[Linux]vmlinux , vmlinux.bin

vmlinux 是ELF格式的一个kernel file,编译好后一半包含调试信息。 vm表示virtual memory vmlinux.bin 是进行如下操作得来,除二进制内容一无所有,而vmlinx是elf格式的文件里面包含了elf头部...

清水湾2012
2013/09/24
999
0
连接时出错,(.ARM.exidx+0x0): undefined reference to `__aeabi_unwind_cpp_pr0'

连接时出错: D:\Program Files (x86)\DS-5\bin\led_on_c>make arm-none-linux-gnueabi-gcc -g -c -o crt0.o crt0.S arm-none-linux-gnueabi-gcc -g -c -o led_on_c.o led_on_c.c arm-none-li......

长平狐
2013/06/03
444
0
linux之readelf命令

1、readelf命令解释 readelf命令用来显示一个或者多个elf格式的目标文件的信息 2、ELF文件类型 可重定位文件:用户和其他目标文件一起创建可执行文件或者共享目标文件,例如lib*.a文件。 可执行...

u011068702
2018/03/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

一起来学Java8(三)——方法引用

在一起来学Java8(一)——函数式编程中有一个简单的函数式编程的例子: import java.util.function.Consumer;class Person { public static void sayHello(String name) { S...

猿敲月下码
22分钟前
11
0
读书笔记:深入理解ES6(十一)

第十一章 Promise与异步编程   Promise可以实现其他语言中类似Future和Deferred一样的功能,是另一种异步编程的选择,它既可以像事件和回调函数一样指定稍后执行的代码,也可以明确指示代码...

张森ZS
45分钟前
19
0
面试官,Java8 JVM内存结构变了,永久代到元空间

在文章《JVM之内存结构详解》中我们描述了Java7以前的JVM内存结构,但在Java8和以后版本中JVM的内存结构慢慢发生了变化。作为面试官如果你还不知道,那么面试过程中是不是有些露怯?作为面试...

程序新视界
53分钟前
28
0
Elasticsearch 实战(一) - 简介

官腔 Elasticsearch,分布式,高性能,高可用,可伸缩的搜索和分析系统 基本等于没说,咱们慢慢看 1 概述 百度:我们比如说想找寻任何的信息的时候,就会上百度去搜索一下,比如说找一部自己喜...

JavaEdge
58分钟前
23
0
【jQuery基础学习】11 jQuery性能简单优化

本文转载于:专业的前端网站➦【jQuery基础学习】11 jQuery性能简单优化 关于性能优化 合适的选择器 $("#id")会直接调用底层方法,所以这是最快的。如果这样不能直接找到,也可以用find方法继...

前端老手
今天
18
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部