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_.*\)/-u\1/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_.*\)/-u\1/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_.*\)/-u\1/p'|sort|uniq`;\
cd /work/system/u-boot-1.1. && arm-linux-ld -Bstatic -T /work/system/u-boot-1.1./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.-glibc-2.3./lib/gcc/arm-linux/3.4. -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();
.text :
{
cpu/arm920t/start.o (.text) //第一个位置存放start.o的代码段
board/100ask24x0/boot_init.o (.text) //第二个位置存放boot_init.o的代码段
*(.text) //剩下的代码段
} . = ALIGN(); //四字节对齐
.rodata : { *(.rodata) } //只读数据段 . = ALIGN(); //四字节对齐
.data : { *(.data) } //数据段 . = ALIGN(); //四字节对齐
.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(); //四字节对齐
__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
#########################################################################
u-boot之make all执行过程分析的更多相关文章
- ASP.NET MVC应用程序执行过程分析
ASP.NET MVC应用程序执行过程分析 2009-08-14 17:57 朱先忠 朱先忠的博客 字号:T | T ASP.NET MVC框架提供了支持Visual Studio的工程模板.本文 ...
- Ansible系列(七):执行过程分析、异步模式和速度优化
本文目录:1.1 ansible执行过程分析1.2 ansible并发和异步1.3 ansible的-t选项妙用1.4 优化ansible速度 1.4.1 设置ansible开启ssh长连接 1.4. ...
- MFC的执行过程分析
MFC程序的执行细节剖析 MFC程序也是Windows程序,所以它应该也有一个WinMain.可是在程序中看不到它的踪影.事实上在程序进入点之前.另一个(并且仅有一个)全局对象(theApp).这就是 ...
- u-boot、kernel和filesystem 执行过程分析
标题: Uboot -kerne-root 启动流程 内容: ※uboot启动流程 ※Kernel启动流程 ※Root启动流程 ※构建根文件系统 /************************** ...
- spring boot mybatis 打成可执行jar包后启动UnsatisfiedDependencyException异常
我的spring boot + mybatis项目在idea里面执行正常,但发布测试环境打成可执行jar包后就启动失败,提示错误如下: [ ERROR] [2018-08-30 17:23:48] o ...
- Spring Boot Maven 打包可执行Jar文件!
Maven pom.xml 必须包含 <packaging>jar</packaging> <build> <plugins> <plugin&g ...
- Spring Boot Gradle 打包可执行Jar文件!
使用Gradle构建项目,继承了Ant的灵活和Maven的生命周期管理,不再使用XML作为配置文件格式,采用了DSL格式,使得脚本更加简洁. 构建环境: jdk1.6以上,此处使用1.8 Gradle ...
- 将 Spring boot 项目打成可执行Jar包,及相关注意事项(main-class、缺少 xsd、重复打包依赖)
最近在看 spring boot 的东西,觉得很方便,很好用.对于一个简单的REST服务,都不要自己部署Tomcat了,直接在 IDE 里 run 一个包含 main 函数的主类就可以了. 但是,转念 ...
- Spring boot 项目导出可执行jar
配置文件中添加插件 <plugin> <groupId>org.springframework.boot</groupId> <artifactId>s ...
- CDH集群spark-shell执行过程分析
目的 刚入门spark,安装的是CDH的版本,版本号spark-core_2.11-2.4.0-cdh6.2.1,部署了cdh客户端(非集群节点),本文主要以spark-shell为例子,对在cdh客 ...
随机推荐
- C语言中插入汇编nop指令
工作过程中,有的时候需要打桩cycle,想在C语言中插入nop指令,可以采取的方法是 头文件中加入#inlude <stdio.h> 定义一个内联函数,然后调用这个函数,不过得测一下平台调 ...
- [Linux]Linux下动态安装PHP扩展的一般方法(图)
---------------------------------------------------------------------------------------------------- ...
- 那些年,我们追过的PHP自加自减运算(2)
----------------------------------------------------------------------------------------- 先来一段例子,来引出 ...
- IIS8.0 部署WCF Services
今天在Win 8的IIS上部署WCF Services,访问SVC文件时出现找不到处理程序的错误,以前遇到这个问题时都是尝试通过注册asp.net的方式处理一下,但是在Win8下这招不灵了,出现如下提 ...
- 创建DLL动态链接库——声明导出法
DLL声明导出法:是通过使用__declspec(dllexport),添加到需要导出的函数前,进行声明. 头文件定义如下(OPdll.h): 源文件定义如下(OPdll.cpp): 通过以上两个文件 ...
- 吴裕雄 python 机器学习-DMT(1)
import numpy as np import operator as op from math import log def createDataSet(): dataSet = [[1, 1, ...
- python垃圾回收机制(转)
Python的GC模块主要运用了“引用计数”(reference counting)来跟踪和回收垃圾.在引用计数的基础上,还可以通过“标记-清除”(mark and sweep)解决容器对象可能产生的 ...
- How to fix the bug “Expected "required", "optional", or "repeated".”?
参考:https://github.com/tensorflow/models/issues/1834 You need to download protoc version 3.3 (already ...
- export default 与 export
export default 只能导出一个 可以用任意的变量来接收 export 可以暴露多个成员,需要用 import {} 接受成员 需要用名字接受 名字必须跟导出名字一致 //或者as作为别名 ...
- 内核进程切换 switch_to
参考: http://www.cnblogs.com/visayafan/archive/2011/12/10/2283660.html