探究ARM架构下的Linux系统:使用Readelf工具解读二进制文件 (arm linux readelf)
随着计算机技术的不断进步和发展,ARM架构的应用越来越广泛,在众多ARM架构下的系统中,Linux系统受到了广泛的欢迎和使用。当我们打开一个Linux系统下的可执行文件时,我们会看到一连串的二进制代码,这些代码是如何生成的?如何理解这些代码?今天我们将介绍Linux系统下的Readelf工具,通过Readelf工具来解析可执行文件的二进制代码。
一、ARM架构
ARM架构是指基于ARM处理器核从而构建计算机系统的架构。ARM架构一般应用于嵌入式系统、移动设备、网络设备、路由器等嵌入式设备。相比x86架构,具有高性能、低功耗、低成本等优点。目前市面上绝大部分移动设备都是以ARM架构为主,因此Linux系统也开始支持ARM架构,并被广泛应用在移动设备、嵌入式系统等领域。
二、Readelf工具
Readelf工具是一款常用的二进制静态分析工具,可以用来解读二进制文件的结构。Readelf工具一般安装在Linux系统上,并且是由GNU开发的。Readelf工具可以读取ELF格式(可执行和链接格式)二进制文件信息,可以显示该文件的头部、节区信息、段区信息、动态链接、符号表信息等。
1.使用Readelf工具查看ELF格式的头部信息
打开终端,进入到ELF格式可执行文件的目录下,输入以下命令:
$ readelf -h myprogram
其中myprogram为可执行的ELF格式文件名。执行完上述命令后,终端输出如下信息:
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2’s complement, little endian
Version: 1 (current)
OS/ABI: UNIX – System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0x2a50
Start of program headers: 52 (bytes into file)
Start of section headers: 63844 (bytes into file)
Flags: 0x5000400, Version5 EABI, soft-float ABI, File has Entry point alignment
…
其中Magic、Class、Data、Version、OS/ABI、ABI Version、Type、Machine、Entry point address、Start of program headers、Start of section headers、Flags等字段分别表示该可执行文件的ELF格式头部信息。当我们使用Readelf工具查看ELF格式头部信息时,可以更清晰地了解该可执行文件的格式和结构。
2.使用Readelf工具查看ELF格式的节区信息
使用Readelf工具查看ELF格式节区信息,可以帮助我们更加深入地了解可执行文件的组成结构。在终端中输入以下命令:
$ readelf -S myprogram
其中myprogram为可执行的ELF格式文件名。执行完上述命令后,终端输出如下信息:
There are 31 section headers, starting at offset 0xf96c:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 000100f0 0000f0 000014 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 00010104 000104 000020 00 A 0 0 4
[ 3] .note.arm.identi NOTE 00010124 000124 000024 00 A 0 0 4
[ 4] .hash HASH 00010148 000148 000118 04 A 5 0 4
[ 5] .dynsym DYNSYM 00010260 000260 000400 10 A 6 1 4
[ 6] .dynstr STRTAB 00010660 000660 0001c6 00 A 0 0 1
[ 7] .gnu.version VERSYM 00010828 000828 0000c6 02 A 5 0 2
[ 8] .gnu.version_r VERNEED 000108f0 0008f0 000038 00 A 6 2 4
[ 9] .rel.dyn REL 00010928 000928 0000c0 08 A 5 0 4
[10] .rel.plt REL 000109e8 0009e8 000080 08 A 5 11 4
[11] .plt PROGBITS 00010a64 000a64 000510 04 AX 0 0 16
[12] .text PROGBITS 00010f78 000f78 0015b0 00 AX 0 0 4
[13] .ARM.exidx ARM_EXIDX 00012428 001428 000070 00 AL 13 0 4
[14] .fini_array FINI_ARRAY 000124fc 0014fc 000004 04 WA 0 0 4
[15] .data.rel.ro PROGBITS 00012500 001500 000480 00 WA 0 0 4
[16] .dynamic DYNAMIC 00012980 001980 0000e8 08 WA 6 0 4
[17] .got PROGBITS 00012a68 002023 000004 04 WA 0 0 4
[18] .data PROGBITS 00012a6c 00206c 0005a4 00 WA 0 0 4
[19] .bss NOBITS 00013010 002610 001630 00 WA 0 0 16
[20] .comment PROGBITS 00000000 002610 000058 01 MS 0 0 1
[21] .ARM.attributes ARM_ATTRIBUTES 00000000 002668 000028 00 0 0 1
[22] .shstrtab STRTAB 00000000 002690 000109 00 0 0 1
[23] .symtab SYMTAB 00000000 0027f8 000750 10 24 210 4
[24] .strtab STRTAB 00000000 002f48 000402 00 0 0 1
[25] .gnu_debuglink PROGBITS 00000000 00334c 000018 00 0 0 1
[26] .gnu_debugdata PROGBITS 00000000 003364 000bb8 00 0 0 16
[27] .ARM.exidx ARM_EXIDX 00000000 004edc 000010 00 AL 13 0 4
[28] .rel.dyn REL 00000000 004eec 000008 08 A 5 0 4
[29] .rel.plt REL 00000000 004ef4 000008 08 A 5 11 4
[30] .init_array INIT_ARRAY 00000000 004efc 000004 04 WA 0 0 4
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
其中,第二行Section Headers:表示可执行文件中的所有节区信息,从第3行开始,每一行表示一个节区信息,由多个字段组成。如:第3行 [ 1] .interp PROGBITS 000100f0 0000f0 000014 00 A 0 0 1,其中[ 1]代表节区的顺序号,”.interp”代表节区的名称,”PROGBITS”代表该节区的类型,000100f0代表节区的地址,0000f0代表偏移量,000014代表节区的大小,”00″、A、0、0、1代表一些其他的属性。通过Readelf工具查看ELF格式的节区信息,可以对可执行文件的组成结构有更深刻的理解。
3.使用Readelf工具查看ELF格式的段区信息
和节区信息一样,使用Readelf工具查看ELF格式的段区信息,可以帮助我们更加深入地了解可执行文件的组成结构。在终端中输入以下命令:
$ readelf -l myprogram
其中myprogram为可执行的ELF格式文件名。执行完上述命令后,终端输出如下信息:
Elf file type is EXEC (Executable file)
Entry point 0x2a50
There are 10 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x00010000 0x00010000 0x004bd8 0x004bd8 RWE 0x8000
LOAD 0x004bd8 0x0005adfc 0x0005adfc 0x000a4c 0x011480 RW 0x8000
DYNAMIC 0x004ce8 0x0005bc08 0x0005bc08 0x000e8 0x000e8 RWE 0x4
GNU_RELRO 0x004bd8 0x0005adfc 0x0005adfc 0x0008d0 0x0008d0 RWE 0x10000
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x0
GNU_EH_FRAME 0x0013a0 0x000113a0 0x000113a0 0x0006e8 0x0006e8 R 0x4
GNU_DEBUGLINK 0x001088 0x00010888 0x00010888 0x00018c 0x00018c R 0x4
GNU_DEBUGDATA 0x001210 0x00012023 0x00012023 0x000bb8 0x000bb8 R 0x4
GNU_RELRO 0x004cc8 0x0005bc08 0x0005bc08 0x000018 0x000018 RW 0x4
Section to Segment mapping:
Segment Sections…
00
01 .hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .plt .text .ARM.exidx .fini_array .data.rel.ro
.dynamic .got .data
02 .dynamic
03 .got .data
04
05 .ARM.exidx
06 .gnu_debuglink
07 .gnu_debugdata
08 .got .data
09
其中,第二行Program Headers:表示可执行文件中的所有段区信息,从第3行开始,每一行表示一个段区信息,由多个字段组成。如:第3行LOAD 0x000000 0x00010000 0x00010000 0x004bd8 0x004bd8 RWE 0x8000,其中LOAD代表段区的类型,0x000000代表偏移量,0x00010000代表虚拟地址,0x00010000代表物理地址,0x004bd8代表文件大小,0x004bd8代表内存大小,RWE代表读写执行的权限,0x8000代表对齐方式。通过Readelf工具查看ELF格式的段区信息,可以对可执行文件的组成结构有更深刻的理解。
三、结语
本文介绍了ARM架构下的Linux系统中一款优秀的二进制静态分析工具——Readelf,讲解了使用Readelf工具查看ELF格式的头部信息、节区信息和段区信息的方法。在嵌入式系统和移动设备领域,Linux系统和ARM架构的应用越来越广泛,掌握二进制的静态分析能力可以更好地理解和调试可执行文件的功能和代码结构。