上文参考:http://www.cnblogs.com/long123king/p/3545991.html
先分析一下linker script的语法。
#ifdef CONFIG_X86_32
#define LOAD_OFFSET __PAGE_OFFSET
#else
#define LOAD_OFFSET __START_KERNEL_map
#endif
/* Text and read-only data */
.text : AT(ADDR(.text) - LOAD_OFFSET) {
_text = .;
/* bootstrapping code */
HEAD_TEXT
#ifdef CONFIG_X86_32
. = ALIGN(PAGE_SIZE);
*(.text..page_aligned)
#endif
. = ALIGN(8);
_stext = .;
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
KPROBES_TEXT
ENTRY_TEXT
IRQENTRY_TEXT
*(.fixup)
*(.gnu.warning)
/* End of text section */
_etext = .;
} :text = 0x9090
这一段定义了.text section中的内容,AT(ADDR(.text) - LOAD_OFFSET)定义了这个section的LMA(Load Memory Address),说白了,而通过.定义的是VMA(Virtual Memory Address)。在x86平台,二者没有区别,都对应相对于加载起始点(LOAD_OFFSET,即0xC0000000, 3GB)的偏移地址。
:text = 0x9090指明这个.section要加载到text segment段中,0x9090指明了用于填充由于section对齐而产生的空隙。90是nop汇编语句。
我们看一下生成的内核映像文件vmlinux的布局
1: daniel@ubuntu:~/linux-3.0$ objdump vmlinux -h
2:
3: vmlinux: file format elf32-i386
4:
5: Sections:
6: Idx Name Size VMA LMA File off Algn
7: 0 .interp 00000013 08048114 08048114 00000114 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA
8: 1 .init.text 0000b35f 08049000 08049000 00001000 2**0 CONTENTS, ALLOC, LOAD, READONLY, CODE
9: 2 .gnu.hash 000002b0 08055000 08055000 0000d000 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
10: 3 .dynsym 00000b00 080552b0 080552b0 0000d2b0 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
11: 4 .dynstr 00000622 08055db0 08055db0 0000ddb0 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA
12: 5 .gnu.version 00000160 080563d2 080563d2 0000e3d2 2**1 CONTENTS, ALLOC, LOAD, READONLY, DATA
13: 6 .gnu.version_r 000000a0 08056534 08056534 0000e534 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
14: 7 .rel.got 00000008 080565d4 080565d4 0000e5d4 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
15: 8 .rel.bss 00000010 080565dc 080565dc 0000e5dc 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
16: 9 .rel.plt 00000460 080565ec 080565ec 0000e5ec 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
17: 10 .init 0000002e 08056a4c 08056a4c 0000ea4c 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE
18: 11 .plt 000008d0 08056a80 08056a80 0000ea80 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE
19: 12 .text 0016bcb0 08057350 08057350 0000f350 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE
20: 13 .syscall_stub 000000cc 081c3000 081c3000 0017b000 2**0 CONTENTS, ALLOC, LOAD, READONLY, CODE
21: 14 .fini 0000001a 081c30cc 081c30cc 0017b0cc 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE
22: 15 .rodata 000592b0 081c4000 081c4000 0017c000 2**5 CONTENTS, ALLOC, LOAD, READONLY, DATA
23: 16 .eh_frame_hdr 00012554 0821d2b0 0821d2b0 001d52b0 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
24: 17 __ksymtab 00004698 0822f808 0822f808 001e7808 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
25: 18 __ksymtab_gpl 00001598 08233ea0 08233ea0 001ebea0 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
26: 19 __ksymtab_strings 0000c299 08235438 08235438 001ed438 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA
27: 20 __param 00000110 082416d4 082416d4 001f96d4 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
28: 21 __modver 0000081c 082417e4 082417e4 001f97e4 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
29: 22 .note 00000044 08242000 08242000 001fa000 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE
30: 23 __ex_table 00000130 08242044 08242044 001fa044 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA
31: 24 .uml.setup.init 00000090 08242178 08242178 001fa178 2**2 CONTENTS, ALLOC, LOAD, DATA
32: 25 .uml.help.init 00000064 08242208 08242208 001fa208 2**2 CONTENTS, ALLOC, LOAD, DATA
33: 26 .init.setup 000002ac 0824226c 0824226c 001fa26c 2**2 CONTENTS, ALLOC, LOAD, DATA
34: 27 .initcall.init 00000270 08243000 08243000 001fb000 2**2 CONTENTS, ALLOC, LOAD, DATA
35: 28 .con_initcall.init 00000004 08243270 08243270 001fb270 2**2 CONTENTS, ALLOC, LOAD, DATA
36: 29 .exitcall 0000005c 08243274 08243274 001fb274 2**2 CONTENTS, ALLOC, LOAD, DATA
37: 30 .uml.exitcall 00000024 082432d0 082432d0 001fb2d0 2**2 CONTENTS, ALLOC, LOAD, DATA
38: 31 .altinstructions 00000030 082432f4 082432f4 001fb2f4 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
39: 32 .altinstr_replacement 0000000c 08243324 08243324 001fb324 2**0 CONTENTS, ALLOC, LOAD, READONLY, CODE
40: 33 .exit.text 000002c3 08243330 08243330 001fb330 2**0 CONTENTS, ALLOC, LOAD, READONLY, CODE
41: 34 init.data 00006ea0 08244000 08244000 001fc000 2**2 CONTENTS, ALLOC, LOAD, DATA
42: 35 .data 00014460 0824aea0 0824aea0 00202ea0 2**5 CONTENTS, ALLOC, LOAD, DATA
43: 36 .eh_frame 0009fbc0 0825f300 0825f300 00217300 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
44: 37 .dynamic 000000d8 082feec0 082feec0 002b6ec0 2**2 CONTENTS, ALLOC, LOAD, DATA
45: 38 .ctors 00000008 082fef98 082fef98 002b6f98 2**2 CONTENTS, ALLOC, LOAD, DATA
46: 39 .dtors 00000008 082fefa0 082fefa0 002b6fa0 2**2 CONTENTS, ALLOC, LOAD, DATA
47: 40 .jcr 00000004 082fefa8 082fefa8 002b6fa8 2**2 CONTENTS, ALLOC, LOAD, DATA
48: 41 .got 00000240 082fefac 082fefac 002b6fac 2**2 CONTENTS, ALLOC, LOAD, DATA
49: 42 .bss 0000d464 082ff200 082ff200 002b71ec 2**5 ALLOC
50: 43 .comment 0000002a 00000000 00000000 002b71ec 2**0 CONTENTS, READONLY
51: 44 .gnu_debuglink 00000024 00000000 00000000 002b7216 2**0 CONTENTS, READONLY
52: 45 .debug_aranges 00005950 00000000 00000000 002b7240 2**3 CONTENTS, READONLY, DEBUGGING
53: 46 .debug_info 01322c32 00000000 00000000 002bcb90 2**0 CONTENTS, READONLY, DEBUGGING
54: 47 .debug_abbrev 000a2c21 00000000 00000000 015df7c2 2**0 CONTENTS, READONLY, DEBUGGING
55: 48 .debug_line 0016b63c 00000000 00000000 016823e3 2**0 CONTENTS, READONLY, DEBUGGING
56: 49 .debug_str 0008d834 00000000 00000000 017eda1f 2**0 CONTENTS, READONLY, DEBUGGING
57: 50 .debug_loc 002823be 00000000 00000000 0187b253 2**0 CONTENTS, READONLY, DEBUGGING
58: 51 .debug_ranges 00058c80 00000000 00000000 01afd618 2**3 CONTENTS, READONLY, DEBUGGING
1: daniel@ubuntu:~/linux-3.0$ readelf -S vmlinux
2: There are 56 section headers, starting at offset 0x1b564bc:
3:
4: Section Headers:
5: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
6: [ 0] NULL 00000000 000000 000000 00 0 0 0
7: [ 1] .interp PROGBITS 08048114 000114 000013 00 A 0 0 1
8: [ 2] .init.text PROGBITS 08049000 001000 00b35f 00 AX 0 0 1
9: [ 3] .gnu.hash GNU_HASH 08055000 00d000 0002b0 04 A 4 0 4
10: [ 4] .dynsym DYNSYM 080552b0 00d2b0 000b00 10 A 5 1 4
11: [ 5] .dynstr STRTAB 08055db0 00ddb0 000622 00 A 0 0 1
12: [ 6] .gnu.version VERSYM 080563d2 00e3d2 000160 02 A 4 0 2
13: [ 7] .gnu.version_r VERNEED 08056534 00e534 0000a0 00 A 5 2 4
14: [ 8] .rel.got REL 080565d4 00e5d4 000008 08 A 4 42 4
15: [ 9] .rel.bss REL 080565dc 00e5dc 000010 08 A 4 43 4
16: [10] .rel.plt REL 080565ec 00e5ec 000460 08 A 4 12 4
17: [11] .init PROGBITS 08056a4c 00ea4c 00002e 00 AX 0 0 4
18: [12] .plt PROGBITS 08056a80 00ea80 0008d0 04 AX 0 0 16
19: [13] .text PROGBITS 08057350 00f350 16bcb0 00 AX 0 0 16
20: [14] .syscall_stub PROGBITS 081c3000 17b000 0000cc 00 AX 0 0 1
21: [15] .fini PROGBITS 081c30cc 17b0cc 00001a 00 AX 0 0 4
22: [16] .rodata PROGBITS 081c4000 17c000 0592b0 00 A 0 0 32
23: [17] .eh_frame_hdr PROGBITS 0821d2b0 1d52b0 012554 00 A 0 0 4
24: [18] __ksymtab PROGBITS 0822f808 1e7808 004698 00 A 0 0 4
25: [19] __ksymtab_gpl PROGBITS 08233ea0 1ebea0 001598 00 A 0 0 4
26: [20] __ksymtab_strings PROGBITS 08235438 1ed438 00c299 00 A 0 0 1
27: [21] __param PROGBITS 082416d4 1f96d4 000110 00 A 0 0 4
28: [22] __modver PROGBITS 082417e4 1f97e4 00081c 00 A 0 0 4
29: [23] .note NOTE 08242000 1fa000 000044 00 AX 0 0 4
30: [24] __ex_table PROGBITS 08242044 1fa044 000130 00 A 0 0 1
31: [25] .uml.setup.init PROGBITS 08242178 1fa178 000090 00 WA 0 0 4
32: [26] .uml.help.init PROGBITS 08242208 1fa208 000064 00 WA 0 0 4
33: [27] .init.setup PROGBITS 0824226c 1fa26c 0002ac 00 WA 0 0 4
34: [28] .initcall.init PROGBITS 08243000 1fb000 000270 00 WA 0 0 4
35: [29] .con_initcall.ini PROGBITS 08243270 1fb270 000004 00 WA 0 0 4
36: [30] .exitcall PROGBITS 08243274 1fb274 00005c 00 WA 0 0 4
37: [31] .uml.exitcall PROGBITS 082432d0 1fb2d0 000024 00 WA 0 0 4
38: [32] .altinstructions PROGBITS 082432f4 1fb2f4 000030 00 A 0 0 4
39: [33] .altinstr_replace PROGBITS 08243324 1fb324 00000c 00 AX 0 0 1
40: [34] .exit.text PROGBITS 08243330 1fb330 0002c3 00 AX 0 0 1
41: [35] init.data PROGBITS 08244000 1fc000 006ea0 00 WA 0 0 4
42: [36] .data PROGBITS 0824aea0 202ea0 014460 00 WA 0 0 32
43: [37] .eh_frame PROGBITS 0825f300 217300 09fbc0 00 A 0 0 4
44: [38] .dynamic DYNAMIC 082feec0 2b6ec0 0000d8 08 WA 5 0 4
45: [39] .ctors PROGBITS 082fef98 2b6f98 000008 00 WA 0 0 4
46: [40] .dtors PROGBITS 082fefa0 2b6fa0 000008 00 WA 0 0 4
47: [41] .jcr PROGBITS 082fefa8 2b6fa8 000004 00 WA 0 0 4
48: [42] .got PROGBITS 082fefac 2b6fac 000240 04 WA 0 0 4
49: [43] .bss NOBITS 082ff200 2b71ec 00d464 00 WA 0 0 32
50: [44] .comment PROGBITS 00000000 2b71ec 00002a 01 MS 0 0 1
51: [45] .gnu_debuglink PROGBITS 00000000 2b7216 000024 00 0 0 1
52: [46] .debug_aranges PROGBITS 00000000 2b7240 005950 00 0 0 8
53: [47] .debug_info PROGBITS 00000000 2bcb90 1322c32 00 0 0 1
54: [48] .debug_abbrev PROGBITS 00000000 15df7c2 0a2c21 00 0 0 1
55: [49] .debug_line PROGBITS 00000000 16823e3 16b63c 00 0 0 1
56: [50] .debug_str PROGBITS 00000000 17eda1f 08d834 01 MS 0 0 1
57: [51] .debug_loc PROGBITS 00000000 187b253 2823be 00 0 0 1
58: [52] .debug_ranges PROGBITS 00000000 1afd618 058c80 00 0 0 8
59: [53] .shstrtab STRTAB 00000000 1b56298 000223 00 0 0 1
60: [54] .symtab SYMTAB 00000000 1b56d7c 04e810 10 55 13787 4
61: [55] .strtab STRTAB 00000000 1ba558c 060090 00 0 0 1
62: Key to Flags:
63: W (write), A (alloc), X (execute), M (merge), S (strings)
64: I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
65: O (extra OS processing required) o (OS specific), p (processor specific)
1: daniel@ubuntu:~/linux-3.0$ readelf -s vmlinux | grep _stext
2: 16700: 08049000 0 NOTYPE GLOBAL DEFAULT ABS _stext
3: daniel@ubuntu:~/linux-3.0$ readelf -s vmlinux | grep _etext
4: 17219: 081c30e6 0 NOTYPE GLOBAL DEFAULT ABS _etext
5: daniel@ubuntu:~/linux-3.0$ readelf -s vmlinux | grep _sdata
6: 14535: 081c4000 0 NOTYPE GLOBAL DEFAULT ABS _sdata
7: daniel@ubuntu:~/linux-3.0$ readelf -s vmlinux | grep _edata
8: 19451: 082ff1ec 0 NOTYPE GLOBAL DEFAULT ABS _edata
因此,内核中的.text section被加载到0x08049000~0x081c30e6范围内,而.data section被加载到0x081c4000~0x082ff1ec范围内,这里面的地址都是指物理地址。
/* Text and read-only data */
.text : AT(ADDR(.text) - LOAD_OFFSET) {
_text = .;
/* bootstrapping code */
HEAD_TEXT
#ifdef CONFIG_X86_32
. = ALIGN(PAGE_SIZE);
*(.text..page_aligned)
#endif
. = ALIGN(8);
_stext = .;
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
KPROBES_TEXT
ENTRY_TEXT
IRQENTRY_TEXT
*(.fixup)
*(.gnu.warning)
/* End of text section */
_etext = .;
} :text = 0x9090
而内核代码段的各个子section,比如HEAD_TEXT, TEXT_TEXT……IRQENTRY_TEXT都按顺序排列在0x08049000~0x081c30e6物理地址范围内。