ELF文件的结构如下图所示:

ELF文件由4部分组成,分别是ELF头(ELF header)、程序头表(Program header table)、节(Sections)和节头表(Section header table)。

实际上,一个文件中不一定包含全部这些内容,而且它们的位置也未必如上图所示这样安排,只有ELF头的位置是固定的,其余各部分的位置、大小等信息由ELF头中的各项值来决定。

ELF header的格式如下代码所示:

#define EI_NIDENT  16

typedef struct{
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Haif e_ehsize;
Elf32_Haif e_phentsize;
Elf32_Haif e_phnum;
Elf32_Haif e_shentsize;
Elf32_Haif e_shnum;
Elf32_Haif e_shstrndx;
}Elf32_Ehdr;

其中各类型的说明见下表,由于ELF文件力求支持从8位到32位不同架构的处理器,所以才定义了下表中这些数据类型,从而让文件格式与机器无关。

下面看一下ELF header中各项的意义。foobar文件:

最开头是16字节的e_ident,其中包含用以表示ELF文件的字符,以及其他一些与机器无关的信息。

开头的4字节是固定不变的,第1个字节值为0x7F,紧跟着就是ELF三个字符,这4字节表明这个文件是个ELF文件。

1.e_type——标识的是该文件的类型,取值就不一一列出了。文件foobar的e_type是2,表明它是一个可执行文件。

2.e_machine——foobar中此项的值为3,表明运行该程序需要的体系结构为Intel 80386.

3.e_version——文件的版本。

4.e_entry——程序的入口地址。文件foobar的入口地址为0x80480A0.

5.e_phoff——Program header table在文件中的偏移量(以字节计数),这里的值是0x34.

6.e_shoff——Section header table在文件中的偏移量(以字节计数),这里的值是0x1C0.

7.e_flags——对IA32而言,此项为0.

8.e_ehsize——ELF header大小(以字节计数),这里值为0x34.

9.e_phentsize——Program header table中每一个条目(一个Program header)的大小。这里值为0x20.

10.e_phnum——Program header table中有多少个条目,这里有3个。

11.e_shentsize——Section header table中每一个条目(一个Section header)的大小,这里值为0x28.

12.e_shnum——Section header table中有多少个条目,这里有6个。

13.e_shstrndx——包含节名称的字符串表是第几个节(从零开始数)。这里值为5,表示第5个节包含节名称。

我们看到,Program header table在文件中的偏移量(e_phoff)为0x34,而ELF header大小(e_ehsize)也是0x34,可见ELF header后面紧接着就是Program header table。Program header数据结构如下:

typedef struct{
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
}Elf32_Phdr;

实际上Program header描述的是系统准备程序运行所需的一个段或其他信息。程序头表中共有三项(e_phnum=3),偏移分别是0x34~0x53、0x54~0x73和0x74~0x93.

1.p_type——当前Program header所描述的段的类型。

2.p_offset——段的第一个字节在文件中的偏移。

3.p_vaddr——段的第一个字节在内存中的虚拟地址。

4.p_paddr——在物理地址定位相关的系统中,此项是为物理地址保留。

5.p_filesz——段在文件中的长度。

6.p_memsz——段在内存中的长度。

7.p_flags——与段相关的标志。

8.p_align——根据此项值来确定段在文件以及内存中如何对齐。

Program header描述的是一个段在文件中的位置、大小以及它被放进内存后所在的位置和大小。如果我们想把一个文件加载进内存的话,需要的正是这些信息。

在foobar中共有三个Program header,其取值如下表所示:

根据这些信息,我们很容易知道foobar在加载进内存之后的情形,如下图:

操作系统开发系列—11.ELF格式 ●的更多相关文章

  1. 操作系统开发系列—12.c.从Loader加载ELF内核,顺便解释下函数调用过程 ●

    实际上,我们要做的工作是根据内核的Program header table的信息进行类似下面这个C语言语句的内存复制: memcpy(p_vaddr, BaseOfLoaderPhyAddr+p_of ...

  2. 操作系统开发系列—9.Loader

    一个操作系统从开机到开始运行,大致经历“引导—>加载内核入内存—>跳入保护模式—>开始执行内核”这样一个过程.也就是说,在内核开始执行之前不但要加载内核,而且还有准备保护模式等一系列 ...

  3. 操作系统开发系列—1.HelloWorld ●

    org 07c00h ;伪指令,告诉编译器程序会被加载到7c00处 mov ax, cs mov ds, ax mov es, ax call DispStr ;调用显示字符串例程 jmp $ ;无限 ...

  4. 操作系统开发系列—13.g.操作系统的系统调用 ●

    在我们的操作系统中,已经存在的3个进程是运行在ring1上的,它们已经不能任意地使用某些指令,不能访问某些权限更高的内存区域,但如果一项任务需要这些使用指令或者内存区域时,只能通过系统调用来实现,它是 ...

  5. 操作系统开发系列—12.f.在内核中添加中断处理 ●

    因为CPU只有一个,同一时刻要么是客户进程在运行,要么是操作系统在运行,如果实现进程,需要一种控制权转换机制,这种机制便是中断. 要做的工作有两项:设置8259A和建立IDT. /*========= ...

  6. 操作系统开发系列—12.d.扩充内核 ●

    现在把esp.GDT等内容放进内核中,我们现在可以用C语言了,只要能用C,我们就避免用汇编. 下面看切换堆栈和GDT的关键代码: ; 导入函数 extern cstart ; 导入全局变量 exter ...

  7. 操作系统开发系列—12.a.从Loader到内核 ●

    Loader要做两项工作,我们先来做第一项,把内核加载到内存: 1.加载内核到内存. 2.跳入保护模式. 首先编译无内核时: nasm boot.asm -o boot.bin nasm loader ...

  8. 操作系统开发系列—10.内核HelloWorld ●

    a.我们先来体验一下在Linux下用汇编编程的感觉,见代码 [section .data] ; 数据在此 strHello db "Hello, world!", 0Ah STRL ...

  9. 操作系统开发系列—13.i.进程调度 ●

    上面的三个进程都是延迟相同的时间,让我们修改一下,尝试让它们延迟不同的时间. void TestA() { int i = 0; while (1) { disp_str("A." ...

随机推荐

  1. 材价看板(2)- 运行两周的kanban,改进的起点

    改进从何谈起?必须找到起点,那起点从哪来? 看板不需要像Scrum那样改变以往工作角色,简单通过任务上墙,配合敏捷的设计就能通过显示化日常工作来让问题自己蹦出来.在任何一个新采用看板的研发团队,执行一 ...

  2. dom4j的读写xml文件,读写xml字符串

    百度了一些博客,大同小异,在选取jar包工具的时候大概看了下,大抵是jdom原始,dom4j优秀.于是做了些练习. 参考:http://www.cnblogs.com/mengdd/archive/2 ...

  3. 加速Web开发的9款知名HTML5框架

    与手工编码比起来,HTML5框架在准确性和正确率方面给予了保证.大多数HTML5框架都会有一个组合或者包含一些额外的组件,比如jQuery Scripts.CSS3样式表则以改善多媒体特征的功能性和响 ...

  4. flexbox简介

    flexbox简介 什么是flexbox flexbox是一种新的布局方式,这种布局方式是2009年W3C提出的方案.它可以简便,完整,完成页面的布局.目前,它已经得到所有浏览器的支持. 但是flex ...

  5. swift3.0的改变

    Swift在这2年的时间内,发展势头迅猛,在它开源后,更是如井喷一样,除了 iOS.mac 平台,还支持了 Linux. 而今年下半年, Swift 3.0 也会随之发布.https://github ...

  6. Redis使用总结(3):实现简单的消息队列

    参考Redis实现简单消息队列 Redis提供了两种方式来作消息队列.一个是使用生产者消费模式模式,另外一个方法就是发布订阅者模式.前者会让一个或者多个客户端监听消息队列,一旦消息到达,消费者马上消费 ...

  7. jquery Ajax异步请求之session

    写了一个脚本,如下: $(function () { $("#btnVcode").click(function () { var receiveMobile = $(" ...

  8. .NET Core配置文件加载与DI注入配置数据

    .NET Core配置文件 在以前.NET中配置文件都是以App.config / Web.config等XML格式的配置文件,而.NET Core中建议使用以JSON为格式的配置文件,因为使用起来更 ...

  9. HoverTree项目添加了查看留言列表功能

    HoverTree项目添加了查看留言列表功能 页面:HoverTreeWeb项目下hvtpanel/usermessage/messagelist.aspx 添加留言页面:addmessage.asx ...

  10. ASP.NET Core WebAPI 开发-新建WebAPI项目

    ASP.NET Core WebAPI 开发-新建WebAPI项目, ASP.NET Core 1.0 RC2 即将发布,我们现在来学习一下 ASP.NET Core WebAPI开发. 网上已经有泄 ...