首先,记住一句话:程序的链接地址必须等于运行地址!

在学习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时指定链接地址的作用的更多相关文章

  1. gcc编译时指定链接库的查找目录

    gcc编译时,如果需要链接的库的目录不在标准目录,则需要通过将保护库的目录/aa/bb/cc通过-L/aa/bb/cc 添加到搜索路径中,如: gcc -o xmltest xml_test.cpp ...

  2. linux系统启动时更改MAC地址

    vim /etc/rc.local #change the server's MAC address("00:50:56:84:5C:76" change to 00:50:56: ...

  3. linux tar 解压文件时指定文件名

      linux解压文件时指定文件夹名称   wget -O mysql-5.6.15.tar.gz  http://oss.aliyuncs.com/aliyunecs/onekey/mysql/my ...

  4. ARM Linux中断发生时内核堆栈切换

    转载注明出处:http://www.wowotech.net/forum/viewtopic.php?id=54 对ARM Linux中断非常简洁.精确的描述. 发生了中断,最重要的是保存现场,在中断 ...

  5. Linux关机时执行指定脚本

    要实现在Linux关机时执行某个脚本的具体思路 1.在文件夹 /etc/init.d/ 下创建关机时需要执行的脚本 file_name; 2.分别在文件夹 /etc/rc0.d/ 和 /etc/rc6 ...

  6. linux 运行时加载不上动态库 解决方法(转)

    1. 连接和运行时库文件搜索路径到设置     库文件在连接(静态库和共享库)和运行(仅限于使用共享库的程序)时被使用,其搜索路径是在系统中进行设置的.一般 Linux 系统把 /lib 和 /usr ...

  7. ARM Linux 3.x的设备树(Device Tree)

    http://blog.csdn.net/21cnbao/article/details/8457546 宋宝华 Barry Song <21cnbao@gmail.com> 1.     ...

  8. 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 ...

  9. sqlite3移植到arm linux

    1,环境: 软件:linux:2.6.38 硬件:6410 交叉编译工具:arm-linux-gcc 也适用于其他linux平台. 2,步骤: 1>下载sqlite3源码包: http://ww ...

随机推荐

  1. 201521123003《Java程序设计》第5周学习总结

    1. 本章学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 参考资料: 百度脑图 XMind 2. 书面作业 Q1.代码阅读:Child压缩包内源代码 1.1 com.parent包中C ...

  2. 201521123030《Java程序设计》第5周学习总结

    1. 本周学习总结 1.代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误.并分析输出结果. 因为i在类中是priv ...

  3. 在Myeclipse中用Java语言操作mysql数据库

    package OperateMysql; import java.sql.*; public class MysqlTest { public static void main(String[] a ...

  4. Windows下chm转换为html的超简单方法

    摘要:通过调用Windows命令,将chm 文件转换为html 文件 概述:很多程序员朋友都会遇到这样的问题,看一个离线版的帮助文档(chm文件),总会产生一个索引文件(该文件的chw文件), 而且有 ...

  5. Tiled Editor 图块的两种导入方式

    一.图块集图块的导入. 打开或者创建地图后,新建 新图块. 弹出新图块面板 图块类型选择 "基于图块集图块",一定要选择"嵌入地图",否则需要另存为其他类型的文 ...

  6. Java为什么把String设计成不可变的(immutable)

    在java中,String是字符串常量,可以从内存,同步机制,数据结构等方面分析 1:字符串中常量池的需要 String不同于普通基础变量类型的地方在于对象.java中的字符串对象都保存在字符串常量池 ...

  7. 每天学点SpringMVC-拦截器

    1. 先写个Hello World 1.1 写一个Interceptor class并实现HandlerInterceptor接口 public class FirstInterceptor impl ...

  8. JDFS:一款分布式文件管理系统,第三篇(流式云存储)

    一 前言 看了一下,距离上一篇博客的发表已经过去了4个月,时间过得好快啊.本篇博客是JDFS系列的第三篇博客,JDFS的目的是为了实现一个分布式的文件管理系统,前两篇实现了基本的上传.下载功能,但是那 ...

  9. windows 结束进程的详细过程

    windows上如何结束进程的详细过程,下面附详细,图文说明 在cmd下,输入  netstat   -ano|findstr  8080      //说明:查看占用8080端口的进程 在cmd下, ...

  10. 【运维】CPU负载

    最近对我的本本(4核8线程)用top命令看系统状况出现了CPU利用率超过200%的情况,非常诧异,查了下相关资料,把这个问题弄清楚了.首先来分析下CPU Load load average: 0.09 ...