第二部分、字符串表(节,.strtab)。
09 00 00 00 //.strtab
03 00 00 00 //3 ,表明本节是字符串表
00 00 00 00 //标志
00 00 00 00 //还没重定位,所以为0
24 1a 00 00 //起始地址:0x1a24
32 02 00 00 //大小 0×232
00 00 00 00
00 00 00 00
01 00 00 00 //对齐
00 00 00 00 //指向的不是表
根据上面的解析,把字符串表拿出来,地址为0x1a24~0x1c55
00 63 72 74 73 74 75 66 66 2e 63 00 5f 5f 43 54 4f 52 5f 4c 49 53 54 5f 5f 00 5f 5f 44 54 4f 52 5f 4c 49 53 54 5f 5f 00 5f 5f 4a 43 52 5f 4c 49 53 54 5f 5f 00 5f 5f 64
6f 5f 67 6c 6f 62 61 6c 5f 64 74 6f 72 73 5f 61 75 78 00 63 6f 6d 70 6c 65 74 65 64 2e 36 30 38 36 00 64 74 6f 72 5f 69 64 78 2e 36 30 38 38 00 66 72 61 6d 65 5f 64 75
6d 6d 79 00 5f 5f 43 54 4f 52 5f 45 4e 44 5f 5f 00 5f 5f 46 52 41 4d 45 5f 45 4e 44 5f 5f 00 5f 5f 4a 43 52 5f 45 4e 44 5f 5f 00 5f 5f 64 6f 5f 67 6c 6f 62 61 6c 5f 63
74 6f 72 73 5f 61 75 78 00 6c 65 61 66 2e 63 00 5f 5f 69 6e 69 74 5f 61 72 72 61 79 5f 65 6e 64 00 5f 44 59 4e 41 4d 49 43 00 5f 5f 69 6e 69 74 5f 61 72 72 61 79 5f 73
74 61 72 74 00 5f 47 4c 4f 42 41 4c 5f 4f 46 46 53 45 54 5f 54 41 42 4c 45 5f 00 5f 5f 6c 69 62 63 5f 63 73 75 5f 66 69 6e 69 00 5f 5f 69 36 38 36 2e 67 65 74 5f 70 63
5f 74 68 75 6e 6b 2e 62 78 00 64 61 74 61 5f 73 74 61 72 74 00 70 72 69 6e 74 66 40 40 47 4c 49 42 43 5f 32 2e 30 00 5f 65 64 61 74 61 00 5f 66 69 6e 69 00 5f 5f 73 74
61 63 6b 5f 63 68 6b 5f 66 61 69 6c 40 40 47 4c 49 42 43 5f 32 2e 34 00 5f 5f 44 54 4f 52 5f 45 4e 44 5f 5f 00 5f 5f 64 61 74 61 5f 73 74 61 72 74 00 5f 5f 67 6d 6f 6e
5f 73 74 61 72 74 5f 5f 00 5f 5f 64 73 6f 5f 68 61 6e 64 6c 65 00 5f 49 4f 5f 73 74 64 69 6e 5f 75 73 65 64 00 5f 5f 6c 69 62 63 5f 73 74 61 72 74 5f 6d 61 69 6e 40 40
47 4c 49 42 43 5f 32 2e 30 00 5f 5f 6c 69 62 63 5f 63 73 75 5f 69 6e 69 74 00 5f 65 6e 64 00 5f 73 74 61 72 74 00 5f 66 70 5f 68 77 00 5f 5f 62 73 73 5f 73 74 61 72 74
00 6d 61 69 6e 00 5f 4a 76 5f 52 65 67 69 73 74 65 72 43 6c 61 73 73 65 73 00 5f 5f 69 73 6f 63 39 39 5f 73 63 61 6e 66 40 40 47 4c 49 42 43 5f 32 2e 37 00 5f 69 6e 69 74 00
既然是字符串表,那就翻译成ASCII字符串,如下:
crtstuff.c __CTOR_LIST__ __DTOR_LIST__ __JCR_LIST__ __do_global_dtors_aux completed.6086 dtor_idx.6088 frame_dummy __CTOR_END__ __FRAME_END__ __JCR_END__ __do_global_ctors_aux leaf.c __init_array_end _DYNAMIC __init_array_start _GLOBAL_OFFSET_TABLE_ __libc_csu_fini __i686.get_pc_thunk.bx data_start printf@@GLIBC_2.0 _edata _fini __stack_chk_fail@@GLIBC_2.4 __DTOR_END__ __data_start __gmon_start__ __dso_handle _IO_stdin_used __libc_start_main@@GLIBC_2.0 __libc_csu_init _end _start _fp_hw __bss_start main _Jv_RegisterClasses __isoc99_scanf@@GLIBC_2.7 _init
仔细看看上面的字符串,我们会发现我们定义的全局变量和函数的名字都在这里,像printf、scanf、main等。但是printf() 函数调用中用到的字符串(像”input gemfield’s blog:”)却没有发现,它们被定义在.rodata 节中,因为它们是字符串常量。
第三部分、代码节(.text),数据如下:
92 00 00 00 //.text
01 00 00 00 //1 ,程序定义
06 00 00 00 /表示此节内容是指令代码,并且要使用内存单元
d0 83 04 08 //代码映射到虚拟内存中的起始地址,为0x080483d0,记住这个数字。
d0 03 00 00 //在gemfield中的偏移地址 0x03d0
dc 01 00 00 //大小 0x1dc个字节
00 00 00 00 //
00 00 00 00
10 00 00 00 //对齐
00 00 00 00 //指向的不是表
我们把这个代码段的数据拿出来,地址为0x3d0~0x5ab,如下:
31 ed 5e 89 e1 83 e4 f0 50 54 52 68 70 85 04 08 68 00 85 04 08 51 56 68 84 84 04 08 e8 bf ff ff ff f4 90 90 90 90 90 90 90 90 90 90 90 90 90 90 55 89 e5 53 83 ec 04 80
3d 1c a0 04 08 00 75 3f a1 20 a0 04 08 bb 20 9f 04 08 81 eb 1c 9f 04 08 c1 fb 02 83 eb 01 39 d8 73 1e 8d b6 00 00 00 00 83 c0 01 a3 20 a0 04 08 ff 14 85 1c 9f 04 08 a1
20 a0 04 08 39 d8 72 e8 c6 05 1c a0 04 08 01 83 c4 04 5b 5d c3 8d 74 26 00 8d bc 27 00 00 00 00 55 89 e5 83 ec 18 a1 24 9f 04 08 85 c0 74 12 b8 00 00 00 00 85 c0 74 09
c7 04 24 24 9f 04 08 ff d0 c9 c3 90 55 89 e5 83 e4 f0 83 ec 50 8b 45 0c 89 44 24 1c 65 a1 14 00 00 00 89 44 24 4c 31 c0 c7 44 24 28 00 00 00 00 b8 d0 85 04 08 89 04 24
e8 cb fe ff ff b8 e8 85 04 08 8d 54 24 2c 89 54 24 04 89 04 24 e8 f6 fe ff ff b8 eb 85 04 08 8d 54 24 2c 89 54 24 04 89 04 24 e8 a1 fe ff ff 8b 54 24 4c 65 33 15 14 00
00 00 74 05 e8 9f fe ff ff c9 c3 90 90 90 90 90 90 90 90 90 90 90 90 90 55 57 56 53 e8 69 00 00 00 81 c3 eb 1a 00 00 83 ec 1c 8b 6c 24 30 8d bb 20 ff ff ff e8 1b fe ff
ff 8d 83 20 ff ff ff 29 c7 c1 ff 02 85 ff 74 29 31 f6 8d b6 00 00 00 00 8b 44 24 38 89 2c 24 89 44 24 08 8b 44 24 34 89 44 24 04 ff 94 b3 20 ff ff ff 83 c6 01 39 fe 75
df 83 c4 1c 5b 5e 5f 5d c3 eb 0d 90 90 90 90 90 90 90 90 90 90 90 90 90 f3 c3 8b 1c 24 c3 90 90 90 90 90 90 90 90 90 90 55 89 e5 53 83 ec 04 a1 14 9f 04 08 83 f8 ff 74
13 bb 14 9f 04 08 66 90 83 eb 04 ff d0 8b 03 83 f8 ff 75 f4 83 c4 04 5b 5d c3 90 90
我们使用反汇编 objdump –disassemble gemfield,输出如下:
*****************************************************************************
Disassembly of section .text:
080483d0 <_start>:
80483d0: 31 ed xor %ebp,%ebp
80483d2: 5e pop %esi
80483d3: 89 e1 mov %esp,%ecx
80483d5: 83 e4 f0 and $0xfffffff0,%esp
80483d8: 50 push %eax
80483d9: 54 push %esp
80483da: 52 push %edx
80483db: 68 70 85 04 08 push $0×8048570
80483e0: 68 00 85 04 08 push $0×8048500
80483e5: 51 push %ecx
80483e6: 56 push %esi
80483e7: 68 84 84 04 08 push $0×8048484
80483ec: e8 bf ff ff ff call 80483b0 <__libc_start_main@plt>
80483f1: f4 hlt
80483f2: 90 nop
80483f3: 90 nop
80483f4: 90 nop
80483f5: 90 nop
80483f6: 90 nop
80483f7: 90 nop
80483f8: 90 nop
80483f9: 90 nop
80483fa: 90 nop
80483fb: 90 nop
80483fc: 90 nop
80483fd: 90 nop
80483fe: 90 nop
80483ff: 90 nop
08048400 <__do_global_dtors_aux>:
8048400: 55 push %ebp
8048401: 89 e5 mov %esp,%ebp
8048403: 53 push %ebx
8048404: 83 ec 04 sub $0×4,%esp
8048407: 80 3d 1c a0 04 08 00 cmpb $0×0,0x804a01c
804840e: 75 3f jne 804844f <__do_global_dtors_aux+0x4f>
8048410: a1 20 a0 04 08 mov 0x804a020,%eax
8048415: bb 20 9f 04 08 mov $0x8049f20,%ebx
804841a: 81 eb 1c 9f 04 08 sub $0x8049f1c,%ebx
8048420: c1 fb 02 sar $0×2,%ebx
8048423: 83 eb 01 sub $0×1,%ebx
8048426: 39 d8 cmp %ebx,%eax
8048428: 73 1e jae 8048448 <__do_global_dtors_aux+0×48>
804842a: 8d b6 00 00 00 00 lea 0×0(%esi),%esi
8048430: 83 c0 01 add $0×1,%eax
8048433: a3 20 a0 04 08 mov %eax,0x804a020
8048438: ff 14 85 1c 9f 04 08 call *0x8049f1c(,%eax,4)
804843f: a1 20 a0 04 08 mov 0x804a020,%eax
8048444: 39 d8 cmp %ebx,%eax
8048446: 72 e8 jb 8048430 <__do_global_dtors_aux+0×30>
8048448: c6 05 1c a0 04 08 01 movb $0×1,0x804a01c
804844f: 83 c4 04 add $0×4,%esp
8048452: 5b pop %ebx
8048453: 5d pop %ebp
8048454: c3 ret
8048455: 8d 74 26 00 lea 0×0(%esi,%eiz,1),%esi
8048459: 8d bc 27 00 00 00 00 lea 0×0(%edi,%eiz,1),%edi
08048460 <frame_dummy>:
8048460: 55 push %ebp
8048461: 89 e5 mov %esp,%ebp
8048463: 83 ec 18 sub $0×18,%esp
8048466: a1 24 9f 04 08 mov 0x8049f24,%eax
804846b: 85 c0 test %eax,%eax
804846d: 74 12 je 8048481 <frame_dummy+0×21>
804846f: b8 00 00 00 00 mov $0×0,%eax
8048474: 85 c0 test %eax,%eax
8048476: 74 09 je 8048481 <frame_dummy+0×21>
8048478: c7 04 24 24 9f 04 08 movl $0x8049f24,(%esp)
804847f: ff d0 call *%eax
8048481: c9 leave
8048482: c3 ret
8048483: 90 nop
08048484 <main>:
8048484: 55 push %ebp
8048485: 89 e5 mov %esp,%ebp
8048487: 83 e4 f0 and $0xfffffff0,%esp
804848a: 83 ec 50 sub $0×50,%esp
804848d: 8b 45 0c mov 0xc(%ebp),%eax
8048490: 89 44 24 1c mov %eax,0x1c(%esp)
8048494: 65 a1 14 00 00 00 mov %gs:0×14,%eax
804849a: 89 44 24 4c mov %eax,0x4c(%esp)
804849e: 31 c0 xor %eax,%eax
80484a0: c7 44 24 28 00 00 00 movl $0×0,0×28(%esp)
80484a7: 00
80484a8: b8 d0 85 04 08 mov $0x80485d0,%eax
80484ad: 89 04 24 mov %eax,(%esp)
80484b0: e8 cb fe ff ff call 8048380 <printf@plt>
80484b5: b8 e8 85 04 08 mov $0x80485e8,%eax
80484ba: 8d 54 24 2c lea 0x2c(%esp),%edx
80484be: 89 54 24 04 mov %edx,0×4(%esp)
80484c2: 89 04 24 mov %eax,(%esp)
80484c5: e8 f6 fe ff ff call 80483c0 <__isoc99_scanf@plt>
80484ca: b8 eb 85 04 08 mov $0x80485eb,%eax
80484cf: 8d 54 24 2c lea 0x2c(%esp),%edx
80484d3: 89 54 24 04 mov %edx,0×4(%esp)
80484d7: 89 04 24 mov %eax,(%esp)
80484da: e8 a1 fe ff ff call 8048380 <printf@plt>
80484df: 8b 54 24 4c mov 0x4c(%esp),%edx
80484e3: 65 33 15 14 00 00 00 xor %gs:0×14,%edx
80484ea: 74 05 je 80484f1 <main+0x6d>
80484ec: e8 9f fe ff ff call 8048390 <__stack_chk_fail@plt>
80484f1: c9 leave
80484f2: c3 ret
80484f3: 90 nop
80484f4: 90 nop
80484f5: 90 nop
80484f6: 90 nop
80484f7: 90 nop
80484f8: 90 nop
80484f9: 90 nop
80484fa: 90 nop
80484fb: 90 nop
80484fc: 90 nop
80484fd: 90 nop
80484fe: 90 nop
80484ff: 90 nop
08048500 <__libc_csu_init>:
8048500: 55 push %ebp
8048501: 57 push %edi
8048502: 56 push %esi
8048503: 53 push %ebx
8048504: e8 69 00 00 00 call 8048572 <__i686.get_pc_thunk.bx>
8048509: 81 c3 eb 1a 00 00 add $0x1aeb,%ebx
804850f: 83 ec 1c sub $0x1c,%esp
8048512: 8b 6c 24 30 mov 0×30(%esp),%ebp
8048516: 8d bb 20 ff ff ff lea -0xe0(%ebx),%edi
804851c: e8 1b fe ff ff call 804833c <_init>
8048521: 8d 83 20 ff ff ff lea -0xe0(%ebx),%eax
8048527: 29 c7 sub %eax,%edi
8048529: c1 ff 02 sar $0×2,%edi
804852c: 85 ff test %edi,%edi
804852e: 74 29 je 8048559 <__libc_csu_init+0×59>
8048530: 31 f6 xor %esi,%esi
8048532: 8d b6 00 00 00 00 lea 0×0(%esi),%esi
8048538: 8b 44 24 38 mov 0×38(%esp),%eax
804853c: 89 2c 24 mov %ebp,(%esp)
804853f: 89 44 24 08 mov %eax,0×8(%esp)
8048543: 8b 44 24 34 mov 0×34(%esp),%eax
8048547: 89 44 24 04 mov %eax,0×4(%esp)
804854b: ff 94 b3 20 ff ff ff call *-0xe0(%ebx,%esi,4)
8048552: 83 c6 01 add $0×1,%esi
8048555: 39 fe cmp %edi,%esi
8048557: 75 df jne 8048538 <__libc_csu_init+0×38>
8048559: 83 c4 1c add $0x1c,%esp
804855c: 5b pop %ebx
804855d: 5e pop %esi
804855e: 5f pop %edi
804855f: 5d pop %ebp
8048560: c3 ret
8048561: eb 0d jmp 8048570 <__libc_csu_fini>
8048563: 90 nop
8048564: 90 nop
8048565: 90 nop
8048566: 90 nop
8048567: 90 nop
8048568: 90 nop
8048569: 90 nop
804856a: 90 nop
804856b: 90 nop
804856c: 90 nop
804856d: 90 nop
804856e: 90 nop
804856f: 90 nop
08048570 <__libc_csu_fini>:
8048570: f3 c3 repz ret
08048572 <__i686.get_pc_thunk.bx>:
8048572: 8b 1c 24 mov (%esp),%ebx
8048575: c3 ret
8048576: 90 nop
8048577: 90 nop
8048578: 90 nop
8048579: 90 nop
804857a: 90 nop
804857b: 90 nop
804857c: 90 nop
804857d: 90 nop
804857e: 90 nop
804857f: 90 nop
08048580 <__do_global_ctors_aux>:
8048580: 55 push %ebp
8048581: 89 e5 mov %esp,%ebp
8048583: 53 push %ebx
8048584: 83 ec 04 sub $0×4,%esp
8048587: a1 14 9f 04 08 mov 0x8049f14,%eax
804858c: 83 f8 ff cmp $0xffffffff,%eax
804858f: 74 13 je 80485a4 <__do_global_ctors_aux+0×24>
8048591: bb 14 9f 04 08 mov $0x8049f14,%ebx
8048596: 66 90 xchg %ax,%ax
8048598: 83 eb 04 sub $0×4,%ebx
804859b: ff d0 call *%eax
804859d: 8b 03 mov (%ebx),%eax
804859f: 83 f8 ff cmp $0xffffffff,%eax
80485a2: 75 f4 jne 8048598 <__do_global_ctors_aux+0×18>
80485a4: 83 c4 04 add $0×4,%esp
80485a7: 5b pop %ebx
80485a8: 5d pop %ebp
80485a9: c3 ret
80485aa: 90 nop
80485ab: 90 nop
*************************************************************
可以看出和我们自己解析的数据是完全匹配的。
第四部分:符号表(.symtab),数据如下:
01 00 00 00 //.symtab
02 00 00 00 //完整的符号表,它往往会包含很多在运行期间( 动态连接) 用不到的符号。
00 00 00 00 //flag
00 00 00 00 //因为没有重定位,地址为0
f4 15 00 00 //在gemfield文件中的偏移:0x15f4
30 04 00 00 //大小:0×0430
1d 00 00 00 //相关字符串表的节头索引
2d 00 00 00 //符号表中最后一个本地符号的索引值加1
04 00 00 00 //对齐 4个字节
10 00 00 00 //指向的是表(没错,符号表),每一个表项大小为0×10个字节。
数据摘录如下,地址范围为0x15f4~1a23,一共67项:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 54 81 04 08 00 00 00 00 03 00 01 00
00 00 00 00 68 81 04 08 00 00 00 00 03 00 02 00
00 00 00 00 88 81 04 08 00 00 00 00 03 00 03 00
00 00 00 00 ac 81 04 08 00 00 00 00 03 00 04 00
00 00 00 00 cc 81 04 08 00 00 00 00 03 00 05 00
00 00 00 00 3c 82 04 08 00 00 00 00 03 00 06 00
00 00 00 00 bc 82 04 08 00 00 00 00 03 00 07 00
00 00 00 00 cc 82 04 08 00 00 00 00 03 00 08 00
00 00 00 00 0c 83 04 08 00 00 00 00 03 00 09 00
00 00 00 00 14 83 04 08 00 00 00 00 03 00 0a 00
00 00 00 00 3c 83 04 08 00 00 00 00 03 00 0b 00
00 00 00 00 70 83 04 08 00 00 00 00 03 00 0c 00
00 00 00 00 d0 83 04 08 00 00 00 00 03 00 0d 00
00 00 00 00 ac 85 04 08 00 00 00 00 03 00 0e 00
00 00 00 00 c8 85 04 08 00 00 00 00 03 00 0f 00
00 00 00 00 04 86 04 08 00 00 00 00 03 00 10 00
00 00 00 00 38 86 04 08 00 00 00 00 03 00 11 00
00 00 00 00 14 9f 04 08 00 00 00 00 03 00 12 00
00 00 00 00 1c 9f 04 08 00 00 00 00 03 00 13 00
00 00 00 00 24 9f 04 08 00 00 00 00 03 00 14 00
00 00 00 00 28 9f 04 08 00 00 00 00 03 00 15 00
00 00 00 00 f0 9f 04 08 00 00 00 00 03 00 16 00
00 00 00 00 f4 9f 04 08 00 00 00 00 03 00 17 00
00 00 00 00 14 a0 04 08 00 00 00 00 03 00 18 00
00 00 00 00 1c a0 04 08 00 00 00 00 03 00 19 00
00 00 00 00 00 00 00 00 00 00 00 00 03 00 1a 00
01 00 00 00 00 00 00 00 00 00 00 00 04 00 f1 ff
0c 00 00 00 14 9f 04 08 00 00 00 00 01 00 12 00
1a 00 00 00 1c 9f 04 08 00 00 00 00 01 00 13 00
28 00 00 00 24 9f 04 08 00 00 00 00 01 00 14 00
35 00 00 00 00 84 04 08 00 00 00 00 02 00 0d 00
4b 00 00 00 1c a0 04 08 01 00 00 00 01 00 19 00
5a 00 00 00 20 a0 04 08 04 00 00 00 01 00 19 00
68 00 00 00 60 84 04 08 00 00 00 00 02 00 0d 00
01 00 00 00 00 00 00 00 00 00 00 00 04 00 f1 ff
74 00 00 00 18 9f 04 08 00 00 00 00 01 00 12 00
81 00 00 00 f8 86 04 08 00 00 00 00 01 00 11 00
8f 00 00 00 24 9f 04 08 00 00 00 00 01 00 14 00
9b 00 00 00 80 85 04 08 00 00 00 00 02 00 0d 00
b1 00 00 00 00 00 00 00 00 00 00 00 04 00 f1 ff
b8 00 00 00 14 9f 04 08 00 00 00 00 00 00 12 00
c9 00 00 00 28 9f 04 08 00 00 00 00 01 00 15 00
d2 00 00 00 14 9f 04 08 00 00 00 00 00 00 12 00
e5 00 00 00 f4 9f 04 08 00 00 00 00 01 00 17 00
fb 00 00 00 70 85 04 08 02 00 00 00 12 00 0d 00
0b 01 00 00 72 85 04 08 00 00 00 00 12 02 0d 00
22 01 00 00 14 a0 04 08 00 00 00 00 20 00 18 00
2d 01 00 00 00 00 00 00 00 00 00 00 12 00 00 00
3f 01 00 00 1c a0 04 08 00 00 00 00 10 00 f1 ff
46 01 00 00 ac 85 04 08 00 00 00 00 12 00 0e 00
4c 01 00 00 00 00 00 00 00 00 00 00 12 00 00 00
68 01 00 00 20 9f 04 08 00 00 00 00 11 02 13 00
75 01 00 00 14 a0 04 08 00 00 00 00 10 00 18 00
82 01 00 00 00 00 00 00 00 00 00 00 20 00 00 00
91 01 00 00 18 a0 04 08 00 00 00 00 11 02 18 00
9e 01 00 00 cc 85 04 08 04 00 00 00 11 00 0f 00
ad 01 00 00 00 00 00 00 00 00 00 00 12 00 00 00
ca 01 00 00 00 85 04 08 61 00 00 00 12 00 0d 00
da 01 00 00 24 a0 04 08 00 00 00 00 10 00 f1 ff
df 01 00 00 d0 83 04 08 00 00 00 00 12 00 0d 00
e6 01 00 00 c8 85 04 08 04 00 00 00 11 00 0f 00
ed 01 00 00 1c a0 04 08 00 00 00 00 10 00 f1 ff
f9 01 00 00 84 84 04 08 6f 00 00 00 12 00 0d 00
fe 01 00 00 00 00 00 00 00 00 00 00 20 00 00 00
12 02 00 00 00 00 00 00 00 00 00 00 12 00 00 00
2c 02 00 00 3c 83 04 08 00 00 00 00 12 00 0b 00
符号表(symbol table) 所包含的信息用于定位和重定位程序中的符号定义和引用。目标文件的其它部分通过一个符号在这个表中的索引值来使用该符号。索引值从0 开始计数,但值为0 的表项(即第一项)并没有实际的意义,它表示未定义的符号。这里用常量STN_UNDEF 来表示未定义的符号。
一个符号表项的格式定义如下:
typedef struct {
Elf32_Word st_name; //符号的名字
Elf32_Addr st_value ; //符号的值
Elf32_Word st_size; //符号的大小
unsigned char st_info;
unsigned char st_other ;
Elf32_Half st_shndx ;
} Elf32_Sym;//恰好16个字节
1、st_name,
符号的名字。但它并不是一个字符串,而是一个指向字符串表(.strtab)的索引值,在字符串表中对应位置上的字符串就是该符号名字的实际文本。如果此值为非0,它代表符号名在字符串 表中的索引值。如果此值为0,那么此符号无名字。
2、符号的值,
这个值其实没有固定的类型,它可能代表一个数值,也可以是一个地址,具体是什么要看上下文。对于不同的目标文件类型,符号表项的st_value 的含义略有不同:
*在重定位文件中,如果一个符号对应的节的索引值是SHN_COMMON,st_value 值是这个节内容的字节对齐数。
*在重定位文件中,如果一个符号是已定义的,那么它的st_value 值是该符号的起始地址在其所在节中的偏移量,而其所在的节的索引由st_shndx 给出。
*在可执行文件和共享库文件中,st_value 不再是一个节内的偏移量,而是一个虚拟地址,直接指向符号所在的内存位置。这种情况下,st_shndx就不再需要了。
如果一个可执行文件中含有一个函数的引用,而这个函数是定义在一个共享目标文件中,那么在可执行文件中,针对那个共享目标文件的符号表应该含有这个函数的符号。符号表的st_shndx 成员值为SHN_UNDEF ,这就告诉了动态连接器,这个函数的符号定义并不在可执行文件中。如果已经在可执行文件中给这个符号申请了一个函数连接表项,而且符号表项的st_value 成员不是 0,那么st_value值就将是函数连接表项中第一条指令的地址。否则,st_value 成员是0。这个函数连接表项地址被动态连接器用来解析函数地址。细节参见 http://civilnet.cn/bbs/topicno/71157 。
3、st_size,
符号的大小。各种符号的大小各不相同,比如一个对象的大小就是它实际占用的字节数。如果一个符号的大小为0 或者大小未知,则这个值为0。
4、st_info,
符号的类型和属性。st_info 由一系列的比特位构成,标识了“符号绑定(symbol binding) ”、“符号类型(symbol type) ”和“符号信息(symbol infomation)”三种属性。下面几个宏分
别用于读取这三种属性值。
#define ELF32_ST_BIND( i ) ((i)>>4)
#define ELF32_ST_TYPE( i ) ((i)&0xf)
#define ELF32_ST_INFO( b,t ) (((b)<<4)+((t)&0xf))
下面分别说明:
符号绑定(Symbol Binding) 属性由ELF32_ST_BIND指定。
名字 值
STB_LOCAL 0
STB_GLOBAL 1
STB_WEAK 2
STB_LOPROC 13
STB_HIPROC 15
STB_LOCAL
表明本符号是一个本地符号。它只出现在本文件中,在本文件外该符号无效。所以在不同的文件中可以定义相同的符号名,它们之间不会互相影响。
STB_GLOBAL
表明本符号是一个全局符号。当有多个文件被连接在一起时,在所有文件中该符号都是可见的。正常情况下,在一个文件中定义的全局符号,一定是在其它文件中需要被引用,否则无须定义为全局。
STB_WEAK
类似于全局符号,但是相对于STB_GLOBAL,它们的优先级更低。 全局符号(global symbol) 和弱符号(weak symbol) 在以下两方面有区别:
*当连接编辑器把若干个可重定位目标文件连接起来时,同名的STB_GLOBAL 符号不允许出现多次。而如果在一个目标文件中已经定义了一个全局的符号(global symbol) ,当一个同名的弱符 号(weak symbol) 出现时,并不会发生错误。连接编辑器会以全局符号为准,忽略弱符号。与全局符号相似,如果已经存在的是一个公用符号,即st_shndx 域为SHN_COMMON值的符号,当一个同名的弱符号(weak symbol) 出现时,也不会发生错误。连接编辑器会以公用符号为准,忽略弱符号。
*在查找符号定义时,连接编辑器可能会搜索存档的库文件。如果是查找全局符号,连接编辑器会提取包含该未定义的全局符号的存档成员,存档成员可能是一个全局的符号,也可能是弱符号 ;而如果是查找弱符号,连接编辑器不会去提取存档成员。未解析的弱符号值为0。
STB_LOPROC ~ STB_HIPROC
为特殊处理器保留的属性区间。 在符号表中,不同属性的符号所在位置也有不同,本地符号(STB_LOCAL)排在前面,全局符号(STB_GLOBAL/STB_WEAK) 排在后面。
符号类型(Symbol Types) 属性由ELF32_ST_TYPE 指定:
名字 值
STT_NOTYPE 0
STT_OBJECT 1
STT_FUNC 2
STT_SECTION 3
STT_FILE 4
STT_LOPROC 13
STT_HIPROC 15
STT_NOTYPE
本符号类型未指定。
STT_OBJECT
本符号是一个数据对象,比如变量、数组等。
STT_FUNC
本符号是一个函数,或者其它的可执行代码。函数符号在共享目标文件中有特殊的意义。当另外一个目标文件引用一个共享目标文件中的函数符号时,连接编辑器为被引用符号自动创建一个连接表项。非STT_FUNC类型的共享目标符号不会通过这种连接表项被自动引用。
STT_SECTION
本符号与一个节相关联,用于重定位,通常具有STB_LOCAL 属性。
STT_FILE
本符号是一个文件符号,它具有STB_LOCAL 属性,它的节索引值是SHN_ABS。在符号表中如果存在本类符号的话,它会出现在所有STB_LOCAL 类符号的前部。
STT_LOPROC ~ STT_HIPROC
这一区间的符号类型为特殊处理器保留。
5、st_other,
本数据成员目前暂未使用,在目标文件中一律赋值为0。
6、st_shndx,
任何一个符号表项的定义都与某一个“节”相联系,因为符号是为节而定义,在节中被引用。本数据成员即指明了相关联的节。本数据成员是一个索引值,它指向相关联的节在节头表中的索引。在重定位过程中,节的位置会改变,本数据成员的值也随之改变,继续指向节的新位置。当本数据成员指向下面三种特殊的节索引值时,本符号具有如下特别的意义:
SHN_ABS
符号的值是绝对的,具有常量性,在重定位过程中,此值不需要改变。
SHN_COMMON
本符号所关联的是一个还没有分配的公共节,本符号的值规定了其内容的字节对齐规则,与sh_addralign相似。也就是说,连接器会为本符号分配存储空间,而且其起始地址是向st_value 对 齐的。本符号的值指明了要分配的字节数。
SHN_UNDEF
当一个符号指向第1 节(SHN_UNDEF) 时,表明本符号在当前目标文件中未定义,在连接过程中,连接器会找到此符号被定义的文件,并把这些文件连接在一起。本文件中对该符号的引用会被连接到实际的定义上去。