移植u-boot到mini2440--理解映像链接脚本lds

  编写好的 .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 需要找到正确的地方。

你可能感兴趣的:(LDS,u-boot,链接脚本,镜像基地址)