十一、 表达式
lds中表达式的文法与C语言的表达式文法一致,表达式的值都是整型,如果ld的运行主机和生成文件的目标机都是32位,则表达式是32位数据,否则是64位数据。
以下是一些常用的表达式:
_fourk_1 = 4K; /* K、M单位 */
_fourk_2 = 4096; /* 整数 */
_fourk_3 = 0×1000; /* 16 进位 */
_fourk_4 = 01000; /* 8 进位 */
注意:1K=1024 1M=1024*1024
11.1、符号名
没有被引号”"包围的符号,以字母、下划线或’.'开头,可包含字母、下划线、’.'和’-'。当符号名被引号包围时,符号名可以与关键字相同。如,
“SECTION”=9;
“with a space” = “also with a space” + 10;
11.2、定位符号’.'
只在SECTIONS命令内有效,代表一个程序地址空间内的地址。
注意:在连接时,当定位符用在SECTIONS命令的输出section描述内时,它代表的是该section的当前**偏移**,而不是程序地址空间的绝对地址。当然当程序载入后,符号最后的地址还是程序地址空间的绝对地址。
示例11.2_1:
SECTIONS
{
output :
{
file1(.text)
. = . + 1000;
file2(.text)
. += 1000;
file3(.text)
} = 0×1234;
}
其中由于对定位符的赋值而产生的空隙由0×1234填充。其他的内容应该容易理解吧。
示例11.2_2:
SECTIONS
{
. = 0×100
.text: {
*(.text)
. = 0×200
}
. = 0×500
.data: {
*(.data)
. += 0×600
}
.text section在程序地址空间的开始位置是0x100
示例11.2_3
文件src\a.c
#include <stdio.h>
int a = 100;
int b=0;
int c=0;
int d=1;
int main()
{
printf( "&a=%p\n", &a );
printf( "&b=%p\n", &b );
printf( "&c=%p\n", &c );
printf( "&d=%p\n", &d );
return 0;
}
文件lds\a.lds
a = 10; /* 全局位置 */
SECTIONS
{
b = 11;
.text :
{
*(.text)
c = .; /* section描述内 */
. = ;
d = .;
}
_bdata = (. + 3) & ~ 4; /* SECTIONS命令内 */
.data : { *(.data) }
}
在没有使用a.lds情况下编译
gcc -Wall -o a-without-lds.exe ./src/a.c
运行./a-without-lds.exe
结果:
&a=0x601020
&b=0x601038
&c=0x60103c
&d=0x601024
在使用a.lds情况下编译
gcc -Wall -o a-with-lds.exe ./src/a.c ./lds/a.lds
运行./a-with-lds.exe
结果:
&a=0xa
&b=0xb
&c=0x400638
&d=0x402b20
10.3、表达式的操作符
在lds中,表达式的操作符与C语言一致。
优先级 结合顺序 操作符
 left ! – ~ (1)
 left * / %
 left + -
 left >>  =
 left &
 left |
 left &&
 left ||
 right ? :
 right &= += -= *= /= (2)
(1)表示前缀符,(2)表示赋值符。
10.4、表达式的计算
连接器延迟计算大部分表达式的值。
但是,对待与连接过程紧密相关的表达式,连接器会立即计算表达式,如果不能计算则报错。比如,对于section的VMA地址、内存区域块的开始地址和大小,与其相关的表达式应该立即被计算。
例子,
SECTIONS
{
.text 9+this_isnt_constant :
{ *(.text) }
}
这个例子中,9+this_isnt_constant表达式的值用于设置.text section的VMA地址,因此需要立即运算,但是由于this_isnt_constant变量的值不确定,所以此时连接器无法确立表达式的值,此时连接器会报错。
10.5、相对值与绝对值
在输出section描述内的表达式,连接器取其相对值,相对与该section的开始位置的偏移
在SECTIONS命令内且非输出section描述内的表达式,连接器取其绝对值
通过ABSOLUTE关键字可以将相对值转化成绝对值,即在原来值的基础上加上表达式所在section的VMA值。
示例
SECTIONS
{
.data : { *(.data) ;_edata = ABSOLUTE(.);
}
}
该例子中,_edata符号的值是.data section的末尾位置(绝对值,在程序地址空间内)。
10.6、内建函数
lds中有以下一些内建函数:
ABSOLUTE(EXP) :转换成绝对值
ADDR(SECTION) :返回某section的VMA值。
ALIGN(EXP) :返回定位符’.'的按照EXP进行对齐后的修调值,对齐后的修调值算法为:(. + EXP – 1) & ~(EXP
– 1)。
BLOCK(EXP) :如同ALIGN(EXP),为了向前兼容。
DEFINED(SYMBOL) :如果符号SYMBOL在全局符号表内,且被定义了,那么返回1,否则返回0。
示例:
SECTIONS { …
.text : {
begin = DEFINED(begin)
? begin : . ;
}
}
LOADADDR(SECTION) :返回三SECTION的LMA
MAX(EXP1,EXP2) :返回大者
MIN(EXP1,EXP2) :返回小者
NEXT(EXP) :返回下一个能被使用的地址,该地址是EXP的倍数,类似于ALIGN(EXP)。除非使用了MEMORY命令定义了一些非连续的内存块,否则NEXT(EXP)与ALIGH(EXP)一定相同。
SIZEOF(SECTION) :返回SECTION的大小。当SECTION没有被分配时,即此时SECTION的大小还不能确定时,连接器会报错。
SIZEOF_HEADERS :返回输出文件头部的字节数。这些信息出现在输出文件的开始处。当设置第一个段的开始地址时,你可以使用这个数字。如果你选择了加速分页,当产生一个ELF输出文件时,如果链接器脚本使用SIZEOF_HEADERS内建函数,连接器必须在它
算出所有段地址和长度之前计算程序头部的数值。如果连接器后来发现它需要附加程序头,它将报告一个“not enough room for 
program headers”错误。为了避免这样的错误,你必须避免使用SIZEOF_HEADERS函数,或者你必须修改你的连接器脚本去避免强制
连接器去使用附加程序头,或者你必须使用PHDRS命令去定义你自己的程序头
十二、 暗含的连接脚本
输入文件可以是目标文件,也可以是连接脚本,此时的连接脚本被称为 暗含的连接脚本
如果连接器不认识某个输入文件,那么该文件被当作连接脚本被解析。更进一步,如果发现它的格式又不是连接脚本的格式,那么连接器报错。
一个暗含的连接脚本不会替换默认的连接脚本,仅仅是增加新的连接而已。
一般来说,暗含的连接脚本符号分配命令,或INPUT、GROUP、VERSION命令。
在连接命令行中,每个输入文件的顺序都被固定好了,暗含的连接脚本在连接命令行内占住一个位置,这个位置决定了由该连接脚本指定的输入文件在连接过程中的顺序。
典型的暗含的连接脚本是libc.so文件,在GNU/linux内一般存在/usr/lib目录下。

Linux下的lds链接脚本简介(四)的更多相关文章

  1. Linux下的lds链接脚本简介

    转载:http://hubingforever.blog.163.com/blog/static/171040579201192472552886/   一. 概论 每一个链接过程都由链接脚本(lin ...

  2. Linux下的lds链接脚本简介(二)

    七. SECTIONS命令 SECTIONS命令告诉ld如何把输入文件的sections映射到输出文件的各个section: 如何将输入section合为输出section; 如何把输出section ...

  3. Linux下的lds链接脚本简介(一)

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

  4. Linux下的lds链接脚本简介(三)

    八. 内存区域命令 在默认情形下,连接器可以为section在程序地址空间内分配任意位置的存储区域.并通过输出section描述的> REGION属性显示地将该输出section限定于在程序地址 ...

  5. Linux下的lds链接脚本详解

    1. 概论2. 基本概念3. 脚本格式4. 简单例子5. 简单脚本命令6. 对符号的赋值7. SECTIONS命令8. MEMORY命令9. PHDRS命令10. VERSION命令11. 脚本内的表 ...

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

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

  7. Linux下的lds链接脚本详解【转】

    转自:http://www.cnblogs.com/li-hao/p/4107964.html 转载自:http://linux.chinaunix.net/techdoc/beginner/2009 ...

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

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

  9. 从四个问题透析Linux下C++编译&链接

    摘要:编译&链接对C&C++程序员既熟悉又陌生,熟悉在于每份代码都要经历编译&链接过程,陌生在于大部分人并不会刻意关注编译&链接的原理.本文通过开发过程中碰到的四个典型 ...

随机推荐

  1. Android 给图片 加边框

    图片处理时,有时需要为图片加一些边框,下面介绍一种为图片添加简单边框的方法. 基本思路是:将边框图片裁剪成八张小图片(图片大小最好一致,不然后面处理会很麻烦),分别对应左上角,左边,左下角,下边,右下 ...

  2. js实现动态添加事件

    js实现动态添加事件 一.实例描述 前一个案例讲了如何在网页中动态添加元素,有时候我们需要添加事件.本例学习如何动态的为元素添加事件. 二.截图 三.代码 <!DOCTYPE html> ...

  3. Linux下MySQL允许远程连接以及授权命令

    --针对某个库做授权 GRANT ALL PRIVILEGES ON *.* TO 'myuser'@'%' IDENTIFIED BY 'mypassword' WITH GRANT OPTION; ...

  4. traceroute----追踪数据包在网络上的传输过程

    traceroute命令 用于追踪数据包在网络上的传输时的全部路径,它默认发送的数据包大小是40字节. traceroute通过发送小的数据包到目的设备直到其返回,来测量其需要多长时间.一条路径上的每 ...

  5. 03005_SQL查询语句

    查询语句,在开发中使用的次数最多,此处使用“zhangwu” 账务表. 1.准备工作 (1)创建财务表: CREATE TABLE zhangwu ( id INT PRIMARY KEY AUTO_ ...

  6. UVALive 5583 Dividing coins

    Dividing coins Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVALive. Ori ...

  7. 洛谷 P2105 K皇后

    P2105 K皇后 题目描述 小Z最近捡到了一个棋盘,他想在棋盘上摆放K个皇后.他想知道在他摆完这K个皇后之后,棋盘上还有多少了格子是不会被攻击到的. (Ps:一个皇后会攻击到这个皇后所在的那一行,那 ...

  8. Codeforces 129A-Cookies(暴力)

    A. Cookies time limit per test 2 seconds memory limit per test 256 megabytes input standard input ou ...

  9. php数组插入数据

    php数组插入数据 一.总结 代码要多敲,看是看不会的 php代码直接在页面不好敲,可以去控制器里面敲 二.目标 在一组数中,要求插入一个数,按其原来顺序插入,维护原来排序方式. 三.代码 (1).思 ...

  10. 在Sql中将 varchar 值 '1,2,3,4,5,6' 转换成数据类型 int

    --问题:将aa转换为Int类型失败 string aa="3,5,11,56,88,45,23"; select * from ERPBuMen where ID in(aa) ...