`
java-mans
  • 浏览: 11392899 次
文章分类
社区版块
存档分类
最新评论

Linux下的lds链接脚本简介(四)

 
阅读更多
十一、 表达式
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描述内 */
. =10000;
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语言一致。
优先级 结合顺序 操作符
1left ! – ~(1)
2left * / %
3left + -
4left >> =
5left &
6left |
7left &&
8left ||
9right ? :
10right &= += -= *= /=(2)
(1)表示前缀符,(2)表示赋值符。
10.4、表达式的计算
连接器延迟计算大部分表达式的值。
但是,对待与连接过程紧密相关的表达式,连接器会立即计算表达式,如果不能计算则报错。比如,对于section的VMA地址、内存区域块的开始地址和大小,与其相关的表达式应该立即被计算。
例子,
SECTIONS
{
.text9+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目录下。

<wbr style="line-height:25px"></wbr>
分享到:
评论

相关推荐

    Linux下的lds链接脚本基础定义.pdf

    Linux下的lds链接脚本基础定义.pdf

    Linux下的lds链接脚本基础 pdf

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

    Linux下的lds链接脚本基础

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

    Linux下的lds链接脚本详解1

    入口地址(entry point)是指进程执行的第一条用户空间的指令在进程地址空间的地址ld有多种方法设置进程入口地址, 按一下顺序: (编号越前, 优先级越高

    Linux下的lds链接脚本

    Linux下的lds链接脚本基础,介绍了链接脚本基本概念,基本格式,以及一些例子等等

    Linux下的lds链接脚本基础[0].pdf

    Linux下的lds链接脚本基础.pdf 链接器把一个或多个输入文件合成一个输出文件. 输入文件: 目标文件或链接脚本文件. 输出文件: 目标文件或可执行文件. 目标文件(包括可执行文件)具有固定的格式, 在UNIX或GNU/...

    Linux下的lds链接脚本资源

    详细讲解了链接脚本的结构,熟读后对于基本的链接脚本问题,可以轻松的分析,并能够自己写一个简单的脚本。

    linux内核链接脚本

    本文简单的介绍了理解内核链接脚本需要的链接器知识和链接脚本语法,从vmlinux_32.lds.S文件分析了内核image的构成,并着重讲解了使用自定义section配合链接脚本动态创建表的方法。这里或许有一些你经常看到但不了解...

    Linker Script in Linux(链接脚本学习)

    Linker Script in Linux(链接脚本学习) Linker Script in Linux(链接脚本学习)--

    lds规则连接脚本的介绍

    最近在看Linux内核时,总是遇到一些和连接脚本相关的东东,搞得人一头雾水,终于下定决心把它搞明白,写下一点心得,希望对和我一样的人有所帮助!sections节的讲解,很好很详细。

    Linker-script-in-Linux.zip_linker script

    linux链接脚本lds解析

    关于gcc ld的链接脚本

    链接脚本的主要目的是描述输入文件中的段如何被映射到输出文件中,并且控制输出文件中的内存排布。比如我们编译生成的文件一般都包含 text 段、 data 段等等。 SECTIONS{ . = 0X10000000; .text : //代码段 { ...

    linux内核编译流程1

    (1)vmlinux-lds:链接脚本确认,在最后阶段需要使用到 (4) kallsyms.o在2.6内核中,为了更好的调试内核,引入了kallsyms机制

    基于友善之臂6410的裸机程序

    Tiny6410的裸机程序,基于linux平台,源代码+makefile+.lds链接器脚本。内容包括硬件初始化(汇编),时钟、内存、mmu、串口、led初始化(c语言)按键中断,,代码搬移是从nandflash搬移到内存,功能:点亮led,使用...

    linux下实现在程序运行时的函数替换(热补丁)

    elf简单地说是由以下四部分组成的,elf...其中program header是运行时使用的,而section header并不会被加载进程序运行空间,但他们可以在编译时被指定该段的加载地址等信息,当然一般这个链接脚本.lds是由gcc默认的。

    ARM_Linux启动分析.pdf

    在arch/alpha/vmlinux.lds 的链接脚本控制下,链接程序将vmlinux的入口置于 "arch/alpha/kernel/head.S"中的__start上,因此当Bootloader跳转到0x100000时, __start处的代码开始执行。__start的代码很简单,只需要...

    ok6410裸机程序,硬件、内存、时钟、串口初始化,printf和scanf函数调用串口打印输出,点亮led

    ok6410裸机驱动程序,基于linux平台,源代码+makefile+.lds链接器脚本。内容包括硬件初始化(汇编),时钟、内存、mmu、串口、led初始化(c语言),代码搬移是从垫脚石搬移到内存,不含从nandflash搬移到内存,功能...

    gnu ld 说明书

    lds 说明书 看懂linux源代码,学习linux内核必须的

    uboott移植实验手册及技术文档

    4、交叉编译器 arm-softfloat-linux-gnu-gcc-3.4.5 【实验步骤】 一、建立自己的平台类型 (1)解压文件 #tar jxvf u-boot-1.3.1.tar.bz2 (2)进入 U-Boot源码目录 #cd u-boot-1.3.1 (3)创建自己的开发板...

Global site tag (gtag.js) - Google Analytics