Kernel Linker Scripts Analysis (ARM Architecture)

来源:互联网 发布:数据库管理系统的应用 编辑:程序博客网 时间:2024/05/01 09:12

1. arch/arm/kernel/vmlinux.lds的生成:

顶层的vmlinux是由arch/arm/kernel/vmlinux.lds链接生成,顶层Makefile里面定义:

693 vmlinux-lds  := arch/$(SRCARCH)/kernel/vmlinux.lds

 

arch/arm/kernel/vmlinux.lds是由arch/arm/kernel/vmlinux.lds.S生成,生成规则在scripts/Makefile.build中定义:

265 # Linker scripts preprocessor (.lds.S -> .lds)

266 # --------------------------------------------------------------------------    -

267 quiet_cmd_cpp_lds_S = LDS     $@

268       cmd_cpp_lds_S = $(CPP) $(cpp_flags) -D__ASSEMBLY__ -o $@ $<

269 

270 $(obj)/%.lds: $(src)/%.lds.S FORCE

271     $(call if_changed_dep,cpp_lds_S)

 

2.顶层vmlinux的起始地址

arch/arm/kernel/vmlinux.lds.S文件中:

 21 #ifdef CONFIG_XIP_KERNEL

 22     . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);

 23 #else

 24     . = PAGE_OFFSET + TEXT_OFFSET;

 25 #endif

由于没有配置CONFIG_XIP_KERNEL(可查看顶层.config文件),后面才是起始地址。

 

arch/arm/kernel/vmlinux.lds.S文件包含了头文件asm/memory.h,查看include/asm/memory.h

34 #define PAGE_OFFSET     UL(CONFIG_PAGE_OFFSET)

查看.config文件,可以得到CONFIG_PAGE_OFFSET=0xC0000000

 

搜索arch/arm目录可以在其下的Makefile文件中找到:

 96 textofs-y   := 0x00008000

160 # The byte offset of the kernel image in RAM from the start of RAM.

161 TEXT_OFFSET := $(textofs-y)

 

3. DEVKIT8000的虚实地址

arch/arm/boot/Makefile中:

 16 ifneq ($(MACHINE),)

 17 include $(srctree)/$(MACHINE)/Makefile.boot

 18 endif

即在arch/arm/mach-omap2/Makefile.boot文件中定义了一个压缩内核镜像zImage的起始地址:

  1   zreladdr-y        := 0x80008000

  2 params_phys-y       := 0x80000100

  3 initrd_phys-y       := 0x80800000

arch/arm/boot/Makefile中:

 24 ZRELADDR    := $(zreladdr-y)

 25 PARAMS_PHYS := $(params_phys-y)

 26 INITRD_PHYS := $(initrd_phys-y)

 

plat-omap/include/mach/memory.h中:

 36 /*

 37  * Physical DRAM offset.

 38  */

 39 #if defined(CONFIG_ARCH_OMAP1)

 40 #define PHYS_OFFSET     UL(0x10000000)

 41 #elif defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)

 42 #define PHYS_OFFSET     UL(0x80000000)

 43 #endif

我们使用0x80000000做为物理的页偏移地址,即sdram地址

这个地址在启动代码arch/arm/kernel/head.S中会用到:

 

4. 压缩的自引导镜像arch/arm/boot/compressed/vmlinux的起始地址

这个vmlinux是由同目录先vmlinux.lds脚本链接而成,而vmlinux.ldsvmlinux.lds.in生成,这个文件开头:

 14   . = TEXT_START;

而此目录下的Makefile中:

113 $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config

114     @sed "$(SEDFLAGS)" < $< > $@

68 SEDFLAGS    = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/

表示把TEXT_START改名为ZTEXTADDR

 56 # We now have a PIC decompressor implementation.  Decompressors running

 57 # from RAM should not define ZTEXTADDR.  Decompressors running directly

 58 # from ROM or Flash must define ZTEXTADDR (preferably via the config)

 59 # FIXME: Previous assignment to ztextaddr-y is lost here. See SHARK

 60 ifeq ($(CONFIG_ZBOOT_ROM),y)

 61 ZTEXTADDR   := $(CONFIG_ZBOOT_ROM_TEXT)

 62 ZBSSADDR    := $(CONFIG_ZBOOT_ROM_BSS)

 63 else

 64 ZTEXTADDR   := 0

 65 ZBSSADDR    := ALIGN(4)

 66 endif

从上面可以看出zImageram中启动ZTEXTADDR= 0,从rom或者flash中启动ZTEXTADDR= $(CONFIG_ZBOOT_ROM_TEXT)

 

5. arch/arm/kernel/vmlinux.lds.S链接文件分析

 1 /* ld script to make ARM Linux kernel

  2  * taken from the i386 version by Russell King

  3  * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>

  4  */

  5 

  6 #include <asm-generic/vmlinux.lds.h>

  7 #include <asm/thread_info.h>

  8 #include <asm/memory.h>

  9 

 10 OUTPUT_ARCH(arm)           /*指定目标板体系结构*/

 11 ENTRY(stext)           /*代码入口*/

 12 

 13 #ifndef __ARMEB__

 14 jiffies = jiffies_64;          /*kernel/timer.c的定义*/

 15 #else

 16 jiffies = jiffies_64 + 4;

 17 #endif

 18 

 19 SECTIONS

 20 {

 21 #ifdef CONFIG_XIP_KERNEL

 22     . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);

 23 #else

 24     . = PAGE_OFFSET + TEXT_OFFSET;            /*代码段起始地址,.表示连接地址*/

 25 #endif

 26     .text.head : {

 27         _stext = .;       /*定义_stext为当前位置*/

 28         _sinittext = .;

 29         *(.text.head)      /*将所有输入文件的.text.head段合并到这里*/

 30     }

 31 

 32     .init : {           /*内核初始化的代码和数据*/

 33             INIT_TEXT

 34         _einittext = .;

 35         __proc_info_begin = .;

 36             *(.proc.info.init)

 37         __proc_info_end = .;

 38         __arch_info_begin = .;

 39             *(.arch.info.init)

33             INIT_TEXT

 34         _einittext = .;

 35         __proc_info_begin = .;

 36             *(.proc.info.init)

 37         __proc_info_end = .;

 38         __arch_info_begin = .;

 39             *(.arch.info.init)

 40         __arch_info_end = .;

 41         __tagtable_begin = .;

 42             *(.taglist.init)

 43         __tagtable_end = .;

 44         . = ALIGN(16);

 45         __setup_start = .;

 46             *(.init.setup)

 47         __setup_end = .;

 48         __early_begin = .;

 49             *(.early_param.init)

 50         __early_end = .;

 51         __initcall_start = .;

 52             INITCALLS

 53         __initcall_end = .;

 54         __con_initcall_start = .;

 55             *(.con_initcall.init)

 56         __con_initcall_end = .;

 57         __security_initcall_start = .;

 58             *(.security_initcall.init)

 59         __security_initcall_end = .;

 60 #ifdef CONFIG_BLK_DEV_INITRD

 61         . = ALIGN(32);

 62         __initramfs_start = .;

 63             usr/built-in.o(.init.ramfs)

 64         __initramfs_end = .;

 65 #endif

 66         . = ALIGN(4096);

 67         __per_cpu_start = .;

 68             *(.data.percpu)

 69             *(.data.percpu.shared_aligned)

70         __per_cpu_end = .;

 71 #ifndef CONFIG_XIP_KERNEL

 72         __init_begin = _stext;

 73         INIT_DATA

 74         . = ALIGN(4096);

 75         __init_end = .;

 76 #endif

 77     }

 78 

 79     /DISCARD/ : {           /*内核退出的代码和数据  */

 80         EXIT_TEXT

 81         EXIT_DATA

 82         *(.exitcall.exit)

 83 #ifndef CONFIG_MMU

 84         *(.fixup)

 85         *(__ex_table)

 86 #endif

 87     }

 88 

 89     .text : {           /*真正的代码段部分*/

 90         _text = .;      /*代码和只读数据*/

 91             __exception_text_start = .;

 92             *(.exception.text)

 93             __exception_text_end = .;

 94             TEXT_TEXT

 95             SCHED_TEXT

 96             LOCK_TEXT

 97             KPROBES_TEXT

 98 #ifdef CONFIG_MMU

 99             *(.fixup)

100 #endif

101             *(.gnu.warning)

102             *(.rodata)

103             *(.rodata.*)

104             *(.glue_7)

105             *(.glue_7t)

106         *(.got)         /* Global offset table      */

107     }

108 

109     RODATA

110 

111     _etext = .;         /*代码段和只读数据结束 */

112 

113 #ifdef CONFIG_XIP_KERNEL

114     __data_loc = ALIGN(4);      /* location in binary */

115     . = PAGE_OFFSET + TEXT_OFFSET;

116 #else

117     . = ALIGN(THREAD_SIZE);

118     __data_loc = .;

119 #endif

120 

121     .data : AT(__data_loc) {       /*数据段起始*/

122         _data = .;      /*内存中的地址 */

123 

124         /*

125          * first, the init task union, aligned

126          * to an 8192 byte boundary.

127          */

128         *(.data.init_task)

129 

130 #ifdef CONFIG_XIP_KERNEL

131         . = ALIGN(4096);

132         __init_begin = .;

133         INIT_DATA

134         . = ALIGN(4096);

135         __init_end = .;

136 #endif

137 

138         . = ALIGN(4096);

139         __nosave_begin = .;

140         *(.data.nosave)

141         . = ALIGN(4096);

142         __nosave_end = .;

143 

144         /*

145          * then the cacheline aligned data

146          */

147         . = ALIGN(32);

148         *(.data.cacheline_aligned)

149 

150         /*

151          * The exception fixup table (might need resorting at runtime)

152          */

153         . = ALIGN(32);

154         __start___ex_table = .;

155 #ifdef CONFIG_MMU

156         *(__ex_table)

157 #endif

158         __stop___ex_table = .;

159 

160         /*

161          * and the usual data section

162          */

163         DATA_DATA

164         CONSTRUCTORS

165 

166         _edata = .;

167     }

168     _edata_loc = __data_loc + SIZEOF(.data);

169 

170     .bss : {                    /*未初始化的全局变量*/

171         __bss_start = .;    /* BSS              */

172         *(.bss)

173         *(COMMON)

174         _end = .;

175     }

176                     /*调试信息和数据段 */

177     .stab 0 : { *(.stab) }

178     .stabstr 0 : { *(.stabstr) }

179     .stab.excl 0 : { *(.stab.excl) }

180     .stab.exclstr 0 : { *(.stab.exclstr) }

181     .stab.index 0 : { *(.stab.index) }

182     .stab.indexstr 0 : { *(.stab.indexstr) }

183     .comment 0 : { *(.comment) }

184 }

185 

186 /*

187  * These must never be empty

188  * If you have to comment these two assert statements out, your

189  * binutils is too old (for other reasons as well)

190  */

191 ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")

192 ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")