Linux下连接脚本lds的一点总结(转载部分)

 

  近期在翻看嵌入式应用开发完全手册中MMU一章中,有一段Makefile代码中使用了lds文件,其Makefile和lds脚本代码分别如下:

objs := head.o init.o leds.o

mmu_bin:$(objs)
	arm-linux-ld -Tmmu.lds -o mmu_elf $^
	arm-linux-objcopy -O binary -S mmu_elf $@
	arm-linux-objdump -D -m arm mmu_elf > mmu_dis
	
%.o:%.c
		arm-linux-gcc -Wall -O2 -c -o $@ $<
%.o:%.S
		arm-linux-gcc -Wall -O2 -c -o $@ $<
clean:
	rm -f mmu_bin mmu_elf mmu_dis *.o
SECTIONS{
	first	0x0000000 : {head.o init.o}
	second	0xB0004000 : AT(2048) { leds.o }	
}

 其中Makefile的语法主要是几个自动变量,$@表示规则的目标文件,$^ 表示所有依赖的名字,名字之间用空格隔开,$< 表示第一个依赖的文件名,% 是通配符,可以和一个字符串中任意个数的字符相匹配。Makefile的语法准备总结下写个博文方便下次复习。

lds脚本的分析有篇博文跟我这个很相似,我就改改拿来用了。

SECTIONS { ... }                  用来描述输出文件的内存布局。

这个脚本里规定了两个段,firtst和cecond

0x00000000   0xB0004000   

表示链接地址或运行地址,指程序在SRAM、SDRAM实际运行的地址,也就是使PC等于这个地址。

这里指head.o init.o 的加载地址为0,运行地址在0x00000000,leds.o运行地址在0xb0004000

AT(2048)                               

表示加载地址或存储地址,指程序编译后存放的地址,一般存在ROM、FLASH中,也就是运行这个指令时,会先将2048地址~(2048+2048)地址处的内容复制到0xb0004000处运行(因为已经初始化了SDRAM以及Nand Flash)。

这里指main.o的加载地址为Nand Flash里的地址2048,运行地址在SDRAM里的地址0xb0004000。

知其然也要知其所以然,所以总结下lds脚本的语法还是很有必要的。

有不少博客都有其详解,以下是我觉得不错的:

https://www.cnblogs.com/li-hao/p/4107964.html

http://blog.chinaunix.net/uid-28732854-id-3899215.html

第一篇博文太过详细,简直无法下手,第二篇很简略,说出本质

一个可执行程序通常是由:代码段,数据段,bss段构成的。同样,在用于链接这个程序的链接器脚本中,就会反应出这几个段的信息。

1>创建链接器脚本-段信息

2>设置起始链接地址

3>对齐设置

4>使用变量

5>设置代码段首文件

下面两段代码是从上面两篇博文中摘取下来的,帮助理解:

SECTIONS {
	. = 0x50008000   //设置起始链接地址
	. = ALIGN(4);	//字节对齐设置
	.text :
	{
		start.o (.text)  /*设置代码段的首文件*/
		*(.text) //所有文件的代码段
	}
	. = ALIGN(4); //字节对齐设置
	.data :
	{
		*(.data) //所有文件的数据段
	}
	. = ALIGN(4); //字节对齐设置
		bss_start = . ;//变量的使用
	.bss :
	{
		*(.bss) //所有文件bss段
	}
	bss_end = .;  //变量的使用
}
OUTPUT_ARCH(arm)                                //设置输出文件的体系架构。
ENTRY(_start)                                   //将_start这个全局符号设置成入口地址。
SECTIONS                                        //输出文件内容布局
{
    . = 0x00000000;                            //指定地址0x00000000
 
    . = ALIGN(4);                             //代码以4字节对齐
    .text      :                                //指定.text section段(位于0x00000000)   
    {
      cpu/arm920t/start.o   (.text)          //添加第一个目标文件: cpu/arm920t/start.o里面的.text代码段
          board/100ask24x0/boot_init.o (.text)   //添加第二个目标文件: board/100ask24x0/boot_init.o里面的.text代码段
      *(.text)                               // *(.text) 表示添加剩下的全部文件的.text代码段
    }
 
    . = ALIGN(4);
    .rodata : { *(.rodata) }        //指定.rodata section段(位于0x00000000+.text section),将所有的.rodata只读数据段合并成一个.rodata只读数据段 
 
    . = ALIGN(4);
    .data : { *(.data) }            //指定读写数据段,     *(data):添加所有文件的数据段
 
    . = ALIGN(4);
    .got : { *(.got) }              //指定got段,got段是uboot自定义的一个段
 
    . = .;
    __u_boot_cmd_start = .;            //把__u_boot_cmd_start赋值为当前位置, 即起始位置
    .u_boot_cmd : { *(.u_boot_cmd) }   // u_boot_cmd段,所有的u-boot命令相关的定义都放在这个位置
    __u_boot_cmd_end = .;              //  u_boot_cmd段结束位置
 
    . = ALIGN(4);
    __bss_start = .;                   //把__bss_start赋值为当前位置,即bss段的开始位置
    .bss : { *(.bss) }                 //指定bss段,这里NOLOAD的意思是这段不需装载,仅在执行域中才会有这段
    _end = .;                          //把_end赋值为当前位置,即bss段的结束位置
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值