vmlinux.lds的理解

ARM 297浏览

内核源码中使用到的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,这也应该改是内核最终的运行地址。