关于使用连接器arm-linux-ld时指定链接地址的作用
首先,记住一句话:程序的链接地址必须等于运行地址!
在学习exynos 4412的启动过程时,发现自己对链接地址的作用不是很了解,于是上网查找了资料做了基本了解,在此做个总结。

上图是exynos 4412启动时iROM、BL1和BL2在iRAM中的分布情况。由图中可以看出,BL2会被加载到0x020_3400的起始地址处(由BL1加载),照理来说,在BL2代码编译链接过程中应该将链接地址指定到0x0202_3400才是正确的,但是在实际做led实验(此处BL2的代码功能即是按键控制led亮灭)过程中发现,将链接地址指定为0x0202_0000也照常运行。以下为链接脚本的内容:
SECTIONS
{
. = 0x02020000; #注:此处正确的链接地址应该为0x0202_3400
.text : { *(.text) }
.rodata ALIGN(4) : {*(.rodata*)}
.data ALIGN(4) : { *(.data*) }
.bss ALIGN(4) : { *(.bss) *(COMMON) }
}
要想明白原因,就得理解链接地址的作用。
先看链接器的作用:
当链接器进行链接的时候,首先决定各个目标文件在最终可执行文件里的位置。然后访问所有目标文件的地址重定义表,对其中记录的地址进行重定向 (加上一个偏移量,即该编译单元在可执行文件上的起始地址)。然后遍历所有目标文件的未解决符号表,并且在所有的导出符号表里查找匹配的符号, 并在未解决符号表中所记录的位置上填写实现地址。最后把所有的目标文件的内容写在各自的位置上,再作一些另的工作,就生成一个可执行文件。
在上述链接脚本中指定的链接地址,即是告诉链接器将程序的起始地址设置为0x0202_0000,由此,链接器会根据这个设定的起始地址设定程序中位置相关代码的地址。假设链接地址是0x0202_0000,而程序的起始地址实际是在0x0202_3400,当运行位置无关代码时(即要跳转的运行地址为当前PC的值加上一个相对偏移量),CPU可以正确找到程序的存放位置,因此运行不会出错。但是如果存在位置相关代码(即链接时指定好的固定具体地址,非当前PC值加相对偏移量获得的相对地址),那么当CPU跳转到对应的运行地址处运行时,由于实际的代码存放地址与运行地址(运行地址由链接时根据链接地址计算得到)不同,那么运行就会出错了。
举个例子:假设当将链接地址指定为0x0202_0000,由此生成的可执行程序中有条位置相关代码是 goto 0x0202_1000 ,而实际可执行程序存放在0x0202_3400的起始地址处,那么实际 goto 0x0202_1000 对应的代码就不在0x0202_1000处了,而CPU通过执行 goto 0x0202_1000 跳转到0x0202_1000处,到那里去运行代码,却找不到对应的代码,因此程序运行就出错了。
如果链接地址与程序在内存中的实际存放起始地址不同,当没有位置相关代码时程序运行不会出错,这就是前面说的led程序可以正常运行的原因。但是如果程序中有位置相关代码,那么当运行到位置相关代码时,便会发生错误。
因此,程序的链接地址必须等于运行地址。
关于使用连接器arm-linux-ld时指定链接地址的作用的更多相关文章
- gcc编译时指定链接库的查找目录
gcc编译时,如果需要链接的库的目录不在标准目录,则需要通过将保护库的目录/aa/bb/cc通过-L/aa/bb/cc 添加到搜索路径中,如: gcc -o xmltest xml_test.cpp ...
- linux系统启动时更改MAC地址
vim /etc/rc.local #change the server's MAC address("00:50:56:84:5C:76" change to 00:50:56: ...
- linux tar 解压文件时指定文件名
linux解压文件时指定文件夹名称 wget -O mysql-5.6.15.tar.gz http://oss.aliyuncs.com/aliyunecs/onekey/mysql/my ...
- ARM Linux中断发生时内核堆栈切换
转载注明出处:http://www.wowotech.net/forum/viewtopic.php?id=54 对ARM Linux中断非常简洁.精确的描述. 发生了中断,最重要的是保存现场,在中断 ...
- Linux关机时执行指定脚本
要实现在Linux关机时执行某个脚本的具体思路 1.在文件夹 /etc/init.d/ 下创建关机时需要执行的脚本 file_name; 2.分别在文件夹 /etc/rc0.d/ 和 /etc/rc6 ...
- linux 运行时加载不上动态库 解决方法(转)
1. 连接和运行时库文件搜索路径到设置 库文件在连接(静态库和共享库)和运行(仅限于使用共享库的程序)时被使用,其搜索路径是在系统中进行设置的.一般 Linux 系统把 /lib 和 /usr ...
- ARM Linux 3.x的设备树(Device Tree)
http://blog.csdn.net/21cnbao/article/details/8457546 宋宝华 Barry Song <21cnbao@gmail.com> 1. ...
- ARM Linux 3.x的设备树(Device Tree)
1. ARM Device Tree起源 Linus Torvalds在2011年3月17日的ARM Linux邮件列表宣称“this whole ARM thing is a f*cking pai ...
- sqlite3移植到arm linux
1,环境: 软件:linux:2.6.38 硬件:6410 交叉编译工具:arm-linux-gcc 也适用于其他linux平台. 2,步骤: 1>下载sqlite3源码包: http://ww ...
随机推荐
- Swing-布局管理器之BorderLayout(边界布局)-入门
注:本文内容基本源于Java图形化界面设计——布局管理器之BorderLayout(边界布局),笔者学习过程中根据自身理解进行少量编辑. 边界布局管理器(BorderLayout)把容器的的布局分为五 ...
- 201521123034 《Java程序设计》第五周学习总结
1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 2. 书面作业 作业参考文件下载 代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件 ...
- 《Java程序设计》第5周学习总结
1. 本章学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 1.2 可选:使用常规方法总结其他上课内容. 2. 书面作业 1. 代码阅读:Child压缩包内源代码 1.1 com.par ...
- Java课程设计—象棋
1. 团队名称.团队成员介绍 团队名称:WY 团队成员: 吴慧婷[组长] 201521123094 网络1514 姚佳希 201521123042 网络1512 2 项目git地址 Java课程设计 ...
- JAVA课程设计 学生成绩管理
学生成绩管理 可实现功能: 添加学生功能:姓名.学号.性别.出生年月日.(学号自动生成且唯一) 添加学生成绩功能:每个人都有数学.Java与体育四门课,可分课程输入成绩. 根据学生学号查找学生成绩功能 ...
- Java:验证在类继承过程中equals()、 hashcode()、toString()方法的使用
以下通过实际例子对类创建过程汇中常用的equals().hashcode().toString()方法进行展示,三个方法的创建过程具有通用性,在项目中可直接改写. //通过超类Employee和其子类 ...
- [js高手之路]Node.js+jade+express+mongodb+mongoose+promise实现todolist
promise主要是用来解决异步回调问题,其实还有好几种比promise更好的方案,后面再说,这节,我们先用promise来改造下,我以前写的一篇文章[js高手之路]javascript腾讯面试题学习 ...
- Docker入门之三容器
上一篇博客学习了下镜像,今天来学习容器.容器类似一个手机中的沙盒环境,用来运行app实例.和镜像一样也是对容器的创建.删除.导出等. 由于我买的参考书中的例子好多都是基于linux的,所以我将dock ...
- struts2---自定义类型转换器
从servlet我们知道从页面获取到的参数都是string类型,但是struts2中基本的数据类型,它可以自动帮我们转化为其对应的包装类,就像获取到123,可以自动转化为Integer,但是比如201 ...
- 在JavaScript中使用json.js:使得js数组转为JSON编码
在json的官网中下载json.js,然后在script中引入,以使用json.js提供的两个关键方法. 1.数组对象.toJSONString() 这个方法将返回一个JSON编码格式的字符串,用来表 ...