我已经开始阅读Miro Samek的用GNU建造裸金属臂系统,并发现自己被困在了一个特定的点上。造成我困惑的原因出现在PDF第10页的注释中:
注意:函数low_level_init()可以使用C/C++编码,但有以下限制。函数必须在ARM状态下执行,它不能依赖于.data节的初始化或.bss节的清除。此外,如果要执行内存重映射,则必须在low_level_init()函数中执行,因为在此函数返回后,代码不再与位置无关。
代码“不再独立于位置”到底是怎么回事?似乎引用的代码(可在PDF的第7-9页上查看)在从low_level_init / _cstartup标签返回后仍然是独立的。_cstartup标签之后的说明唯一不同之处是,它们引用了链接器脚本中定义的标签(指南第3节)。
那么,重新映射究竟如何影响它后面的指令是否与位置无关?
发布于 2020-03-30 22:31:25
位置无关是一个负载时间概念,而不是运行时概念。位置无关是一种代码质量,它允许将其加载到内存中的任何地址,并且仍然可以工作,但是位置无关并不是运行程序的质量。
一旦我们有了引用代码的调用堆栈和/或(重新定位)数据,我们就不再具有代码或数据的位置独立性,并且无法移动它们。实际上,当程序开始执行时(尽管位置无关代码),位置独立性就消失了。
这两个返回地址--通过调用(例如BL)动态生成--以及指向代码的数据指针(代码指针向量(在vtable中),以及初始化的全局函数指针)破坏正在运行的程序的位置独立性。
作者的警告节点是描述位置独立性消失的一种方式。更令人困惑的是,通过非常仔细的操作,即使代码的执行已经开始,它们仍然允许实际移动代码,因此,在执行开始后,位置独立性实际上会持续一些小的时间。
但是一个程序不能正常工作(例如,调用和使用函数指针)而不放弃位置独立性,因此他们选择在low_level_init的末尾画一条线。
例如,reset代码需要很长的时间来使用非标准调用来调用low_level_init --在不使用BL或mov lr,pc的情况下为其提供lr值(这将捕获cstartup的预映射(ROM)地址。) lr值提供的是low_level_init将“返回”的(重新定位的) cstartup地址!
(10) LDR r0,=_reset /* pass the reset address as the 1st argument */
(11) LDR r1,=_cstartup /* pass the return address as the 2nd argument */
(12) MOV lr,r1 /* set the return address after the remap */
(13) LDR sp,=__stack_end__ /* set the temporary stack pointer */
(14) B low_level_init /* relative branch enables remap */
_cstartup:B与MOV lr,r1相结合的调用就是调用。
https://stackoverflow.com/questions/60937370
复制相似问题