Linux的连接脚本,Linux连接脚本

Linux连接脚本

连接脚本的基本命令是SECTIONS命令,它描述了输出文件的“映射图”:输出文件中各段、各文件怎么放置。一个SECTIONS命令内部包含一个或多个段,段(SECTIONS)是连接脚本的基本单元,它表示输入文件中的某部分怎么放置。

完整的连接脚本格式如下,它的核心部分是段(SECTIONS):

SECTIONS{

...........

secname start ALIGN(align)  (NOLOAD):AT(ldadr)

{ contents } >region :phdr=fill

...........

}

secname和contents是必须的,前者用来命名这个段,后者用来确定代码中的什么部分放在这个段中。

start是这个段的重定位地址,也称为运行地址。如果代码中有位置相关的指令,程序在运行时,这个段必须放在这个地址上。

ALIGN(align):虽然start指定了运行地址,但是仍可以指定对齐的要求,这个对齐的地址才是真正的运行地址。

(NOLOAD):用来告诉加载器,在运行时不用加载这个段。显然,这个选项只有在有操作系统的情况下才有意义。

AT(ldadr):指定这个段在编译出来的映像文件中的地址——加载地址。如果不使用这个选项,则加载地址等于运行地址。通过这个选项,可以控制各段分别保存输出文件中不同的位置,便于把文件保存到单板上:A段放在A处,B段放在B处,运行前再把A、B段分别读出来组装成一个完整的执行程序。

后面的三个选项在例子中没有使用到,所以不作介绍。

@$(LD) -Tbin.lds -o $(OBJ_DIR)/rom_elf  $(addprefix $(OBJ_DIR)/,$(notdir $^))

以上使用了连接脚本bin.lds来设置可执行文件rom_elf的地址信息,bin.lds的内容如下:

SECTIONS {

. = 0x00000000;

.init : AT(0){ /home/txgcwm/weidongshan/arm_sources/code/obj/2440start.o /home/txgcwm/weidongshan/arm_sources/code/obj/init.o /home/txgcwm/weidongshan/arm_sources/code/obj/nand.o}

. = 0x30000000;

.text : AT(4096) { *(.text) }

.rodata ALIGN(4) : AT((LOADADDR(.text)+SIZEOF(.text)+3)&~(0x03)) {*(.rodata*)}

.data ALIGN(4)   : AT((LOADADDR(.rodata)+SIZEOF(.rodata)+3)&~(0x03)) { *(.data) }

__bss_start = .;

.bss ALIGN(4)  : { *(.bss)  *(COMMON) }

__bss_end = .;

}

以上已经有了整体的介绍,下面介绍一下注意点:

a.第4行中的地址需要正确的填写,否则连接不能正常通过,或者生成的bin不能执行;

b.一般启动代码的加载地址为0(存在Nand flash上的地址)。从nand flash启动时,这些代码被复制到steppingstone后就可以直接运行了。arm的steppingstone只有4k,所以这部分代码我们要严格控制住;

c.第6、7行表示其余的代码的运行地址为0x30000000,加载的地址设为4096,表示代码将存在nand flash地址4096处;

d.(LOADADDR(...)表示某段的加载地址,SIZEOF(...)表示某段的大小。虽然前面指明了ALIGN(4)让它们的运行地址为4字节对齐,为了使各段之间加载地址的相对偏移值等于运行地址的相对偏移量,需要将AT(...)中的值也设为4字节对齐:先加上3,然后与~(0x03)进行与操作。

以上提到了下面这句话(通过这个选项,可以控制各段分别保存输出文件中不同的位置,便于把文件保存到单板上:A段放在A处,B段放在B处,运行前再把A、B段分别读出来组装成一个完整的执行程序),给出启动代码中例子,便于大家的理解,代码如下:

Reset:

ldr sp, =4096           @ 设置栈指针,以下都是C函数,调用前需要设好栈

bl  disable_watch_dog   @ 关闭WATCHDOG,否则CPU会不断重启

bl  clock_init          @ 设置MPLL,改变FCLK、HCLK、PCLK

bl  memsetup            @ 设置存储控制器以使用SDRAM

bl  s3c2440_nand_init

ldr r0, =0x30000000         @ 1. 目标地址 = 0x30000000,这是SDRAM的起始地址

mov r1, #4096                   @ 2. 源地址         = 4096,运行地址在SDRAM中的代码保存在NAND Flash 4096地址开始处

mov r2, #16*1024            @ 3. 复制长度 = 16K,对于本实验,这是足够了

bl  CopyCode2SDRAM           @ 调用C函数CopyCode2SDRAM

bl  clean_bss                   @ 清除bss段,未初始化或初值为0的全局/静态变量保存在bss段

因为前4k,硬件会完成自动的搬运,不需要我们考虑。请留意代码中的这两个值(0x30000000和4096),就是我们连接脚本中提到的!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值