加载地址和运行时地址 & 代码重定位 (2020)

2018年曾经写过该内容,2020年回顾了一下,发现之前所述有些谬误,加上排版有些问题,因此这里就再开一篇再做一次记录,也当是自己这些年的成长对比了。(该主题是对链接脚本中所用到的地址结合实际使用中的一些概念得出,链接脚本内容可以参考 http://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_mono/ld.html#IDX237 )

2018的标题为编译地址和运行地址,这里更加准确的应该为加载地址运行时地址(或重定位地址),还需要引入一个存储地址

首选需要知道的是裸机运行的程序需要存储在存储器中,可以是NorFlash或者NandFlash及各种可以掉电保存的静态存储器,当程序读取存储器保存的程序进行解码执行时,程序就启动了,一般裸板程序都是从0地址开始取代码,而我们的程序也自然地需要从存储器0地址开始存储,这里的0就是程序的存储地址,存储地址仅跟对存储器的写有关,可以任意确定,你也可以把程序写到存储器的中间位置,当然这样仍需要0地址处存在引导程序,因此为了裸板程序能够正常运行,我们将程序保存到0地址处。

但是程序运行起来之后,因为各种原因不能在原来的存储地址处运行,这里的原因可能是:

1.我们用的存储器是NorFlash只读存储器(仅针对运行时而言,NorFlash使用芯片手册提供命令也可写),这会导致程序中用到的全局变量或者静态局部变量等data和bss段数据都无法被修改,从而影响到程序的逻辑。

2.使用的是NandFlash,以S3C2440芯片为例,使用NandFlash作为boot Flash时,2440存在机制将NandFlash中的前4K内容复制到片内SRAM中,SRAM作为0地址运行程序,此时如果我们的程序超过4K大小,将会导致程序无法运行。

正是因为上述的原因存在,所以我们需要将程序重定位到一片可用的内存上,一般为SDRAM,这里假设SDRAM的base address为0x3000,则我们程序需要通过一种机制,使得程序在运行之后在0x3000地址处运行,这种机制就叫做代码重定位,0x3000为程序的运行时地址

运行时地址是程序运行的地址,不管程序存储在哪里,以什么地址开始运行,程序都会认为自己在运行时地址处运行中,所有全局变量和静态局部变量等data段或者bss段数据都以运行时地址编址进行访问,如一个全局变量a,运行时地址为0x301F,所有需要使用到该变量的代码都会到0x301F这个地址去访问取值或者赋值,此时就出现一个问题,我们的程序存储在0地址处,未重定位前,0x3000及往后地址数据都是未知的,这时候去0x301F取值是未定义行为。同样如果存在一个函数functionA,他的运行时地址是0x321F,可能他的存储地址在0x11FF,但是未定位前使用绝对跳转指令跳转到运行时地址也是未定义行为。

简单来说就是程序存储在0地址为起始的地方,程序运行起来是在0地址开始运行,但是程序自己觉得(实际上编译时也确定了各个指令的地址,反汇编即可看到)已经在0x3000这一运行时地址处运行了,因此对全局变量的访问也是通过运行时地址进行访问,如果直接使用会出现问题。程序之所以能够正常运行,是因为使用了位置无关码,进行了相对跳转,如果使用的是绝对跳转,直接跳转也是会有问题。

代码重定位就是在运行时地址处相应区域填充代码和数据,这个是编译时已经确定好的,存储地址处有所有需要的“原材料”。一般代码重定位包含1.将程序从存储地址 我复制我自己 到运行时地址中 ;2.清除bss段 等。

最后是加载地址,对于裸板程序而言,编译输出的bin文件结构与NorFlash 0地址处存放的结构一样,而加载地址即存储地址处结构的相对位置地址,这也影响着bin文件的大小,一般可以紧凑着排放,重定位到运行时地址时再从对应的加载地址中复制数据到运行时地址处。

发现两年过去自己的描述能力仍旧没什么进步,思绪万千落实到文字全部变了样,还是附上图希望有些帮助把。

下图采用链接脚本描述一个文件最终的内存分布。

加载地址和运行时地址 & 代码重定位 (2020)_第1张图片

如图中假设我们的代码段加载地址为0,数据段加载地址为0x80,而运行时地址分别为0x3000和0x31FF,同时假设代码段长度为0x80,则加载后代码段和数据段紧挨着,bin的大小也为段大小的总和没有空洞,存储到0地址NorFlash时(这里并非加载地址为0,存储地址就为0,存储地址是我们自己确定的,想存哪里存哪里,加载地址只是一个相对的结构,只是统一会简化代码工作量,为0则是芯片运行要求),如下:

加载地址和运行时地址 & 代码重定位 (2020)_第2张图片

 通过上图可以清晰看到重定位所做的事情以及加载地址运行时地址的情况。

受表达能力所限,有些未能很好的描述清楚,如有疑问欢迎提出,也欢迎交流讨论指出不正确指出。不忘初心 。

你可能感兴趣的:(计算机常识类)