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

在学习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. 201521123088《Java程序》第二周总结

    #1. 本章学习总结 ①java基本数据类型 ②String类对象使用 #2. 书面作业 使用Eclipse关联jdk源代码,并查看String对象的源代码(截图)?分析String使用什么来存储字符 ...

  2. java课设

    1.代码截图: 2.设计思路 建立GUI界面,系统产生一个随机数(对用户不可见),然后用户输入猜测数,系统根据用户每次输入的数据给出评语(偏大,偏小,猜测成功).当用户最终猜测成功后,就把当次的随机数 ...

  3. Java:final、static关键字 详解+两者结合使用

    一  final关键字 1) 关于final的重要知识点 final关键字可以用于成员变量.本地变量.方法以及类. final成员变量必须在声明的时候初始化或者在构造器中初始化,否则就会报编译错误. ...

  4. Thinkphp3.2结合phpqrcode生成二维码(含Logo的二维码),附案例

    首先,下载phpqrcode,将其解压到项目ThinkPHP\Library\Vendor目录下.Index_index.html(模板可自行配置) <form action="{:U ...

  5. python之面向对象2

    一.类命名空间与对象.实例的命名空间    常见一个类就会创建一个类的名称空间,用来储存类中定义的所有名字,这些名字成为类的属性  而类有两种属性:静态属性和动态属性 静态属性就是直接在类中定义的变量 ...

  6. Mybatis第四篇【多表连接】

    Mybatis多表连接 我们在学习Hibernate的时候,如果表涉及到两张的话,那么我们是在映射文件中使用<set>..<many-to-one>等标签将其的映射属性关联起来 ...

  7. 用户登陆注册【JDBC版】

    前言 在讲解Web开发模式的时候,曾经写过XML版的用户登陆注册案例!现在在原有的项目上,使用数据库版来完成用户的登陆注册!如果不了解的朋友,可以看看我Web开发模式的博文! 本来使用的是XML文件作 ...

  8. 06jQuery-01-基本选择器

    1.jQuery概要 JavaScript的一个库,只是一个jquery-xxx.js的文件,它可以让你写更少的代码,做更多的事. $是著名的jQuery符号.实际上,jQuery把所有功能全部封装在 ...

  9. PHP 安装配置

    ./configure --prefix=/usr/local/php --with-libdir=/lib/x86_64-linux-gnu --with-config-file-path=/usr ...

  10. showfm练习小项目总结

    Showfm 项目总结: 有一个主页面, 有一个service,启动和结束一般在主页面里面完成. OnCreate启动service OnDestroy关闭service EventBus 信息传递 ...