Linux 可执行文件 ELF结构 及程序加载运行

 Linux下ELF文件类型分为以下几种:

    1、可重定位文件,例如SimpleSection.o;

    2、可执行文件,例如/bin/bash;

    3、共享目标文件,例如/lib/libc.so。

    在Linux 可重定位文件 ELF结构一文中,我们已经分析了可重定位文件ELF结构。本文分析可执行文件的ELF结构。

    首先附上源代码:

    SectionMapping.c 


#include <stdlib.h>
 
int main()
{
    while(1)
    {
        sleep(1000);
    }
    return 0;
}

    使用命令gcc -static SectionMapping.c -o SectionMapping.elf,静态链接为可执行文件。

    接着使用命令readelf -S SectionMapping.elf得到Section Table。如下:


There are 33 section headers, starting at offset 0xc3878:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .note.ABI-tag     NOTE             0000000000400190  00000190
       0000000000000020  0000000000000000   A       0     0     4
  [ 2] .note.gnu.build-i NOTE             00000000004001b0  000001b0
       0000000000000024  0000000000000000   A       0     0     4
  [ 3] .rela.plt         RELA             00000000004001d8  000001d8
       0000000000000120  0000000000000018   A       0     5     8
  [ 4] .init             PROGBITS         00000000004002f8  000002f8
       0000000000000018  0000000000000000  AX       0     0     4
  [ 5] .plt              PROGBITS         0000000000400310  00000310
       00000000000000c0  0000000000000000  AX       0     0     16
  [ 6] .text             PROGBITS         00000000004003d0  000003d0
       0000000000094988  0000000000000000  AX       0     0     16
  [ 7] __libc_thread_fre PROGBITS         0000000000494d60  00094d60
       00000000000000a8  0000000000000000  AX       0     0     16
  [ 8] __libc_freeres_fn PROGBITS         0000000000494e10  00094e10
       000000000000181c  0000000000000000  AX       0     0     16
  [ 9] .fini             PROGBITS         000000000049662c  0009662c
       000000000000000e  0000000000000000  AX       0     0     4
  [10] .rodata           PROGBITS         0000000000496640  00096640
       000000000001d344  0000000000000000   A       0     0     32
  [11] __libc_thread_sub PROGBITS         00000000004b3988  000b3988
       0000000000000008  0000000000000000   A       0     0     8
  [12] __libc_subfreeres PROGBITS         00000000004b3990  000b3990
       0000000000000058  0000000000000000   A       0     0     8
  [13] __libc_atexit     PROGBITS         00000000004b39e8  000b39e8
       0000000000000008  0000000000000000   A       0     0     8
  [14] .eh_frame         PROGBITS         00000000004b39f0  000b39f0
       000000000000d4c4  0000000000000000   A       0     0     8
  [15] .gcc_except_table PROGBITS         00000000004c0eb4  000c0eb4
       0000000000000172  0000000000000000   A       0     0     1
  [16] .tdata            PROGBITS         00000000006c1ef0  000c1ef0
       0000000000000020  0000000000000000 WAT       0     0     16
  [17] .tbss             NOBITS           00000000006c1f10  000c1f10
       0000000000000038  0000000000000000 WAT       0     0     16
  [18] .init_array       INIT_ARRAY       00000000006c1f10  000c1f10
       0000000000000008  0000000000000000  WA       0     0     8
  [19] .fini_array       FINI_ARRAY       00000000006c1f18  000c1f18
       0000000000000008  0000000000000000  WA       0     0     8
  [20] .ctors            PROGBITS         00000000006c1f20  000c1f20
       0000000000000010  0000000000000000  WA       0     0     8
  [21] .dtors            PROGBITS         00000000006c1f30  000c1f30
       0000000000000010  0000000000000000  WA       0     0     8
  [22] .jcr              PROGBITS         00000000006c1f40  000c1f40
       0000000000000008  0000000000000000  WA       0     0     8
  [23] .data.rel.ro      PROGBITS         00000000006c1f50  000c1f50
       0000000000000080  0000000000000000  WA       0     0     16
  [24] .got              PROGBITS         00000000006c1fd0  000c1fd0
       0000000000000010  0000000000000008  WA       0     0     8
  [25] .got.plt          PROGBITS         00000000006c1fe8  000c1fe8
       0000000000000078  0000000000000008  WA       0     0     8
  [26] .data             PROGBITS         00000000006c2060  000c2060
       0000000000001690  0000000000000000  WA       0     0     32
  [27] .bss              NOBITS           00000000006c3700  000c36f0
       0000000000002ba8  0000000000000000  WA       0     0     32
  [28] __libc_freeres_pt NOBITS           00000000006c62b0  000c36f0
       0000000000000048  0000000000000000  WA       0     0     16
  [29] .comment          PROGBITS         0000000000000000  000c36f0
       000000000000002a  0000000000000001  MS       0     0     1
  [30] .shstrtab         STRTAB           0000000000000000  000c371a
       000000000000015b  0000000000000000           0     0     1
  [31] .symtab           SYMTAB           0000000000000000  000c40b8
       000000000000c168  0000000000000018          32   870     8
  [32] .strtab           STRTAB           0000000000000000  000d0220
       0000000000007a26  0000000000000000           0     0     1
                                     表 1

    这个可执行文件共有33个Section。

    接着我们使用readelf -h SectionMapping.elf,读取elf可执行文件头部信息。如下图:

                                     图 1

    可以对比,Linux 可重定位文件 ELF结构,这里多了program header。

    Entry point address:程序的入口地址是0x401058,使用objdump -d SectionMapping.elf | less,可以查看到程序的入口地址是<_start>。如下图:

                                           图 2

    Start of program headers:program headers的偏移,由于头文件大小为64,所以program headers紧挨着头文件存放。

    Size of program headers:program headers的大小。为56个字节。

    Number of section headers:program headers的数量。为6个。

    在表1中,第一个section在文件中的偏移是0x190,头文件大小为64 + program header大小为56 * program header数量6 = 400 = 0x190。

    然后,我们使用命令readelf -l SectionMapping.elf,我们会得到program header部分。如下图:

                                 图  3

    从图中可见,分为6个Segment。注意表1中每个段叫Section。

    Offset:这个Segment在文件中偏移。

    VirtAddr:这个Segment在虚拟地址的偏移。

    FileSiz:在ELF文件中所占的长度。

    MemSiz:在进程虚拟空间所占的长度。

    我们发现第二个Segment,MemSiz > FileSiz,表示在内存中分配的空间大小超过文件实际大小。超过的部分全部初始化为0,作为BSS段。因为数据段和BSS段的唯一区别是,数据段从文件中初始化内容,BSS段内容全部初始化为0。

    我们主要关心前两个Segment,第一个是代码段,虚拟地址从0x00400000到0x004c1026。文件偏移从0x00000000到0x000c1026。

    第二个是数据段,虚拟地址为从0x006c1ef0到0x006c1ef0+0x4408=0x6c62f8。文件偏移从0x000c1ef0到0x000c1ef0+0x1800=0x000C36f0。

    结合表1和两个Segment的文件偏移,可以得出:

    第一个Segment从第0个Section到第15个Section。(0x00000000-0x000c1026)

  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .note.ABI-tag     NOTE             0000000000400190  00000190
       0000000000000020  0000000000000000   A       0     0     4
  [ 2] .note.gnu.build-i NOTE             00000000004001b0  000001b0
       0000000000000024  0000000000000000   A       0     0     4
  [ 3] .rela.plt         RELA             00000000004001d8  000001d8
       0000000000000120  0000000000000018   A       0     5     8
  [ 4] .init             PROGBITS         00000000004002f8  000002f8
       0000000000000018  0000000000000000  AX       0     0     4
  [ 5] .plt              PROGBITS         0000000000400310  00000310
       00000000000000c0  0000000000000000  AX       0     0     16
  [ 6] .text             PROGBITS         00000000004003d0  000003d0
       0000000000094988  0000000000000000  AX       0     0     16
  [ 7] __libc_thread_fre PROGBITS         0000000000494d60  00094d60
       00000000000000a8  0000000000000000  AX       0     0     16
  [ 8] __libc_freeres_fn PROGBITS         0000000000494e10  00094e10
       000000000000181c  0000000000000000  AX       0     0     16
  [ 9] .fini             PROGBITS         000000000049662c  0009662c
       000000000000000e  0000000000000000  AX       0     0     4
  [10] .rodata           PROGBITS         0000000000496640  00096640
       000000000001d344  0000000000000000   A       0     0     32
  [11] __libc_thread_sub PROGBITS         00000000004b3988  000b3988
       0000000000000008  0000000000000000   A       0     0     8
  [12] __libc_subfreeres PROGBITS         00000000004b3990  000b3990
       0000000000000058  0000000000000000   A       0     0     8
  [13] __libc_atexit     PROGBITS         00000000004b39e8  000b39e8
       0000000000000008  0000000000000000   A       0     0     8
  [14] .eh_frame         PROGBITS         00000000004b39f0  000b39f0
       000000000000d4c4  0000000000000000   A       0     0     8
  [15] .gcc_except_table PROGBITS         00000000004c0eb4  000c0eb4
       0000000000000172  0000000000000000   A       0     0     1

    第二个Segment从第16个Section到26个Section。(0x000c1ef0-0x000C36f0)
  [16] .tdata            PROGBITS         00000000006c1ef0  000c1ef0
       0000000000000020  0000000000000000 WAT       0     0     16
  [17] .tbss             NOBITS           00000000006c1f10  000c1f10
       0000000000000038  0000000000000000 WAT       0     0     16
  [18] .init_array       INIT_ARRAY       00000000006c1f10  000c1f10
       0000000000000008  0000000000000000  WA       0     0     8
  [19] .fini_array       FINI_ARRAY       00000000006c1f18  000c1f18
       0000000000000008  0000000000000000  WA       0     0     8
  [20] .ctors            PROGBITS         00000000006c1f20  000c1f20
       0000000000000010  0000000000000000  WA       0     0     8
  [21] .dtors            PROGBITS         00000000006c1f30  000c1f30
       0000000000000010  0000000000000000  WA       0     0     8
  [22] .jcr              PROGBITS         00000000006c1f40  000c1f40
       0000000000000008  0000000000000000  WA       0     0     8
  [23] .data.rel.ro      PROGBITS         00000000006c1f50  000c1f50
       0000000000000080  0000000000000000  WA       0     0     16
  [24] .got              PROGBITS         00000000006c1fd0  000c1fd0
       0000000000000010  0000000000000008  WA       0     0     8
  [25] .got.plt          PROGBITS         00000000006c1fe8  000c1fe8
       0000000000000078  0000000000000008  WA       0     0     8
  [26] .data             PROGBITS         00000000006c2060  000c2060
       0000000000001690  0000000000000000  WA       0     0     32

    以上分析的都是静态状态下的程序,下面我们看看动态下的进程的空间是怎么分配的。
    首先使用命令, ./SectionMapping.elf &,输出如下:

    

    然后使用命令:cat /proc/2184/maps,输出如下:

                                    图 4

    

    静态时,我们计算出的两个Segment的虚拟空间的偏移分别为:

    第一个是代码段,虚拟地址从0x00400000到0x004c1026。在图4中,因为要页面对齐,所以分配了0x400000到0x4c2000。

    第二个是数据段,虚拟地址为从0x006c1ef0到0x006c1ef0+0x4408=0x6c62f8。在图4中,因为要页面对齐,所以分配了0x6c1000到0x6c4000。注意,0x6c62f8大于0x6c4000,具体原因以后再分析。

    第三个紧接着是堆。用于动态分配内存。

    第四个是栈。用于存放局部变量。

    整体的结构如下图:

    程序运行的过程:建立虚拟空间(分配一个页目录)-> 建立虚拟空间与可执行文件映射(页目录项指向磁盘的程序) -> 跳到程序入口 -> 缺页异常-> 在内存中寻找空闲页,将对应的页换入 -> 建立映射 -> 开始执行。

原文:https://blog.csdn.net/jltxgcy/article/details/39233689 
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/381047.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前途未必是光明的,道路却一定是曲折的

今天搜psm的文章&#xff0c;结果搜到了几位很厉害的人的blog&#xff0c;其中有一个还在写关于次时代的引擎&#xff0c;好像是在那啥 而另外两位都在07年就开始实现这个技术了。。。看到了真的就是那个感觉 井蛙观天尤不知 另外看到的就是工程实践真的是很难的过程&#…

如何输入一个整数逆序输出_如何匹配DSP输入输出信号

mosconi DSP可以通过DSP监察界面查看信号输入及输出的情况。对于主机是全频信号输出在 mosconi DSP的混合调校中进行的匹配&#xff0c;还有主机是主动分频信号输出在 mosconi DSP的混合调校中进行的匹配。若主机部分输出信号是反相(如视频案例)&#xff0c;又该如何匹配信号…

IDA——动态调试Linux上的ELF文件(整合他人博客)

先查看机器之间是否可以ping通 0x00&#xff1a;环境 待调试ELF文件 IDA 7.0 主机&#xff1a;Windows 虚拟机&#xff1a;Linux 达成效果&#xff1a;在Window上利用IDA远程动态调试linux里的ELF文件 0x01&#xff1a;Unbuntu里运行IDA的服务器组件 IDA附带以下组件&#x…

SQL SERVER最大用户连接数

使用 user connections 选项指定允许同时连接到 Microsoft SQL Server 的最大用户数。实际允许的用户连接数还取决于正使用的 SQL Server 版本以及应用程序和硬件的限制。SQL Server 最多允许同时 32,767 个用户连接。 因为 user conn…

Linux获得命令帮助

一、获得命令帮助 1.1、内部命令与外部命令 简单来说&#xff0c;在linux系统中有存储位置的命令为外部命令&#xff1b; 没有存储位置的为内部命令&#xff0c;可以理解为内部命令嵌入在linux的shell中&#xff0c;所以看不到。 type来判断到底为内部命令还是内部命令 [ro…

2019输入序列号闪退_正式告别60秒长语音 讯飞输入法新版评测:能动口我绝不动手...

一、前言&#xff1a;60秒长语音有希望消灭了从2010年&#xff0c;讯飞推出业界首个中文语音输入法&#xff0c;将语音输入带到大众面前直到今天&#xff0c;语音输入早就不再是当初功能机时代“语音王”的土味儿模样。如今&#xff0c;语音输入已经逐渐超过手写&#xff0c;成…

c#扩展方法奇思妙用性能篇一:扩展方法性能初测

最近写了几篇《c#扩展方法奇思妙用》的文章&#xff0c;一直只是讨论如何扩展、如何使用的问题&#xff0c;几乎没有涉及效率方面。而大家的回复好多都在问效率如何、性能怎样&#xff0c;也引起了我对效率的关注&#xff0c;今天将初步测试的结果发出来&#xff0c;大家一起探…

云服务器抢票咋用_[Mac] 阿里云服务器+分流抢票教程

一.前言临近过年, 抢春运的票成为了我们人生的头等大事, 我们都知道分流是最好用的抢票软件之一, 但是只支持windows, 又因为我工作的电脑是Mac所以不能安装, 是得想个办法才好, 最终决定了使用 阿里云服务器 分流 进行抢票, 是不是听起来很高级呢? 下面就跟着我们的上下文一…

Centos7忘记密码——转

应用场景 linux管理员忘记root密码&#xff0c;需要进行找回操作。 注意事项&#xff1a;本文基于centos7环境进行操作&#xff0c;由于centos的版本是有差异的&#xff0c;继续之前请确定好版本。 操作步骤 一、重启系统&#xff0c;在开机过程中&#xff0c;快速按下键盘上…

收集到的非常好的第三方控件

1. vs2010:增强xmal智能提示 http://visualstudiogallery.msdn.microsoft.com/en-us/1a67eee3-fdd1-4745-b290-09d649d07ee02. PowerCommands for Visual Studio 2008:http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectNamePowerCommands&Downl…

IDA

国庆礼物最强反编译工具 ida pro 7.0 破解补丁7.0sdk all sdk_utils 国内某团购群最新泄露的的版本 x86 arm x64 f5插件为最新版本 正版价值人民币3-5万 资源包含 ida pro 7.0 for mac ida pro 7.0 for windows IDA_Pro_7.0去局域网检测和兼容老版本idb补丁 2017/09/21 21…

hsql mybatis 表不存在_单元测试MyBatis与HSQL而不是Oracle

我想使用HSQL内存数据库对MyBatis持久层进行单元测试.真正的应用程序使用Oracle数据库.这工作正常,我们开始为id列添加自动递增的数字. Oracle需要使用序列来获取递增的数字,因此在Oracle数据库中创建了一个名为basis_seq的序列.在我的MyBatis mapperXML文件中我有这个&#xf…

AjaxToolKit学习笔记 之 ModalPopupExtender

1.控件功能描述 以模式窗口的方式弹出客户或服务器控件,以突出显示! 弹出的一般是DIV或PANEL. 2.控件属性描述 TargetControlID : 控制是否弹出的控件的ID. PopupDragHandleControlID : 允许拖拽的控件的ID. PopupControlID: 指定要弹出的控件的ID. BackgroundCssClass: 指定弹…

WIN10中DOCKER的安装与使用

WIN10中DOCKER的安装与使用 WIN10中DOCKER的安装与使用 1.docker的安装 环境准备 下载安装 2.docker的入门 开始使用 3.docker的常用配置 在PowerShell中设置 tab键自动补全&#xff08;其实用的都是cmd.exe&#xff09; Settings 4.用Dockerfile定义一个镜像 新建目录文件 构建…

单片机涡轮流量传感器_关于涡轮流量计传感器的维护保养

涡轮流量计是一种精密流量测量仪表&#xff0c;与相应的流量积算仪表配套可用于测量液体的流量和总量。广泛用于石油、化工、冶金、科研等领域的计量、控制系统。配备有卫生接头的涡轮流量计传感器可以应用于制药、食品等行业。 涡轮流量计传感器部分的维护保养要注意以下几点&…

孩子在华艺舞校的画画投稿-天女之梦

转载于:https://www.cnblogs.com/speeding/archive/2010/05/24/2623966.html

controller控制器怎么写_I2C控制器编程_框架

来源&#xff1a;百问网_嵌入式Linux wiki_jz2440 新1期视频维基教程 (视频文字版)作者&#xff1a;韦东山本文字数&#xff1a;3776&#xff0c;阅读时长&#xff1a;5分钟我们现在来讲I2C控制器怎么写&#xff0c;它是I2C程序中最核心的地方&#xff0c;我们要先构造几个结构…

关于数据库主键和外键

一、什么是主键、外键&#xff1a; 关系型数据库中的一条记录中有若干个属性&#xff0c;若其中某一个属性组(注意是组)能唯一标识一条记录&#xff0c;该属性组就可以成为一个主键 比如 学生表(学号&#xff0c;姓名&#xff0c;性别&#xff0c;班级) 其中每个学生的学号…

sql server charindex函数和patindex函数详解(转)

charindex和patindex函数常常用来在一段字符中搜索字符或字符串。假如被搜索的字符中包含有要搜索的字符&#xff0c;那么这两个函数返回一个非零的整数&#xff0c;这个整数是要搜索的字符在被搜索的字符中的开始位数。patindex函数支持使用通配符来进行搜索&#xff0c;然而c…

Win10最新批量激活

W269N-WFGWX-YVC9B-4J6C9-T83GX 先来说下使用激活码使用方法&#xff1a; 1、同时按下Win键X&#xff0c;然后选择命令提示符&#xff08;管理员&#xff09; 2、在命令提示符中依次输入&#xff1a; slmgr.vbs /upk &#xff08;此时弹出窗口显未“已成功卸载了产品密钥”…