基础笔记-5 ld链接控制脚本

参考资料:
<<程序员的自我修养–链接,装载与库>>

1 常用参数

各个链接器平台的链接控制过程各不相同,这里介绍的为ld。

  • -static
    表示使用静态链接方式来链接程序,而不是用默认的动态链接的方式。

  • -e
    指定该程序的入口函数。

  • -o
    指定输出文件名。

  • -T
    指定链接控制脚本。

  • -Tbss
    -Tbss ADDRESS,设置.bss section地址。

  • -Tdata
    -Tdata ADDRESS,设置.data section地址。

  • -Ttext
    -Ttext ADDRESS,设置.text section地址。

2 链接控制脚本

链接器一般都提供多种控制整个链接过程的方法,以产生用户所需的文件,一般有如下三种方法:

  1. 使用命令行给链接器指定参数,如 -e指定入口函数。
  2. 将链接指令存放在目标文件里,编译器经常会通过这种方法给链接器传递指令。
  3. 使用链接控制脚本,这种比较灵活和强大,使用-T指定脚本。

无论是输入文件还是输出文件,它们的主要数据就是文件中的各种section,我们把输入文件中的section称为input sections(输入段),输出文件中的section称为output sections(输出段)。简单来说,控制链接过程无非就是控制输入段如何变成输出段,如哪些section要丢弃,合并的顺序等。

3 链接控制脚本语言

链接控制脚本是用特殊的语言写成的,并不复杂,只有为数不多的几种操作。

3.1 语法介绍

ld链接器的链接脚本语法继承于AT&T链接器命令语言的语法。链接脚本由一系列语句组成,语句分两种,一种是命令语句、另一种是赋值语句。

语句之间用";“作为分割符,命令语句可以用换行来结束该语句。赋值语句只能用”;"结尾。
表达式与运算符可以使用C语言类似的表达式和运算操作符.如:+,-,*,/,+=,>>,<<,|,&等。注释和字符引用 使用/**/作为注释。

3.2 常用的命令语句

  • ENTRY(symbol)
    指定符号symbol的值为入口地址(Entry Point),ld有多种方法可以设置入口地址,它们之间的优先级顺序如下:
  1. ld -e参数,优先级最高。
  2. 链接脚本里的ENTRY(symbol)命令。
  3. 如果定义了_start符号,则使用_start。
  4. 如果存在.text section,则使用.text section的第一个字节地址。
  5. 使用值0。
  • STARTUP(filename)
    将文件filename作为链接过程的第一个输入文件,输入文件顺序不同会生成不同的输出文件。(运行地址和section偏移可能不一样)。

  • SEARCH_DIR(path)
    将路径path加入到ld链接器的库查找目录。跟"-Lpath"差不多。

  • INPUT(file, file)
    将指定文件作为链接过程的输入文件。

  • INCLUDE(filename)
    指定的文件包含进链接脚本。

  • OUTPUT_FORMAT(default,big,little)
    定义三种输出文件的格式(大小端)。

  • OUTPUT_ARCH(bfdarch)
    设置输出文件的体系结构,BFDARCH为被BFD库使用的名字之一。

  • SECTIONS
    {

    secname : { contents }

    }
    secname表示输出段的段名,secname后面必须有一个空格,防止输出section有歧义。
    contents中可以包含若干个条件,每个条件之间用空格隔开,如果输入段符合这些条件中的任意一个即表示这个输入段符contents规则。条件写法如下:
    filename(sections)
    filename表示输入文件字,sections表示输入段名。例如:

  • file1.o(.data)
    表示输入文件中名为file.o的文件中名为.data的section符合条件。

  • file1.o(.data .rodata)
    表示输入文件中名为file.o的文件中名为.data或.rodata的section符合条件。

  • file1.o
    如果直接指定文件名而忽略后面的小括号和section名,则表示file1.o的所有section都符合条件。

  • (.data)
    所有输入文件中的名为.data的section的文件符合条件。*是通配符

链接脚本以hi3516dv300的u-boot.lds为例,这里就不具体分析了。

$cat u-boot.lds

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
	. = 0x80700000;	/*将当前地址设置为0x80700000*/
	__image_copy_start =.;	/*__image_copy_start = 0x80700000*/
	. = ALIGN(4);	/*对当前地址进行4字节对齐*/
	.text	:	/*.text section*/
	{
        __text_start = .;
		start.o (.text*)	/*start.o中的.text* section放在放在开头地址*/
		init_registers.o (.text*) /*由于生成的是.bin镜像,不是elf文件,所以必须是start.o放在开始地址*/
		lowlevel_init_v300.o (.text*)
		ddr_training_impl.o (.text*)
		ddr_training_console.o (.text*)
		ddr_training_ctl.o (.text*)
		ddr_training_boot.o (.text*)
		ddr_training_custom.o (.text*)
		uart.o (.text*)
		div0.o (.text*)
		emmc_boot.o (.text*)
		image_data.o (.text*)
        	startup.o(.text*)
        	reset.o(.text*)
        __init_end = .;
        ASSERT(((__init_end - __text_start) < 0x6000), "init sections too big!");
		*(.text*)
	}
	__text_end = .;

	. = ALIGN(4);
	.image : { *(.image) }

	. = ALIGN(4);
	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }

	. = ALIGN(4);
	.data : { *(.data) }

	. = ALIGN(4);
	.got : { *(.got) }

	. = ALIGN(4);
	__image_copy_end =.;
	__bss_start = .;
	.bss : { *(.bss) }
	__bss_end = .;
	_end = .;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值