嵌入式工具集合介绍



工具集合介绍


接下来我们来看在交叉编译工具集中一个工具集的概念,也就是说我们交叉编译工具主要的一个目标也就是工具就是gcc,aim-linux_gcc,但是我们在安装gcc的同时也安装了一些其他的工具,这些工具我们称之为工具集。那么这个工具集对于我们开发者来说,主要起到一些分析问题和解决问题一些的辅助工具。但是对于编译来说可能用得到也可能用不到。比如objdump 和objcopy,其实objcopy我们之前讲arm的时候说过,它就可能是最后生产arm裸机开发的重要程序。


tool1.png


如图,当然还是一样,我们现在先来理解一下这些常用的命令集。命令集大家随着开发的深入或者是以后不断去做调试的经验的丰富这些命令级你可能会慢慢的越来越熟悉。下面我们来看第一个叫readelf,那这个名字其实很好理解read也就是读而elf,至于什么叫做elf我先简单提一个概念如下图:


tool2.png


如图,就说在我们之前学习操作系统的时候我们其实有这样一个思想,图上最下面的四边形就是硬件上面四边形是操作系统,上面四边形也就是操作系统上面会提供相应的应用程序开发。那很显然,大家来思考一下我们的hello world这样的程序最终是由操作系统来执行最后由操作系统控制硬件操作的。那么我们操作系统去解释hello world是什么怎么去解释的呢?它不是一个二进制一个二进制的命令的执行的效果。就是说我们一个hello world编译成一个build,我们不能光认为build它只是一个代码的集合(图上右边的四边形)。其实我们的程序中分了两块,也就是说我们真正可执行文件其实分为两个部分,一个就是我们真正的执行程序的代码,但是我们说光有这个不行,因为我们的操作系统光有这个它是不知道如何去和操作系统打交道的,因为这个只是一个程序只是一个你的程序并没有操作系统中需要的其他数据的类型。所以我们操作系统上运行的程序有一个非常重要的特点,它一般是由两个部分组成的,一个是正文也就是真正代码的集合,另外一个是在正文的上面一般有一个头信息(图上右边四边形上面的椭圆)而这个头的格式是不同的,比如说我们的windows我们叫PE头那么我们的linux我们就叫做ELF头,也就是说我们真正的文件的内部实际上,上面它是有一个信息的,这个信息是专门给操作系统去看的。比如说我们的Linux是以ELF这样一个格式去把这个头给它切割的,如图上椭圆形就相当于一堆二进制的数据,而这堆数据我们用了一种ELF的规范去把数据给取出来然后就有相应的一些信息了,而Windows不一样(如图中椭圆下的四边形)Windows叫PE,那么Windows操作系统自然用PE的格式去解释这个头然后把头信息拿到,我们一般情况下只要知道有这个ELF头就可以,然后像我们开发裸机程序也说过因为这里ELF是不具备执行的,它只具备操作系统的一个阅读能力,所以我们需要通过objcopy这个命令把这个头给去掉,只取出里面真正的代码和数据。


所以说这个是readelf中的,它相当于跟objcopy是不一样的,objcopy是不要ELF而readelf最主要的目的是读这个东西,那么怎么读呢?


tool3.png


如图,还是按照我们之前的那个程序,因为我们之前是用build去编的那自然而然我们要用x86的readelf,如果说我们是abc的话那么用普通的readelf也能读,只是说它可能读不了,就是说在没有加前缀的readelf我们认为这个readelf实际上是x86情况下能运行的程序,那么我们先读abc的时候要注意一个选项“-h”也就是说专门读这个头信息然后点击回车键,大家看其实也一样的可以读出来的,因为abc里虽然是arm程序但是上面还是个头信息,我们先用file看一下,file中大家可以看第一个类型是ELF 32-bit小端可执行程序,也就是说我们后面是arm的前面的头信息还是ELF,而标准ELF它只是给操作系统去读跟平台没有关系所以我们仍然能够读的出来。


而file凭什么能够读到arm里面的信息,其原因就是abc前面的头信息中其实已经包含了很多很多字节段,而这些字节段它肯定是集合我们通过我们标准的ELF的形式通过file就可以把arm的头信息给取出来,这样我们就可以知道上面的ARM其实就在下面file abc读出的内容中。


以上就是这个的基本特点,也就是ELF的第一个作用。就是它可以标识底下的正文是什么类型如下图:


tool4.png


如图,我们还是先看x86的情况,然后输入命令“readelf -h build”点击回车键后,build中大家注意其中涉及到一些很奇怪的值,然后我们来看看这些值是怎么理解,当然我们现在在Linux里面看,如果想看这个文件真正的内容有一个命令是od就是看它里面二进制的程序,但是这不是很方便我们还是把它转到Windows下,用Windows的一些软件去看一下,比如说我们在这里有个空目录,然后我们把刚才的一个目录拷过来,然后输入命令“gcc -o build 1.c”把1.c给它编译出来,这个时候Windows下就应该有Windows程序了。


tool5.png


如图,我们看到Windows里已经有build这个程序了,我们可以用一些工具打开它,其中Notepad++看着大家知道是乱码,所以如果是Notepad++的同学可能要注意在上面要安装一个插件,这个插件叫做HEX-Editor,就是说这个插件是专门来看十六进制的如下图:


tool6.png


如图,点击图上鼠标那里会发现其实它就是分两列,一列就是真正的二进制以十六进制呈现出来的另一列就是十六进制对应的码。然后看之前的那个程序,我们会发现Magic的信息和图上左边第一排信息是一样的,说明readelf其实就是读的我们前面的那个字节,所以这个我们要清楚。


然后对应ELF我还想说最后一个小问题:


tool7.png


如图,看到图中入口点地址,其实我们的Windows包括Linux一样双击一个程序的时候其实并不是从main函数中运行,它实际上是在我们双击这个程序(图中大长方形)中的时候就是在我们入口点地址有个头信息也就是0x400440其实是放到我们真正的第一个程序(图中打长方形中的下方长方形),然后在这个程序中我们其实会跳,不断初始化,最后会在最后一个程序中去(有一句话比如在arm中就是blmain就相当于是bl跳到main中)寻找main标签(图中大长方形上面的小长方形)如果main标签在这它就运行,那像我们平时写程序大家都知道如果我记这些编译的时候我没有main函数,编译器就会直接报错也就是找不到,因为编译的时候它跳到main的时候结果blmain标签找不到,它链接就失败了,所以说这个是现在操作系统上程序运行的一个比较典型的思路,也就是在0x400440这个值上,这个值是在我们操作系统中自动默认的虚拟地址,这个我们不用管,但是假设这是个黑客程序,如果我现在把一个程序放到一个比较特殊的位置(图中的椭圆)比如说这是串病毒,然后这个病毒假设是300或800这样的地址,那我可以通过之前学IO的办法,我们如果能在前面的头信息能定位到0x400440这个位置,定位到这个地址后我通过文件IO的方法把它改了,就改成300或800这样一个值。然后这样一看这个程序一执行就先执行的是我的病毒,然后最后可能通过病毒的某些特别的程序跳到可能执行blmain,也可能直接死掉。所以有很多病毒程序我们一双击可执行程序它就先运行病毒或者木马程序,其原理就是很多病毒的设计者都是按照入口点地址的值去进行设计的。


有些同学会问入口点地址0x400440到底在头文件中在不在呢?


因为我们是十六进制的所以我们要两个两个看。那么在下面这个图中:


tool8.png


如图,因为这个地方设计到的是大端小端的问题也就是说它是一个从小到大的问题,其中大家可以看到前面是头信息也就是我们刚才读出的头信息,后面可能看不懂,但是看到图中加深颜色那里的时候跟上图的“0x400440”是一样的。因为我们现在这个读法是读之前那个值的后面六位。所以说“0x400440”这个值其实就在文件IO中十六个字节到第七个字节就得放得我们的入口地址,如果我通过文件IO的方法把它定位然后相应的去写相应的值,就相当于我文件到另一个地方去运行,那么就可能程序运行飞了或者运行到一个病毒程序。


所以我们将ELF也是告诉大家一下,我们真正的一个在操作系统之上的可执行程序实际上是有一个头信息的概念。


以上,这就是我们说的ELF。下面我们说一下size,size其实就是代表读取我们可执行程序。如下图:


tool9.png


如图,我们输入size build命令,它就可以把我们的代码段、数据段都给列出来,然后你就可以知道我们代码段、数据段有多少个字节。当然比如说当我们把这个程序改变一下“int abc =100”这个时候数据段就多了四个字节,然后我们在编译一下,输入命令“gcc -o build 1.c”这个时候我们在用size看这个build,然后看跟刚才的560来比现在变成了564。


所以说size就是一个查看ELF信息的或者是ELF可执行程序每个段的一个大小信息。



【本文由麦子学院独家原创,转载请注明出处并保留原文链接】

logo
© 2012-2016 www.maiziedu.com
蜀ICP备13014270号-4 Version 5.0.0 release20160127

免费领取价值1888元求职宝典!

客服热线 400-862-8862

回到顶部