1.前言

本章继续讲述简单脚本命令的后半部分

2.Assigning Values to Symbols

你可以给一个符号(symbol)赋值,它会把这些定义的符号放入全局符号表(symbols table)中

2.1 Assigning Values to Symbols

可以使用下面的C操作为一个符号指定值:

symbol = expression ;
symbol += expression ;
symbol -= expression ;
symbol *= expression ;
symbol /= expression ;
symbol <<= expression ;
symbol >>= expression ;
symbol &= expression ;
symbol |= expression ;

注:[1]第一条语句为symbol赋值,其它情况symbol必需提前定义。

[2]特别的符号名:"."代表位置计数符,只能在SECTIONS命令中使用

[3]赋值语句后面必需跟一个;

[4]可以把符号赋值作为一个命令写在它的右侧;也可以作为声明写在SECTIONS命令里面;或者作为SECTIONS命令中输出section的一部分

如下示例显示了赋值语句位于不同的位置:

floating_point = 0;
SECTIONS
{
.text :
{46 The GNU linker
*(.text)
_etext = .;
}
_bdata = (. + 3) & ~ 3;
.data : { *(.data) }
}

在这个例子中,‘floating_point’符合被定义为0。‘_etext’符号被定义为‘.text’输入段最后的地址。‘_bata’符号被定义为‘.text’输出段最后按4字节对齐的地址

2.2 PROVIDE

很多情况下,脚本中定义的符号任何对象只能对其引用而不能定义它,比如传统链接器定义的'etext'符号。

然而,ANSI C要求用户使用‘etext’符号作为函数名而不能报错,在程序仅仅是引用某个符号而非定义时,RPOVIDE关键字可以定义一个符号,比如‘etext’,语法是PROVIDE(symbol = expression)

下面是一个‘etext’使用的例子:

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

在这个例子中,如果程序定义‘_etext’(带有前导下划线),链接器会报很多重定义错误。

另一方面,如果程序定义‘etext’(没有前导下划线),那么链接器会默默地使用程序中的定义,如果程序中只是引用了‘etext’而没有定义它,链接器则使用脚本中的定义

2.3 PROVIDE_HIDDEN

类似PROVIDE的用法。对于ELF目标文件,定义的符号会被隐藏不会被导出

补充:如果你查看链接后的文件的符号表,会发现它的符号绑定信息是LOCAL,即内部可见的

2.4 Source Code Reference

从源代码来访问链接脚本中定义的变量其实并不直观,脚本中的符号和高级语言中定义的变量不能等同,它是一个符号而不是一个值

在进一步讨论之前,需要注意的是当源代码中的符号名字被放入符号表(symbol table)中时,编译器通常会把它们进行转换。

举例来说,Fortran语言编译器通常会加前导或后接一个下划线,C++编译器会进行扩展的‘name mangling’。

因此在源代码中的使用的变量和在链接脚本中定义的变量是可能有差异的。举例来说,C语言中引用脚本中的变量像这样:

extern int foo;  

但是在链接脚本中它被定义为这样:

_foo = 1000; 

不过,在下面的例子中我们假设没有名称转换

当一个符号被声明,比如用C语言,那么会有两件事情发生,第一件事情是编译器会保留一块内存空间来存储这个符号的值,

第二件事情是编译器会在符号表中创建一个符号并存储好该符号的地址,符号表中包含的是存储该符号的值的地址,比如在文件中这样一个C语言的声明:

int foo = 1000;

会做如下两件事情:

(1)在内存中留出4字节空间,存储1000

(2)在符号表中创建一个‘foo’的符号,符号的地址为整数型数字1000存储在内存中的地址

当一个程序要引用一个符号时,编译器首先会生成一段去符号表中找到该符号内存块地址的代码,然后在生成一段读取内存块值的代码,比如:

foo = 1;

去符号表中查询‘foo’符号的地址值,然后往这个地址里写值1,然而:

int * a = & foo; 

去符号表中查询‘foo’符号的地址值,然后将地址直接拷贝到变量‘a’的内存块里面

对比一下链接脚本中的符号声明,它会在符号表中创建一个符号,但是不会给它分配任何内存,所以它们仅仅是一个地址没有值,比如脚本中这样定义:

foo = 1000;  

在符号表中创建一个‘foo’的符号,然后存储它的地址值为1000,但地址1000指向的存储位置没有任何意义。

这就意味着你不能访问链接脚本中定义的符号的值(它没有值),你唯一能做的就是访问符号的地址

注:foo并不是一个变量,它只是一个值,并不需要在内存中留出一段空间来保存它;
在C语言中,符号表中会有一个名为foo的项,这个项目中的值(地址值)是1000;
注意,这个1000并没有实际存在的内存

因此,当你在源代码中使用一个链接脚本定义的符号时,你应该使用它的地址,而不去尝试使用它的值。

举例,假设你想拷贝一个叫.ROM段的内容到.FLASH段中,链接脚本这样声明的:

start_of_ROM   = .ROM;
end_of_ROM     = .ROM + sizeof (.ROM) - 1;
start_of_FLASH = .FLASH;  

你的C语言代码应该这样写:

extern char start_of_ROM, end_of_ROM, start_of_FLASH;  memcpy (& start_of_FLASH, & start_of_ROM, & end_of_ROM - & start_of_ROM);  

注意,使用‘&’操作也是完全正确的,使用取址符号&去得到它在符号表中的值

转载于:https://www.cnblogs.com/smartjourneys/p/8334375.html

Linker Scripts3--简单的链接脚本命令2-Assigning Values to Symbols相关推荐

  1. [GNU LD系列 3.3] 简单的链接脚本例程

    许多链接脚本是相当简单的. 可能最简单的链接脚本只包含一个命令:'SECTIONS'.我们使用'SECTIONS'命令来描述输出文件的内存布局. 'SECTIONS'命令是一个很强大的命令.在这里我们 ...

  2. 链接脚本(Linker Scripts)语法和规则解析(翻译自官方手册)

    原链接:链接脚本(Linker Scripts)语法和规则解析(翻译自官方手册)_BSP-路人甲的博客-CSDN博客_链接脚本语法 为了便于与英文原文对照学习与理解(部分翻译可能不准确),本文中的每个 ...

  3. LD链接脚本解析-STM32F4xx

    本篇文章主要围绕项目 STM32_RTOS_GUN 的链接脚本 STM32F417IG_FLASH.ld 进行分析,同时对编写链接脚本的方法进行相应的讲解,尽可能地做到通过阅读这篇文章后能够学会编写简 ...

  4. STM32跑MicroPython的链接脚本分析

    一.链接脚本的简单常识   有时候我们很多文件需要链接到指定的区域,或者叫做段里面,比如在 Linux 里面初始化函数就会放到 init 段里面.因此我们需要能够自定义一些段,这些段的起始地址我们可以 ...

  5. arm-gcc链接器和链接脚本

    本文主要介绍了链接器和链接脚本的基本内容.主要偏向于入门级以及常见容易混淆的知识点. 1. 链接器介绍 在现在软件工程中,程序一般都比较复杂,通常由多个源文件组成.在编译的过程中会对这些源文件进行汇编 ...

  6. 嵌入式Linux系统中的.lds链接脚本基础

    from:http://www.embeddedlinux.org.cn/html/xinshourumen/201203/04-1989.html 连接脚本的格式 ================= ...

  7. 第四天:关看门狗、设置栈、控制icache、重定位、链接脚本

    1.汇编写启动代码:关看门狗 什么是看门狗? 看门狗(watch dog timer看门狗定时器),比如:家门口有一只狗,这个狗定时会饿(譬如两小时一饿),狗饿了就会胡乱咬人,人进进出出要想保证安全必 ...

  8. 链接脚本.lds文件分析

    本篇文章是我特地转载的,以作为我博客中其他文章的基本知识的补充,同时也方便自己学习使用.本篇详细全面的介绍了连接脚本lds文件的介绍与使用,这个脚本文件很重要,在最后的链接阶段,决定了各个文件的位置安 ...

  9. win7 cmd终端连接android手机运行adb shell脚本命令

    win7 cmd终端连接android手机运行adb shell脚本命令 (2013-03-22 20:13:57) 转载▼ 标签: android it shell 连接 linux 分类: 嵌入式 ...

最新文章

  1. jQuery带缩略图的宽屏焦点图插件
  2. 给Repeater、Datalist和Datagrid增加自动编号列
  3. PHP 使用 AES/ECB/PKCS7 padding 加密
  4. matlab函数采样,[转载]matlab采样函数
  5. UVa 11806 Cheerleaders
  6. 你的代码是否按照高内聚、低耦合的原则来设计的?
  7. [转]Oracle_ProC编程
  8. 【Linux】linux系统很卡排除
  9. react 类暴露_react如何将组件内部的方法暴露给外部
  10. Android4.4 多媒体开发(五)----OpenMax简介
  11. icesat/glas与SRTM参考椭球、基准对比
  12. 【ESRI论坛6周年征文】ArcEngine注记(Anno/ Label/Element等)处理专题 -入门篇
  13. cpu vtx测试软件,推荐几个好用的检测电脑CPU是否支持(Virtualization Technology)虚拟化技术的工具-推荐实用小软件 -亦是美网络...
  14. 仓储物流机器人:快仓、海柔创新“极速前进”
  15. con和com开头单词规律_英语单词速记小技巧
  16. 徐梓萌 受邀担任 火星少年计划 第四季 特邀小主持人
  17. Cordova app中点击打开微信功能
  18. 运营必备九大互联网思维
  19. C语言自动预订飞机票问题
  20. [附源码]计算机毕业设计springboot动物保护协会网站

热门文章

  1. 基于 ELK Stack 和 Spark Streaming 的日志处理平台设计与实现
  2. 用 Go 构建一个区块链 -- Part 3: 持久化和命令行接口
  3. Truffle 4.0、Geth 1.7.2、TestRPC在私有链上搭建智能合约
  4. (原创)Android6.0亮屏流程之Keyguard Window绘制
  5. 你应该知道的那些Android小经验
  6. 新一代开源Android渠道包生成工具Walle
  7. php 比较数组的不同的值,php array_udiff 比较两个数组的键值,并返回差集
  8. spark 写tidb_优秀的数据工程师,怎么用Spark在TiDB上做OLAP分析
  9. IMEI 码的校验和生成
  10. uvalive4744(数论)