Linker Scripts3--链接脚本概述
1.前言
本文主要翻译了The Link Script英文文献。
(1)每个链接都是由链接脚本控制,链接脚本是用链接命令语言写的;
(2)链接脚本的主要目的是描述输入文件的sections如何映射到输出文件的sections,并控制输出文件的内存分布;
(3)必要时,链接脚本会指导连接器执行很多其它操作;
(4)链接器总是使用一个链接脚本,如果不能自行提供链接脚本,则使用默认的链接脚本;
(5)可以使用ld --verbose命令行选项来查看默认的链接脚本,选项-r和-N可以影响默认的连接脚本;
(6)-T选项用以指定自己的链接脚本, 它将代替默认的连接脚本
2.基本的链接脚本概念
- 链接器
把一个或多个输入文件合成一个输出文件.
- 输入文件
目标文件或链接脚本文件.
- 输出文件
目标文件或可执行文件
- 目标文件(包括可执行文件)
具有固定的格式, 在UNIX或GNU/Linux平台下, 一般为ELF格式. 若想了解更多, 可参考 UNIX/Linux平台可执行文件格式分析
- 输入section和输出section
有时把输入文件内的section称为输入section(input section), 把输出文件内的section称为输出section(output sectin)
- section
目标文件的每个section至少包含两个信息: 名字和大小,大部分section还包含与它相关联的一块数据, 称为section contents(section内容)
- loadable section
一个section可被标记为“loadable(可加载的),意思是输出文件运行时可以将section的内容加载到memory
- allocatable
内容为空的section可被标记为alocatable“可分配的”. 在输出文件运行时, 在进程地址空间中空出大小同section指定大小的部分.
某些情况下, 这块内存必须被置零.
注:如果一个section不是“可加载的”或“可分配的”, 那么该section通常包含了调试信息. 可用objdump -h命令查看相关信息.
- VMA和LMA
每个loadable或allocatable的输出section有两个地址。VMA和LMA
(1)VMA(virtual memory address): VMA是执行输出文件时section所在的地址
(2)LMA(Load Memory Address):LMA是加载输出文件时section所在的地址
(3)通常VMA和LMA是相同的
(4)两者不同的情况
比如将输出文件加载到开发板的flash中(由LMA指定), 而在运行时将位于flash中的输出文件复制到SDRAM中(由VMA指定).
(5)可以使用objdump -h选项来查看VMA和LMA
(6)VMA和LMA举例1
.data section对应的VMA地址是0×08050000, 该section内包含了3个32位全局变量, i、j和k, 分别为1,2,3.
.text section内包含由”printf( “j=%d “, j );”程序片段产生的代码.
连接时指定.data section的VMA为0×08050000, 产生的printf指令是将地址为0×08050004处的4字节内容作为一个整数打印出来。
如果.data section的LMA为0×08050000,显然结果是j=2
如果.data section的LMA为0×08050004,显然结果是j=1
(7)VMA和LMA举例2
.text section内容的开始处包含如下两条指令(intel i386指令是10字节,每行对应5字节):
jmp 0×08048285
movl $0×1,%eax
如果.text section的LMA为0×08048280, 那么在进程地址空间内0×08048280处为“jmp 0×08048285”指令, 0×08048285处为movl $0×1,%eax指令.
假设某指令跳转到地址0×08048280, 显然它的执行将导致%eax寄存器被赋值为1.
如果.text section的LMA为0×08048285, 那么在进程地址空间内0×08048285处为“jmp 0×08048285”指令, 0×0804828a处为movl $0×1,%eax指令.
假设某指令跳转到地址0×08048285, 显然它的执行又跳转到进程地址空间内0×08048285处, 造成死循环.
- 符号表
每个目标文件都有一系列符号,被称作符号表。一个符号可以被定义也可以没有定义
每个符号都有一个名字,被定义的符号都有一个地址,还包含一些其它信息
每个目标文件都有符号表(SYMBOL TABLE), 包含已定义的符号(对应全局变量和static变量和定义的函数的名字)和未定义符号(未定义的函数的名字和引用但没定义的符号)信息.
每个符号对应一个地址, 即符号值(这与c程序内变量的值不一样, 某种情况下可以把它看成变量的地址).可以使用nm命令或objdump -t来查看符号表
3. 链接脚本格式
(1)链接脚本是文本文件。
(2)链接脚本由一系列命令组成, 每个命令由一个关键字(一般在其后紧跟相关参数)或对符号的赋值语句组成.
(3)命令由分号‘;’分隔开.空格被忽略
(4)文件名或格式名可以直接输入,如果文件名内包含分号’,'或其他分隔符, 则要用引号‘”’将名字全称引用起来.
(5)不能在文件名里使用双引号
(5)/* */之间的是注释。
4. 简单的链接脚本举例
(1)很多链接脚本是很简单的。最简单的链接脚本只有一个命令:SECTIONS,使用SECTIONS命令来描述输出文件的内存布局。
(2)SECTIONS命令是一个很强大的命令,这里我们将描述它的一个简单应用。
(3)假设程序只包含了code,initialized data和uninitialized data,这些将分别放在.text .data .bss三个 sections,进一步假设你的程序中就包含如上这个几个sections
假定code加载地址为0x10000,数据的开始地址为0x8000000,如下是一个链接脚本:
SECTIONS
{
. = 0x10000;
.text : { *(.text) }
. = 0x8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}
对如上例子的解释:
(1)SECTIONS命令采用 'SECTIONS' 关键字,后跟一串符号定义和输出section描述,用"{}"包起来;
(2)上例SECTIONS命令的第一行,设置了特殊符号“.”的值,“.”称为定位符。
注:[1]如果没有采用其它方式为输出section指定地址,则输出section的地址就是定位符的当前值
[2]定位符随后会增加输出section的大小
[3]在SECTIONS命令的开始定位符的值为0
(3)上例SECTIONS命令的第二行,定义了输出section .text,":"是必需的
输出section名后的"{}"里列出了输入section,这些输入section会放到输出section,"*"表示所有输入文件名,‘*(.text)’ 表示所有输入文件的'.text'输入section
‘.text’输出section被定义时,定位符是0x10000,链接器将在输出文件中将'.text'输出section的地址设为0x10000
(4)上例剩下的行定义了输出文件的.data section和.bss section
链接器将把.data 输出section放在输出文件的0x8000000位置,之后定位符将被设置为 0x8000000+.data section的大小
链接器将把.bss输出section放在输出文件的 0x8000000+.data section的大小 的位置
(5)链接器要保证每个输出section符合地址对齐,如果需要的话会增加定位符的值
本例中.text section和.data section符合对齐要求,.bss section 可能为了对齐会增加定位符的值,因此.data section和.bss section之间会有一个gap
5. 参考文献
[1] The GNU LInker.pdf
Linker Scripts3--链接脚本概述的更多相关文章
- Linker Scripts3--简单的链接脚本命令2-Assigning Values to Symbols
1.前言 本章继续讲述简单脚本命令的后半部分 2.Assigning Values to Symbols 你可以给一个符号(symbol)赋值,它会把这些定义的符号放入全局符号表(symbols ta ...
- Linker Scripts3--简单的链接脚本命令1
1.前言 这个部分我们描述了简单的链接脚本命令 2.设置entry point 程序中第一条运行的指令被称为入口点entry point,可以使用ENTRY链接脚本命令设置entry point,参数 ...
- 链接脚本(Linker Script)用法解析(一) 关键字SECTIONS与MEMORY
1.MEMORY关键字用于描述一个MCU ROM和RAM的内存地址分布(Memory Map),MEMORY中所做的内存描述主要用于SECTIONS中LMA和VMA的定义. 2.SECTIONS关键字 ...
- 链接脚本(Linker Script)应用实例(一)使用copy table将函数载入到RAM中运行
将函数载入到RAM中运行需要以下三个步骤: (1)用编译器命令#pragma section "<section name>" <user functions&g ...
- 链接脚本(Linker Script)用法解析(二) clear_table & copy_table
可执行文件中的.bss段和.data段分别存放未赋初值的全局变量和已赋初值的全局变量,两者的特点分别为: (1).bss段:①无初值,所以不占ROM空间:②运行时存储于RAM:③默认初值为0 (2). ...
- GNU linker script,ld script,GNU链接脚本
https://blog.csdn.net/itxiebo/article/details/50937412 https://blog.csdn.net/itxiebo/article/details ...
- [转]Linux下的lds链接脚本详解
转载自:http://linux.chinaunix.net/techdoc/beginner/2009/08/12/1129972.shtml 一. 概论 每一个链接过程都由链接脚本(lin ...
- Linux下的lds链接脚本基础
转载:http://soft.chinabyte.com/os/104/12255104.shtml 今天在看uboot引导Linux部分,发现要对链接脚本深入了解,才能知道各个目标文件的内存分布 ...
- Linux下的lds链接脚本简介
转载:http://hubingforever.blog.163.com/blog/static/171040579201192472552886/ 一. 概论 每一个链接过程都由链接脚本(lin ...
随机推荐
- Java案例整理
1.随机点名器案例 1.1 案例介绍 随机点名器,即在全班同学中随机的找出一名同学,打印这名同学的个人信息. 此案例在我们昨天课程学习中,已经介绍,现在我们要做的是对原有的案例进行升级,使用 ...
- python中import问题
https://blog.csdn.net/aspenstars/article/details/69605318 Python包含子目录中的模块方法比较简单,关键是能够在sys.path里面找到通向 ...
- 6-(基础入门篇)学会编译lua固件,固件的合成
http://www.cnblogs.com/yangfengwu/p/9336274.html 基础教程源码链接请在淘宝介绍中下载,由于链接很容易失效,如果失效请联系卖家,谢谢 https://it ...
- Hadoop生态圈-Ranger数据安全管理框架
Hadoop生态圈-Ranger数据安全管理框架 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Ranger简介 Apache Ranger是一款被设计成全面掌握Hadoop生 ...
- dubbo基础
一.什么是dubbo,有什么用 dubbo是阿里巴巴开源的一个RPC框架,用于多个应用相互通信.使用dubbo需要安装一zookepper 二.dubbo的基本使用 1.构建一个maven的多模块项目 ...
- Dubbo优雅关机原理
Dubbo是通过JDK的ShutdownHook来完成优雅停机的 所以如果用户使用 kill -9 PID 等强制关闭命令,是不会执行优雅停机的 只有通过 kill PID时,才会执行 原理: · 服 ...
- Linux记录-使用python临时搭建web服务器
python2: python -m SimpleHTTPServer 8888 python3: python -m http.server 8888 wget ip:8888/文件
- layui(六)——upload组件常见用法总结
layui中提供了非常简单的文件上传组件,这里写了一个上传图片的栗子,上传成功后返回图片在服务器的路径,并设置为页面中img的src属性.因为上传十分简单,没什么可说的,就直接上代码了. html代码 ...
- Golang入门教程(六)关键字和数据类型
在 Go 编程语言中,数据类型用于声明函数和变量. 数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存. 一.25个关键字 二.18 ...
- java枚举(enum)
1. 创建枚举类型要使用 enum 关键字,隐含了所创建的类型都是 java.lang.Enum (抽象类) 类的子类. enum AccountType { SAVING, FIXED, CURRE ...