网站备案是否收费标准,网站建设公司利润,北京城建建设工程有限公司网站,做网站优化的公司0. 前言
每一个链接都是由链接脚本控制的#xff0c;链接脚本是用链接命令语言编写的脚本。链接都会用到一个链接脚本#xff0c;如果你没有指定自己的脚本#xff0c;就会使用默认的链接脚本。可以用 --verbose 命令行选项显示默认的连接脚本。指定命令行参数…0. 前言
每一个链接都是由链接脚本控制的链接脚本是用链接命令语言编写的脚本。链接都会用到一个链接脚本如果你没有指定自己的脚本就会使用默认的链接脚本。可以用 --verbose 命令行选项显示默认的连接脚本。指定命令行参数比如 -r、-N都会影响默认的链接脚本。也可以用 -T 来指定自己的链接脚本也可以隐式地把自己的连接脚本当成链接输入文件就像普通的链接文件一 样参见链接文件说明。 如上图链接器是将多个对象文件链接成可执行程序。
链接器输入文件目标文件或链接脚本文件
链接器输出文件可执行文件
目标文件(包括可执行文件) 具有固定的格式在 Unix 或GNU/linux 平台下一般为 ELF 格式。 1. 链接器脚本
链接器是由链接器脚本控制该链接器脚本控制输入文件的链接方式。该脚本以连接器命令语言编写控制一下链接属性
输入文件中的部分如何映射到输出文件输出文件的文件格式和内存布局已创建段的运行时加载属性代码执行入口点共享库版本
链接器有一个内置脚本它用作将代码和数据分配到内存的默认链接器脚本。用户不能修改默认脚本但是它可以通过两种方式进行更改
它可以完全由用户定义的脚本文件替换。在这种情况下文件名在链接器命令行上指定为链接器选项 -T 的参数可以通过将链接器命令上的用户定义脚本文件指定为普通链接器输入文件来扩充它
指定为普通链接器输入文件的脚本称为隐式脚本。因为它们扩充了默认链接描述文件所以隐式脚本通常只包含 symbol assignments(符号分配) 或INPUT、GROUP、VERSION 命令。 2. 基础知识
2.1 分号
在连接器脚本中分号通常仅出于美观用作分隔符否则将被忽略。但一下地方是必需的
分号必需出现在 symbol assignments 的末尾分号必需出现在 PHDRS 命令的末尾 2.2 注释
可以使用标准 C 分隔符将注释包含在链接描述文件中
/* ... */ 2.3 字符串
文件或格式名称等字符串通常可以直接输入无需分隔符。
如果文件名包含逗号等字符否则该字符将用于分隔文件名则文件名可以用双引号引起来。 文件名中不能使用双引号字符。 2.4 表达式
许多命令参数接受算术表达式。 表达式的语法与 C 中的表达式语法相同具有以下特点
所有表达式都被计算为 long 或 unsigned long 类型的整数所有常量都是整数提供所有 C 算术运算符可以定义、创建和引用全局变量支持多种预定义功能 2.5 位置计数器
链接器中有个特殊变量点号 .
点号始终包含当前输出位置计数器由于 点号 始终引入输出节中的位置它必须始终出现在 SECTIONS 命令中的表达式中。
点号 可以出现在表达式中允许使用普通符号的任何位置但它的赋值有副作用。 3. 脚本命令
3.1 指定入口地址命令
程序运行的第一条指令就是调用入口地址可以使用 ENTRY 链接命令来指定程序的入口地址。
入口地址的指定方式有
通过命令行指定gcc -e symbol链接脚本指定ENTRY(symbol) 4. 文件处理命令
4.1 INCLUDE
使用 INCLUDE 将其他链接脚本包含到当前脚本链接器会在当前目录和用 -L 参数指定过的目录下查找被包含的文件。
链接脚本可以嵌套包含最多层数为 10 层。
INCLUDE 既可以放在链接脚本的开始也可以放在 MEMROY 或 SECTIONS 命令里面或放在输出节的描述里面。 格式INCLUDE filename功能包含其他脚本文件。搜索路径当前目录、-L添加的目录。放置位置链接脚本开始、MEMORY或SECTIONS中、输出节描述中。 4.2 INPUT
INPUT 命令直接链接指定的文件名就像从命令行输入一样。
例如如果要包含subr.o 但是又不想在每一条链接命令中都写上的话就可以在链接脚本中使用 ‘INPUT(subr.o)’。实际上还可以把所有输入文件 (*.o) 都写在链接脚本里面然后只要用 -T 指定一下链接脚本就好了。
为了防止设置了根目录文件名要用/开始这样连接脚本就会从根目录开始检索文件否则链接器就会在当前目录下查找文件如果找不到文件链接器就会在所有归档库里面检索。根目录也可以在文件名一开始的时候用 ‘’ 来强制指定或者在文件名前面加上 $SYSROOT。
如果使用 ‘INPUT (-lfile)’链接器会自动翻译成libfile.a就好像使用命令行参数 -l 一样。如果使用INPUT命令在链接脚本中包含文件的话文件会从链接脚本所在的目录开始检索。这会影响到归档文件的检索。 格式 INPUT(file, file, …) INPUT(file file …)功能指定要链接的输入文件(.o,.a)。 搜索路径$SYSROOT、当前目录。 subr.o包含INPUT(subr.o) libfile.a包含INPUT(-lfile) 4.3 GROUP
格式
GROUP(file, file, …)
GROUP(file file …)
GROUP命令语法跟 INPUT 差不多但是专门用来指定归档文件 (*.a)这个会不断的检索直到发现一个新的未定义的符号引用。参见命令行参数里面关于 -( 的描述。 4.4 OUTPUT
OUTPUT用来设置输出文件的名称等价的命令行参数为-o filename。默认输出文件名称为a.out。
格式OUTPUT(filename)功能设置输出文件名称。 等价命令行参数-o filename 4.5 SEARCH_DIR
SEARCH_DIR命令用来添加链接器的搜索路径等价的命令行参数是 -L path。
如果即用了 -L 也用了SEARCH_DIR那么链接器会优先使用 -L 设置的路径。 格式SEARCH_DIR(path)功能添加链接器的搜索路径。 等价命令行参数-L path 4.6 STARTUP
STARTUP命令用来指定第一个被链接的输入文件等价于命令行中第一个输入文件当目标操作系统的要求程序入口地址必须位于第一个输入文件的时候使用。 格式STARTUP(filename)功能指定第一个被链接的输入文件。使用场景目标操作系统的要求程序入口地址必须位于第一个输入文件的时候。 5. 输出文件格式命令
5.1 OUTPUT_FORMAT
OUTPUT_FORMAT命令用来设置输出文件使用的BFD格式。等价的命令行参数为 --oformat bfdname。命令行参数优先。
OUTPUT_FORMAT可以设置三个格式当命令行没有 -EB 和 -EL的时候使用第一个格式当有-EB的时候使用第二个参数当有 -EL 的时候使用第三个参数。 格式 OUTPUT_FORMAT(bfdname) OUTPUT_FORMAT(default, big, little)功能设置输出文件使用的BFD格式。 等价命令行--oformat bfdname 5.2 TARGET
TARGET命令用来设置链接器读取输入文件的时候使用的BFD格式。等价命令行参数 -b bfdname。
格式 TARGET(bfdname) 6. 其他命令 7. 符号赋值
7.1 像C 一样简单的赋值
symbol expression ;
symbol expression ;
symbol - expression ;
symbol * expression ;
symbol / expression ;
symbol expression ;
symbol expression ;
symbol expression ;
symbol | expression ;
符号被定义为在脚本中具有全局范围
符号赋值语句在两方面与链接器脚本表达式中使用运算符不同
赋值只能在表达式的根部进行例如 a b3; 是允许的但 ab3; 是一个错误赋值语句必须以尾部分号结束
赋值语句可以出现在下面位置
作为链接器脚本中的独立命令作为 SECTIONS 命令中的独立语句作为 SECTIONS 命令中某一节定义内容的一部分 7.2 HIDDEN
格式
HIDDEN(symbol expression) 定义成 HIDDEN 的符号不会被输出到目标文件如
HIDDEN(floating_point 0);
SECTIONS
{.text :{*(.text)HIDDEN(_etext .);}HIDDEN(_bdata (. 3) ~ 3);.data : { *(.data) }
} 7.3 PROVIDE
格式
PROVIDE(symbol expression) 定义一个输入文件里面引用但未定义的符号如
SECTIONS
{.text :{*(.text)_etext .;PROVIDE(etext .);}
}
_etext 可以在输入文件中引用如果输入文件中也定义了 _etext那么优先使用输入文件中的但是如果输入文件中定义了_etext链接的时候就会报多重定义的错误。 7.4 PROVIDE_HIDDEN
跟 PROVIDE 功能类似但不会输出到目标文件中。 8. SECTIONS 命令
SECTIONS
{sections-commandsections-command…
}
在一个脚本文件中只能声明一条 SECTIONS 命令但是该命令可以包含任意数量的语句来指定必要的映射和放置信息。 每一个SECTIONS 的组成都有
ENTRY 命令符号排列输出section 的描述覆盖描述
如果链接文件中没有定义SECTIONS那么输入文件中的节就会原封不动的输出到目标文件中。 8.1 输出section 描述
SECTIONS命令中最常用的语句是输出部分描述它指定了输出部分的属性它的位置、对齐方式、内容、填充模式和目标内存区域。 格式
section [address] [(type)] :[AT(lma)][ALIGN(section_align) | ALIGN_WITH_INPUT][SUBALIGN(subsection_align)][constraint]{output-section-commandoutput-section-command…} [region] [ATlma_region] [:phdr :phdr …] [fillexp] [,]
一个输出section 的名称可以由任何字符序列组成section 名称声明周围需要留白以确保名称的明确性输出section 名称后面冒号 : 和 { } 是必需的 ALIGN 强制输出section地址对齐SUBALIGN 强制输入section 地址对齐一个输出section 的描述由一个或多个语句组成包括 符号分配输入section 描述直接包含是输出section 的数据特殊的输出section 关键字 8.2 输入 section 描述
输入section 的描述指定了被映射到输出section 的输入部分。
*(.init.rodata .init.rodata.*)
这里使用了通配符表示输入部分为
* 代表所有目标文件后面括号是指.init.rodata 段 和 .init.rodata.* 段
这句话意思是将所有目标文件中的 .init.rodata 段和 .init.rodata.* 段都包含到输出 section 中。 8.2.1 输入 section 描述的通配符
* 号任意数量的字符
? 号任何单个字符
[CHARS] 号匹配任意一个CHARS内的单个字符可用 - 号表示范围。例如[ A-Z ]表示匹配 A~Z之间的单个字符 8.2.2 KEEP
KEEP(*(.initcallearly.init))
当链接命令行使用选项 --gc-secionts 后链接器可能将某些它认为没用的 section 过滤掉。
KEEP 用来强制链接器保留一些特定的 section。
例如上面代码其实可以看成
*(.initcallearly.init)
加上KEEP则要求链接器不能优化掉这个section哪怕是没用。 参考
https://blog.csdn.net/shenjin_s/article/details/88712249
https://zhuanlan.zhihu.com/p/516338675