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

在上一节中,我们讲述了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属性,表示本段对齐的方式。

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

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

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

相关文章

百度飞桨顶会论文复现(5):视频分类论文之《Representation Flow for Action Recognition》篇

这次老师在课上总共领读了4篇分类论文,我这里分享其中的一篇论文,是关于使用神经网络对光流进行学习。 课程地址是:https://aistudio.baidu.com/aistudio/education/group/info/1340。 论文地址是:https://arxiv.org/abs/1810.014…

智能算法(GA、DBO等)求解零等待流水车间调度问题(NWFSP)

先做一个声明:文章是由我的个人公众号中的推送直接复制粘贴而来,因此对智能优化算法感兴趣的朋友,可关注我的个人公众号:启发式算法讨论。我会不定期在公众号里分享不同的智能优化算法,经典的,或者是近几年…

一步步编写操作系统 50 加载内核3

接上节,在这里,我们把参数放到了栈中保存,大家注意到了,参数入栈的顺序是先从最右边的开始,最后压入的参数最左边的,其实这是某种约定,要不,为什么不先把中间的参数src入栈呢。既然主…

动手学无人驾驶(5):多传感器数据融合

本系列的前4篇文章主要介绍了深度学习技术在无人驾驶环境感知中的应用,包括交通标志识别,图像与点云3D目标检测。关于环境感知部分的介绍本系列暂且告一段落,后续如有需要再进行补充。 现在我们开启新的篇章,在本文中将会介绍无人…

详解两阶段3D目标检测网络PVRCNN:Point-Voxel Feature Set Abstraction for 3D Object Detection

在《动手学无人驾驶(4):基于激光雷达点云数据3D目标检测》一文中介绍了3D目标检测网络PointRCNN。今天介绍该作者新提出的3D检测模型:PVRCNN,论文已收录于CVPR2020。 作者个人主页为:https://sshaoshuai.gi…

一步步编写操作系统 53 任务状态段TSS介绍

操作系统是利用PCB来维护所有任务的,包括进程和线程,但cpu提供的是TSS,linux系统可没用它,因为效率太低。但是还是要了解下TSS才清楚操作系统中某些操作的原因。 本节中所讲的特权级与它有着密不可分的联系,TSS作用不…

动手学无人驾驶(6):基于IMU和GPS数据融合的自车定位

在上一篇博文《动手学无人驾驶(5):多传感器数据融合》介绍了如何使用Radar和LiDAR数据对自行车进行追踪,这是对汽车外界运动物体进行定位。 对于自动驾驶的汽车来说,有时也需要对自身进行更精确的定位,今天…

【Codeforces - 798C】 Mike and gcd problem(思维,贪心)

题干: Mike has a sequence A  [a1, a2, ..., an] of length n. He considers the sequence B  [b1, b2, ..., bn] beautiful if the gcd of all its elements is bigger than 1, i.e. . Mike wants to change his sequence in order to make it beauti…

一步步编写操作系统 48 加载内核1

其实,我们等了这一刻好久好久,即使我不说,大家也有这样的认识,linux内核是用c 语言写的,咱们肯定也要用c语言。其实...说点伤感情的话,今后的工作只是大部分(99%)都要用c语言来写&am…

Coursera自动驾驶课程第1讲:Welcome to the self-driving cars specialization

本专栏为Coursera自动驾驶课程笔记,B站上也有配套课程视频,对自动驾驶技术感兴趣的朋友可以看看。 本讲对应视频: https://www.bilibili.com/video/BV1WE411D74g?p1https://www.bilibili.com/video/BV1WE411D74g?p2https://www.bilibili.…

Coursera自动驾驶课程第2讲:The Requirements for Autonomy

上一讲《Coursera自动驾驶课程第1讲:Welcome to the self-driving cars specialization》对本课程进行了整体概述,同时回顾了自动驾驶汽车的发展历史。 从本讲我们开始进入正式的学习,我们将首先了解到如何划分自动驾驶汽车等级、以及自动驾…

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

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

Coursera自动驾驶课程第3讲:Self-Driving Hardware and Software Architectures

在上一讲《Coursera自动驾驶课程第2讲:The Requirements for Autonomy》中我们了解到了如何划分自动驾驶汽车等级、以及自动驾驶三大模块:感知、决策和执行。 本讲我们将学习新的模块:自动驾驶汽车的硬件和软件架构。 B站视频链接&#xff…

一步步编写操作系统 54 CPL和DPL入门1

我们在工作中,公司都给员工配有员工卡,此员工卡就是员工身份的“标签”,用它来出入公司、食堂就餐等。给公司创造价值的是员工的生产力,不是员工卡,员工卡只是公司人事部门管理员工的一种手段而已。 现在说计算机&…

Coursera自动驾驶课程第4讲:Safety Assurance for Autonomous Vehicles

在上一讲《Coursera自动驾驶课程第3讲:Self-Driving Hardware and Software Architectures》中我们了解了自动驾驶汽车常用的传感器和硬件组件、软件系统。 本讲我们将学习新的模块,也是自动驾驶汽车最重要的模块之一:安全模块。 B站视频链…

【Codeforces - 1000C】Covered Points Count(思维,离散化,差分)

题干: You are given nn segments on a coordinate line; each endpoint of every segment has integer coordinates. Some segments can degenerate to points. Segments can intersect with each other, be nested in each other or even coincide. Your task i…

Coursera自动驾驶课程第5讲:Vehicle Dynamic Modeling

在上一讲《Coursera自动驾驶课程第4讲:Safety Assurance for Autonomous Vehicles》中我们了解了自动驾驶汽车中一个非常重要的模块:安全模块。 本讲我们将学习新的模块:汽车运动学和动力学模块。(这部分可能需要一定的理论力学和…

Java同步锁——lock与synchronized 的区别【转】

在网上看来很多关于同步锁的博文,记录下来方便以后阅读 一、Lock和synchronized有以下几点不同: 1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现,synchronized是在JVM层面…

Coursera自动驾驶课程第6讲:Vehicle Longitudinal Control

在上一讲《Coursera自动驾驶课程第5讲:Vehicle Dynamic Modeling》中我们了解了汽车运动学和动力学模块。 本讲我们继续学习新的模块:汽车纵向控制。具体地,我们将学习PID控制算法,看看该算法是如何在自动驾驶汽车中应用的。 B站…

Java并发:线程共享变量可见性原理

0、线程安全性:线程安全性包括两个方面,①可见性。②原子性。 0.1、线程之间的通信:线程的通信是指线程之间以何种机制来交换信息。在命令式编程中,线程之间的通信机制有两种共享内存和消息传递。 (1)在共…