代码
参考第4章,使用如下代码:
建立工程:
编译结果:
目标文件分析
先看b.o文件:
fromelf -v b.o
打印结果:
========================================================================
** ELF Header Information
File Name: b.o
Machine class: ELFCLASS32 (32-bit)
Data encoding: ELFDATA2LSB (Little endian)
Header version: EV_CURRENT (Current version)
Operating System ABI: none
ABI Version: 0
File Type: ET_REL (Relocatable object) (1)
Machine: EM_ARM (ARM)
Entry offset (in SHF_ENTRYSECT section): 0x00000000
Flags: None (0x05000000)
ARM ELF revision: 5 (ABI version 2)
Header size: 52 bytes (0x34)
Program header entry size: 0 bytes (0x0)
Section header entry size: 40 bytes (0x28)
Program header entries: 0
Section header entries: 11
Program header offset: 0 (0x00000000)
Section header offset: 1096 (0x00000448)
Section header string table index: 8
========================================================================
** Section #1
Name : i.swap
Type : SHT_PROGBITS (0x00000001)
Flags : SHF_ALLOC + SHF_EXECINSTR (0x00000006)
Addr : 0x00000000
File Offset : 52 (0x34)
Size : 22 bytes (0x16)
Link : SHN_UNDEF
Info : 0
Alignment : 2
Entry Size : 0
====================================
** Section #2
Name : .arm_vfe_header
Type : SHT_PROGBITS (0x00000001)
Flags : None (0x00000000)
Addr : 0x00000000
File Offset : 76 (0x4c)
Size : 4 bytes (0x4)
Link : SHN_UNDEF
Info : 0
Alignment : 4
Entry Size : 0
====================================
** Section #3
Name : .comment
Type : SHT_PROGBITS (0x00000001)
Flags : None (0x00000000)
Addr : 0x00000000
File Offset : 80 (0x50)
Size : 375 bytes (0x177)
Link : SHN_UNDEF
Info : 0
Alignment : 1
Entry Size : 0
Component: ARM Compiler 5.06 update 6 (build 750) Tool: ArmCC [4d3637]
ArmCC --c99 --split_sections -c --gnu -o.\objects\b.o --depend=.\objects\b.d --cpu=Cortex-M3 --apcs=interwork -O0 --diag_suppress=9931 -I.\RTE\_DebugOnFlash -IC:\Keil_v5\ARM\Packs\Keil\STM32F1xx_DFP\2.3.0\Device\Include -IC:\Keil_v5\ARM\CMSIS\Include -D__UVISION_VERSION=529 -DSTM32F10X_XL ..\..\src\b.c
====================================
** Section #4
Name : .data
Type : SHT_PROGBITS (0x00000001)
Flags : SHF_ALLOC + SHF_WRITE (0x00000003)
Addr : 0x00000000
File Offset : 456 (0x1c8)
Size : 4 bytes (0x4)
Link : SHN_UNDEF
Info : 0
Alignment : 4
Entry Size : 0
====================================
** Section #5
Name : .debug_frame
Type : SHT_PROGBITS (0x00000001)
Flags : None (0x00000000)
Addr : 0x00000000
File Offset : 460 (0x1cc)
Size : 68 bytes (0x44)
Link : SHN_UNDEF
Info : 0
Alignment : 1
Entry Size : 0
====================================
** Section #7
Name : .rel.debug_frame
Type : SHT_REL (0x00000009)
Flags : None (0x00000000)
Addr : 0x00000000
File Offset : 688 (0x2b0)
Size : 16 bytes (0x10)
Link : Section 6 (.symtab)
Info : Section 5 (.debug_frame)
Alignment : 4
Entry Size : 8
====================================
** Section #6
Name : .symtab
Type : SHT_SYMTAB (0x00000002)
Flags : None (0x00000000)
Addr : 0x00000000
File Offset : 528 (0x210)
Size : 160 bytes (0xa0)
Link : Section 9 (.strtab)
Info : Last local symbol no = 6
Alignment : 4
Entry Size : 16
====================================
** Section #8
Name : .shstrtab
Type : SHT_STRTAB (0x00000003)
Flags : None (0x00000000)
Addr : 0x00000000
File Offset : 704 (0x2c0)
Size : 98 bytes (0x62)
Link : SHN_UNDEF
Info : 0
Alignment : 1
Entry Size : 0
====================================
** Section #9
Name : .strtab
Type : SHT_STRTAB (0x00000003)
Flags : None (0x00000000)
Addr : 0x00000000
File Offset : 802 (0x322)
Size : 222 bytes (0xde)
Link : SHN_UNDEF
Info : 0
Alignment : 1
Entry Size : 0
====================================
** Section #10
Name : .ARM.attributes
Type : SHT_ARM_ATTRIBUTES (0x70000003)
Flags : None (0x00000000)
Addr : 0x00000000
File Offset : 1024 (0x400)
Size : 72 bytes (0x48)
Link : SHN_UNDEF
Info : 0
Alignment : 1
Entry Size : 0
'aeabi' file build attributes:
0x000000: 43 32 2e 30 39 00 05 43 6f 72 74 65 78 2d 4d 33 C2.09..Cortex-M3
0x000010: 00 06 0a 07 4d 09 02 11 01 12 02 14 02 17 01 18 ....M...........
0x000020: 01 19 01 1a 01 1e 06 22 01 .......".
Tag_conformance = "2.09"
Tag_CPU_name = "Cortex-M3"
Tag_CPU_arch = ARM v7 (=10)
Tag_CPU_arch_profile = The microcontroller profile 'M' (e.g. for Cortex M3) (=77)
Tag_THUMB_ISA_use = Thumb2 instructions were permitted (implies Thumb instructions permitted) (=2)
Tag_ABI_PCS_GOT_use = Data are imported directly (=1)
Tag_ABI_PCS_wchar_t = Size of wchar_t is 2 (=2)
Tag_ABI_FP_denormal = This code was permitted to require that the sign of a flushed-to-zero number be preserved in the sign of 0 (=2)
Tag_ABI_FP_number_model = This code was permitted to use only IEEE 754 format FP numbers (=1)
Tag_ABI_align_needed = Code was permitted to depend on the 8-byte alignment of 8-byte data items (=1)
Tag_ABI_align_preserved = Code was required to preserve 8-byte alignment of 8-byte data objects (=1)
Tag_ABI_enum_size = Enum values occupy the smallest container big enough to hold all values (=1)
Tag_ABI_optimization_goals = Optimized for best debugging illusion, speed and small size sacrificed (=6)
Tag_CPU_unaligned_access = The producer was permitted to generate architecture v6-style unaligned data accesses (=1)
'ARM' file build attributes:
0x000000: 12 01 ..
====================================
从文件头部信息中可以得知:
b.o是可重定位对象(ET_REL):b.o不是最终的可执行文件,而是中间目标文件。
Entry offset 为0。
没有程序头表(Program header entries)
有11个节表头,从0x0448开始。每40个字节(0x28)表示一个。
空节
第0#节为全零:(0x0448~0x46F).
节名字符串表
文件头中指明,节名字符串表在第8个节。起始地址在0x0448 + 0x28 * 8 = 0x0588
字节内容为:
与结构体的元素相对应的关系为:
元素 | 数值 |
sh_name | 0x19 |
sh_type | 0x03 |
sh_flags | 0x00 |
sh_addr | 0x00 |
sh_offset | 0x02C0 |
sh_size | 0x62 |
sh_link | 0x00 |
sh_info | 0x00 |
sh_addralign | 0x01 |
sh_entsize | 0x00 |
解析结果为:
====================================
** Section #8
Name : .shstrtab
Type : SHT_STRTAB (0x00000003)
Flags : None (0x00000000)
Addr : 0x00000000
File Offset : 704 (0x2c0)
Size : 98 bytes (0x62)
Link : SHN_UNDEF
Info : 0
Alignment : 1
Entry Size : 0
====================================
可以看出,字符串在ELF文件的偏移量为0x02C0,总长度为0x62
本节的名称在0x19处,即文件中的0x02c0 + 0x0019 = 0x02d9开始:正是“.shstrtab”
代码节
第1个节为代码。看看0x0470~0x0497:
与结构体的元素相对应的关系为:
元素 | 数值 |
sh_name | 0x5B |
sh_type | 0x01 |
sh_flags | 0x06 |
sh_addr | 0x00 |
sh_offset | 0x34 |
sh_size | 0x16 |
sh_link | 0x00 |
sh_info | 0x00 |
sh_addralign | 0x02 |
sh_entsize | 0x00 |
解析结果为:
** Section #1
Name : i.swap
Type : SHT_PROGBITS (0x00000001)
Flags : SHF_ALLOC + SHF_EXECINSTR (0x00000006)
Addr : 0x00000000
File Offset : 52 (0x34)
Size : 22 bytes (0x16)
Link : SHN_UNDEF
Info : 0
Alignment : 2
Entry Size : 0
====================================
同样的,名称在节名字符串表中的偏移量为0x5B,即:"i.swap"
代码内容在0x34,长度为0x16。
正是函数swap的汇编指令:
通过-c参数也要打印出来:
========================================================================
** Section #1 'i.swap' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR]
Size : 22 bytes (alignment 2)
Address: 0x00000000
$t
i.swap
swap
0x00000000: 6802 .h LDR r2,[r0,#0]
0x00000002: 680b .h LDR r3,[r1,#0]
0x00000004: 405a Z@ EORS r2,r2,r3
0x00000006: 6002 .` STR r2,[r0,#0]
0x00000008: 680b .h LDR r3,[r1,#0]
0x0000000a: 405a Z@ EORS r2,r2,r3
0x0000000c: 600a .` STR r2,[r1,#0]
0x0000000e: 6803 .h LDR r3,[r0,#0]
0x00000010: 405a Z@ EORS r2,r2,r3
0x00000012: 6002 .` STR r2,[r0,#0]
0x00000014: 4770 pG BX lr
符号表
第6节为符号表。表头位置在0x0448 + 0x28 * 6 = 0x0538
与结构体的元素相对应的关系为:
元素 | 数值 |
sh_name | 0x34 |
sh_type | 0x02 |
sh_flags | 0x00 |
sh_addr | 0x00 |
sh_offset | 0x0210 |
sh_size | 0xA0 |
sh_link | 0x09 |
sh_info | 0x07 |
sh_addralign | 0x04 |
sh_entsize | 0x10 |
解析结果为:
====================================
** Section #6
Name : .symtab
Type : SHT_SYMTAB (0x00000002)
Flags : None (0x00000000)
Addr : 0x00000000
File Offset : 528 (0x210)
Size : 160 bytes (0xa0)
Link : Section 9 (.strtab)
Info : Last local symbol no = 6
Alignment : 4
Entry Size : 16
====================================
说明:符号表的内容在文件0x0210处,总大小为0xA0(160个字符)。每个符号的描述符有16个字节,因此,共有10个符号项。
符号表项
一个符号表表项的数据结构定义如下:
/* Symbol table entry. */
typedef struct
{
Elf32_Word st_name; /* Symbol name (string tbl index) */
Elf32_Addr st_value; /* Symbol value */
Elf32_Word st_size; /* Symbol size */
unsigned char st_info; /* Symbol type and binding */
unsigned char st_other; /* Symbol visibility */
Elf32_Section st_shndx; /* Section index */
} Elf32_Sym;
其中,st_info字节分为两部分,高4位为绑定属性,低4位为类型。
高4位定义符号的绑定[binding ]:
- STB_LOCAL (0) symbol is local to the file
- STB_GLOBAL (1) symbol is visible to all object files
- STB_WEAK (2) symbol is global with lower precedence
低4位定义符号的类型:
- STT_NOTYPE (0) 无类型
- STT_OBJECT (1) 数据对象(变量)
- STT_FUNC (2) 函数
- STT_SECTION (3) section名
- STT_FILE (4) 文件名
st_shndx:定义符号section的索引.特殊的section数包括:
- SHN_UNDEF (0x0000) 未定义section
- SHN_ABS (0xfff1) 绝对, 不可重定位符号
- SHN_COMMON (0xfff2) 不分配, 外部变量
具体分析
第0个符号表项的内容为全零。
以第1个符号表项来分析:
元素 | 数值 |
st_name | 0x000000D0 |
st_value | 0x00000000 |
st_size | 0x00000000 |
st_info | 0x04 |
st_other | 0x00 |
st_shndx | 0xFFF1 |
st_name: 这里不再是相对shstrtab的偏移,而是基于strtab的。第9个节为strtab,起始地址为0x322(是接在shstrtab的后面),其名称字符串地址为0x0322+0x00D0=03F2,内容为:“..\..\src\b.c”
st_info=0x04. 高4位=0=STB_LOCAL;低4位=4=STT_FILE。
st_shndx=0xFFF1=SHN_ABS=绝对符号,不可重定位。
再看第7个:起始地址为0x0280。
元素 | 数值 |
st_name | 0x00000016 |
st_value | 0x00000000 |
st_size | 0x00000004 |
st_info | 0x11 |
st_other | 0x02 |
st_shndx | 0x0004 |
st_name=0x0322+0x0016=0x0338="shared",是代码中变量shared的名字。
st_value=0x00000000。在段.data中的偏移量。
st_size=0x04=变量的大小(int型,32位,占4个字节)
st_info=0x11. 高4位=Binding=1=STB_GLOBAL;低4位=Type=1=STT_OBJECT=数据对象,即变量。
st_shndx=0x0004 --> section #4(.data节)
最后,再来看第8个:起始地址为0x0290。
元素 | 数值 |
st_name | 0x000000C2 |
st_value | 0x00000001 |
st_size | 0x00000016 |
st_info | 0x12 |
st_other | 0x02 |
st_shndx | 0x0001 |
st_name=0x0322+0x00C2=0x03E4="swap"
st_value=0x00000001。在段i.swap中的偏移量。本来应该是0,但由于是thumb指令,需要加1.
st_size=0x16=swap函数代码的大小,参见“代码节”
st_info=0x12. 高4位=Binding=1=STB_GLOBAL;低4位=Type=2=STT_FUNC
st_shndx=0x0001 --> section #1(i.swap节)
验证
使用命令打印符号表:fromelf -s b.o
** Section #6 '.symtab' (SHT_SYMTAB)
Size : 160 bytes (alignment 4)
String table #9 '.strtab'
Last local symbol no. 6
Symbol table .symtab (9 symbols, 6 local)
# Symbol Name Value Bind Sec Type Vis Size
========================================================================
1 ..\..\src\b.c 0x00000000 Lc Abs File De
2 $t 0x00000000 Lc 1 -- De
3 .data 0x00000000 Lc 4 Sect De 0x4
4 i.swap 0x00000000 Lc 1 Sect De
5 BuildAttributes$$THM_ISAv4$P$D$K$B$S$PE$A:L22UL41UL21$X:L11$S22US41US21$IEEE1$IW$USESV6$~STKCKD$USESV7$~SHL$OSPACE$EBA8$REQ8$PRES8$EABIv2
0x00000000 Lc Abs -- De
6 __ARM_grp_.debug_frame$5 0x00000000 Lc 5 Data De
7 shared 0x00000000 Gb 4 Data Hi 0x4
8 swap 0x00000001 Gb 1 Code Hi 0x16
9 Lib$$Request$$armlib 0x00000000 Wk Ref Code Hi