在上一节中,我们讲述了elf格式的部分理论知识,为什么是部分呢?因为我们本着“够用”的原则,只把我们需要了解的部分说完啦。不过,我相信大部分同学仅仅凭上一节中的理论知识还是领悟不到elf本质,咱们在本节开始分析前面咱们写过的“内核”,让大家看清elf文件的每一个字节。

为了让大家看清楚elf文件内部,咱们要用之前的xxd命令,为了方便使用,如很久很久以前所述,已经将其封装成了xxd.sh脚本,参数1是待查看的文件名,参数2是文件内的起始字节,参数3是查看的连续字节数。脚本是逐字节输出文件的内容。脚本内容很简单,就是xxd命令而已:xxd -u -a -g 1 -s $2 -l $3 $1,您也看到了,参数比较多,弄成脚本完全是为了避免每次复杂的参数键入。为了让大家方便使用,我已经将其放到了tool目录下,脚本中有参数说明,这里不再列出。下面是用此脚本处理kernel.bin的输出,见图

之前我们就用过多次xxd命令啦,对于输出想必大家一定很熟悉啦。脚本的输出大概分了三部分,最左边的一列是16进制的地址,或者称为偏移量最为恰当。中间这一大块矩阵似的16进制数字是文件中的内容,每两位16进制数字为一字节,每行共16个字节。最右边那一列,含有点点的、偶尔伴有可读字符的部分是字符显示区,这部分将内容按照字符编码显示,当然,前提肯定得是可打印字符,控制字符肯定不行,所以只要不是可显示的字符便显示为‘.’。

为了方便大家查看elf文件中各部分属性,我在各属性下面用下划线予以区分。其中,细下划线属于elf header的范围,粗下划线属于program header table程序头表的范围。在各范围之中的各属性,又以明显的下划线分隔,相信大家一定能一目了然。

咱们按照从上到下的顺序,先从细下划线的elf header部分说起。

第一行是e_ident数组,前4字节是固定的elf魔数,正如您看到的,它们是0x7f、和字符ELF的ascii:0x45、0x4c、0x46。所以您在显示区看到了ELF的三个字符。紧跟其后的三个1分别是e_ident[4]、e_ident[5]、e_ident[6]三个成员,代表的意义是32位elf文件、小端字节序、当前版本。后面的9个00是e_ident[7]~ e_ident[15],这些确实都已经初始化为0。

现在看第二行。

第1个下划线处的内容是02 00,由于是小端字节序,所以其值为0x0002。以下为方便陈述,只说该字节序所表示的数值。这个是e_type属性,它占2字节,值为2表示类型为ET_EXEC,即可执行文件(有兴趣的同学可以自行查看linux下的.o目标文件,其e_type类型是值为1的ET_REL,即待重定位类型)。

本行的第2个下划线处的内容是0x0003,占2字节。该位置是e_machine属性,即EM_386,表示该elf文件是运行在Intel 80386平台。

第3个下划线处的内容是0x00000001,占4字节。该位置是e_version属性,即版本信息。

第4个下划线处的内容是0xc0001500,占4字节,该位置是e_entry属性,即程序的虚拟入口地址。

第5个下划线处的内容是0x00000034,占4字节,该位置是e_phoff属性,表示program header table程序头表在文件中的偏移量,这里的偏移量是0x34。

现在看第三行。

第1个下划线处的内容是0x0000055c,占4字节,该位置是e_shoff,表示section header table节头表在文件内的偏移量,这里的值为0x55c,表示在本文件偏移0x55c字节处为节头表。之前说过啦,若没有节头表,此处便为0。

第2个下划线处的内容是0x00000000,占4字节,该位置是e_flags属性。

第3个下划线处的内容是0x0034,占2字节,该位置是e_ehsize属性,表示elf header大小是0x34字节。这和前面e_phoff属性值大小一致,可见,程序头表紧跟着elf header之后。

第4个下划线处的内容是0x0020,占2字节,该位置是e_phentsize属性,即program header的结构:struct Elf32_Phdr的字节大小,值为0x20字节。

第5个下划线处的内容是0x0002,占2字节,该位置是e_phnum属性,即程序头表中段的个数,这里为2个段。

第6个下划线处的内容是0x0028,占2字节,该位置是e_shentsize属性,即节头表中各个节的大小。

现在看第四行。

第1个下划线处的内容是0x0006,占2字节,该位置是e_shnum属性,即节头表中节的个数,这里表示有6个节。

第2个下划线处的内容是0x0003,占2字节,该位置是e_shstrndx属性,即string name table在节头表中的索引为3。

现在开始分析粗下划线范围的程序头表部分。

从第4行到第8行是程序头表的范围,前面说过啦,程序头表中共有2个段,每个段大小是0x20字节。这有两个粗下划线,每个占0x20字节。大家注意图中,在两个粗下划线间有个小竖线,这是用来区分两个段的。竖线左右两边各是一个段。

下面咱们按照struct Elf32_Phdr结构来分析,该结构中每个属性都占4字节,不再赘述。现在还是继续说图的第4行。

第1个粗下划线值为0x00000001,该位置是p_type属性,值为1,即表示PT_LOAD类型,可加载程序段,由于kernel.bin已经是链接后的可执行程序啦,所以,这PT_LOAD类型符合我们的认知。

第2个粗下划线值为0x00000000,该位置是p_offset属性,表示本段在文件内的偏移量。这个偏移量为0,似乎很奇怪,这表示该段的起始是从文件头开始也算起啦,文件开头的部分不是elf header吗?不是代码啊,这是要闹哪样?好吧,到底是什么情况,一会咱们细说。

第3个粗下划线值为0xc0001000,该位置是p_vaddr属性,表示本段被加载到内存后的起始虚拟地址。看到这里,似乎觉得上面的p_offset为0有那么一点合理啦,结合elf header中的e_entry的值为0xc0101500,不知您想到了点什么。咱们先把剩下的说完。

第4个粗下划线值为0xc0001000,该位置是p_paddr属性,它通常和p_vaddr值一致,但该属性是保留项,咱们不用关注。

第5个粗下划线值为0x00000505,该位置是p_filesz属性,表示本段在文件中的字节大小。

第6个粗下划线值也应该是0x00000505,该位置是p_memsz属性,表示本段在内存中的大小,因为段无论在哪里,逻辑大小是不变的,故该值等于p_filesz。

第7个粗下划线值为0x00000005,该位置是p_flags属性,表示与本段相关的标志。5=4+1=PF_R+PF_X,在此表示可读,可执行,根据此属性,我们推测此段为代码段。

第8个粗下划线值为0x00001000,该位置是p_align属性,表示本段对齐的方式。

第一个段咱们说完了,第二个段这里就不解释啦,留着大家自己练手吧。

一步步编写操作系统 47 elf格式文件分析实验相关推荐

  1. 一步步编写操作系统 47 48 二进制程序运行方式

    操作系统并不是在功能上给予用户的支持,这种支持是体现在机制上.也就是说,单纯的操作系统,用户拿它什么都做不了,用户需要的是某种功能.而操作系统仅仅是个提供支持的平台. 虽然我们是模仿linux来写一个 ...

  2. 一步步编写操作系统 71 直接操作显卡,编写自己的打印函数71-74

    一直以来,我们在往屏幕上输出文本时,要么利用bios中断,要么利用系统调用,这些都是依赖别人的方法.咱们还用过一个稍微有点独立的方法,就是直接写显存,但这貌似又没什么含量.如今我们要写一个打印函数了, ...

  3. 一步步编写操作系统 69 汇编语言和c语言共同协作 70

    由于有了上一节的铺垫,本节的内容相对较少,这里给大家准备了两个小文件来实例演示汇编语言和c语言相互调用. 会两种不同语言的人,只是掌握了同一件事物的两种表达方式.人在学习一种新语言时,潜意识里是建立了 ...

  4. 一步步编写操作系统 62 函数调用约定

    由于我们要将c语言和汇编语言结合编程啦,所以一定会存在汇编代码和c代码相互调用的问题,有些事情还是要提前交待给大家的,本节就是要给大家说下函数调用规约中的那些事儿. 函数调用约定是什么? 调用约定,c ...

  5. QT 编写Rtf(富文本格式) 文件实例

    QT 编写Rtf(富文本格式) 文件实例 2016-01-10 14:11:25 小K小Q 阅读数 3450更多 分类专栏: QT学习之路 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA ...

  6. 一步步编写操作系统 46 linux的elf可执行文件格式1

    ELF文件格式依然是分为文件头和文件体两部分,只是该文件头相对稍显复杂,类似层次化结构,先用个ELF header从"全局上"给出程序文件的组织结构,概要出程序中其它头表的位置大小 ...

  7. 一步步编写操作系统 67 系统调用的实现1-2 68

    接上文: 系统调用的子功能要用eax寄存器来指定,所以咱们要看看有哪些系统调用啦,在linux系统中,系统调用是定义在/usr/include/asm/unistd.h文件中,该文件只是个统一的入口, ...

  8. 一步步编写操作系统 51 加载内核4

    咱们的内容都是连栽的,如果您没看过我之前的文章,本节您是看不懂的. 接上节. 介绍完内核初始化的函数kernel_init后,本节代码部分还差一点点没说啦,下面看代码: -略 179 ;在开启分页后, ...

  9. linux中elf文件的作用,Linux中ELF格式文件介绍

    一. ELF简介 ELF(Executable and Linkable Format)即可执行连接文件格式,是一种比较复杂的文件格式,但其应用广泛.与linux下的其他可执行文件(a.out,cof ...

最新文章

  1. 《思科UCS服务器统一计算》一1.2 数据中心的演变
  2. Hoogle之装饰模式设计手机(下)
  3. Effective Java读书笔记六:方法
  4. fluent的udf需要c语言环境吗,[转载]FLUENT UDF 使用指导
  5. hdu 5131 Song Jiang#39;s rank list 【2014ACM/ICPC亚洲区广州站-重现赛】
  6. 表达式_ya是不合法的c语言标识符,高级语言程序设计复习题.doc
  7. 2012年12月第二个周末
  8. console java_Java Console format()方法与示例
  9. number类型转换java_Number()数据类型转换
  10. 三十分钟包会——正则表达式
  11. inject 响应式_Vue 3 组合式 provide/inject
  12. Xp系统优化 预读文件(8)
  13. PaddleOCR二次全流程——2.使用StyleText合成图片
  14. matlab盒子分形维数_根据计盒维数原理求一维曲线分形维数的matlab程序
  15. 云服务器宽带1M代表的什么意思?下载速度是1M/S吗?
  16. 【Elementory OS 6】安装 tweak
  17. 计算机技术毕业生个人简历,计算机技术毕业生个人简历模板
  18. A/N GPU架构解析
  19. 如何做个人微信号营销,一个人人都能月入3000微信营销方法你真的知道吗?
  20. win10 卸载软件 清除注册表 Revo Uninstaller Pro

热门文章

  1. android旋转动画的两种实现方式
  2. 《科技之巅2》序——机器智能数据智能:工具之王
  3. Python学习札记(十七) 高级特性3 列表生成式
  4. iOS9适配(包括APNs)的改变
  5. IOS开发学习记录第4天之C语言学习
  6. 使用客户端对象模型读取SharePoint列表数据
  7. Delphi 对象的创建(create)与释放(free/destory)
  8. hdu 4324 Triangle LOVE
  9. HDU 3306 Another kind of Fibonacci
  10. 信息系统项目管理系列之九:项目质量管理