移植u-boot到mini2440--理解映像链接脚本lds
2016-05-03 14:28
274 查看
编写好的 .lds 文件,在用 arm-linux-ld 连接命令时带 -Tfilename 来调用执行,如
arm-linux-ld-Tnand.lds x.o y.o -o xy.o 也用-Ttext参数直接指定连接地址,如
arm-linux-ld-Ttext 0x30000000 x.o y.o -oxy.o
既然程序有了两种地址,就涉及到一些跳转指令的区别。
ARM汇编中,常有两种跳转方法:b跳转指令、ldr指令向PC赋值。
要特别注意这两条指令的意思:
1> b step:b跳转指令是相对跳转,依赖当前PC的值,偏移量是通过该指令本身的bit[23:0]算出来的,这使得使用b指令的程序不依赖于要跳到的代码的位置,只看指令本身。
2> ldr pc, =board_init_r :该指令是一个伪指令编译后会生成以下代码:
从内存中的某个位置读出数据并赋给PC,同样依赖当前PC的值,所以可以用它实现从Flash到RAM的程序跳转。
下面是 u-boot-2016.01 根目录下的 u-boot.lds 简单分析下:
先简单分析到这里,如果以后考虑到SPL还需要加上 nandflash 拷贝的问题。到那时再接着分析。
上面提到有2种方式指明程序地址,这里分析下第二种方式,在根目录 Makefile文件有如下一行:
在文件
最后看下生成的 u-boot.dis 文件,可见基地址是由 mini2440.h 里面的宏定义指定的,而不是在u-boot.lds 脚本指定。
经过实验得知根目录下的 u-boot.lds 脚本是由
arm-linux-ld-Tnand.lds x.o y.o -o xy.o 也用-Ttext参数直接指定连接地址,如
arm-linux-ld-Ttext 0x30000000 x.o y.o -oxy.o
既然程序有了两种地址,就涉及到一些跳转指令的区别。
ARM汇编中,常有两种跳转方法:b跳转指令、ldr指令向PC赋值。
要特别注意这两条指令的意思:
1> b step:b跳转指令是相对跳转,依赖当前PC的值,偏移量是通过该指令本身的bit[23:0]算出来的,这使得使用b指令的程序不依赖于要跳到的代码的位置,只看指令本身。
2> ldr pc, =board_init_r :该指令是一个伪指令编译后会生成以下代码:
ldr pc, [pc, #8]
从内存中的某个位置读出数据并赋给PC,同样依赖当前PC的值,所以可以用它实现从Flash到RAM的程序跳转。
下面是 u-boot-2016.01 根目录下的 u-boot.lds 简单分析下:
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") /*指定输出可执行文件是elf格式,32位ARM指令,小端 */ OUTPUT_ARCH(arm) /* 指定输出文件的平台体系是ARM */ ENTRY(_start) /*指定可执行映像文件的起始段的段名是_start*/ SECTIONS { /DISCARD/ : { *(.rel._secure*) } /*指定可执行image文件的全局入口点,通常这个地址都放在ROM(flash)0x0位置。 必须使编译器知道这个地址,一般不修改此处,而是修改其它地方的宏定义*/ . = 0x00000000; . = ALIGN(4); .text : { *(.__image_copy_start) /* 映像文件复制起始地址,它在文件arch/arm/lib/sections.c 中定义: char __image_copy_start[0] __attribute__((section(".__image_copy_start"))); */ *(.vectors) /* 注意到 arch/arm/lib/vectors.S 里面有一句 .section ".vectors" 这里的 vectors 是让 vector.S 链接到二进制文件的开头部分 */ arch/arm/cpu/arm920t/start.o (.text*) /* 紧跟着就是,start.S */ *(.text*) /* 其余的代码 */ } . = ALIGN(4); .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } /* 只读数据段,所有的只读数据段都放在这个位置*/ . = ALIGN(4); .data : { *(.data*) /* 可读写数据段,所有的可读写数据段都放在这里*/ } . = ALIGN(4); . = .; . = ALIGN(4); .u_boot_list : { KEEP(*(SORT(.u_boot_list*))); } . = ALIGN(4); .image_copy_end : { *(.__image_copy_end) } .rel_dyn_start : { *(.__rel_dyn_start) } .rel.dyn : { *(.rel*) } .rel_dyn_end : { *(.__rel_dyn_end) } .end : { *(.__end) } _image_binary_end = .; . = ALIGN(4096); .mmutable : { *(.mmutable) } .bss_start __rel_dyn_start (OVERLAY) : { KEEP(*(.__bss_start)); __bss_base = .; } .bss __bss_base (OVERLAY) : { *(.bss*) . = ALIGN(4); __bss_limit = .; } .bss_end __bss_limit (OVERLAY) : { KEEP(*(.__bss_end)); } .dynsym _image_binary_end : { *(.dynsym) } .dynbss : { *(.dynbss) } .dynstr : { *(.dynstr*) } .dynamic : { *(.dynamic*) } .plt : { *(.plt*) } .interp : { *(.interp*) } .gnu.hash : { *(.gnu.hash) } .gnu : { *(.gnu*) } .ARM.exidx : { *(.ARM.exidx*) } .gnu.linkonce.armexidx : { *(.gnu.linkonce.armexidx.*) } }
先简单分析到这里,如果以后考虑到SPL还需要加上 nandflash 拷贝的问题。到那时再接着分析。
上面提到有2种方式指明程序地址,这里分析下第二种方式,在根目录 Makefile文件有如下一行:
LDFLAGS_u-boot += -Ttext $(CONFIG_SYS_TEXT_BASE)
在文件
include/configs/mini2440.h有定义
#define CONFIG_SYS_TEXT_BASE 0x0 /*0x33F80000*/
最后看下生成的 u-boot.dis 文件,可见基地址是由 mini2440.h 里面的宏定义指定的,而不是在u-boot.lds 脚本指定。
经过实验得知根目录下的 u-boot.lds 脚本是由
arch/arm/cpu/u-boot.lds在编译的时候生成的,所以如果要修改u-boot.lds 需要找到正确的地方。
相关文章推荐
- U-Boot源码分析及移植-fs2410
- U-BOOT源码分析及移植
- U-Boot启动过程--详细版的完全分析(二)
- U-Boot-2009-03移植笔记(移植准备)
- U-Boot-2009-03移植笔记(点亮第一展灯)
- U_boot 的 bootcmd 和bootargs参数详解
- U-Boot移植全程指导
- u-boot1.1.6-undefined reference to "raise"
- Arduino作为编程器读写BIOS、bootloader、uboot或者breed
- 09课01节 u-boot-1.1.16编译补丁;
- u-boot模仿
- 自定义u-boot启动logo的方法
- 2440 u-boot编译
- u-boot.lds与-Ttext $(TEXT_BASE)
- A20网络机顶盒移植4.5内核+U-Boot+rootfs
- 链接文件lds
- U-Boot移植(1)--在U-boot中建立自己的开发板
- 追踪uboot下tftp命令的代码执行过程-Nagul
- 嵌入式系统 Boot Loader 技术内幕
- 嵌入式linux系统log文件的几个地方