U-boot.lds是一个链接脚本,那什么是链接脚本?链接脚本就是程序链接时的的参考文件,其目的是描述输入文件中各段应该怎么样被映射到输出文件,以及程序运行时的内存布局等等。
在这里我有一个小小的疑问,在顶层的config.mk文件中有一下语句:
- ifdef VENDOR
- BOARDDIR = $(VENDOR)/$(BOARD)
- else
- BOARDDIR = $(BOARD)
- endif
- ifndef LDSCRIPT
- #LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds.debug
- ifeq ($(CONFIG_NAND_U_BOOT),y)
- LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-nand.lds
- else
- LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds
- endif
这里可以看出如果定义厂商的话,
BOARDDIR = $(VENDOR)/$(BOARD) 如BOARDDIR = samsung/smdk2410,如果没有定义的话,如BOARDDIR = smdk2410/,然后看
LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds 这一句,那么按照这个推理来说u-boot.lds应该在:u-boot-2010.09/board/samsung/smkd2410下才对,但是我在u-boot-2010.09这个版本下并没有发现,看了一下黄刚和
tekkamanninja 的博客,他们都是在cpu/arm920t下找的u-boot.lds,而在uboot1.6版本中/board/samsung/smkd2410是有u-boot.lds的。这一点有疑问,还请知道的指点一下。那下面就贴上u-boot-2010.09\arch\arm\cpu\arm920t目录下的u-boot.lds来分析:
- OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
- OUTPUT_ARCH(arm)
- ENTRY(_start)
- SECTIONS
- {
- . = 0x00000000;
- . = ALIGN(4);
- .text :
- {
- arch/arm/cpu/arm920t/start.o (.text)
- *(.text)
- }
- . = ALIGN(4);
- .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
- . = ALIGN(4);
- .data : { *(.data) }
- . = ALIGN(4);
- .got : { *(.got) }
- . = .;
- __u_boot_cmd_start = .;
- .u_boot_cmd : { *(.u_boot_cmd) }
- __u_boot_cmd_end = .;
- . = ALIGN(4);
- __bss_start = .;
- .bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
- _end = .;
- }
首先,是讲下第一句,看一段英文,相信大家都看得懂:
You can use OUTPUT_FORMAT with three arguments to use different formats based on the -EB and -EL command line options. This permits the linker script to set the output format based on the desired endianness.
If neither -EB nor -EL are used, then the output format will be the first argument, default. If -EB is used, the output format will be the second argument, big. If -EL is used, the output format will be the third argument, little.
这里既没有用-EB,也没有用-EL指定,那么指定的就是
elf32-littlearm 格式,即指定输出文件是elf格式,32位ARM指令,小端模式,
紧接着
OUTPUT_ARCH(arm) 指定的是输出可执行文件的运行平台为ARM,
ENTRY(_start)指定_start函数为程序的入口,
SECTIONS这个命令用来描述输出文件的内存布局的,
. = 0x00000000;这里的点号称为位置计数器,通俗的讲,它代表这当前位置,这条语句的意思就是当前位置定义为0地址。
. = ALIGN(4); ALGN勇于产生对齐的代码或数据,因为在一些体系结构对处理对齐的数据或代码时效率更高,这条语句的意思就是位置计数器向高地址方向取最近的4字节的整数倍。
.text :定义了该输出位置为代码段,花括号里定义了代码段的具体内容,
arch/arm/cpu/arm920t/start.o (.text)这个指定了start.o文件将出现在代码段的最前面,
*(.text)星号代表所有文件,意思是将所有目标文件的代码段都链接到这一区域。
.rodata :定义了只读数据段,
.data :定义了数据段
.got定义了got段,got段是uboot自己定义的一个非标准段
__u_boot_cmd_start = .;将当前位置赋值为
__u_boot_cmd_start
这里说明一点:在没有对位置技术器进行赋值时,位置计数器会动态的增加,比如
. = .;这一条语句,此时位置技术器的位置就是从0开始加上代码段,只读数据段,数据段,got段的大小,紧接着之后的位置,下面的赋值类似,就不一一详细说明了。
另外还要说明一点:向输出段的定义如:text,rodata,data,got这些关键词完全可以任意定义,因为输出段的实际内容与输出段的命名无关,而至于花括号内的具体内容有关。
主要参考:李无言 一步步写嵌入式操作系统