elf文件格式和运行时内存布局

elf的类型: Linux下的可执行文件格式叫做elf,全称是Executable Linkable Format。其实不仅仅是可执行文件,linux中常见的目标文件有目标文件.o、可执行文件如/bin/bash、共享目标文件(.so)、和核心转储文件core dump。可以使用file命令确定文件格式。 elf的结构: 如其结构如下图所示:

ELF file format:
+---------------+
|  File header  |
+---------------+
| .text section |
+---------------+
| .data section |
+---------------+
| .bss section  |
+---------------+
|      ...      |
+---------------+
|  xxx section  |
+---------------+

elf由很多段组成,文件头中保存各段的类型和长度,每个段存放不同属性内容,这样elf可以有很高的灵活性。同时,x86保护模式的内存也是段页式存储的,elf文件中的段很容易映射到内存中的段。 上图列出了elf文件中最主要的几个段,他们和c语言程序的映射关系如下(代码和表格摘自《程序员的自我修养》p58页):

int global_init_var = 84;            -------------------- .data section
int global_uninit_var;               -------------------- .bass section

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

int main(void)                       -------------------- .text section
{                                    -------------------- .text section
        static int static_var = 85;  -------------------- .data section
        static int static_var;       -------------------- .bass section

        int a = 1;                   -------------------- .text section
        int b;                       -------------------- .text section
        func1 ( static_var + static_var2 + ----------------- .text section
                        a + b );     -------------------- .text section
        return 0;                    -------------------- .text section
}                                    -------------------- .text section

代码和指令放在代码段(.text);未初始化的全局变量和静态变量放在bss段中,在运行时这些变量会被自动初始化为0;初始化的全局变量和静态变量存放在数据段中;局部变量和函数参数分别在栈中分配(栈和堆分别在内存中分配,在elf文件中不存在对应的部分)。

elf中的段:
elf中常见的段有如下几种:
代码段   text   存放函数指令
数据段   data   存放已初始化的全局变量和静态变量,
只读数据段 rodata 存放只读常量或const关键字标识的全局变量
bss段   bss   存放未初始化的全局变量和静态变量,这些变量由于为初始化,所以没有必要在elf中为其分配空间。bss段的长度总为0。
调试信息段 debug  存放调试信息
行号表   line   存放编译器代码行号和指令的duiing关系
字符串表  strtab   存储elf中存储的各种字符串
符号表   symtab   elf中到处的符号,用于链接 注:局部变量在函数中运行中动态的分配和释放,在elf中并没有对应的段。使用malloc和free函数动态申请的空间在运行时在堆中分配,elf中没有对应的段。

运行时内存布局 Linux程序运行时的内存布局如下:

 +------------------------+ Oxffffffff
        |     kernel space       |
        +------------------------+ 0xC0000000
        |        stack           |
        +------------------------+
        |                        |
        |        unused          |
        |                        |
        +------------------------+
        |   dynamic libraries    |
        +------------------------+ 0x40000000
        |                        |
        |        unused          |
        |                        |
        +------------------------+
        |         heap           |
        +------------------------+
        |  read/write sections   |
        |      (.data .bss)      |
        +------------------------+
        |   read only sections   |
        | (.init .rodata .text)  |
        +------------------------+ 0x08048000
        |       reserved         |
        +------------------------+ 0

elf文件中的段和内存布局的关系如括号中的小字所示。

转载自:http://blog.sina.com.cn/s/blog_4ed962ae01013vhr.html


				
时间: 2024-08-24 23:23:18

elf文件格式和运行时内存布局的相关文章

一文搞懂 JVM 架构和运行时数据区 (内存区域)

前言 了解 JVM 是对 Java 开发人员的基本要求,JVM 的相关内容自然也成了现在 Java 程序员面试的重要考点.不过估计很多小伙伴和我一样,长时间醉心于 CRUD,却忘了去了解一下更底层.更基础的东西,殊不知这些才是决定你能在这条路上走多远的关键因素,那接下来我们就一起来深入学习一下看似神秘的 JVM 吧.JVM 总体来看内容还是很多的,我会把最重要的内容介绍给大家,不过如果你有时间和精力的话,还是推荐你去看一下<深入理解Java虚拟机>这本书,确实是有口皆碑.本文也会引用很多此书的

C语言程序的内存布局

一:C语言程序的存储区域 C语言编写的程序经过编绎-链接后,将形成一个统一的文件,它由几个部分组成,在程序运行时又会产生几个其他部分,各个部分代表了不同的存储区域: 1.代码段(Code or Text): 代码段由程序中的机器码组成.在C语言中,程序语句进行编译后,形成机器代码.在执行程序的过程中,CPU的程序计数器指向代码段的每一条代码,并由处理器依次运行. 2.只读数据段(RO data): 只读数据段是程序使用的一些不会被更改的数据,使用这些数方式类似查表式的操作,由于这些变量不需要更改

一个由进程内存布局异常引起的问题

一个由进程内存布局异常引起的问题 前段时间业务反映某类服务器上更新了 bash 之后,ssh 连上去偶发登陆失败,客户端吐出错误信息如下所示:图 - 0 该版本 bash 为部门这边所定制,但实现上并没有改动原有逻辑,只是加入了些监控功能,那么这些错误从哪里来呢? 是 bash 的锅吗 从上面的错误信息可以猜测,异常是 bash 在启动过程中分配内存失败所导致,看起来像是某些情况下该进程错误地进行了大量内存分配,最后导致内存不足,要确认这个事情比较简单,动态内存分配到系统调用这一层上主要就两种方

ELF文件格式解析

1. ELF文件简介 首先,你需要知道的是所谓对象文件(Object files)有三个种类: 可重定位的对象文件(Relocatable file) 这是由汇编器汇编生成的 .o 文件.后面的链接器(link editor)拿一个或一些 Relocatable object files 作为输入,经链接处理后,生成一个可执行的对象文件 (Executable file) 或者一个可被共享的对象文件(Shared object file).我们可以使用 ar 工具将众多的 .o Relocata

C语言的ELF文件格式学习

最近的lab里面有ELF文件相关的,所以成这个几乎,学点ELF的东西. ELF,是一种文件格式.暂时,只看可执行文件的ELF文件格式. 首先,给出文件的格式的布局图: 光看这个很难理解,所以写一个小的程序,用readelf来结合的看. 程序比较简单: #include <stdio.h> #include <stdlib.h> int data[100] ={0}; int bss[100]; int main() { int i=0; for(i=0; i<100; i++

elf文件格式

android是建立在linux的基础上,其底层代码是安装linux可执行文件——elf的格式来组装的.本文结合android中的so文件来了解elf格式,资料大多收集于网上:elf格式位于android源码:elf.h. elf大致可分为三部分:elf头.程序头表.节区头表:当然还有上图没标出的动态符号表, elf头: #define EI_NIDENT 16 typedef struct { unsigned char e_ident[EI_NIDENT]; //magic Elf32_Ha

Objective-C内存布局

在我的理解来说: 对象(object)即一块内存,本文要探讨的是一个Objective-C对象在内存的布局(layout)问题,水果的官方文档有说,一个类(class)如果不需要从NSObject继承其某些特定的行为是不用继承NSObject的,这里我将讨论限制在继承了NSObject的类的对象范围内. 首先来看一下,NSObject的定义: 1 @interface NSObject <NSObject> { 2 Class isa; 3 } (由于我们讨论的是内存布局,因此将其方法的定义撇

UNIX高级环境编程(8)进程环境(Process Environment)- 进程的启动和退出、内存布局、环境变量列表

在学习进程控制相关知识之前,我们需要了解一个单进程的运行环境. 本章我们将了解一下的内容: 程序运行时,main函数是如何被调用的: 命令行参数是如何被传入到程序中的: 一个典型的内存布局是怎样的: 如何分配内存: 程序如何使用环境变量: 程序终止的各种方式: 跳转(longjmp和setjmp)函数的工作方式,以及如何和栈交互: 进程的资源限制 ? 1 main函数 main函数声明: int main (int argc, char *argv[]); 参数说明: argc:命令行参数个数

c++对MFC消息映射机制和运行时类型识别的理解

对MFC消息映射机制和运行时类型识别的理解 对MFC消息映射机制的理解 MFC中派生于Cobject的每个类都有一个消息映射表,所有MFC窗口都有一个同样的窗口过程AfxWndProc(),AfxWndProc的参数列表中有一个是窗口句柄,在AfxWndProc函数中将句柄(HWND)转换成了窗口指针(CWnd*),通过这个窗口指针就可以获得该窗口的消息映射表.对于WM_COMMAND这类特殊消息,将依据C++的虚函数多态机制来决定调用哪个类的函数. 对MFC运行时类型识别的理解 定义一个CRu