您的位置:首页 > 其它

移植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 :该指令是一个伪指令编译后会生成以下代码:

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 需要找到正确的地方。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息