内核源码中使用到的vmlinux.lds总共有两个分别是
1.arch/arm/kernel/vmlinux.lds
2.arch/arm/boot/compressed/vmlinux.lds
其中1用于生成未压缩的内核image
2用于生成经过压缩的内核image
这两个ld 文件中的连接地址有一些区别
/kernel/vmlinux.lds:
421 OUTPUT_ARCH(arm)
422 ENTRY(stext)
423 jiffies = jiffies_64;
424 SECTIONS
425 {
426 /*
427 * XXX: The linker does not define how output sections are
428 * assigned to input sections when there are multiple statements
429 * matching the same input section name. There is no documented
430 * order of matching.
431 *
432 * unwind exit sections must be discarded before the rest of the
433 * unwind sections get included.
434 */
435 /DISCARD/ : {
436 *(.ARM.exidx.exit.text)
437 *(.ARM.extab.exit.text)
438
439
440
441
442 *(.exitcall.exit)
443 *(.alt.smp.init)
444 *(.discard)
445 *(.discard.*)
446 }
447 . = 0xC0000000 + 0x00008000;
448 .head.text : {
449 _text = .;
450 *(.head.text)
451 }
compressed/vmlinux.lds
10 OUTPUT_ARCH(arm)
11 ENTRY(_start)
12 SECTIONS
13 {
14 /DISCARD/ : {
15 *(.ARM.exidx*)
16 *(.ARM.extab*)
17 /*
18 * Discard any r/w data - this produces a link error if we have any,
19 * which is required for PIC decompression. Local data generates
20 * GOTOFF relocations, which prevents it being relocated independently
21 * of the text/got segments.
22 */
23 *(.data)
24 }
25
26 . = 0;
27 _text = .;
可以发现压缩内核的连接地址是从0开始的,未压缩的内核连接地址是从0xC0000000+0x00008000开始的。
首先uboot使用到的内核是压缩过的内核也就是uimage,此时内核连接到的是0地址,入口是_start
而vmlinux中有如下定义
.text : {
30 _start = .;
31 *(.start)
32 *(.text)
33 *(.text.*)
34 *(.fixup)
35 *(.gnu.warning)
36 *(.glue_7t)
37 *(.glue_7)
38 }
所以压缩内核的入口就是连接的0地址开始的。
根据上一篇文章,压缩内核来源于压缩的vmlinux,而压缩的vmlinux是通过head.o, misc.o piggy.o加工而来的。
这个压缩的vmlinux连接顺序可以从arch/arm/boot/compressed/Makefile中得到如下信息
HEAD = head.o
OBJS += misc.o decompress.o
vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o
所以其实压缩内核的入口就是arch/arm/boot/compressed/head.s文件,并且这个文件应该也就是uboot跳转到内核之后的总入口,这部分代码是位置无关,所以连接到0地址也没关系。
内核的入口的这段代码应该还包含搬运内核到高地址空间的代码,搬运的目的地址应该就是arch/arm/kernel/vmlinux.lds文件中的连接地址0xC0000000+0x00008000,这也应该改是内核最终的运行地址。