一、 链接脚本的整体认识

什么是链接文件呢?作用是什么呢?
当编写了多个C文件时,我们将他们编译链接成一个可执行的文件,此时就需要用到链接脚本文件(ld)。ld脚本主要功能就是:将多个目标文件(.o)和库文件(.a)链接成一个可执行的文件。

链接脚本文件主要有什么内容呢? 为了规范,我们分为三个部分:

  1. 链接配置(可有可无)

如一些符号变量的定义、入口地址、输出格式等

STACK_SIZE = 0X200;
OUTPUT_FORMAT(elf32-littlearm)
OUTPUT_ARCH(arm)
ENTRY(_start)
  1. 内存布局定义

脚本中以MEMORY命令定义了存储空间,其中以ORIGIN定义地址空间的起始地址,LENGTH定义地址空间的长度。

MEMORY
{
FLASH (rx) : ORIGIN = 0, LENGTH = 64K
}
  1. 段链接定义

脚本中以SECTIONS命令定义一些段(text、data、bss等段)链接分布。

SECTIONS
{
.text :
{
*(.text*)
} > FLASH
}

.text段即代码段,* (.text*)指示将工程中所有目标文件的.text段链接到FLASH中

二、常用关键字、命令

  1. MEMORY命令

使用MEMORY来定义内存如下:

MEMORY {
NAME1 [(ATTR)] : ORIGIN = ORIGIN1, LENGTH = LEN2
NAME2 [(ATTR)] : ORIGIN = ORIGIN2, LENGTH = LEN2

}

NAME :存储区域的名字。(自己可以随意命名)

ATTR :定义该存储区域的属性。ATTR属性内可以出现以下7 个字符:

  • R 只读section
  • W 读/写section
  • X 可执行section
  • A 可分配的section
  • I 初始化了的section
  • L 同I
  • ! 不满足该字符之后的任何一个属性的section

ORIGIN :关键字,区域的开始地址,可简写成org 或o

LENGTH :关键字,区域的大小,可简写成len 或l

MEMORY
{
rom (rx) : ORIGIN = 0, LENGTH = 256K
ram (!rx) : org = 0×40000000, l = 4M
}
  1. 定位符号‘.’的使用

‘.’表示当前地址,它可以被赋值也可以赋值给某个变量。
如下为将当前地址赋值给某个变量(链接器链接是按照SECTIONS里的段顺序排列的,前面的排列完之后就能计算出当前地址)

RAM_START = .;

如下为将段存放在特定的地址中:

SECTIONS
{
. = 0×10000;
.text :
{
*(.text)
} . = 0×8000000;
.data :
{
*(.data)
}
}

“. = 0×10000;”该语句表示将当前地址设置为0x10000。如上代码中,意思是将所有目标文件的text段从0x10000地址开始存放。

3 SECTIONS 命令

SECTIONS基本的命令语法如下:

SECTIONS
{
...
secname start BLOCK(align) (NOLOAD) : AT ( ldadr )
{
contents
} >region :phdr =fill
...
}

这么多参数中,只有secname 和 contents 是必须的,即可简写成:

SECTIONS
{
...
secname :
{
contents
}
...
}

链接脚本本质就是描述输入和输出。secname表示输出文件的段,即输出文件中有哪些段。而contents就是描述输出文件的这个段从哪些文件里抽取而来,即输入文件,一般就是目标文件之类的。
如下,将目标文件的数据段存放在输出文件的数据段(段名自己定义,段名前后必须要有空格)

SECTIONS
{
...
.data :
{
main.o(.data)
*(.data)
}
...
}

其中 *(.data) 表示将所有的目标的.data段链接到输出文件.datad段中, 特别注意的是,之前链接的就不会再链接,这样做的目的是可以将某些特殊的目标文件链接到地址前面。

我们继续来讲一下其他参数。

  • start :表示将某个段强制链接到的地址。
  • AT(addr):实现存放地址和加载地址不一致的功能,AT表示在文件中存放的位置,而在内存里呢,按照普通方式存储。
  • region:这个region就是前面说的MEMORY命令定义的位置信息。
  1. PROVIDE关键字:

该关键字定义一个(目标文件内被引用但没定义)符号。相当于定义一个全局变量,其他C文件可以引用它。

SECTIONS
{
.text :
{
*(.text)
_etext = .;
PROVIDE(etext = .);
}
}

如上,目标文件可以引用etext符号,其地址为定义为.text section之后的第一个字节的地址。C文件中引用。

int main()
{
//引用该变量
extern char _etext;
//...
}
  1. KEEP 关键字

在连接命令行内使用了选项–gc-sections后,连接器可能将某些它认为没用的section过滤掉,此时就有必要强制连接器保留一些特定的 section,可用KEEP()关键字达此目的。如KEEP(* (.text))或KEEP(SORT(*)(.text))

作者:小王子_f27a
链接:https://www.jianshu.com/p/42823b3b7c8e
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

简单的ld链接脚本学习的更多相关文章

  1. Linux链接脚本学习--lds(转)

    Linux链接脚本学习--lds 一.概论 ld: GNU的链接器. 用来把一定量的目标文件跟档案文件链接在一起,并重新定位它们的数据,链接符号引用. 一般编译一个程序时,最后一步就是运行ld进行链接 ...

  2. Linux链接脚本学习--lds

    一.概论 ld: GNU的链接器. 用来把一定量的目标文件跟档案文件链接在一起,并重新定位它们的数据,链接符号引用. 一般编译一个程序时,最后一步就是运行ld进行链接 每一个链接都被一个链接脚本所控制 ...

  3. makefile使用.lds链接脚本以及 $@ ,$^, $,< 解析

    先来分析一个简单的.lds链接脚本 例1,假如现在有head.c init.c nand.c main.c这4个文件: 1.1 首先创建链接脚本nand.lds: SECTIONS { firtst ...

  4. makefile使用.lds链接脚本以及 $@ ,$^, $,< 解析【转】

    转自:http://www.cnblogs.com/lifexy/p/7089873.html 先来分析一个简单的.lds链接脚本 例1,假如现在有head.c init.c nand.c main. ...

  5. 驱动开发学习笔记. 0.07 Uboot链接地址 加载地址 和 链接脚本地址

    驱动开发学习笔记. 0.07 Uboot链接地址 加载地址 和 链接脚本地址 最近重新看了乾龙_Heron的<ARM 上电启动及 Uboot 代码分析>(下简称<代码分析>) ...

  6. GNU linker script,ld script,GNU链接脚本

    https://blog.csdn.net/itxiebo/article/details/50937412 https://blog.csdn.net/itxiebo/article/details ...

  7. gcc ld 链接器相关知识,调试指令(程序员的自我修养----链接、装载与库)

    最近解决一个动态链接上的问题,因为以前从来没有接触过这方面的知识,所以恶补了一下,首先要了解gcc编译指令(makefile),ld链接器的选项(还有连接脚本section指定内存位置),熟悉查看连接 ...

  8. [转]Linux下的lds链接脚本详解

    转载自:http://linux.chinaunix.net/techdoc/beginner/2009/08/12/1129972.shtml     一. 概论 每一个链接过程都由链接脚本(lin ...

  9. Linux下的lds链接脚本基础

    转载:http://soft.chinabyte.com/os/104/12255104.shtml   今天在看uboot引导Linux部分,发现要对链接脚本深入了解,才能知道各个目标文件的内存分布 ...

随机推荐

  1. MongoDB的Replica Set以及Auth的配置

    http://blog.0x01.site/2017/01/13/MongoDB%E7%9A%84Replica-Set%E4%BB%A5%E5%8F%8AAuth%E7%9A%84%E9%85%8D ...

  2. yii2.0 邮件发送如何配置

    邮件发送配置: 打开配置文件将下面代码添加到 components => [...]中(例:高级版默认配置在/common/config/main-local.php)         'mai ...

  3. springboot练习

    https://www.jianshu.com/p/9a08417e4e84 1.@Controller和@RestController的区别? Spring4之后加入的注解,原来在@Controll ...

  4. GUI学习之五——QAbstractButton类学习笔记

    今天总结一下AbstractButton类的学习笔记. 一.描述 AbstractButton是对各种按键的抽象类他的继承关系是这样的 首先,QAbstractButton继承了QWidget类的各种 ...

  5. 分布式一致性的基石---Paxos算法(1)

    分布式一致性的基石---Paxos算法(1) Paxos算法是由微软的工程师Lamport提出,Lamport依靠Paxos算法获得图灵奖: Paxos算法旨在解决相互信任的分布式系统中,多个节点能快 ...

  6. IDEA debugger模式下启动慢

    很可能是因为代码里面有端点造成的. 点击如下图的重叠红点,找到对应端点点掉就可以了.

  7. JAVA实训第二次作业

    一维数组的创建和遍历. 声明并创建存放4个人考试成绩的一维数组,并使用for循环遍历数组并打印分数.要求: (1) 首先按"顺序"遍历,即打印顺序为:从第一个人到第四个人: (2) ...

  8. ----constructor 与 object----

    CONSTRUCTOR constructor是一种特殊的object,同样是用来创建和声明一个类 语法规则: constructor([arguments]) { ... } 注意: 1.在类中,只 ...

  9. 动态库的链接和链接选项-L,-rpath-link,-rpath

    https://my.oschina.net/shelllife/blog/115958 链接动态库 如何程序在连接时使用了共享库,就必须在运行的时候能够找到共享库的位置.linux的可执行程序在执行 ...

  10. ProcessingElement.h

    processing element模块 #ifndef __NOXIMPROCESSINGELEMENT_H__ #define __NOXIMPROCESSINGELEMENT_H__ #incl ...