~Linux C_5/6/7/12_ELF链接
==== nm 查看符号表 ====
main.c
/* main.c */ #include <stdio.h> int a, b = 1; int main(void) { push('a'); push('b'); push('c'); while(!is_empty()) putchar(pop()); putchar('\n'); return 0; } [root@localhost my_play]# nm main.o 00000004 C a // 声明未初始化 00000000 D b // 声明已初始化 U is_empty // 该目标文件内未定义 00000000 T main U pop U push U putchar
stack.c
/* stack.c */ char stack[512]; int top = -1; void push(char c) { stack[++top] = c; } char pop(void) { return stack[top--]; } int is_empty(void) { return top == -1; } [root@localhost my_play]# nm stack.o 00000047 T is_empty 00000026 T pop 00000000 T push 00000200 C stack 00000000 D top
目标文件的虚拟地址
未链接的.o文件,是否有必要“有地址” ---- 没必要。
链接后才有必要。
关于这个问题,可以直接联系到”ARM的MMU的原理“。
- 可重定位的目标文件:linux上是.o文件 win上是.obj文件 其中的符号 数据 指令的地址都是无效的
- 可执行的目标文件: linux上默认是a.out win上是.exe
- 共享的目标文件 : 实际是一种特殊的可重定位的目标问价,是不能执行的,一般在运行的时候别链接使用 linux 上是.so windows 上是.DLL。
- 可重定位的文件是不可执行的,所有程序的入口地址是0。
- 之所以不可执行,是因为还没经过链接的过程,没有进行重定位,所有需要rel文件来帮助进行重定位。
- 可执行文件将来使用装载到存储器中,所以程序头表记录着对应的节将来放在哪个存储器中。
- 多出的一个init,实际上是一个函数,进行程序执行前的一些初始化工作。
==== readelf ====
ELF文件由四部分组成,分别是:
-
- ELF头(ELF header)
- 程序头表(Program header table)
- 节(Sections)
- 节头表(Section header table)
More details:
-
- Goto: ELF 和 sectionheadertable (节头表)
- Goto: 操作系统开发系列—11.ELF格式
ELF Header 描述了体系结构和操作系统等基本信息,并指出Section Header Table和Program Header Table在文件中的什么位置。
Section Header Table 中保存了所有Section的描述信息,通过它可以找到每个Section在文件中的位置。
Program Header Table 中保存了所有Segment的描述信息 。
===
区别:
===
一个 Segment 由一个或多个Section组成,这些Section加载到内存时具有相同的访问权限。
有些 Section 只对链接器有意义,在运行时用不到,也不需要加载到内存,那么就不属于任何Segment。
Program headers are only important in executable and shared object files.
假如一个程序头表(program header table)存在,那么它告诉系统如何来创建一个进程的内存映象。
被用来建立进程映象 (执行一个程序) 的文件必须要有一个 程序头表(program header table);
可重定位文件不需要这个头表。
一个section头表(section header table)包含了描述文件sections的信息。
每个section在这个表中有一个入口;
每个入口给出了该section的名字,大小,等等信息。在联接过程中的文件必须有一个section头表;
其他object文件可要可不要这个section头表。
注意: 虽然图显示出程序头表立刻出现在一个ELF头后,section头表跟着其他section部分出现,事实是的文件是可以不同的。
此外,sections和段(segments) 没有特别的顺序。只有ELF头(elf header)是在文件的固定位置。
目标文件的虚拟地址
main.o
[root@localhost my_play]# readelf -a main.o
ELF Header: Magic: 7f 45 4c 46 01 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: REL (Relocatable file) Machine: Intel 80386 Version: 0x1 Entry point address: 0x0 Start of program headers: 0 (bytes into file) Start of section headers: 280 (bytes into file) *** Flags: 0x0 Size of this header: 52 (bytes) Size of program headers: 0 (bytes) Number of program headers: 0 Size of section headers: 40 (bytes) Number of section headers: 10 Section header string table index: 7 Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .text PROGBITS 00000000 000034 000067 00 AX 0 0 4 [ 2] .rel.text REL 00000000 0003b4 000038 08 8 1 4 // 可执行文件已经重定位,做完链接就没用了 [ 3] .data PROGBITS 00000000 00009c 000004 00 WA 0 0 4 [ 4] .bss NOBITS 00000000 0000a0 000000 00 WA 0 0 4 [ 5] .comment PROGBITS 00000000 0000a0 00002e 00 0 0 1 [ 6] .note.GNU-stack PROGBITS 00000000 0000ce 000000 00 0 0 1 [ 7] .shstrtab STRTAB 00000000 0000ce 000049 00 0 0 1 [ 8] .symtab SYMTAB 00000000 0002a8 0000e0 10 9 7 4 [ 9] .strtab STRTAB 00000000 000388 00002b 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific)
0 ELF Header //size of this header 0x34 .text 0x60 .data 0x98 .bss(此段为空) 0x98 .shstrtab //保存着“目标文件中的Section”的名字,每个名字都是以'\0'结尾的字符串 0xc8 Section Header Table 0x208 .symtab //符号表,汇编中的符号在哪些段里 0x288 .strtab //保存着“汇编程序中的符号”的名字,每个名字都是以'\0'结尾的字符串 0x2b0 .rel.text //告诉链接器 哪些地方需要做重定位
There are no section groups in this file. There are no program headers in this file. Relocation section '.rel.text' at offset 0x3b4 contains 7 entries: Offset Info Type Sym.Value Sym. Name 00000019 00000902 R_386_PC32 00000000 push 00000025 00000902 R_386_PC32 00000000 push 00000031 00000902 R_386_PC32 00000000 push 00000038 00000a02 R_386_PC32 00000000 pop 00000040 00000b02 R_386_PC32 00000000 putchar 00000045 00000c02 R_386_PC32 00000000 is_empty 00000055 00000b02 R_386_PC32 00000000 putchar There are no unwind sections in this file. Symbol table '.symtab' contains 14 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 FILE LOCAL DEFAULT ABS main.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 6 6: 00000000 0 SECTION LOCAL DEFAULT 5 7: 00000000 4 OBJECT GLOBAL DEFAULT 3 b 8: 00000000 103 FUNC GLOBAL DEFAULT 1 main 9: 00000000 0 NOTYPE GLOBAL DEFAULT UND push 10: 00000000 0 NOTYPE GLOBAL DEFAULT UND pop 11: 00000000 0 NOTYPE GLOBAL DEFAULT UND putchar 12: 00000000 0 NOTYPE GLOBAL DEFAULT UND is_empty 13: 00000004 4 OBJECT GLOBAL DEFAULT COM a No version information found in this file.
stack.o
[root@localhost my_play]# readelf -a stack.o ELF Header: Magic: 7f 45 4c 46 01 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: REL (Relocatable file) Machine: Intel 80386 Version: 0x1 Entry point address: 0x0 Start of program headers: 0 (bytes into file) Start of section headers: 268 (bytes into file) Flags: 0x0 Size of this header: 52 (bytes) Size of program headers: 0 (bytes) Number of program headers: 0 Size of section headers: 40 (bytes) Number of section headers: 10 Section header string table index: 7 Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .text PROGBITS 00000000 000034 00005a 00 AX 0 0 4 [ 2] .rel.text REL 00000000 000384 000040 08 8 1 4 [ 3] .data PROGBITS 00000000 000090 000004 00 WA 0 0 4 [ 4] .bss NOBITS 00000000 000094 000000 00 WA 0 0 4 [ 5] .comment PROGBITS 00000000 000094 00002e 00 0 0 1 [ 6] .note.GNU-stack PROGBITS 00000000 0000c2 000000 00 0 0 1 [ 7] .shstrtab STRTAB 00000000 0000c2 000049 00 0 0 1 [ 8] .symtab SYMTAB 00000000 00029c 0000c0 10 9 7 4 [ 9] .strtab STRTAB 00000000 00035c 000025 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) There are no section groups in this file. There are no program headers in this file. Relocation section '.rel.text' at offset 0x384 contains 8 entries: Offset Info Type Sym.Value Sym. Name 0000000e 00000701 R_386_32 00000000 top 00000018 00000901 R_386_32 00000020 stack 00000020 00000701 R_386_32 00000000 top 0000002a 00000701 R_386_32 00000000 top 00000032 00000701 R_386_32 00000000 top 00000037 00000701 R_386_32 00000000 top 0000003e 00000901 R_386_32 00000020 stack 0000004b 00000701 R_386_32 00000000 top There are no unwind sections in this file. Symbol table '.symtab' contains 12 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 FILE LOCAL DEFAULT ABS stack.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 6 6: 00000000 0 SECTION LOCAL DEFAULT 5 7: 00000000 4 OBJECT GLOBAL DEFAULT 3 top 8: 00000000 38 FUNC GLOBAL DEFAULT 1 push 9: 00000020 512 OBJECT GLOBAL DEFAULT COM stack 10: 00000026 33 FUNC GLOBAL DEFAULT 1 pop 11: 00000047 19 FUNC GLOBAL DEFAULT 1 is_empty
// 可执行文件 Value 将会有绝对地址
No version information found in this file.
main
[root@localhost my_play]# readelf -a main ELF Header: Magic: 7f 45 4c 46 01 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: Intel 80386 Version: 0x1 Entry point address: 0x80482b0 ////这是_start符号的地址; 连接后,这里有了地址,难道是绝对地址? Start of program headers: 52 (bytes into file) //这里也不是0了 Start of section headers: 2120 (bytes into file) Flags: 0x0 Size of this header: 52 (bytes) Size of program headers: 32 (bytes) //看来program header开始有了值 Number of program headers: 7 Size of section headers: 40 (bytes) Number of section headers: 28 Section header string table index: 25 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 08048114 000114 000013 00 A 0 0 1 [ 2] .note.ABI-tag NOTE 08048128 000128 000020 00 A 0 0 4 [ 3] .gnu.hash GNU_HASH 08048148 000148 000020 04 A 4 0 4 [ 4] .dynsym DYNSYM 08048168 000168 000050 10 A 5 1 4 [ 5] .dynstr STRTAB 080481b8 0001b8 00004d 00 A 0 0 1 [ 6] .gnu.version VERSYM 08048206 000206 00000a 02 A 4 0 2 [ 7] .gnu.version_r VERNEED 08048210 000210 000020 00 A 5 1 4 [ 8] .rel.dyn REL 08048230 000230 000008 08 A 4 0 4 [ 9] .rel.plt REL 08048238 000238 000018 08 A 4 11 4 [10] .init PROGBITS 08048250 000250 000017 00 AX 0 0 4 [11] .plt PROGBITS 08048268 000268 000040 04 AX 0 0 4 [12] .text PROGBITS 080482b0 0002b0 000248 00 AX 0 0 16 [13] .fini PROGBITS 080484f8 0004f8 00001c 00 AX 0 0 4 [14] .rodata PROGBITS 08048514 000514 00000c 00 A 0 0 4 [15] .eh_frame PROGBITS 08048520 000520 000004 00 A 0 0 4 [16] .ctors PROGBITS 08049524 000524 000008 00 WA 0 0 4 [17] .dtors PROGBITS 0804952c 00052c 000008 00 WA 0 0 4 [18] .jcr PROGBITS 08049534 000534 000004 00 WA 0 0 4 [19] .dynamic DYNAMIC 08049538 000538 0000c8 08 WA 5 0 4 [20] .got PROGBITS 08049600 000600 000004 04 WA 0 0 4 [21] .got.plt PROGBITS 08049604 000604 000018 04 WA 0 0 4 [22] .data PROGBITS 0804961c 00061c 00000c 00 WA 0 0 4 [23] .bss NOBITS 08049640 000628 000220 00 WA 0 0 32 [24] .comment PROGBITS 00000000 000628 000142 00 0 0 1 [25] .shstrtab STRTAB 00000000 00076a 0000db 00 0 0 1 [26] .symtab SYMTAB 00000000 000ca8 0004c0 10 27 49 4 [27] .strtab STRTAB 00000000 001168 000283 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) There are no section groups in this file. Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000034 0x08048034 0x08048034 0x000e0 0x000e0 RE 0x4 INTERP 0x000114 0x08048114 0x08048114 0x00013 0x00013 R 0x1
// -->
[Requesting program interpreter: /lib/ld-linux.so.2] LOAD 0x000000 0x08048000 0x08048000 0x00524 0x00524 R E 0x1000 LOAD 0x000524 0x08049524 0x08049524 0x00104 0x0033c RW 0x1000 DYNAMIC 0x000538 0x08049538 0x08049538 0x000c8 0x000c8 RW 0x4 NOTE 0x000128 0x08048128 0x08048128 0x00020 0x00020 R 0x4 GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 Section to Segment mapping: Segment Sections... 00 01 .interp 02 .interp .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame 03 .ctors .dtors .jcr .dynamic .got .got.plt .data .bss 04 .dynamic 05 .note.ABI-tag 06 Dynamic section at offset 0x538 contains 20 entries: Tag Type Name/Value 0x00000001 (NEEDED) Shared library: [libc.so.6] 0x0000000c (INIT) 0x8048250 0x0000000d (FINI) 0x80484f8 0x6ffffef5 (GNU_HASH) 0x8048148 0x00000005 (STRTAB) 0x80481b8 0x00000006 (SYMTAB) 0x8048168 0x0000000a (STRSZ) 77 (bytes) 0x0000000b (SYMENT) 16 (bytes) 0x00000015 (DEBUG) 0x0 0x00000003 (PLTGOT) 0x8049604 0x00000002 (PLTRELSZ) 24 (bytes) 0x00000014 (PLTREL) REL 0x00000017 (JMPREL) 0x8048238 0x00000011 (REL) 0x8048230 0x00000012 (RELSZ) 8 (bytes) 0x00000013 (RELENT) 8 (bytes) 0x6ffffffe (VERNEED) 0x8048210 0x6fffffff (VERNEEDNUM) 1 0x6ffffff0 (VERSYM) 0x8048206 0x00000000 (NULL) 0x0 Relocation section '.rel.dyn' at offset 0x230 contains 1 entries: Offset Info Type Sym.Value Sym. Name 08049600 00000106 R_386_GLOB_DAT 00000000 __gmon_start__ Relocation section '.rel.plt' at offset 0x238 contains 3 entries: Offset Info Type Sym.Value Sym. Name 08049610 00000107 R_386_JUMP_SLOT 00000000 __gmon_start__ 08049614 00000207 R_386_JUMP_SLOT 00000000 putchar 08049618 00000307 R_386_JUMP_SLOT 00000000 __libc_start_main There are no unwind sections in this file. Symbol table '.dynsym' contains 5 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 2: 00000000 257 FUNC GLOBAL DEFAULT UND (2) 3: 00000000 415 FUNC GLOBAL DEFAULT UND (2) 4: 08048518 4 OBJECT GLOBAL DEFAULT 14 _IO_stdin_used Symbol table '.symtab' contains 76 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 08048114 0 SECTION LOCAL DEFAULT 1 2: 08048128 0 SECTION LOCAL DEFAULT 2 3: 08048148 0 SECTION LOCAL DEFAULT 3 4: 08048168 0 SECTION LOCAL DEFAULT 4 5: 080481b8 0 SECTION LOCAL DEFAULT 5 6: 08048206 0 SECTION LOCAL DEFAULT 6 7: 08048210 0 SECTION LOCAL DEFAULT 7 8: 08048230 0 SECTION LOCAL DEFAULT 8 9: 08048238 0 SECTION LOCAL DEFAULT 9 10: 08048250 0 SECTION LOCAL DEFAULT 10 11: 08048268 0 SECTION LOCAL DEFAULT 11 12: 080482b0 0 SECTION LOCAL DEFAULT 12 13: 080484f8 0 SECTION LOCAL DEFAULT 13 14: 08048514 0 SECTION LOCAL DEFAULT 14 15: 08048520 0 SECTION LOCAL DEFAULT 15 16: 08049524 0 SECTION LOCAL DEFAULT 16 17: 0804952c 0 SECTION LOCAL DEFAULT 17 18: 08049534 0 SECTION LOCAL DEFAULT 18 19: 08049538 0 SECTION LOCAL DEFAULT 19 20: 08049600 0 SECTION LOCAL DEFAULT 20 21: 08049604 0 SECTION LOCAL DEFAULT 21 22: 0804961c 0 SECTION LOCAL DEFAULT 22 23: 08049640 0 SECTION LOCAL DEFAULT 23 24: 00000000 0 SECTION LOCAL DEFAULT 24 25: 080482d4 0 FUNC LOCAL DEFAULT 12 call_gmon_start 26: 00000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 27: 08049524 0 OBJECT LOCAL DEFAULT 16 __CTOR_LIST__ 28: 0804952c 0 OBJECT LOCAL DEFAULT 17 __DTOR_LIST__ 29: 08049534 0 OBJECT LOCAL DEFAULT 18 __JCR_LIST__ 30: 08049640 4 OBJECT LOCAL DEFAULT 23 dtor_idx.5793 31: 08049644 1 OBJECT LOCAL DEFAULT 23 completed.5791 32: 08048300 0 FUNC LOCAL DEFAULT 12 __do_global_dtors_aux 33: 08048360 0 FUNC LOCAL DEFAULT 12 frame_dummy 34: 00000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 35: 08049528 0 OBJECT LOCAL DEFAULT 16 __CTOR_END__ 36: 08048520 0 OBJECT LOCAL DEFAULT 15 __FRAME_END__ 37: 08049534 0 OBJECT LOCAL DEFAULT 18 __JCR_END__ 38: 080484d0 0 FUNC LOCAL DEFAULT 12 __do_global_ctors_aux 39: 00000000 0 FILE LOCAL DEFAULT ABS main.c 40: 00000000 0 FILE LOCAL DEFAULT ABS stack.c 41: 08049524 0 NOTYPE LOCAL HIDDEN 16 __preinit_array_start 42: 08049524 0 NOTYPE LOCAL HIDDEN 16 __fini_array_end 43: 08049604 0 OBJECT LOCAL HIDDEN 21 _GLOBAL_OFFSET_TABLE_ 44: 08049524 0 NOTYPE LOCAL HIDDEN 16 __preinit_array_end 45: 08049524 0 NOTYPE LOCAL HIDDEN 16 __fini_array_start 46: 08049524 0 NOTYPE LOCAL HIDDEN 16 __init_array_end 47: 08049524 0 NOTYPE LOCAL HIDDEN 16 __init_array_start 48: 08049538 0 OBJECT LOCAL HIDDEN 19 _DYNAMIC 49: 0804961c 0 NOTYPE WEAK DEFAULT 22 data_start 50: 08048450 5 FUNC GLOBAL DEFAULT 12 __libc_csu_fini 51: 080482b0 0 FUNC GLOBAL DEFAULT 12 _start 52: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 53: 00000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses 54: 08048514 4 OBJECT GLOBAL DEFAULT 14 _fp_hw 55: 080484f8 0 FUNC GLOBAL DEFAULT 13 _fini 56: 00000000 257 FUNC GLOBAL DEFAULT UND 57: 08048412 33 FUNC GLOBAL DEFAULT 12 pop 58: 00000000 415 FUNC GLOBAL DEFAULT UND _ 59: 08049624 4 OBJECT GLOBAL DEFAULT 22 top 60: 08048518 4 OBJECT GLOBAL DEFAULT 14 _IO_stdin_used 61: 0804961c 0 NOTYPE GLOBAL DEFAULT 22 __data_start 62: 08049648 4 OBJECT GLOBAL DEFAULT 23 a 63: 080483ec 38 FUNC GLOBAL DEFAULT 12 push 64: 0804851c 0 OBJECT GLOBAL HIDDEN 14 __dso_handle 65: 08049530 0 OBJECT GLOBAL HIDDEN 17 __DTOR_END__ 66: 08048460 105 FUNC GLOBAL DEFAULT 12 __libc_csu_init 67: 08048433 19 FUNC GLOBAL DEFAULT 12 is_empty 68: 08049628 0 NOTYPE GLOBAL DEFAULT ABS __bss_start 69: 08049620 4 OBJECT GLOBAL DEFAULT 22 b 70: 08049860 0 NOTYPE GLOBAL DEFAULT ABS _end 71: 08049660 512 OBJECT GLOBAL DEFAULT 23 stack 72: 08049628 0 NOTYPE GLOBAL DEFAULT ABS _edata 73: 080484c9 0 FUNC GLOBAL HIDDEN 12 __i686.get_pc_thunk.bx 74: 08048384 103 FUNC GLOBAL DEFAULT 12 main 75: 08048250 0 FUNC GLOBAL DEFAULT 10 _init Histogram for `.gnu.hash' bucket list length (total of 2 buckets): Length Number % of total Coverage 0 1 ( 50.0%) 1 1 ( 50.0%) 100.0% Version symbols section '.gnu.version' contains 5 entries: Addr: 0000000008048206 Offset: 0x000206 Link: 4 (.dynsym) 000: 0 (*local*) 0 (*local*) 2 (GLIBC_2.0) 2 (GLIBC_2.0) 004: 1 (*global*) Version needs section '.gnu.version_r' contains 1 entries: Addr: 0x0000000008048210 Offset: 0x000210 Link to section: 5 (.dynstr) 000000: Version: 1 File: libc.so.6 Cnt: 1 0x0010: Name: GLIBC_2.0 Flags: none Version: 2 Notes at offset 0x00000128 with length 0x00000020: Owner Data size Description GNU 0x00000010 NT_VERSION (version)
//--> 备注
Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x000000 0x08048000 0x08048000 0x0009e 0x0009e R E 0x1000 LOAD 0x0000a0 0x080490a0 0x080490a0 0x00038 0x00038 RW 0x1000
Section to Segment mapping:
Segment Sections...
00 .text
01 .data
多出来的Program Header Table描述了两个Segment的信息。
.text段和前面的ELF Header、Program Header Table一起组成一个Segment(FileSiz指出总长度是0x9e)
.data段组成另一个Segment(总长度是0x38)
VirtAddr列指出:
第一个Segment加载到虚拟地址0x08048000(注意在x86平台上后面的PhysAddr列是没有意义的,并不代表实际的物理地址),
第二个Segment加载到地址0x080490a0。
Flg列指出:
第一个Segment的访问权限是可读可执行,
第二个Segment的访问权限是可读可写。
最后一列Align的值0x1000(4K)是x86平台的内存页面大小。
可执行文件很小,总共也不超过一页大小,但是两个Segment必须加载到内存中两个不同的页面,因为MMU的权限保护机制是以页为单位的,一个页面只能设置一种权限。
此外还规定每个Segment在文件页面内偏移多少加载到内存页面仍然要偏移多少,比如第二个Segment在文件中的偏移是 0xa0,在内存页面0x08049000中的偏移仍然是0xa0,所以从0x080490a0开始,这样规定是为了简化链接器和加载器的实现。从上图也可以看出.text段的加载地址应该是0x08048074,_start符号位于.text段的开头,所以_start符号的地址也是0x08048074,从符号表中可以验证这一点。
链接的过程是由一个链接脚本(Linker Script)控制的,链接脚本决定了给每个段分配什么地址,如何对齐,哪个段在前,哪个段在后,哪些段合并到同一个Segment。
链接脚本还要插入一些符号到最终生成的文件中,例如__bss_start、_edata、_end等。
==== 默认链接脚本 ====
[root@localhost my_play]# ld --verbose
GNU ld version .0.6-14.el5 20061020 Supported emulations: elf_i386 i386linux elf_x86_64 using internal linker script: ------------------------------------------------------------------------------- /* Script for -z combreloc: combine and sort reloc sections */ OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_ARCH(i386) ENTRY(_start) //整个程序的入口点 SEARCH_DIR("/usr/i386-redhat-linux/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib"); SECTIONS { //==============> /* Read-only sections, merged into text segment: */ PROVIDE (__executable_start = 0x08048000); . = 0x08048000 + SIZEOF_HEADERS; //Text Segment的起始地址 .interp : { *(.interp) } //最终生成的文件的.interp段由各目标文件的.iterp段组成。 .hash : { *(.hash) } .gnu.hash : { *(.gnu.hash) } .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .gnu.version : { *(.gnu.version) } .gnu.version_d : { *(.gnu.version_d) } .gnu.version_r : { *(.gnu.version_r) } .rel.dyn : { *(.rel.init) *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) *(.rel.fini) *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) *(.rel.ctors) *(.rel.dtors) *(.rel.got) *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } .rela.dyn : { *(.rela.init) *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) *(.rela.fini) *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) *(.rela.ctors) *(.rela.dtors) *(.rela.got) *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } .rel.plt : { *(.rel.plt) } .rela.plt : { *(.rela.plt) } .init : { KEEP (*(.init)) } =0x90909090 .plt : { *(.plt) } .text : { *(.text .stub .text.* .gnu.linkonce.t.*) KEEP (*(.text.*personality*)) /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) } =0x90909090 .fini : { KEEP (*(.fini)) } =0x90909090 PROVIDE (__etext = .); PROVIDE (_etext = .); PROVIDE (etext = .); .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } .rodata1 : { *(.rodata1) } .eh_frame_hdr : { *(.eh_frame_hdr) } .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } //==============> /* Adjust the address for the data segment. We want to adjust up to the same address within the page on the next page up. */ . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); //Data Segment的起始地址 /* Exception handling */ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } /* Thread Local Storage sections */ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } .preinit_array : { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); } .init_array : { PROVIDE_HIDDEN (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) PROVIDE_HIDDEN (__init_array_end = .); } .fini_array : { PROVIDE_HIDDEN (__fini_array_start = .); KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) PROVIDE_HIDDEN (__fini_array_end = .); } .ctors : { /* gcc uses crtbegin.o to find the start of the constructors, so we make sure it is first. Because this is a wildcard, it doesn't matter if the user does not actually link against crtbegin.o; the linker won't look for a file to match a wildcard. The wildcard also means that it doesn't matter which directory crtbegin.o is in. */ KEEP (*crtbegin.o(.ctors)) KEEP (*crtbegin?.o(.ctors)) /* We don't want to include the .ctor section from the crtend.o file until after the sorted ctors. The .ctor section from the crtend file contains the end of ctors marker and it must be last */ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) } .dtors : { KEEP (*crtbegin.o(.dtors)) KEEP (*crtbegin?.o(.dtors)) KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) } .jcr : { KEEP (*(.jcr)) } .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } .dynamic : { *(.dynamic) } .got : { *(.got) } . = DATA_SEGMENT_RELRO_END (12, .); .got.plt : { *(.got.plt) } .data : { *(.data .data.* .gnu.linkonce.d.*) KEEP (*(.gnu.linkonce.d.*personality*)) SORT(CONSTRUCTORS) } .data1 : { *(.data1) } _edata = .; PROVIDE (edata = .); __bss_start = .; .bss : { *(.dynbss) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) /* Align here to ensure that the .bss section occupies space up to _end. Align after .bss to ensure correct alignment even if the .bss section disappears because there are no input sections. FIXME: Why do we need it? When there is no .bss section, we don't pad the .data section. */ . = ALIGN(. != 0 ? 32 / 8 : 1); } . = ALIGN(32 / 8); . = ALIGN(32 / 8); _end = .; PROVIDE (end = .); . = DATA_SEGMENT_END (.); /* Stabs debugging sections. */ .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } .stab.excl 0 : { *(.stab.excl) } .stab.exclstr 0 : { *(.stab.exclstr) } .stab.index 0 : { *(.stab.index) } .stab.indexstr 0 : { *(.stab.indexstr) } .comment 0 : { *(.comment) } /* DWARF debug sections. Symbols in the DWARF debugging sections are relative to the beginning of the section so we begin them at 0. */ /* DWARF 1 */ .debug 0 : { *(.debug) } .line 0 : { *(.line) } /* GNU DWARF 1 extensions */ .debug_srcinfo 0 : { *(.debug_srcinfo) } .debug_sfnames 0 : { *(.debug_sfnames) } /* DWARF 1.1 and DWARF 2 */ .debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } /* DWARF 2 */ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_line 0 : { *(.debug_line) } .debug_frame 0 : { *(.debug_frame) } .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } /* SGI/MIPS DWARF 2 extensions */ .debug_weaknames 0 : { *(.debug_weaknames) } .debug_funcnames 0 : { *(.debug_funcnames) } .debug_typenames 0 : { *(.debug_typenames) } .debug_varnames 0 : { *(.debug_varnames) } /* DWARF 3 */ .debug_pubtypes 0 : { *(.debug_pubtypes) } .debug_ranges 0 : { *(.debug_ranges) } /DISCARD/ : { *(.note.GNU-stack) } } -------------------------------------------------------------------------------
http://hi.baidu.com/kebey2004/item/302856ded35efbffca0c39ff
http://hi.baidu.com/kebey2004/item/98427aeca555bbf7e1a5d4fe