ld,连接器
连接器的功能,是将一个可执行程序所需的目标文件和库文件最终整合为一体。一个程序通常包含传统的三个段,.test, .data, .bss段。连接器的功能就是将各个目标文件个库文件中的三个段进行合并。
重定位的概念
链接而生成的可执行程序虽然是放在文件中的,但当程序运行时需要加载到内存中。各段应该放在内存空间的声明位置是由可执行文件内的头部信息指定的。
一个程序一旦被加载到内存中,就意味着不论函数还是变量,它们都会在内存中占据一定的内存空间,而这关系到内存地址。假设foo()函数在加载到内存中后其地址刚好位于ox10000处,从处理器的角度看,当我们在c程序写下一句调用foo()函数的语句时,意味着在调用foo()函数时需要跳转到ox10000的内存地址处,那如何知道调用foo()函数时应当跳转到ox10000地址处的呢?这就是连接器所需要完成的工作。
链接脚本的功能是告诉连接器,如何将各个不同的目标文件(包括库)中的段合在一起并最终生成一个可执行程序(文件)。从链接脚本的角度来看,一方面它需要描述输出,即最终输出到可执行程序文件中的段;另一方面又要描述输入,即来自各个目标文件中的段。
/*********以下摘自:http://www.cnblogs.com/amanlikethis/p/3344519.html *********/
1.连接顺序的问题
SECTIONS {
firtst 0x00000000 : {head.o init.o nand.o}
second x30000000 : AT(4096){ main.o}
}
这个规则中定义了两个大段,first和second。
first的链接顺序为head.o init.o nand.o. Second的链接顺序为main.o。
2.链接地址的问题
先说明一下链接地址的概念,链接地址是程序实际运行的地址。通常程序中有位置无关代码和位置有关代码。位置无关代码是对于链接地址无要求,可以在不是它链接地址的地方运行;但是位置有关代码,必须在链接地址运行。也就是说当运行位置有关代码时,程序必须事先在链接地址上,如果没有在,通常需要COPY到那个位置或者利用MMU映射一下。
下边以一个例子来说明一下链接脚本中链接地址的问题。
SECTIONS {
firtst 0x00000000 : {head.o}
second 0x00000200 : AT(300) {init.o}
third 0x00000400 : AT(500) {nand.o}
fourth 0x30000000 : AT(3096) { main.o}
}
四个部分:first、second、third、foutth,它们的链接地址分别是0x00000000、0x00000200、0x00000400、0x30000000。
3.加载地址
加载地址指的是程序编译后的存放地址,通常存放在ROM、FLASH中,所以就是指这段程序在ROM、FLASH中的存放位置。还是以上边的连接脚本为例。
SECTIONS {
firtst 0x00000000 : {head.o}
second 0x00000200 : AT(300) {init.o}
third 0x00000400 : AT(500) {nand.o}
fourth 0x30000000 : AT(3096) { main.o}
}
它们的存放地址分别是0、300、500、3096。
/**********摘抄完毕********/
之所以摘抄这一段园友的博客,是因为在2440上,就有这样的链接脚本:
因为之前看关于ld的介绍资料,全是data,bss,test段开头,其实段名是可以自己取得;
SECTIONS {
firtst 0x00000000 : { head.o init.o }
second 0x30000000 : AT(4096) { main.o }
}
以上,head.o放在0x00000000地址开始处,init.o放在head.o后面,他们的运行地址也是0x00000000,即连接和存储地址相同(没有AT指定);main.o放在4096(0x1000,是AT指定的,存储地址)开始处,但是它的运行地址在0x30000000,运行之前需要从0x1000(加载处)复制到0x30000000(运行处),此过程也就用到了读取Nand flash。
这就是存储地址和连接(运行)地址的不同,称为加载时域和运行时域,可以在.lds连接脚本文件中分别指定。
这里有很多选项,但常用的也就那么一点。关于链接在第六章还有其他一些介绍,但是目前只是为了学习arm板,如果以后在2440上用到了其他功能,再在这里补充。
ld,连接器的更多相关文章
- Linux Kernel Makefile Test
一.本文说明 本文为linux内核Makefile整体分析的续篇,是依据Linux内核Makefile体系的主要内容编写一个简要的测试工程.Linux内核Makefile体系就好像一只“大鸟”,而这篇 ...
- GNU工具链学习笔记
GNU工具链学习笔记 1..so为动态链接库,.a为静态连接库.他们在Linux下按照ELF格式存储.ELF有四种文件类型.可重定位文件(Relocatable file,*.o,*.a),包含代码和 ...
- tiny210——uboot移植Makefile文章分析
这东西已经写,我们没有时间发布,如今,终于有时间稍微长送记录汇总uboot学习过程.具体了.以后忘了也能够再温习回来嘛有些特殊字符显示得乱掉了 Makefile追踪技巧: 技巧1:能够先从编译目标開始 ...
- 【嵌入式开发】gcc 学习笔记(一) - 编译C程序 及 编译过程
一. C程序编译过程 编译过程简介 : C语言的源文件 编译成 可执行文件需要四个步骤, 预处理 (Preprocessing) 扩展宏, 编译 (compilation) 得到汇编语言, 汇编 (a ...
- 【转】关于编译链接——gcc/g++
添加运行时共享库目录 运行使用共享库的程序需要加载共享库(不同于G++ 编译时指定的链接库),添加共享库的步骤: 修改文件 /etc/ld.so.conf 添加共享库目录 运行 ldconfig 同步 ...
- ARM GNU常用汇编语言介绍
ARM GNU常用汇编语言介绍 ARM汇编语言源程序语句,一般由指令,伪操作,宏指令和伪指令组成. ARM汇编语言的设计基础是汇编伪指令,汇编伪操作和宏指令. 伪操作,是ARM汇编语言程序里的一些特殊 ...
- gcc 学习笔记(一) - 编译C程序 及 编译过程
一. C程序编译过程 编译过程简介 : C语言的源文件 编译成 可执行文件需要四个步骤, 预处理 (Preprocessing) 扩展宏, 编译 (compilation) 得到汇编语言, 汇编 (a ...
- [zhuan]arm中的汇编指令
http://blog.csdn.net/qqliyunpeng/article/details/45116615 一. 带点的(一般都是ARM GNU伪汇编指令) 1. ".text& ...
- ARM中的---汇编指令
一. 带点的(一般都是ARM GNU伪汇编指令) 1. ".text".".data".".bss" 依次表示的是"以下是代码段& ...
- uboot学习之uboot-spl的程序流程分析
uboot-spl的程序流程主要包含下面的几个函数: _start->reset->save_boot_params->cpu_init_crit->lowlevel_init ...
随机推荐
- lambda 2
# -*- coding: utf-8 -*- #python 27 #xiaodeng def action(x): return (lambda y:x+y) act=action(99) pri ...
- Eclipse常用且不易记快捷键
大小写转换:CTRL+SHIFT+X,Y 复制行:CTRL+ALT+↑,↓(部分无法使用) 查看继承关系:CTRL+T 直接查看系统源码:CTRL+SHIFT+T 查看所有快捷键:CTRL+SHIFT ...
- Java BigDecimal进行精确计算
前言 float和double类型的主要设计目标是为了科学计算和工程计算.他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的.然而,它们没有提供完全精确的结果,所以 ...
- Git恢复之前版本的两种方法reset、revert(图文详解)
一.问题描述在利用github实现多人合作程序开发的过程中,我们有时会出现错误提交的情况,此时我们希望能撤销提交操作,让程序回到提交前的样子,本文总结了两种解决方法:回退(reset).反做(reve ...
- A brief introduction to Hashing and Rehashing
偶然发现一篇哈希的综述文章,虽然是1996年写的,里面的一些评测在今天看来早已经小case了.但是今天仍然极具参考价值. 地址:http://www.drdobbs.com/database/hash ...
- hdu4135容斥原理 组合遍历
容斥原理实现的关键在于:组合遍历,即如何遍历2^n种组合. 容斥原理的三种写法: DFS 队列数组 位数组 #include<stdio.h> #include<iostream&g ...
- android 添加桌面快捷方式
.在桌面创建快捷方式方法: 方法一:通过长按某一个应用程序的图标在桌面上创建启动该应用程序的快捷方式. 这个方法安装完程序都用户都能实现. 方法二:在应用程序中构建一个Intent,然后以Broadc ...
- Python练习笔记——斐波那契数列
斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一 ...
- python学习笔记011——内置函数pow()
1 语法 pow(x, y[, z]) x -- 数值表达式. y -- 数值表达式. z -- 数值表达式. 函数是计算 x 的 y 次方,如果 z 在存在,则再对结果进行取模,其结果等效于pow( ...
- Linux时间子系统(十三) Tick Device layer综述
一.前言 时间子系统中的tick device layer主要涉及kernel/time/tick-*相关的文件,本文的主要内容就是从high level层次(不纠缠在具体的每行代码)描述tick d ...