下面分析$(obj)u-boot的各个依赖:
1依赖目标depend
# Explicitly make _depend in subdirscontaining multiple targets to prevent
# parallel sub-makes creating .depend filessimultaneously.
depend dep: $(TIMESTAMP_FILE) $(VERSION_FILE) $(obj)include/autoconf.mk
fordir in $(SUBDIRS) cpu/$(CPU) $(dir $(LDSCRIPT)) ; do \
$(MAKE)-C $$dir _depend ; done
对于$(SUBDIRS),cpu/$(CPU),$(dir $(LDSCRIPT))中的每个元素都进入该目录执行“make_depend”,生成各个子目录的.depend文件,.depend列出每个目标文件的依赖文件。
2依赖SUBDIRS
SUBDIRS = tools \
examples/standalone \
examples/api
$(SUBDIRS): depend
$(MAKE)-C $@ all
执行tools ,examples/standalone ,examples/api目录下的Makefile。
3OBJS
OBJS的值是“cpu/arm920t/start.o”。它使用如下代码编译得到:
$(OBJS): depend
$(MAKE)-C cpu/$(CPU) $(if $(REMOTE_BUILD),$@,$(notdir $@))
以上规则表明,对于OBJS包含的每个成员,都进入cpu/$(CPU)目录(即cpu/arm920t)编译它们。
4LIBBOARD
LIBBOARD = board/$(BOARDDIR)/lib$(BOARD).a
LIBBOARD := $(addprefix$(obj),$(LIBBOARD))
… …
$(LIBBOARD): depend $(LIBS)
$(MAKE)-C $(dir $(subst $(obj),,$@))
这里LIBBOARD的值是$(obj)board/samsung/mini2440/libmini2440.a。make执行board/samsung/mini2440/目录下的Makefile,生成libmini2440.a 。
5LIBS
LIBS变量中的每个元素使用如下的规则编译得到:
$(LIBS): depend$(SUBDIRS)
$(MAKE)-C $(dir $(subst $(obj),,$@))
上面的规则表明,对于LIBS中的每个成员,都进入相应的子目录执行“make”命令编译它们。例如对于LIBS中的“common/libcommon.a”成员,程序将进入common目录执行Makefile,生成libcommon.a 。
6LDSCRIPT
LDSCRIPT := $(SRCTREE)/cpu/$(CPU)/u-boot.lds
… …
$(LDSCRIPT): depend
$(MAKE)-C $(dir $@) $(notdir $@)
“$(MAKE) -C $(dir $@)$(notdir $@)”命令经过变量替换后就是“make-C cpu/arm920t/ u-boot.lds”。也就是转到cpu/arm920t/目录下,执行“make u-boot.lds”命令。
7$(obj)u-boot.lds
$(obj)u-boot.lds: $(LDSCRIPT)
$(CPP)$(CPPFLAGS) $(LDPPFLAGS) -ansi -D__ASSEMBLY__ -P - 《$^ 》$@
以上执行结果实质上是将cpu/arm920t/u-boot.lds经编译器简单预处理后输出到U-Boot顶层目录下的u-boot.lds文件。其中的cpu/arm920t/u-boot.lds文件内容如下:
/* 输出为ELF文件,小端方式, */
OUTPUT_FORMAT(“elf32-littlearm”,“elf32-littlearm”, “elf32-littlearm”)
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
。= 0x00000000;
。= ALIGN(4);
.text:
{
/* cpu/arm920t/start.o放在最前面,保证最先执行的是start.o */
cpu/arm920t/start.o (.text)
/*以下2个文件必须放在前4K,因此也放在前面,其中board/samsung/mini2440/lowlevel_init.o包含内存初始化所需代码,而board/samsung/mini2440/nand_read.o 包含U-Boot从NAND Flash搬运自身的代码 */
board/samsung/mini2440/lowlevel_init.o(.text)
board/samsung/mini2440/nand_read.o(.text)
/* 其他文件的代码段 */
*(.text)
}
/* 只读数据段 */
。= ALIGN(4);
.rodata: { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
/* 代码段 */
。= ALIGN(4);
.data: { *(.data) }
/* u-boot自定义的got段 */
。= ALIGN(4);
.got: { *(.got) }
。= 。;
__u_boot_cmd_start= 。; /*将 __u_boot_cmd_start指定为当前地址 */
.u_boot_cmd: { *(.u_boot_cmd) } /* 存放所有U-Boot命令对应的cmd_tbl_t结构体 */
__u_boot_cmd_end= 。; /* 将__u_boot_cmd_end指定为当前地址 */
/* bss段 */
。= ALIGN(4);
__bss_start= 。;
.bss(NOLOAD) : { *(.bss) 。 = ALIGN(4); }
_end= 。; /* 将_end指定为当前地址 */
}
u-boot.lds实质上是U-Boot连接脚本。对于生成的U-Boot编译生成的“u-boot”文件,可以使用objdump命令可以查看它的分段信息:
$ objdump -x u-boot | more
部分输出信息如下:
u-boot: file format elf32-little
u-boot
architecture: UNKNOWN!, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x33f80000
Program Header:
LOAD off 0x00008000 vaddr0x33f80000 paddr 0x33f80000 align 2**15
filesz 0x0002f99c memsz 0x00072c94 flags rwx
STACK off 0x00000000 vaddr0x00000000 paddr 0x00000000 align 2**2
filesz 0x00000000 memsz 0x00000000 flags rwx
Sections:
Idx Name Size VMA LMA File off Algn
0.text 00024f50 33f80000 33f80000 00008000 2**5
CONTENTS, ALLOC, LOAD,READONLY, CODE
1.rodata 00008b78 33fa4f50 33fa4f50 0002cf50 2**3
CONTENTS, ALLOC, LOAD, READONLY,DATA
2.data 00001964 33fadac8 33fadac8 00035ac8 2**2
CONTENTS, ALLOC, LOAD, DATA
3.u_boot_cmd 00000570 33faf42c 33faf42c 0003742c 2**2
CONTENTS, ALLOC, LOAD, DATA
4.bss 00043294 33fafa00 33fafa00 0003799c 2**8
ALLOC
… …
u-boot.lds还跟U-Boot启动阶段复制代码到RAM空间的过程以及U-Boot命令执行过程密切相关,具体请结合U-Boot源代码理解。
评论
查看更多