Linker Scripts3--简单的链接脚本命令1
1.前言
这个部分我们描述了简单的链接脚本命令
2.设置entry point
程序中第一条运行的指令被称为入口点entry point,可以使用ENTRY链接脚本命令设置entry point,参数是一个符号名:
ENTRY(symbol)
有几种方法可以设置entry point,链接器会按照如下的顺序来try各种方法,只要任何一种方法成功则会停止:
- the ‘-e’ entry command-line option;
 - the ENTRY(symbol) command in a linker script;
 - the value of the symbol start, if defined;
 - the address of the first byte of the ‘.text’ section, if present;
 - The address 0
 
3.Commands Dealing with Files
有几种处理文件的链接脚本命令:
- INCLUDE filename:这里包含了链接脚本文件名
 
这个文件会在当前目录搜索,或者在"-L"指定的目录搜索,可以嵌套调用INCLUDE达10级
即: 文件1内INCLUDE文件2, 文件2内INCLUDE文件3… , 文件10内INCLUDE文件11. 那么文件11内不能再出现 INCLUDE指令了.
可以把INCLUDE命令放到文件的最前面,也可以放到MEMORY或SECTIONS命令里面,或者放到输出section描述里面。
- INPUT(file, file, ...)
 - INPUT(file file ...)
 
INPUT命令指导链接器在链接时包含文件,否则它们必须出现在命令行
举例来说,如果你链接的时候总是想包含"subr.o",但是不想在每行命令行里输入,可以把‘INPUT (subr.o)’放到链接脚本里
事实上可以把所有的输入文件放到链接脚本里,然后通过-T选项来调用链接器
这种情况下,sysroot前缀被配置,文件名以“/”开始,被处理的脚本位于sysroot前缀,文件名将在sysroot前缀搜索。
否则链接器将在当前目录搜索,如果没有发现,将搜索archive库搜索路径,可以参考‘-L’ in Section 2.1 [Command Line Options], page 3.
如果使用‘INPUT (-lfile)’,则ld将转换文件名为libfile.a,与命令行参数"-l"一样
- GROUP(files) : 指定需要重复搜索符号定义的多个输入文件
 
除了file必须是库文件以外,该命令与INPUT相似, 且file文件作为一组被ld重复扫描,直到不在有新的未定义的引用出现。
- OUTPUT(FILENAME) : 定义输出文件的名字
 
同ld的-o选项, 不过-o选项的优先级更高. 所以它可以用来定义默认的输出文件名. 如a.out
- SEARCH_DIR(PATH) :定义搜索路径,
 
同ld的-L选项, 不过由-L指定的路径要比它定义的优先被搜索。
- STARTUP(filename) : 指定filename为第一个输入文件
 
在链接过程中, 每个输入文件是有顺序的. 此命令设置文件filename为第一个输入文件。
就象这个文件是在命令行上第一个被指定的文件一样, 如果在一个系统中,,入口点总是存在于第一个文件中,那这个就很有用。
4.Commands Dealing with Object File Formats
- OUTPUT_FORMAT(BFDNAME) : 设置输出文件使用的BFD格式
 
同ld选项-o format BFDNAME, 不过ld选项优先级更高.
- OUTPUT_FORMAT(DEFAULT,BIG,LITTLE) : 定义三种输出文件的格式(大小端)
 
对于此命令,要在命令行中使用-EB或-EL选项来指定不同的输出文件格式
如果'-EB'和'-EL'都没有使用, 那输出格式会是第一个参数 DEFAULT,
如果使用了'-EB',输出格式会是第二个参数 BIG,
如果使用了'-EL', 输出格式会是第三个参数, LITTLE.
比如:缺省的基于 MIPS ELF 平台连接脚本使用如下命令:
OUTPUT_formAT(elf32-bigmips, elf32-bigmips, elf32-littlemips)
这表示缺省的输出文件格式是'elf32-bigmips', 但是当用户使用'-EL'命令行选项的时候, 输出文件就会被以`elf32-littlemips'格式创建.
- TARGET(BFDNAME):设置输入文件的BFD格式
 
同ld选项-b BFDNAME. 若使用了TARGET命令, 但未使用OUTPUT_FORMAT命令, 则最用一个TARGET命令设置的BFD格式将被作为输出文件的BFD格式.
5. Assign alias names to memory regions
别名可以被加到用MEMORY命令创建的存储区域.每个名称对应着最多一个存储区域
REGION_ALIAS函数创建了存储区域region的一个别名.这使得输出section可以灵活地映射到存储区域。后面有一个例子。
假设我们有一个具有各种存储设备的嵌入式系统的应用:
(1)各存储设备存储特性
易失性存储器RAM允许执行代码或存储数据;
非易失性存储器ROM允许执行代码和数据只读访问;
非易失性存储器ROM2,具有只读数据访问和不可运行代码的特性。
(2)我们有四个输出sections:
.text 程序代码
.rodata 只读数据
.data 可读写初始化数据
.bss 可读写初始化数据,但数据必须被初始化为0.
(3)目标是提供一个链接器命令文件,该文件包含定义输出sections的系统独立部分和映射输出sections到系统上有效的存储区域的系统非独立部分.我们的嵌入式系统带有三种不同的存储配置A,B和C:
| Section | Variant A | Variant B | Variant C | 
| .text | RAM | ROM | ROM | 
| .rodata | RAM | ROM | ROM2 | 
| .data | RAM | RAM/ROM | RAM/ROM2 | 
| .bss | RAM | RAM | RAM | 
注:符号RAM/ROM 或 RAM/ROM2 表示这个section会被加载到相应的区域ROM 或 ROM2.请注意data section的加载地址是基于三个变量中.rodata section的末尾开始的.
(4)基本链接器脚本处理了如下输出section.它包含了系统非独立的linkcmds.memory文件,该文件用于描述存储分布:
INCLUDE linkcmds.memory SECTIONS
{
.text :
{
*(.text)
} > REGION_TEXT
.rodata :
{
*(.rodata)
rodata_end = .;
} > REGION_RODATA
.data : AT (rodata_end)
{
data_start = .;
*(.data)
} > REGION_DATA
data_size = SIZEOF(.data);
data_load_start = LOADADDR(.data);
.bss :
{
*(.bss)
} > REGION_BSS
}
(5)现在我们需要三个不同的 linkcmds.memory 文件来定义存储区域和别名。 针对A,B和C三种的linkcmds.memory的内容如下:
A Here everything goes into theRAM.- 这里所有的都进入到RAM
MEMORY
{
RAM : ORIGIN = , LENGTH = 4M
} REGION_ALIAS("REGION_TEXT", RAM);
REGION_ALIAS("REGION_RODATA", RAM);
REGION_ALIAS("REGION_DATA", RAM);
REGION_ALIAS("REGION_BSS", RAM); B Program code and read-only data go into theROM.Read-write data goes into theRAM.An image of the initialized data is loaded into theROMand will be copied during system start into theRAM.程序代码和只读数据进入的是ROM。可读写的数据进入的是RAM。初始化数据的一个镜像被加载到ROM并且当系统启动时会被拷贝到RAM。
MEMORY
{
ROM : ORIGIN = , LENGTH = 3M
RAM : ORIGIN = 0x10000000, LENGTH = 1M
} REGION_ALIAS("REGION_TEXT", ROM);
REGION_ALIAS("REGION_RODATA", ROM);
REGION_ALIAS("REGION_DATA", RAM);
REGION_ALIAS("REGION_BSS", RAM);
C Program code goes into the ROM. Read-only data goes into the ROM2. 
Read-write data goes into theRAM.An image of the initialized data is loaded into theROM2and will be copied during system start into theRAM.
程序代码进入的是ROM。只读数据进入的是ROM2。可读写的数据进入的是RAM。初始化数据的一个镜像被加载到ROM2并且当系统启动时被拷贝到RAM。
MEMORY
{
ROM : ORIGIN = , LENGTH = 2M
ROM2 : ORIGIN = 0x10000000, LENGTH = 1M
RAM : ORIGIN = 0x20000000, LENGTH = 1M
} REGION_ALIAS("REGION_TEXT", ROM);
REGION_ALIAS("REGION_RODATA", ROM2);
REGION_ALIAS("REGION_DATA", RAM);
REGION_ALIAS("REGION_BSS", RAM);
It is possible to write a common system initialization routine to copy the .data section from ROM or ROM2 into the RAM if necessary:
如果需要,请尽可能地写一个通用的系统初始化例程,实现把.data section从ROM/ROM2拷贝到RAM。
#include <string.h> extern char data_start [];
extern char data_size [];
extern char data_load_start []; void copy_data(void)
{
if (data_start != data_load_start)
{
memcpy(data_start, data_load_start, (size_t) data_size);
}
}
6. Other Linker Script Commands
- ASSERT(exp, message)
 
确保exp是非0的
如果是0则退出链接,并返回错误码,打印message
- EXTERN(symbol symbol ...)
 
强制未定义的符号链接进输出文件,这样可以触发链接器从标准库文件链接。
每个EXTERN可以列出几个symbol,也可以使用多个EXTERN,跟在命令行使用-u选项是一样的
- FORCE_COMMON_ALLOCATION
 
- INHIBIT_COMMON_ALLOCATION
 
- INSERT [ AFTER | BEFORE ] output_section
 
- NOCROSSREFS(section section ...)
 
让ld产生一个错误
- OUTPUT_ARCH(bfdarch)
 
指定一个特别的输出机器结构,参数用的是BFD库的名字。你可以使用objdump程序的‘-f’选项查看目标文件的机器结构
参考文献
[1] http://blog.csdn.net/han22647/article/details/64920623
[2] http://blog.csdn.net/huiyuyang_fish/article/details/16884593
Linker Scripts3--简单的链接脚本命令1的更多相关文章
- Linker Scripts3--简单的链接脚本命令2-Assigning Values to Symbols
		
1.前言 本章继续讲述简单脚本命令的后半部分 2.Assigning Values to Symbols 你可以给一个符号(symbol)赋值,它会把这些定义的符号放入全局符号表(symbols ta ...
 - Linux链接脚本学习--lds
		
一.概论 ld: GNU的链接器. 用来把一定量的目标文件跟档案文件链接在一起,并重新定位它们的数据,链接符号引用. 一般编译一个程序时,最后一步就是运行ld进行链接 每一个链接都被一个链接脚本所控制 ...
 - Linux链接脚本学习--lds(转)
		
Linux链接脚本学习--lds 一.概论 ld: GNU的链接器. 用来把一定量的目标文件跟档案文件链接在一起,并重新定位它们的数据,链接符号引用. 一般编译一个程序时,最后一步就是运行ld进行链接 ...
 - arm链接脚本
		
一. 为什么需要链接脚本 1.1. 从源码到可执行程序(主要有三个步骤:预编译.编译.链接) 1.1.1. 预编译 a. 预编译器执行.譬如C中的宏定义就是由预编译器处理,注释等也是由预编译器处理的. ...
 - win7 cmd终端连接android手机运行adb shell脚本命令
		
win7 cmd终端连接android手机运行adb shell脚本命令 (2013-03-22 20:13:57) 转载▼ 标签: android it shell 连接 linux 分类: 嵌入式 ...
 - 链接脚本(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 ...
 - 链接脚本(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 ...
 
随机推荐
- windows下配置host不生效问题
			
今天遇到了host配置之后不生效的问题,原因是文本编辑器用的是非windows格式,再notepad++右下角切换一下即可,将notepad++ 视图-显示符号-显示所有字符勾上之后可以看到windo ...
 - 怎么停止yum安装并kill进程
			
1. ctrl + z 2. ps -ef | grep 正在安装的包名称 3. kill -9 进程Id
 - 2017-12-15python全栈9期第二天第一节之昨日内容回顾
 - RocketMQ_问题_启动报错,修改堆内存大小
			
1.启动broker报错 虚拟机内存小,导致虚拟机中的JVM内存小,进而在启动broker时分配JVM内存遇到问题 查询网上得知,查看/usr/local/rocketmq-all-4.3.0/dis ...
 - Servlet_问题总结
			
1.Servlet转发到JSP后页面的CSS样式丢失,页面布局混乱,原来能点的链接现在失效 原因:原来前台页面(JSP|HTML)在引用静态资源(CSS|JS|JSP页面)时使用的是相对路径, 导致由 ...
 - MyBatis-Configuration
			
一.引用 properties 配置文件 db.properties driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://192.168.8.136:33 ...
 - Jquery 添加插件
			
原文:http://www.iteye.com/topic/545971 jQuery插件的开发包括两种: 一种是类级别的插件开发,即给jQuery添加新的全局函数,相当于给jQuery类本身添加方法 ...
 - wav音频文件格式解析【个人笔记】(自用)
			
1. WAV格式 wav是微软开发的一种音频文件格式,注意,wav文件格式是无损音频文件格式,相对于其他音频格式文件数据是没有经过压缩的,通常文件也相对比较大些.. 支持多种音频数字,取样频率和声道, ...
 - docker搭建lnmp环境
			
1.搭建lnmp网站平台 1.创建mysql数据库容器 docker run -it -d --name lnmp_mysql -p 3308:3306 -e MYSQL_ROOT_PASSWORD= ...
 - Puppeteer - 谷歌推出的自动化测试工具库
			
Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制无头 Chrome 或 Chromium.它允许你从浏览器之外的环境(即命令行)与Chromium ...