link链接脚本

1. 链接脚本的作用是什么?

简单的说法:链接脚本是一个规则文件,用来指导链接器工作。
正规的说法:链接脚本描述如何将输入文件中的各个程序段(英文section)映射到输出文件中,并控制输出文件的内存布局。

通俗的理解:每个.o文件一般包含着若干个程序段,比如数据段、代码段等。如果某个工程编译得到很多.o文件,则会有非常多的程序段。如果想将它们组合成一个可执行程序,就要考虑这些段应该放在什么位置,前后顺序是怎样的。链接脚本就是一个描述如何放置程序段的规则文件,链接器会根据这些规则,合理安排每个程序段的位置,将其链接成一个可执行程序。

2. 用什么语言编写链接脚本?

用链接器命令语言编写。

3. 默认的链接脚本是怎样的?

链接器总是使用链接脚本。
你没有提供自定义的链接脚本,则链接器将使用一个默认的链接脚本,可以使用“ld --verbose”命令来显示这个链接脚本的内容。
如果你要使用自定义的链接脚本,可以使用“-T scriptName”指定链接脚本为scriptName。此时指定的链接脚本将替换默认的链接脚本。

4. 链接脚本的语法

一个简单的链接脚本内容如下(只有SECTIONS命令,该命令描述l输出文件的内存布局),它由链接地址与程序段组成。

SECTIONS  //SECTIONS{},这个表示整个链接脚本。
{    
    //点号表示当前地址,因为接下来就是文本段,所以它是文本段的链接地址
	. = 0xd0024000; 
	
    //段名为.text,即文本段
	.text : {   //冒号是语法要求必需的
		start.o  (.text) //表示start.o中的代码段是代码段的第一个段
		* (.text)//*是一个通配符,可以匹配任何文件名。表达式*(.text)表示所有输入文件的.text段
	}
    //段名为.data,即数据段
	   .data : {
		* (.data)
	}
	   bss_start = .; //标号bss_start指向bss段的开始位置
    //段名为.bss,即bss段
	.bss : {
		* (.bss)
	}
	bss_end  = .;//标号bss_end指向bss段的结束位置
}

4.1 链接地址

在程序编译的时候,每个目标文件都是由源代码编译得到,最终多个目标文件链接生成一个可执行文件,而链接地址就是告知链接器,各个目标文件在可执行程序中的位置。比如,一个可执行程序a.out由a.o、b.o、c.o组成,那么最终的a.out中谁在前谁在中间谁在结尾,都可以通过制定链接地址来决定。链接地址是静态的,在进行程序编译的时候指定的。

P.S.上面这段话感觉是链接脚本的含义,而不是链接地址的含义。我理解的链接地址,指的是可执行文件将来要下载到哪个地址;链接地址在链接脚本中只定义一次,即链接脚本开头的第一句代码“ . = 0xd0024000; ”。但实际学习下来,好像上面这段话是对的。

4.2 程序段

程序段,是指程序的某部分。整个程序可以分为许多程序段,我们给这些程序段起名字,方便在链接的时候用段名来指代这些段,从而让这些程序段位于合适的位置。
程序段分为以下几种:代码段(.text)、数据段(.data)、bss段(ZI段)、自定义段。其中代码段(.text)、数据段(.data)、bss段(ZI段)这些段名是编译器链接器内部定好的。程序员也可以自己给某些段起名字,这些段就称为自定义段。

**代码段:**也叫文本段,用符号“.text”表示。它其实就是函数编译后生成的东西。
**数据段:**用符号“.data”表示,它其实就是C语言中有显式初始化为非0的全局变量。
**bss 段:**也叫ZI段,即零初始化段,用符号“.bss”表示。它对应C语言中初始化为0(或者没有显式初始化)的全局变量。
**自定义段:**段名由程序员自己定义,段的属性和特征也由程序员自己定义。

4.3 扩展说明

【1】C语言中全局变量如果未显式初始化则其值为何是0?
本质就是C语言把这类全局变量放在了bss段,从而保证其值为0。

【2】如何保证显式初始化为非0的全局变量的值在main之前就被赋值了?
编译器与链接器这类变量放在.data段中,而.data段会在main执行之前被处理(初始化)。

4.4 语法补充

命令用分号隔开。
空格将被忽略。
可以添加注释,方法与C中一样。
点号,是位置计数器,表示当前地址,然后按输出节的大小递增。

你可能感兴趣的:(编译链接,c语言)