当前位置:文档之家› ARM平台下ELF文件反汇编

ARM平台下ELF文件反汇编

ARM平台下ELF文件反汇编
ARM平台下ELF文件反汇编

ARM平台下的反汇编

目的

作为代码插桩过程的前提,首先需要对于所提供的二进制代码进行必要的分析,了解ELF文件的结构以及ARM平台的指令编码,将二进制01码翻译成为用户可读的汇编代码。通过对于汇编代码的分析,用户可以得到程序应用中各个函数起始地址以及程序各个模块的流程调用等重要信息,为代码插桩提供详细的数据。经过插桩的代码最后通过再一次汇编的过程输出到目标文件。因此,正确、快速地进行平台下的反汇编工作显得十分关键。

ARM平台介绍[1-2]

ARM(Advanced RISC Machines)是微处理器行业的一家知名企业,设计了大量高性能、廉价、耗能低的RISC(精简指令集计算机)处理器、相关技术及软件。技术具有性能高、成本低和能耗低等特点。经历过早期自己设计和制造芯片的不景气之后,公司自己开始不制造芯片,只将芯片的设计方案授权(licensing)给其他公司,由它们来生产,形成了较为独特的盈利模式。RISC结构优先选取使用频率最高的简单指令,避免复杂指令;将指令长度固定,指令格式和寻地方式种类减少;以控制逻辑为主,不用或少用微码控制等。ARM处理器在秉承RISC体系优点的基础上,进行了针对嵌入式系统的功能扩展,使得指令更加灵活,处理器性能在嵌入式平台上更加突出。

ARM微处理器的核心结构如下图所示:

Figure 1.ARM处理器核心结构示意图[2]

数据指令通过数据总线进入到处理器核心,然后在指令被执行之前经由指令解码器翻译。和所有精简指令集处理器一样,ARM采用了load-store架构,load指令将数据从内存拷贝到寄存器,store指令将数据从寄存器转储到内存,所有的数据处理在寄存器中完成。

ARM处理器是32位的处理器,所有的指令默认将寄存器视为32位的值,因此Sign extend会在数据写入寄存器之前将所有8位或者12位的数值转换为32位的数值。ARM指令通常有两个源寄存器: Rn, Rm 以及一个目标寄存器,操作数都是从寄存器通过内部总线读取得到。

核心的ALU (arithmetic logic unit) or MAC (multiply-accumulate unit) 从内部总线A,B上取得操作数进行运算,然后将结果写入目标寄存器。

ARM处理器一个很大的特色是寄存器Rm可以选择性地在进入ALU运算之前在barrel shifter中进

行预处理,barrel和shifter的结合可以高效地计算计算许多复杂的表达式和地址。

对于load和store指令操作来说,最后的incrementer用来更新地址寄存器在读写下一个寄存器的

值到下一个内存地址之前。

ARM处理器的架构形成了以下几个特点:

1.体积小、低功耗、低成本、高性能。这一特点使得ARM处理器在移动设备上得到广泛的应用,这也是ARM处理器能够占有移动设备市场80%份额的强有力原因。

2.支持Thumb(16位)/ARM(32位)双指令集。ARM指令集支持ARM核所有的特性,具有高效、快速的特点;Thumb指令集具有灵活、小巧的特点。双指令集的特点使得ARM 处理器能够很好地兼容8位/16位器件,使得代码更加紧凑。指令长度的固定在一定程度上方便了ELF文件的分析以及插桩工作的进行。另外在ARM的指令系统中设计者还加入了一些在嵌入式系统中经常用到的一些DSP操作指令,使得一些系统的设计没有考虑添加额外的DSP模块来支持系统的功能。

3.大量使用寄存器,指令执行速度更快,大多数数据操作都可以在寄存器中直接完成,大大增强了地址处理的执行效率。

4.寻址方式灵活简单,执行效率高;ARM拥有常见的寻址方式之外,另外还增加了一些非常实用的寻址方式,如:

●多寄存器寻址:MOV R1, {R2-R4, R6}.多寄存器寻址一次可传送几个寄存器值,允许一条

指令传送16个寄存器的任何子集或所有寄存器。它还将寄存器之间的简单加减操作囊

括于指令当中,大大精简了这些简单指令所占有的代码空间,也使得程序的可读性有

所提升。

●寄存器移位寻址:MOV R0, R2, LSL #3. ARM处理器中特有的Barrel Shifter使得数据的移

位操作能够在运算单元之外进行,方便了程序代码的编写,同时也提高了代码执行的

效率。

●堆栈寻址:LDMFD SP!, {R1-R7, PC}。堆栈是一个按特定顺序进行存取的存储区,操作

顺序为“后进先出”。堆栈寻址是隐含的,它使用一个专门的寄存器(堆栈指针)指向一块

存储区域(堆栈),指针所指向的存储单元即是堆栈的栈顶。存储器堆栈根据增长方向可

分为两种:递增和递减;根据栈顶指向的位置内容又可分为满堆栈和空堆栈。这些寻

址方式的选项可以满足各种堆栈的需求,将堆栈的内容直接作为操作数参与运算。

这些新的寻址方式的增加极大地方便了汇编程序的编写,当然同时也使得编译的结果更为整洁精炼。

5.指令数据并行存取。由于数据的存取操作在指令流中占据了将近四分之一的比例。一个基本的load操作需要3个时钟周期,一个store操作也需要2个时钟周期,这大大影响到了平均CPI——指令的执行效率,因此如何有效地优化这些指令在高速处理器中显得格外重要。

在ARM 9处理器中采用了Harvard Memory Architecture,这使得指令的获取和数据的读取能够同时进行。[3]

Figure 2. ARM 7与ARM 9 指令执行流程对比图[3]

由图可见,在ARM 9的指令执行流程中额外增加了两步,这使得原本拥挤的执行步骤可以将任务相对平均地分布到其它步骤中去,由此增大了指令的执行频率。另外在解码阶段,在ARM 9中更是增设了一个Thumb decoder,使得两种指令的解码得以并行处理,也省去了将thumb指令转换为ARM指令带来的麻烦与时间消耗。

ARM处理器的这些设计要点使得处理器在性能、能耗方面都有很好的表现,这也正是ARM处

理器能被广泛应用于手机等移动电子产品上的重要原因。

ARM平台下可执行文件的反汇编

ELF文件简介[4]

ELF (Executable and Linkable Format)是UNIX 类操作系统中普遍采用的目标文件格式,分为三种

类型:

●可重定位文件 (Relocatable File)包含适合于与其他目标文件链接来创建可执行文件或者共享

目标文件的代码和数据。

●可执行文件 (Executable File)包含适合于执行的一个程序,此文件规定了 exec() 如何创建一

个程序的进程映像。

●共享目标文件(Shared Object File)包含可在两种上下文中链接的代码和数据。首先链接编辑

器可以将它和其它可重定位文件和共享目标文件一起处理,生成另外一个目标文件。其次,动态链接器(Dynamic Linker)可能将它与某个可执行文件以及其它共享目标一起组合,创建进程映像。

目标文件全部是程序的二进制表示,目的是直接在某种处理器上直接执行。

ELF文件剖析

ELF文件在不同的视图下有不同的文件结构,共有两种视图:链接视图和执行视图。

Figure 3.ELF文件内容结构示意图(链接视图、执行视图)[2]

两种结构视图的顶部都含有一些头部信息,包括文件的类型、可执行的平台信息以及一些头部

表的属性信息:表的开始字节、表项大小以及表项数量。ELF文件中有两个非常重要的头部表格:节区头部表、程序头部表。

●节区头部表包含了文件中所有节区的基本信息,每一个节区在表中都有一个项,描述了该

节区的名字、大小、偏移位置等关键信息。节区头部表在链接的过程中指导链接器将相同属性的节区合并成为一个段,因此需要进行链接的文件必须包含节区头部表。

可执行文件或者共享目标文件的程序头部是一个结构数组,每个结构描述了一个段或者系统准备程序执行所必需的其它信息。目标文件的“段”包含一个或者多个链接视图下的

“节区”,也就是“段内容(Segment Contents)”。程序头部表仅对于可执行文件和共享目标文件有意义,它指导系统如何去创建一个进程映像。

链接视图下保留的节区有.text(代码段), .data(初始化数据段), .bss(未初始化数据段), .symtab(符

号表,包含用来定位、重定位程序中符号定义和引用的信息), .strtab(字符串表,包括头部表或

程序中字符串的引用映射)等等,非保留的节区中包括用户自定义的函数等。用户可以在编译

的时候增加选项,根据需求指定这些特殊节区的起始位置、对齐方式等。

值得注意的是,符号表中的所包含的通常是一些静态变量或者函数的定义位置,但是由于通常

文件与文件之间存在函数和变量的调用关系,在文件进行链接生成可执行文件之前,符号表结

构体中的值是未定义的,必须通过链接器确定函数和变量在输出可执行文件中的确切偏移位置。

ELF文件的查看工具

现今已存在一些ELF文件查看工具,如通用的objdump以及经常的readelf,通过这些工具我们可以查看ELF文件的具体内容,方便进行文件的分析。

objdump

objdump是以一种可阅读的格式让你更多地了解二进制文件带有的信息的工具。objdump借助BFD,更加通用一些, 可以应付不同文件格式,它提供反汇编的功能。

由于本项目中所要解析的是在ARM平台下可执行的ELF文件,gcc自带的objdump工具不支持arm平台下的编译文件。因此需要构建linux下交叉编译环境,在基于ARM的嵌入式系统开发中,常常用到交叉编译的GCC工具链有两种:arm-linux-*和arm-elf-*,两者区别主要在于使用

不同的C库文件。arm-linux-*使用GNU的Glibc,而arm-elf-*一般使用uClibc/uC-libc或者使用REDHAT专门为嵌入式系统的开发的C库newlib。两类交叉编译环境的构建比较繁琐,一般用

户可以下载构建好的交叉编译工具,这样用户可以直接使用对应的arm-linux-objdump或arm-

elf-objdump查看相应ELF 文件的可读反汇编结果。使用者可以通过arm-*-objdump –D *.elf 直

接查看反汇编的结果:

Figure 4.Arm-linux-objdump反汇编结果

当然用户还可以通过参数的设定有选择地进行文件内容信息的查看。

readelf

另一个常用的查看工具是readelf,readelf则并不借助BFD,而是直接读取ELF格式文件的信息,得到的信息也略细致一些。通过指令readelf –a *.elf用户可以看到文件的具体结构和内容对照。

Figure 5.Readelf执行结果

由图可见,readelf将ELF文件信息按照字节顺序将一些重要的信息以可读的形式显示出来。但

是readelf本身不具备反汇编的功能,由于本项目需要对于汇编指令进行分析和插桩工作,还

需要对于汇编代码进行流程的分析,现有的ELF文件查看工具显然不能够满足这些具体的需求,因此需要在一些开源工具的基础上进行功能的扩展或者根据ELF文件描述文档独立开发出新的

带有插桩功能的反汇编工具。

代码控制流程图的生成

通常代码插桩的位置位于函数的出入口、循环的头尾等地方,为了保证插桩的准确性和全面行,插桩程序需要对于汇编程序的代码块绘制详细的控制流程图,清楚地了解各个代码块之间的调

用跳转关系。Diablo就是这样一个满足这类需求的工具。

Figure 6.程序指令流程控制图

Diablo是一个二进制代码编辑的架构,它支持ARM,X86等多种目标平台下可执行文件格式。Diablo的核心和后台提供了读写目标文件、汇编反汇编代码、创建控制流程图(Interprocedural Control Flow Graph) 等功能,同时它的数据结构分为架构相关和架构无关两个部分,方便架构依赖和架构无关的代码分析。[5-6]

Figure 7.Diablo执行流程

Diablo的工作过程分为4个流程,链接、编译、流程图绘制以及流程图转换。它分析链接后反编译的代码绘制出流程之间的控制逻辑关系,根据调用关系以及实际的需求进行代码的插桩和优化工作。由于Diablo是开源的,可以利用它源代码中流程控制图的部分,生成流程控制图,继而进行代码的插桩工作。

小结

在代码插桩的过程中,反汇编和流程控制图的生成是极为基础,也是关键的两个前提步骤。这需要程序员对于所用平台的二进制文件的结构和内容都有全面的了解,充分利用现有的工具和开放源码,对文件进行必要的解析和流程分析,根据用户定制的代码插桩要求进行插桩工作。

参考资料

1. 百度百科. ARM. Available from: https://www.doczj.com/doc/0211072752.html,/view/11200.htm.

2. Seal, D., ARM Architecture Reference Manual. 2000.

3. The ARM9 Family - High Performance Microprocessors for Embedded Applications, in

Proceedings of the International Conference on Computer Design. 1998, IEEE Computer

Society. p. 230.

4. 滕启明, ELF文件格式分析, in JBEOS-TN-03-00

5. 2003, 北京大学信息科学技术学院操作系

统实验室.

5. Bus, B.D., et al., The design and implementation of FIT: a flexible instrumentation toolkit, in

Proceedings of the 5th ACM SIGPLAN-SIGSOFT workshop on Program analysis for software

tools and engineering. 2004, ACM: Washington DC, USA. p. 29-34.

6. Ghent University, B. Diablo Manual. Available from: http://diablo.elis.ugent.be/manual_main.

[6]

pe文件格式

PE文件格式详解(一)――基础知识 什么是PE文件格式: 我们知道所有文件都是一些连续(当然实际存储在磁盘上的时候不一定是连续的)的数据组织起来的,不同类型的文件肯定组织形式也各不相同;PE文件格式便是一种文件组织形式,它是32位Wind ow系统中的可执行文件EXE以及动态连接库文件DLL的组织形式。为什么我们双击一个EXE文件之后它就会被Window运行,而我们双击一个DOC文件就会被Word打开并显示其中的内容;这说明文件中肯定除了存在那些文件的主体内容(比如EXE文件中的代码,数据等,DOC文件中的文件内容等)之外还存在其他一些重要的信息。这些信息是给文件的使用者看的,比如说EXE文件的使用者就是Window,而DOC文件的使用者就是Word。Window可以根据这些信息知道把文件加载到地址空间的那个位置,知道从哪个地址开始执行;加载到内存后如何修正一些指令中的地址等等。那么PE文件中的这些重要信息都是由谁加入的呢?是由编译器和连接器完成的,针对不同的编译器和连接器通常会提供不同的选项让我们在编译和 联结生成PE文件的时候对其中的那些Window需要的信息进行设定;当然也可以按照默认的方式编译连接生成Window中默认的信息。例如:WindowNT默认的程序加载基址是0x40000;你可以在用VC连接生成EXE文件的时候使用选项更改这个地址值。在不同的操作系统中可执行文件的格式是不同的,比如在Linux上就有一种流行的ELF格式;当然它是由在Linux上的编译器和连接器生成的,

所以编译器、连接器是针对不同的CPU架构和不同的操作系统而涉及出来的。在嵌入式领域中我们经常提到交叉编译器一词,它的作用就是在一种平台下编译出能在另一个平台下运行的程序;例如,我们可以使用交叉编译器在跑Linux的X86机器上编译出能在Arm上运行的程序。 程序是如何运行起来的: 一个程序从编写出来到运行一共需要那些工具,他们都对程序作了些什么呢?里面都涉及哪些知识需要学习呢?先说工具:编辑器-》编译器-》连接器-》加载器;首先我们使用编辑器编辑源文件;然后使用编译器编译程目标文件OBJ,这里面涉及到编译原理的知识;连接器把OBJ文件和其他一些库文件和资源文件连接起来生成EXE文件,这里面涉及到不同的连接器的知识,连接器根据OS的需要生成EXE文件保存着磁盘上;当我们运行EXE文件的时候有W indow的加载器负责把EXE文件加载到线性地址空间,加载的时候便是根据上一节中说到的PE文件格式中的哪些重要信息。然后生成一个进程,如果进程中涉及到多个线程还要生成一个主线程;此后进程便开始运行;这里面涉及的东西很多,包括:PE文件格式的内容;内存管理(CPU内存管理的硬件环境以及在此基础上的OS内存管理方式);模块,进程,线程的知识;只有把这些都弄清楚之后才能比较清楚的了解这整个过程。下面就让我们先来学习PE文件格式吧。

试验二ARM汇编语言程序设计

实验二 ARM汇编语言程序设计 一、实验目的 1.了解ARM汇编语言的基本框架,学会使用ARM的汇编语言编程 2.掌握ARM汇编指令 二、实验设备 1. EL-ARM-830教学实验箱,PentiumII以上的PC机,仿真器电缆。 2. PC操作系统WIN98或WIN2000或WINXP, ADS1.2集成开发环境,仿真器驱动程序。 三、汇编语言简介 1.ARM汇编的一些简要的书写规范 ARM汇编中,所有标号必须在一行的顶格书写,其后面不要添加“:”,而所有指令均不能顶格书写。ARM汇编对标识符的大小写敏感,书写标号及指令时字母大 小写要一致。在ARM汇编中,ARM指令、伪指令、寄存器名等可以全部大写或者全 部小写,但不要大小写混合使用。注释使用“;”号,注释的内容由“;”号起到此 行结束,注释可以在一行的顶格书写。 详细的汇编语句及规范请参照ARM汇编的相关书籍、文档。 2. ARM汇编语言程序的基本结构 在ARM汇编语言程序中,是以程序段为单位来组织代码。段是相对独立的指令或数据序列,具有特定的名称。段可以分为代码段的和数据段,代码段的内容为执 行代码,数据段存放代码运行时所需的数据。一个汇编程序至少应该有一个代码段,当程序较长时,可以分割为多个代码段和数据段,多个段在程序编译链接时最终形 成一个可执行文件。可执行映像文件通常由以下几部分构成: ◆ 一个或多个代码段,代码段为只读属性。 ◆ 零个或多个包含初始化数据的数据段,数据段的属性为可读写。 ◆ 零个或多个不包含初始化数据的数据段,数据段的属性为可读写。 链接器根据系统默认或用户设定的规则,将各个段安排在存储器中的相应位置。源程序中段之间的相邻关系与执行的映象文件中的段之间的相邻关系不一定 相同。 3. 简单的小例子 下面是一个代码段的小例子 AREA Init,CODE,READONLY ENTRY LDR R0, =0x3FF5000 LDR R1, 0x0f STR R1, [R0]

elf文件格式

第1章文件格式 1.1 Executable and Linking Format (ELF) 1.1.1整体结构 ELF对象格式用于目标文件(.o扩展名)和执行文件. 有些信息只出现在目标文件或执行文件中. ELF文件由下列部件构成. ELF header必须放在文件的开始;其他部件可以随便排放(ELF header给出了其他部件的偏移量). 1.1.2ELF头[ELF Header] ELF头包含目标文件的一般信息;具有如下结构(from elf.h): #define EI_NIDENT 16 typedef struct { unsigned char e_ident[EI_NIDENT]; Elf32_Half e_e_type; Elf32_Half e_machine; Elf32_Word e_version; Elf32_Addr e_entry; Elf32_Off e_phoff; Elf32_Off e_shoff; Elf32_Word e_flags; Elf32_Half e_ehsize; Elf32_Half e_phentsize; Elf32_Half e_phnum; Elf32_Half e_shentsize; Elf32_Half e_shnum; Elf32_Half e_shstrndx; }; ELF头域描述:

1.1.3程序头[Program Header] 程序头为一结构数组,每个元素描述执行文件的一个可载入段. 元素结构如下(from elf.h): typedef struct { Elf32_Word p_type; Elf32_Off p_offset; Elf32_Addr p_vaddr; Elf32_Addr p_paddr; Elf32_Word p_filesz; Elf32_Word p_memsz; Elf32_Word p_flags; Elf32_Word p_align; } Elf32_Phdr;

一个简单的C程序反汇编解析.

一个简单的 C++程序反汇编解析 本系列主要从汇编角度研究 c++语言机制和汇编的对应关系。第一篇自然应该从最简单的开始。 c++的源代码如下: class my_class { public : my_class( { m_member = 1; } void method(int n { m_member = n; } ~my_class( { m_member = 0; } private :

int m_member; }; int _tmain(int argc, _tchar* argv[] { my_class a_class; a_class.method(10; return 0; } 可以直接 debug 的时候看到 assembly 代码,不过这样获得的代码注释比较少。比较理想的方法是利用 vc 编译器的一个选项 /fas来生成对应的汇编代码。 /fas还会在汇编代码中加入注释注明和 c++代码的对应关系,十分有助于分析。 build 代码便可以在输出目录下发现对应的 .asm 文件。本文将逐句分析汇编代码和 c++的对应关系。 首先是 winmain : _text segment _wmain proc push ebp ; 保存旧的 ebp mov ebp, esp ; ebp保存当前栈的位置 push -1 ; 建立 seh(structured exception handler链 ; -1表示表头 , 没有 prev

push __ehhandler$_wmain ; seh异常处理程序的地址 mov eax, dword ptr fs:0 ; fs:0指向 teb 的内容,头 4个字节是当前 seh 链的地址 push eax ; 保存起来 sub esp, d8h ; 分配 d8h 字节的空间 push ebx push esi push edi lea edi, dword ptr [ebp-e4h] ; e4h = d8h + 4 * 3,跳过中间 ebx, esi, edi mov ecx, 36h ; 36h*4h=d8h,也就是用 36h 个 cccccccch 填满刚才分配的 d8h 字节空间 mov eax, cccccccch rep stosd mov eax, dword ptr ___security_cookie xor eax, ebp push eax ; ebp ^ __security_cookie压栈保存 lea eax, dword ptr [ebp-0ch] ; ebp-0ch 是新的 seh 链的结构地址(刚压入栈中的栈地址 mov dword ptr fs:0, eax ; 设置到 teb 中作为当前 active 的 seh 链表末尾 到此为止栈的内容是这样的: 低地址 security cookie after xor

反汇编基础知识

计算机寄存器分类简介: 32位CPU所含有的寄存器有: 4个数据寄存器(EAX、EBX、ECX和EDX) 2个变址和指针寄存器(ESI和EDI) 2个指针寄存器(ESP和EBP) 6个段寄存器(ES、CS、SS、DS、FS和GS) 1个指令指针寄存器(EIP) 1个标志寄存器(EFlags) 1、数据寄存器 数据寄存器主要用来保存操作数和运算结果等信息,从而节省读取操作数所需占用总线和访问存储器的时间。 32位CPU有4个32位的通用寄存器EAX、EBX、ECX和EDX。 对低16位数据的存取,不会影响高16位的数据。 这些低16位寄存器分别命名为:AX、BX、CX和DX,它和先前的CPU中的寄存器相一致。 4个16位寄存器又可分割成8个独立的8位寄存器(AX:AH-AL、BX:BH-BL、CX:CH-CL、DX:DH-DL),每个寄存器都有自己的名称,可独立存取。 程序员可利用数据寄存器的这种“可分可合”的特性,灵活地处理字/字节的信息。 寄存器EAX通常称为累加器(Accumulator),用累加器进行的操作可能需要更少时间。可用于乘、除、输入/输出等操作,使用频率很高; 寄存器EBX称为基地址寄存器(Base Register)。它可作为存储器指针来使用; 寄存器ECX称为计数寄存器(Count Register)。

在循环和字符串操作时,要用它来控制循环次数;在位操作中,当移多位时,要用CL来指明移位的位数; 寄存器EDX称为数据寄存器(Data Register)。在进行乘、除运算时,它可作为默认的操作数参与运算,也可用于存放I/O的端口地址。在16位CPU中,AX、BX、CX和DX不能作为基址和变址寄存器来存放存储单元的地址, 在32位CPU中,其32位寄存器EAX、EBX、ECX和EDX不仅可传送数据、暂存数据保存算术逻辑运算结果, 而且也可作为指针寄存器,所以,这些32位寄存器更具有通用性。 2、变址寄存器 32位CPU有2个32位通用寄存器ESI和EDI。 其低16位对应先前CPU中的SI和DI,对低16位数据的存取,不影响高16位的数据。 寄存器ESI、EDI、SI和DI称为变址寄存器(Index Register),它们主要用于存放存储单元在段内的偏移量, 用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。 变址寄存器不可分割成8位寄存器。作为通用寄存器,也可存储算术逻辑运算的操作数和运算结果。 它们可作一般的存储器指针使用。在字符串操作指令的执行过程中,对它们有特定的要求,而且还具有特殊的功能。 3、指针寄存器 其低16位对应先前CPU中的BP和SP,对低16位数据的存取,不影响高16位的数据。 32位CPU有2个32位通用寄存器EBP和ESP。 它们主要用于访问堆栈内的存储单元,并且规定: EBP为基指针(Base Pointer)寄存器,用它可直接存取堆栈中的数据;

ARM汇编程序设计

cmp r0,#5 bcs aaa add r0,r0,#1 aaa nop cmp r0,#5 addcc r0,r0,#1 bl指令完成两个功能:将子程序的返回地址保存在LR即R14同时将PC的值改为目标子程序的第一条指令的地址。 Start: Mov r0,#10 Mov r1,#3 Bl doadd Mov r1,r1,r0 Doadd Add r0,r0,r1 Mov pc,lr .end 用汇编程序实现IF语句的功能: Mov r0,#15 Mov r1,#12 Cmp r0,r1

Movhi r2,#100 Movls r2,#50 用汇编程序实现FOR循环的功能:Mov r0,#0 Mov r1,#10 Mov r2,#0 L1: cmp r0,r1 Bhs l2 Add r2,r2,#1 Add r0,r0,#1 B l1 L2: .end 用汇编语言实现WHILE循环While(x<=y) X=x*2; mov r0,#1 mov r1,#20 b l2 l1: mov r0,r0, lsl #1 l2: cmp r0,r1 bls l1 end

用汇编语言实现计算算术功能:n equ 100 .global _start -start: .arm arm_code: Ldr sp,=0x40003f00 Adr r0,thumbcode+1 Bx r0 .ltorg .thumb Thumb_code: Ldr r0,=n Bl sum_n B thumb_code Sum_n: Push {r1-r7,lr} Movs r2,r0 Beq sum_end Cmp r2,#1 Beq sum_end Mov r1,#1

arm反汇编.

在bin文件中,就是一条条的机器指令,每条指令4个字节。 在ADS中打开一个.s文件,选择project->disassemble 可以看到汇编的机器码 汇编代码如下(ADS中的一个例程\ARM\ADSv1_2\Examples\asm\armex.s): AREA ARMex, CODE, READONL Y ; name this block of code ENTRY ; mark first instruction ; to execute start MOV r0, #10 ; Set up parameters MOV r1, #3 ADD r0, r0, r1 ; r0 = r0 + r1 stop MOV r0, #0x18 ; angel_SWIreason_ReportException LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit SWI 0x123456 ; ARM semihosting SWI END ; Mark end of file 执行project->disassemble后: ** Section #1 'ARMex' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR + SHF_ENTRYSECT] Size : 28 bytes (alignment 4) start $a ARMex 0x00000000: e3a0000a .... MOV r0,#0xa 0x00000004: e3a01003 .... MOV r1,#3 0x00000008: e0800001 .... ADD r0,r0,r1 stop 0x0000000c: e3a00018 .... MOV r0,#0x18 0x00000010: e59f1000 .... LDR r1,0x18 0x00000014: ef123456 V4.. SWI 0x123456 $d 0x00000018: 00020026 &... DCD 131110 使用UltraEdit看bin文件如下: 可以看到,与上面的一样。 其中MOV的机器码如下(ARM体系结构pdf:p156):

elf详解

ARM-ELF文件格式与GNU ARM Linker机制 作者:admin 日期:2008-10-13 字体大小: 小中大

里面除了二进制的机器代码,还有一些可用于进行重定位的信息。它主要是作为LINKER(ld)的输入,LINKER将跟据这些信息,将需要重定位的符号重定位,进而产生可执行的OBJECT 文件。ELF格式的可重定位OBJECT文件由header与section 组成。 Header 包括ELF header 与 section header. ELF header 位于文件的头部,用于存储目标机器的架构,大小端配置,ELF header 大小,object文件类型,section header 在文件中的偏移,section header 的大小,section header 中的项目数等信息。Section header 则定义了文件中每个section 的类型,位置,大小等信息。Linker就是通过查找ELF header,找到 section header 的入口,再在section header 中找到相应的section 入口,进而定位到目标section 的。 Section 包括 .text :经过编译的机器代码。 .rodata :只读的数据,例如printf(“hello!”)中的字符串hello。.data :已初始化的全局变量,局部变量将在运行时被存放在堆栈中,不会在.data或 .bss段中出现。 .bss :未初始化的全局变量,在这里只是一个占位符,在object 文件中并没有实际的存储空间。 .symtab :符号表,用于存放程序中被定义的或被引用到的全局变量和函数的信息。

实验二_ARM汇编语言程序设计

实验二ARM汇编语言程序设计 实验目的 1、了解ARM汇编语言程序的结构特点 2、了解ARM汇编语言程序的编写方法 3、掌握用ARM汇编语言设计简单程序 实验仪器设备及软件 ARM实验箱,计算机,ADS程序开发软件 实验原理 1、存储空间的格式 ARM920将存储空间视为从0开始由字节组成的线性集合,字节0-3中保存了第一个字,字节4-7中保存了第二个字,依此类推。字节还可以按小端格式或大端格式排列。ARM实验箱中存储器的配置见附录C。 2、ARM的寄存器 ARM状态下任何时刻都可以看到16个通过寄存器(r0-r15),1或2个状态寄存器(CPSR,SPSR),在特权模式下会切换到具体模下的寄存器组。每个寄存器都是32位的,并且每个通用寄存器都可以作为数据处理的源数据或目标数据寄存器。因此可以编写出更精简的程序。 3、ARM指令的条件执行 状态寄存器中的N,Z,C,V是数据处理指令影响的标志。几乎每条ARM指令可以根据状态位或状态位的逻辑运算有条件执行。条件执行的指令后缀参考教材。 4、桶形移器 ARM的桶形移位器,使ARM指令的中第二个操作数非常录活。利用移位器,一条ARM 指令可以完成更多功能。移位操作有: LSL 逻辑左移 LSR 逻辑右移 ASL 算术左移 ASR 算术右移 ROR 循环右移 RRX 带扩展循环右称 实验内容 1、把内存中ramaddr开始的ramword个字清零 (1)用后变址法 ramaddr equ 0x31000000 ramword equ 64 clrram mov r0,#0 mov r1,#ramword ldr r2,=ramaddr clrram1 str r0,[r2],#4 subs r1,r1,#1

OllyICE反汇编教程及汇编命令详解

OllyICE反汇编教程及汇编命令详解[转] 2009-02-11 08:09 OllyICE反汇编教程及汇编命令详解 内容目录 计算机寄存器分类简介 计算机寄存器常用指令 一、常用指令 二、算术运算指令 三、逻辑运算指令 四、串指令 五、程序跳转指令 ------------------------------------------ 计算机寄存器分类简介: 32位CPU所含有的寄存器有: 4个数据寄存器(EAX、EBX、ECX和EDX) 2个变址和指针寄存器(ESI和EDI) 2个指针寄存器(ESP和EBP) 6个段寄存器(ES、CS、SS、DS、FS和GS) 1个指令指针寄存器(EIP) 1个标志寄存器(EFlags) 1、数据寄存器 数据寄存器主要用来保存操作数和运算结果等信息,从而节省读取操作数所需占用总线和访问存储器的时间。 32位CPU有4个32位的通用寄存器EAX、EBX、ECX和EDX。 对低16位数据的存取,不会影响高16位的数据。 这些低16位寄存器分别命名为:AX、BX、CX和DX,它和先前的CPU中的寄存器相一致。4个16位寄存器又可分割成8个独立的8位寄存器(AX:AH-AL、BX:BH-BL、CX:CH-CL、DX:DH-DL),每个寄存器都有自己的名称,可独立存取。 程序员可利用数据寄存器的这种“可分可合”的特性,灵活地处理字/字节的信息。 寄存器EAX通常称为累加器(Accumulator),用累加器进行的操作可能需要更少时间。可用于乘、除、输入/输出等操作,使用频率很高; 寄存器EBX称为基地址寄存器(Base Register)。它可作为存储器指针来使用; 寄存器ECX称为计数寄存器(Count Register)。 在循环和字符串操作时,要用它来控制循环次数;在位操作中,当移多位时,要用CL来指明移位的位数; 寄存器EDX称为数据寄存器(Data Register)。在进行乘、除运算时,它可作为默认的操作数参与运算,也可用于存放I/O的端口地址。 在16位CPU中,AX、BX、CX和DX不能作为基址和变址寄存器来存放存储单元的地址,在32位CPU中,其32位寄存器EAX、EBX、ECX和EDX不仅可传送数据、暂存数据保存算术逻辑运算结果, 而且也可作为指针寄存器,所以,这些32位寄存器更具有通用性。 2、变址寄存器 32位CPU有2个32位通用寄存器ESI和EDI。 其低16位对应先前CPU中的SI和DI,对低16位数据的存取,不影响高16位的数据。 寄存器ESI、EDI、SI和DI称为变址寄存器(Index Register),它们主要用于存放存储单元在段内的偏移量,

elf文件资料格式(中文版)

3. 页标题的容和文章的页脚已经在开始的时候被换掉了。 4. 文章的排版也已经修正过了。 5. 如果必要,不同的字体已经被忽略了。大部分地方,这片文档能让你 充分的理解。然而,很小的地方,原始的文档使用了斜体字来指出文 章中的字符变量。在那种情况下,本文使用<尖括号>。在原始的文档 中没有出现尖括号。 6. 原始的文档有三个错误,如果你是不经意读它的话,是不会明显 就能找出的。但是在这里,明确的被鉴别出来了。 我很冒昧的纠正了那些错误。在他们的位置用一个{*}做上了标记。 可能还有其他我没有看出来的的错误。 如果有如何其他的区别都是我的责任。这样的错误请 mailto:breadboxmuppetlabs.. Brian Raiter [Last edited Fri Jul 23 1999] ________________________________________________________________ EXECUTABLE AND LINKABLE FORMAT (ELF) Portable Formats Specification, Version 1.1 Tool Interface Standards (TIS) ________________________________________________________________ =========================== Contents 容=========================== 序言 1. OBJECT文件 导言 ELF头(ELF Header) Sections String表(String Table) Symbol表(Symbol Table) 重定位(Relocation) 2. 程序装载与动态连接 导言 Program头(Program Header)

第二章逆向与反汇编工具

第二章逆向与反汇编工具 知道了一些反汇编的背景知识后,在开始深入学习IDA pro之前,了解一些其他用于逆向工程的工具知识也会非常有用。这些工具大部分都要早于IDA出生并且依然是很好的快速分析二进制文件的工具,同时它们也可以用来与IDA对照。就如我们所见到的,IDA已把这些工具的许多功能都集合到了它的用户界面中,这为逆向工程提供了一个简一的,集成的环境。然而,尽管IDA拥有一个集成的调试器,但我们并不打算讨论它,因为单就这个主题就可以出本书了。 分类工具(Classification Tools) 当我们一开始遇到一个不熟悉的文件时,问一些比较简单的问题,如“这是什么文件”,通常会很有用的。回答这问题的首要原则就是千万不要依靠这文件的扩展名来决定它是什么类型的文件。这甚至也是第二、三、四条原则。一旦你已经明白了文件扩展名对确定文件的类型没有任何意义之后,你也就会考虑学习使用如下的几个工具了。 file file是一个标准的工具,存在于*NIX类操作系统和Windows下的Cygwin[1]程序中。file试图通过检查文件里的某些特定域来确认文件的类型。在某些情况下,file能检测出常见的字符串,如“#!/bin/sh”(shell 脚本文件),或“”(HTML 文件)。然而检测某些非ASCII 文件将会变得更加困难,在这种情况下,file首先判断该文件是否是符合某定已知的文件格式。在大多情况下,它是通过搜索一个唯一的已知特征值(通常被称为幻数(magic number)[2])来决定文件的类型的。下面的十六进制表列出了一些常用文件类型的幻数。 file可以识别大量的文件格式,这其中包括许多ASCII文本格式,许多可执行文件格式和一些数据文件格式。file使用magic file来管理幻数检测。不同的操作系统拥有不同的magic flie,但是一般情况下位于/usr/share/file/magic,/usr/share/misc/magic或/edt/magic文件里。请参阅file的文档查询更多关于magic file的信息。 1. 更多资料请访问https://www.doczj.com/doc/0211072752.html,/. 2. 幻数(magic number)被很多文件格式规范用来表明该文件符合该文件格式。有时候幻数的选择还伴随着有趣的原由呢,如,MS-DOS可执行文件文件头的MZ特征值是由一位最初的MS-DOS结构师Mark Zbikowski的名字的每个单词的第一个字母组成,又如,十六进制数0xcafebabe是众所周知的Java .class文件的幻数,选择它仅公是因为它是一个很容易记的十六进制串。

关于ELF文件格式

现代Linux采用ELF(Executable and Linking Format)做为其可连接和可执行文件的格式,因此ELF格式也向我们透出了一点Linux核内的情景,就像戏台维幕留下的一条未拉严的缝。 PC世界32仍是主流,但64位的脚步却已如此的逼近。如果你对Windows比较熟悉,本文还将时时把你带回到PE中,在它们的相似之处稍做比较。ELF文件以“ELF 头”开始,后面可选择的跟随着程序头和节头。地理学用等高线与等温线分别展示同一地区的地势和气候,程序头和节头则分别从加载与连接角度来描述EFL文件的组织方式。 ELF头 ------------------------------------------------ ELF头也叫ELF文件头,它位于文件中最开始的地方。 /usr/src/linux/include/linux/elf.h typedef struct elf32_hdr{ unsigned char e_ident[EI_NIDENT]; Elf32_Half e_type; Elf32_Half e_machine; Elf32_Word e_version; Elf32_Addr e_entry; /* Entry point */ Elf32_Off e_phoff;

Elf32_Off e_shoff; Elf32_Word e_flags; Elf32_Half e_ehsize; Elf32_Half e_phentsize; Elf32_Half e_phnum; Elf32_Half e_shentsize; Elf32_Half e_shnum; Elf32_Half e_shstrndx; } Elf32_Ehdr; #define EI_NIDENT 16 ELF头中每个字段的含意如下: Elf32_Ehdr->e_ident[] (Magic) 这个字段是ELF头结构中的第一个字段,在elf.h中EI_NIDENT被定义为16,因此它占用16个字节。e_ident的前四个字节顺次应该是0x7f、 0x45、 0x4c、 0x46,也就是"\177ELF"。这是ELF文件的标志,任何一个ELF文件这四个字节都完全相同。 16进制 8进制字母 0x7f 0177 0x45 E 0x4c L

反汇编基础知识

计算机寄存器分类简介 32位CPU所含有的寄存器有: 4个数据寄存器(EAX、EBX ECX和EDX) 2个变址和指针寄存器(ESI和EDI) 2个指针寄存器(ESP和EBP) 6个段寄存器(ES、CS SS DS FS和GS) 1个指令指针寄存器(EIP) 1个标志寄存器(EFlags) 1、数据寄存器 数据寄存器主要用来保存操作数和运算结果等信息,从而节省读取操作数所需占用总线和访问存储器的时间。 32位CPU有4个32位的通用寄存器EAX EBX ECX和EDX 对低16位数据的存取,不会影响高16位的数据。 这些低16位寄存器分别命名为:AX、BX、CX和DX,它和先前的CPU中的寄存器相一致。 4个16位寄存器又可分割成8个独立的8位寄存器(AX:AH-AL、BX BH-BL、CX CH-CL、DX DH-DL),每个寄存器都有自己的名称,可独立存取。 程序员可利用数据寄存器的这种“可分可合”的特性,灵活地处理字/字节的信息。 寄存器EAX通常称为累加器(Accumulator),用累加器进行的操作可能需要更少时间。可用于乘、除、输入/输出等操作,使用频率很高; 寄存器EBX称为基地址寄存器(Base Register)。它可作为存储器指针来使用; 寄存器ECX称为计数寄存器(Count Register)

在循环和字符串操作时,要用它来控制循环次数;在位操作中,当移多位时,要用 CL来指明移位的位数; 寄存器EDX称为数据寄存器(Data Register)。在进行乘、除运算时,它可作为默认的操作数参与运算,也可用于存放I/O的端口地址。在16位CPU中,AX BX CX和DX不能作为基址和变址寄存器来存放存储单元的地址, 在32位CPU中,其32位寄存器EAX EBX ECX和EDX不仅可传送数据、暂存数据保存算术逻辑运算结果, 而且也可作为指针寄存器,所以,这些32位寄存器更具有通用性。 2、变址寄存器 32位CPU有2个32位通用寄存器ESI和EDI。 其低16位对应先前CPU中的SI和DI,对低16位数据的存取,不影响高16位的数据 寄存器ESI、EDI、SI和DI称为变址寄存器(Index Register),它们主要用于存放存储单元在段内的偏移量, 用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。 变址寄存器不可分割成8位寄存器。作为通用寄存器,也可存储算术逻辑运算的操作数和运算结果。 它们可作一般的存储器指针使用。在字符串操作指令的执行过程中,对它们有特定的要求,而且还具有特殊的功能。 3、指针寄存器 其低16位对应先前CPU中的BP和SP,对低16位数据的存取,不影响高16位的数据 32位CPU有2个32位通用寄存器EBP和ESR 它们主要用于访问堆栈内的存储单元,并且规定:

反汇编 第二节 常用汇编指令

——啊冲 第二节常用汇编指令 说明:汇编语言也是一门语言,其指令相当的多,非常丰富,在此我只介绍几个常用的、简单的汇编指令,让大家与我一同入门。其实在超多的计算机知识领域里我和大家一样只是个学生而已。所以,我所要求的同学级别(本视频所针对的对象)是:有一点编程经验,对反汇编感兴趣、零基础的朋友。 堆栈操作指令PUSH和POP ?格式: PUSH XXXX ?POP XXXX ?功能: 实现压入操作的指令是PUSH指令;实现弹出操作的指令是POP指令. ? 加减法操作add和sub指令 ?格式: ADD XXXX1,XXXX2 ?功能: 两数相加 ?格式: SUB XXXX1,XXXXX2 ?功能: 两个操作数的相减,即从OPRD1中减去OPRD2,其结果放在OPDR1中.

调用和返回函数CALL和RET(RETN) ?过程调用指令CALL ?格式: CALL XXXX ?功能: 过程调用指令 ?返回指令RET ?格式: RET ?功能: 当调用的过程结束后实现从过程返回至原调用程序的下一条指令,本指令不影响标志位. ? 数据传送MOV 格式: MOV XXXX1,XXXX2 ?功能: 本指令将一个源操作数送到目的操作数中,即XXXX1<--XXXX2. ? 逻辑异或运算XOR ?格式: XOR OPRD1,OPRD2 ?功能: 实现两个操作数按位‘异或’运算,结果送至目的操作数中. ? 逻辑或指令OR ?格式: OR OPRD1,OPRD2 ?功能: OR指令完成对两个操作数按位的‘或’运算,结果送至目的操作数中,本指令可以进行字节或字的‘或’运算.

有效地址传送指令LEA ?格式: LEA OPRD1,OPRD2 ?功能: 将源操作数给出的有效地址传送到指定的的寄存器中. ?实际上,有时候lea用来做mov同样的事情,比如赋值: ?Lea edi,[ebp-0cch] ? 字符串存储指令STOS ?格式: STOS OPRD ?功能: 把AL(字节)或AX(字)中的数据存储到DI为目的串地址指针所寻址的存储器单元中去.指针DI将根据DF的值进行自动调整. ?说明:在VC的DEBUG版里经常用来为局部变量空间写上cccccccc指令 ? 比效指令CMP(CoMPare) ?格式: CMP OPRD1,OPRD2 ?功能: 对两数进行相减,进行比较. ?说明:经常与跳转指令相配合来形成循环或跳出操作 ? 跳转指令JXX ?JMP:无条件转移指令

目标文件格式分析工具-ar-nm等等

目标文件格式分析工具: ar,nm,objdump,objcopy,readelf 如果普通编程不需要了解这些东西,如果想精确控制你的目标文件的格式或者你想查看一下文件里的内容以便作出某种判断,那么你可以看一下下面的工具:ar,nm,objdump,objcopy。具体用法请参考man在线手册。 ar基本用法 ar命令可以用来创建、修改库,也可以从库中提出单个模块。库是一单独的文件,里面包含了按照特定的结构组织起来的其它的一些文件(称做此库文件的member)。原始文件的内容、模式、时间戳、属主、组等属性都保留在库文件中。 下面是ar命令的格式: ar [-]{dmpqrtx}[abcfilNoPsSuvV] [membername] [count] archive files... 例如我们可以用ar rv libtest.a hello.o hello1.o来生成一个库,库名字是test,链接时可以用-ltest链接。该库中存放了两个模块hello.o和hello1.o。选项前可以有‘-'字符,也可以没有。下面我们来看看命令的操作选项和任选项。现在我们把{dmpqrtx}部分称为操作选项,而[abcfilNoPsSuvV]部分称为任选项。 {dmpqrtx}中的操作选项在命令中只能并且必须使用其中一个,它们的含义如下: ?d:从库中删除模块。按模块原来的文件名指定要删除的模块。如果使用了任选项v 则列出被删除的每个模块。 ?m:该操作是在一个库中移动成员。当库中如果有若干模块有相同的符号定义(如函数定义),则成员的位置顺序很重要。如果没有指定任选项,任何指定的成员将移到库的最后。也可以使用'a','b',或'I'任选项移动到指定的位置。 ?p:显示库中指定的成员到标准输出。如果指定任选项v,则在输出成员的内容前,将显示成员的名字。如果没有指定成员的名字,所有库中的文件将显示出来。 ?q:快速追加。增加新模块到库的结尾处。并不检查是否需要替换。'a','b',或'I'任选项对此操作没有影响,模块总是追加的库的结尾处。如果使用了任选项v则列出每个模块。 这时,库的符号表没有更新,可以用'ar s'或ranlib来更新库的符号表索引。 ?r:在库中插入模块(替换)。当插入的模块名已经在库中存在,则替换同名的模块。 如果若干模块中有一个模块在库中不存在,ar显示一个错误消息,并不替换其他同名模块。默认的情况下,新的成员增加在库的结尾处,可以使用其他任选项来改变增加的位置。 ?t:显示库的模块表清单。一般只显示模块名。 ?x:从库中提取一个成员。如果不指定要提取的模块,则提取库中所有的模块。 下面在看看可与操作选项结合使用的任选项: ?a:在库的一个已经存在的成员后面增加一个新的文件。如果使用任选项a,则应该为命令行中membername参数指定一个已经存在的成员名。

反汇编语言常用指令

内容目录 计算机寄存器分类简介 计算机寄存器常用指令 一、常用指令 二、算术运算指令 三、逻辑运算指令 四、串指令 五、程序跳转指令 ------------------------------------------ 计算机寄存器分类简介: 32位CPU所含有的寄存器有: 4个数据寄存器(EAX、EBX、ECX和EDX) 2个变址和指针寄存器(ESI和EDI) 2个指针寄存器(ESP和EBP) 6个段寄存器(ES、CS、SS、DS、FS和GS) 1个指令指针寄存器(EIP) 1个标志寄存器(EFlags) 1、数据寄存器 数据寄存器主要用来保存操作数和运算结果等信息,从而节省读取操作数所需占用总线和访问存储器的时间。 32位CPU有4个32位的通用寄存器EAX、EBX、ECX和EDX。 对低16位数据的存取,不会影响高16位的数据。 这些低16位寄存器分别命名为:AX、BX、CX和DX,它和先前的CPU中的寄存器相一致。 4个16位寄存器又可分割成8个独立的8位寄存器(AX:AH-AL、BX:BH-BL、CX:CH-CL、DX:DH-DL),每个寄存器都有自己的名称,可独立存取。 程序员可利用数据寄存器的这种“可分可合”的特性,灵活地处理字/字节的信息。 寄存器EAX通常称为累加器(Accumulator),用累加器进行的操作可能需要更少时间。可用于乘、除、输入/输出等操作,使用频率很高; 寄存器EBX称为基地址寄存器(Base Register)。它可作为存储器指针来使用; 寄存器ECX称为计数寄存器(Count Register)。 在循环和字符串操作时,要用它来控制循环次数;在位操作中,当移多位时,要用CL来指明移位的位数;寄存器EDX称为数据寄存器(Data Register)。在进行乘、除运算时,它可作为默认的操作数参与运算,也可用于存放I/O的端口地址。 在16位CPU中,AX、BX、CX和DX不能作为基址和变址寄存器来存放存储单元的地址, 在32位CPU中,其32位寄存器EAX、EBX、ECX和EDX不仅可传送数据、暂存数据保存算术逻辑运算结果, 而且也可作为指针寄存器,所以,这些32位寄存器更具有通用性。 2、变址寄存器 32位CPU有2个32位通用寄存器ESI和EDI。 其低16位对应先前CPU中的SI和DI,对低16位数据的存取,不影响高16位的数据。 寄存器ESI、EDI、SI和DI称为变址寄存器(Index Register),它们主要用于存放存储单元在段内的偏移量,用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。 变址寄存器不可分割成8位寄存器。作为通用寄存器,也可存储算术逻辑运算的操作数和运算结果。 它们可作一般的存储器指针使用。在字符串操作指令的执行过程中,对它们有特定的要求,而且还具有特殊的功能。 3、指针寄存器

计算机操作系统实验_解析ELF文件

西北工业大学操作系统实验实验报告 一、实验目的 熟悉可执行链接文件(ELF)的结构,了解GeekOS将ELF格式的可执行程序加载到内存,建立内核线程并运行的实现技术。 二、实验要求 1.修改Project1项目中的/GeekOS/elf.c文件:在函数Parse_ELF_Executable()中添加代码,分析ELF格式的可执行文件(包括分析得出ELF文件头、程序头),获取可执行文件长度、代码段、数据段等信息,并打印输出。并且,填充Exe_Format 数据结构中的值域。 2.掌握GeekOS在核心态运行可执行程序的原理,绘制出可执行程序在内核中加载、运行的流程图(需反映关键函数的调用关系)。 3.回答实验讲义P125页的思考题。 三、实验过程及结果 1、修改Project1项目中的/GeekOS/elf.c文件:在函数Parse_ELF_Executable()中添加代码,分析ELF格式的可执行文件(包括分析得出ELF文件头、程序头),获取可执行文件长度、代码段、数据段等信息,并打印输出。并且,填充Exe_Format 数据结构中的值域。 答:修改Project1项目中的/GeekOS/elf.c文件:在函数Parse_ELF_Executable()中添加代码,如下: ==============elf.c=================== int Parse_ELF_Executable(char *exeFileData, ulong_t exeFileLength, struct Exe_Format *exeFormat) { int i; elfHeader *head=(elfHeader*)exeFileData; programHeader *proHeader=(programHeader *)(exeFileData+head->phoff); KASSERT(exeFileData!=NULL); KASSERT(exeFileLength>head->ehsize+head->phentsize*head->phnum); KASSERT(head->entry%4==0); exeFormat->numSegments=head->phnum;

相关主题
文本预览
相关文档 最新文档