ELF文件格式 (2)

.data段保存的是已经初始化了的全局静态变量和局部静态变量。前面SimpleSection.c中的global_init_varabal和static_var正是这样的变量。使用objdump -x -s -d SimpleSection.o查看:

Contents of section .data: 0000 54000000 55000000 T...U... Contents of section .rodata: 0000 25640a00 %d..

最左边的0000是偏移,不用看,后面跟着的0x00000054和0x00000055正是global_init_varabal和static_var的初始值。
.rodata段存放的是只读数据,包括只读变量(const修饰的变量和字符串常量),这个例子中保存了"%d\n"正是调用printf的时候使用的字符常量。

符号表段

符号表段一般叫做.symtab,以数组结构保存符号信息(函数和变量),对于函数和变量符号值就是它们的地址。主要关注两类符号:

定义在目标文件中的全局符号,可以被其他目标文件引用,比如SimpleSction.o里面的func1, main和global_init_var。

在本目标文件中引用的全局符号,却没有定义在本目标文件,比如pritnf。

可以用readelf -s SimpleSection.o查看SimpleSection.o的符号:

Symbol table '.symtab' contains 16 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 FILE LOCAL DEFAULT ABS SimpleSection.c 2: 00000000 0 SECTION LOCAL DEFAULT 1 3: 00000000 0 SECTION LOCAL DEFAULT 3 4: 00000000 0 SECTION LOCAL DEFAULT 4 5: 00000000 0 SECTION LOCAL DEFAULT 5 6: 00000004 4 OBJECT LOCAL DEFAULT 3 static_var.1488 7: 00000000 4 OBJECT LOCAL DEFAULT 4 static_var2.1489 8: 00000000 0 SECTION LOCAL DEFAULT 7 9: 00000000 0 SECTION LOCAL DEFAULT 8 10: 00000000 0 SECTION LOCAL DEFAULT 6 11: 00000000 4 OBJECT GLOBAL DEFAULT 3 global_init_var 12: 00000004 4 OBJECT GLOBAL DEFAULT COM global_uniit_var 13: 00000000 28 FUNC GLOBAL DEFAULT 1 func1 14: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf 15: 0000001c 70 FUNC GLOBAL DEFAULT 1 main

可以看到:

func1和main的Ndx对应的值是1,表示在.text段(.text段在段表中的索引是1),类型是FUNC,value分别是0x00000000和0x0000001c,表明这两个函数指令字节码的首字节分别在.text段的0x00000000和0x0000001c偏移处。

printf的Ndx是UND,表明这个符号没有在SimpleSection.o中定义,仅仅是被引用。

global_init_var和static_var.1488两个符号的Ndx都是3,说明他们被定义在数据段,value分别是0x00000000和0x00000004,表示这个符号的位置在数据段的0x00000000和0x00000004偏移处,翻看上一节

Contents of section .data: 0000 54000000 55000000 T...U...

数据段0x00000000和0x00000004偏移处保存的正是global_init_var和static_var这两个变量。

重定位表段

重定位表也是一个段,用于描述在重定位时链接器如何修改相应段里的内容。对于.text段,对应的重定位表是.rel.text表。使用objdump -r SimpleSection.o查看重定位表。

SimpleSection.o: file format elf32-i386 RELOCATION RECORDS FOR [.text]: OFFSET TYPE VALUE 0000000d R_386_32 .rodata 00000012 R_386_PC32 printf 00000036 R_386_32 .data 0000003b R_386_32 .bss 00000050 R_386_PC32 func1

printf对应的那行的OFFSET为0x00000012,表明.text段的0x00000012偏移处需要修改。我们objdump -s -d SimpleSection.o查看代码段的0x00000012偏移,发现是”fc ff ff ff“是call指令的操作数。

00000000 <func1>: 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 83 ec 08 sub $0x8,%esp 6: 83 ec 08 sub $0x8,%esp 9: ff 75 08 pushl 0x8(%ebp) c: 68 00 00 00 00 push $0x0 11: e8 fc ff ff ff call 12 <func1+0x12> 16: 83 c4 10 add $0x10,%esp 19: 90 nop 1a: c9 leave 1b: c3 ret

也就是说,在没有重定位前call指令的操作”fc ff ff ff“是无效的,需要在重定位过程中进行修正。func1那行也同理。

总结

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyzggw.html