• u-boot之make all执行过程分析


    在执行make 100ask24x0_config之后就配置完成了针对JZ2440开发板的UBOOT,接下来需要执行make all进行编译链接最终生成u-boot.map、u-boot.srec、u-boot.bin文件,下面主要针对这一过程进行分析:

    1、u-boot.map、u-boot.srec、u-boot.bin、u-boot四个文件的作用

    2、从Make all逐步深入分析

    3、分析子Makefile过程

    1、u-boot.map、u-boot.srec、u-boot.bin、u-boot四个文件是编译链接后生成的,它们的作用如下:

    a、u-boot.map:

    1)、map文件是程序的全局符号、源文件和代码行号信息的唯一的文本表示方法,是整个程序工程信息的静态文本,通常由linker生成。

    2)、map文件保存整个工程的静态文本信息,里面有所有函数的入口地址。

    3)、通过查看map文件,我们可以找到代码段(.text),全局未初始化区(.bss),数据段(.data),未初始化段(.bss),还有些不懂的.debug_line、.comment、.got等段

    4)、map文件的作用是,我们可以根据程序产生错误地址在map文件中找到相应的函数、变量地址。

    b、u-boot.srec:Motorola S-Record格式的可执行文件

    c、u-boot:elf格式的可执行文件,里面包含了调试信息

    d、u-boot.bin:二进制格式的可执行文件,它就是可以直接烧入ROM、NOR Flash的文件

    2、从Make all逐步深入分析Makefile

    变量:这些变量在很多Make规则中调用

    OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))执行了这条之后则认为BUILD_DIR=CURDIR=/work/system/u-boot-1.1.6
    SRCTREE := $(CURDIR)
    TOPDIR := $(SRCTREE)
    LNDIR := $(OBJTREE)

    OBJTREE = /work/system/u-boot-1.1.6
    SRCTREE = /work/system/u-boot-1.1.6
    TOPDIR = /work/system/u-boot-1.1.6
    LNDIR = /work/system/u-boot-1.1.6
    obj :=
    src :=

    调用文件:调用文件中的很多内容被Make规则调用(下面文件包括了用什么编译器编译、链接的地址等等需要的内容)

    include /work/system/u-boot-1.1.6/config.mk
    include /work/system/u-boot-1.1.6/include/config.mk
    sinclude /work/system/u-boot-1.1.6/arm_config.mk
    sinclude /work/system/u-boot-1.1.6/cpu/arm920t/config.mk
    sinclude /work/system/u-boot-1.1.6/board/100ask24x0/config.mk 

    跟随make all一步步往下看,all依赖于ALL,ALL则依赖于u-boot.srec 、u-boot.bin 、System.map、 $(U_BOOT_NAND)

    ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)
    
    all:            $(ALL)

    下面是生成u-boot.srec的规则

    $(obj)u-boot.srec:      $(obj)u-boot
                    $(OBJCOPY) ${OBJCFLAGS} -O srec $< $@

    u-boot.srec依赖于u-boot,下面是生产u-boot的规则。

    $(obj)u-boot:           depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)
                    UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed -n -e 's/.*(__u_boot_cmd_.*)/-u1/p'|sort|uniq`;
                    cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) 
                            --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) 
                            -Map u-boot.map -o u-boot

    先分析第一行,等价于u-boot: depend version $(SUBDIRS) cpu/arm920t/start.o $(LIBS) $(LDSCRIPT)

    LIBS的值,为所有子目录下的.a文件即子目录下编译后产生的所以.o文件的集合

    LIBS  = lib_generic/libgeneric.a
    LIBS += board/$(BOARDDIR)/lib$(BOARD).a
    LIBS += cpu/$(CPU)/lib$(CPU).a
    ifdef SOC
    LIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).a
    endif
    LIBS += lib_$(ARCH)/lib$(ARCH).a
    LIBS += fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a 
        fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a
    LIBS += net/libnet.a
    LIBS += disk/libdisk.a
    LIBS += rtc/librtc.a
    LIBS += dtt/libdtt.a
    LIBS += drivers/libdrivers.a
    LIBS += drivers/nand/libnand.a
    LIBS += drivers/nand_legacy/libnand_legacy.a
    LIBS += drivers/usb/libusb.a
    LIBS += drivers/sk98lin/libsk98lin.a
    LIBS += common/libcommon.a
    LIBS += $(BOARDLIBS)

    LDSCRIPT的值LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds等价于/work/system/u-boot-1.1.6/board/100ask24x0/u-boot.lds  (定义在/work/system/u-boot-1.1.6/config.mk中)

    依赖depend不存在,version表示把版本号等等信息存放在VERSION_FILE文件中,依赖规则为:

    version:
                    echo -n "#define U_BOOT_VERSION "U-Boot " > $(VERSION_FILE); 
                    echo -n "$(U_BOOT_VERSION)" >> $(VERSION_FILE); 
                    echo -n $(shell $(CONFIG_SHELL) $(TOPDIR)/tools/setlocalversion 
                             $(TOPDIR)) >> $(VERSION_FILE); 
                    echo """ >> $(VERSION_FILE)

    $(SUBDIRS)规则为,等价于cd SUBDIRS && make。解释为进入相应的子目录然后make。(对应子目录的make后面再介绍,这里只需知道有这么一个依赖即可,tool是编译的第一个目录)。

    $(SUBDIRS):
                    $(MAKE) -C $@ all

    接着往下看,将以下所有变量都翻译出来得到翻译后的语句。

    UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed -n -e 's/.*(__u_boot_cmd_.*)/-u1/p'|sort|uniq`;
                    cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) 
                            --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) 
                            -Map u-boot.map -o u-boot
    UNDEF_SYM=`arm-linux-objdump -x lib_generic/libgeneric.a board/100ask24x0/lib100ask24x0.a cpu/arm920t/libarm920t.a cpu/arm920t/s3c24x0/libs3c24x0.a 
                                              lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a fs/reiserfs/libreiserfs.a 
                                              fs/ext2/libext2fs.a net/libnet.a disk/libdisk.a rtc/librtc.a dtt/libdtt.a drivers/libdrivers.a drivers/nand/libnand.a 
                                              drivers/nand_legacy/libnand_legacy.a drivers/usb/libusb.a 
                                              drivers/sk98lin/libsk98lin.a common/libcommon.a |sed  -n -e 's/.*(__u_boot_cmd_.*)/-u1/p'|sort|uniq`;
    cd /work/system/u-boot-1.1.6 && arm-linux-ld -Bstatic -T /work/system/u-boot-1.1.6/board/100ask24x0/u-boot.lds -Ttext 0x33F80000 
    $UNDEF_SYM cpu/arm920t/start.o --start-group lib_generic/libgeneric.a board/100ask24x0/lib100ask24x0.a cpu/arm920t/libarm920t.a 
                                                                                             cpu/arm920t/s3c24x0/libs3c24x0.a lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a 
                                                                                             fs/fdos/libfdos.a fs/jffs2/libjffs2.a fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a net/libnet.a 
                                                                                             disk/libdisk.a rtc/librtc.a dtt/libdtt.a drivers/libdrivers.a drivers/nand/libnand.a 
                                                                                             drivers/nand_legacy/libnand_legacy.a drivers/usb/libusb.a drivers/sk98lin/libsk98lin.a 
                                                                                             common/libcommon.a --end-group -L /work/tools/gcc-3.4.5-glibc-2.3.6/lib/gcc/arm-linux/3.4.5 -lgcc 
                                                          -Map u-boot.map -o u-boot

    大致意思是把所以.a文件、.o文件以及静态库文件链接在0x33F80000开头的地方最终生成u-boot.map文件以及u-boot文件。具体链接规则参见work/system/u-boot-1.1.6/board/100ask24x0/u-boot.lds。详细分析参考https://blog.csdn.net/gongyuan073/article/details/13168239

    OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")//小端模式
    /*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
    OUTPUT_ARCH(arm)            //arm架构
    ENTRY(_start)              //入口地址为_start
    SECTIONS
    {
        . = 0x00000000;        //当前地址为0x00000000+0x33f80000。装载地址与链接地址一样
    
        . = ALIGN(4);
        .text      :
        {
          cpu/arm920t/start.o    (.text)                //第一个位置存放start.o的代码段
              board/100ask24x0/boot_init.o (.text)      //第二个位置存放boot_init.o的代码段
          *(.text)                                      //剩下的代码段
        }
    
        . = ALIGN(4);                                   //四字节对齐
        .rodata : { *(.rodata) }                        //只读数据段
    
        . = ALIGN(4);                                   //四字节对齐
        .data : { *(.data) }                            //数据段
    
        . = ALIGN(4);                                   //四字节对齐
        .got : { *(.got) }                              //got段
    
        . = .;
        __u_boot_cmd_start = .;                         //__u_boot_cmd_start=当前地址
        .u_boot_cmd : { *(.u_boot_cmd) }                //u_boot_cmd段
        __u_boot_cmd_end = .;                           //__u_boot_cmd_end=当前地址
    
        . = ALIGN(4);                                   //四字节对齐
        __bss_start = .;                                //__bss_start=当前地址
        .bss : { *(.bss) }                              //bss段未初始化段
        _end = .;                                       //_end=当前地址
    }

     最后再根据u-boot文件生成u-boot.srec文件与u-boot.bin文件

    arm-linux-objcopy --gap-fill=0xff -O srec u-boot u-boot.srec
    arm-linux-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin

    3、分析子Makefile过程

     在分析make all过程当中提到了子Makefile这一概念。$(MAKE) -C $@ all等价于cd SUBDIRS && make。这几个子Makefile内容有点多,为了简单明了的理解子Makefile,下面以/work/system/u-boot-1.1.6/board/100ask24x0/Makefile文件做说明。

    这里make以后需要被执行的目标文件是$(LIB): $(obj).depend $(OBJS) $(SOBJS)。

    CROSS_COMPILE = arm-linux-(在work/system/u-boot-1.1.6/config.mk中定义)

    AR = $(CROSS_COMPILE)ar(在work/system/u-boot-1.1.6/include/config.mk中定义)

    ARFLAGS = crv(在work/system/u-boot-1.1.6/config.mk中定义)

    .depend的内容为.c或者.s文件生成的.o文件,查看得到里面的内容为:

    lowlevel_init.o: lowlevel_init.S
    /work/System2/u-boot-1.1.6/include/config.h
    /work/System2/u-boot-1.1.6/include/configs/100ask24x0.h
    /work/System2/u-boot-1.1.6/include/cmd_confdefs.h
    /work/System2/u-boot-1.1.6/include/version.h
    /work/System2/u-boot-1.1.6/include/version_autogenerated.h
    100ask24x0.o: 100ask24x0.c /work/System2/u-boot-1.1.6/include/common.h
    /work/System2/u-boot-1.1.6/include/config.h
    /work/System2/u-boot-1.1.6/include/configs/100ask24x0.h
    /work/System2/u-boot-1.1.6/include/cmd_confdefs.h
    /work/System2/u-boot-1.1.6/include/linux/bitops.h
    /work/System2/u-boot-1.1.6/include/asm/bitops.h
    /work/System2/u-boot-1.1.6/include/linux/types.h
    /work/System2/u-boot-1.1.6/include/linux/config.h
    /work/System2/u-boot-1.1.6/include/linux/posix_types.h
    /work/System2/u-boot-1.1.6/include/linux/stddef.h
    /work/System2/u-boot-1.1.6/include/asm/posix_types.h
    /work/System2/u-boot-1.1.6/include/asm/types.h
    /work/System2/u-boot-1.1.6/include/linux/string.h
    /work/System2/u-boot-1.1.6/include/asm/string.h
    /work/System2/u-boot-1.1.6/include/asm/ptrace.h
    /work/System2/u-boot-1.1.6/include/asm/proc/ptrace.h
    /work/tools/gcc-3.4.5-glibc-2.3.6/lib/gcc/arm-linux/3.4.5/include/stdarg.h
    /work/System2/u-boot-1.1.6/include/part.h
    /work/System2/u-boot-1.1.6/include/ide.h
    /work/System2/u-boot-1.1.6/include/flash.h
    /work/System2/u-boot-1.1.6/include/image.h
    /work/System2/u-boot-1.1.6/include/asm/u-boot.h
    /work/System2/u-boot-1.1.6/include/asm/global_data.h
    /work/System2/u-boot-1.1.6/include/asm/mach-types.h
    /work/System2/u-boot-1.1.6/include/asm/setup.h
    /work/System2/u-boot-1.1.6/include/asm/u-boot-arm.h
    /work/System2/u-boot-1.1.6/include/s3c2410.h
    /work/System2/u-boot-1.1.6/include/s3c24x0.h
    boot_init.o: boot_init.c /work/System2/u-boot-1.1.6/include/common.h
    /work/System2/u-boot-1.1.6/include/config.h

    具体生成它的规则在/work/system/u-boot-1.1.6/rules.mk,这是一个通用规则,每一个子目录丢调用这个规则生成.o文件,具体分析参见https://blog.csdn.net/mars1743/article/details/24180349,具体为:

    _depend:    $(obj).depend
    
    $(obj).depend:    $(src)Makefile $(TOPDIR)/config.mk $(SRCS)//依赖为当前目录下的Makefile、顶层的config.mk以及SRCS
            @rm -f $@
            @for f in $(SRCS); do 
                g=`basename $$f | sed -e 's/(.*).w/1.o/'`; 
                $(CC) -M $(HOST_CFLAGS) $(CPPFLAGS) -MQ $(obj)$$g $$f >> $@ ;   //
            done
    include $(TOPDIR)/config.mk               //等价于调用/work/system/u-boot-1.1.6/config.mk  
    
    LIB = $(obj)lib$(BOARD).a                 //等价于LIB = lib100ask24x0.a,BOARD在/work/system/u-boot-1.1.6/include/config.mk里定义
    
    COBJS := 100ask24x0.o boot_init.o
    SOBJS    := lowlevel_init.o
    
    SRCS    := $(SOBJS:.o=.S) $(COBJS:.o=.c)
    OBJS    := $(addprefix $(obj),$(COBJS))
    SOBJS    := $(addprefix $(obj),$(SOBJS))
    
    $(LIB):    $(obj).depend $(OBJS) $(SOBJS) //等价于 lib100ask24x0.a:.depend 100ask24x0.o boot_init.o lowlevel_init.o
    $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)   //等价于 arm-linux-ar crv lib100ask24x0.a 100ask24x0.o boot_init.o lowlevel_init.o
    clean:
    rm -f $(SOBJS) $(OBJS)                //删除生成的.o文件
    
    distclean:    clean
    rm -f $(LIB) core *.bak .depend       //删除生成的.a文件、.bak文件、.depend文件以及core
    
    #########################################################################
    
    # defines $(obj).depend target
    include $(SRCTREE)/rules.mk  //通用规则调用,生成.o文件
    
    sinclude $(obj).depend     //当前目录下的.depend 
    #########################################################################
  • 相关阅读:
    六、显式锁和AQS
    五、原子操作(CAS)
    四、线程的并发工具类
    BZOJ 2176 Strange string ——最小表示法
    BZOJ 2882 工艺 ——后缀自动机 最小表示法
    Codeforces Round #401 (Div. 2)
    BZOJ 2331 [SCOI2011]地板 ——插头DP
    BZOJ 2005 [Noi2010]能量采集 ——Dirichlet积
    BZOJ 1087 [SCOI2005]互不侵犯King ——状压DP
    BZOJ 1072 [SCOI2007]排列perm ——状压DP
  • 原文地址:https://www.cnblogs.com/andyfly/p/9342550.html
Copyright © 2020-2023  润新知