简单的ld链接脚本学习

摘要:
当编写了多个C文件时,我们将他们编译链接成一个可执行的文件,此时就需要用到链接脚本文件。MEMORY{FLASH:ORIGIN=0,LENGTH=64K}段链接定义脚本中以SECTIONS命令定义一些段链接分布。3SECTIONS命令SECTIONS基本的命令语法如下:SECTIONS{...secnamestartBLOCK:AT{contents}˃region:phdr=fill...}这么多参数中,只有secname和contents是必须的,即可简写成:SECTIONS{...secname:{contents}...}链接脚本本质就是描述输入和输出。

一、 链接脚本的整体认识

什么是链接文件呢?作用是什么呢?
当编写了多个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 = 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链接脚本学习》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇内存之RAM、SRAM、DRAM、ROM、FLASH、SDRAM、DDR*PreTranslateMessage作用和用法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

使用Jenkins合并gitlab服务器上的代码

1、申请gitlab读写权限账号 2、在Jenkins的主机上,运行Jenkins程序的用户的home目录下,执行: touch .git-credentialsvim .git-credentialshttp://{用户名}:{密码}@{IP地址} git config --global credential.helper store 查看.gitcon...

在vscode中用Git管理项目

一、新建仓库 1、新建仓库-->填写仓库名称-->一定要将对钩去掉-->公开-->创建 Git全局设置: git config --global --add user.name "zhouwenhao"git config --global --add user.email "1141180185@qq.com" 二、推送代码 2、...

v4l2视频采集摄像头

v4l2 --是Linux内核中关于视频设备的内核驱动框架,为上层访问底层的视频设备提供了统一的接口。/dev/vidioX 1.打开设备文件 fd=open("/dev/video3",O_RDWR); /dev/video3:视频设备文件名 O_RDWR:可读可写 fd: open成功反返回文件描述符 jpeg yuv2.查询设备支持哪种格式 str...

dmidecode的Python解析

#!/usr/bin/env python # -*- coding: utf-8 -*- """ 解析dmidecode命令输出结果,返回JSON格式数据 测试服务器Dell VMware虚拟机 测试系统为CentOS 6.x 7.x Python版本为Python3.6 原版参考的是 https://pypi.org/project/dm...

GitHub的基本使用

GitHub的基本使用 一、什么是GitHub Github是一个基于git(我所使用的Git版本为:Git_2.11.1_64 (提取码:1i72))的社会化代码分享社区。GitHub的官网地址是https://github.com。 你可以在Github上创建免费的远程仓库(remote repository),分享你的代码,当然也可以关注其他人的代码...

latex 页眉设置 [转]

//注意加粗部分\documentclass{article} \usepackage{CJK}\usepackage{fancyhdr} \title{\textbf{Title}} \begin{document} \begin{CJK*}{GBK}{song} \pagestyle{fancy} \lhead{中文页眉} \rhea...