Gcc “与”的区别是什么;“加载地址”;及;搬迁地址;?
关于Gcc “与”的区别是什么;“加载地址”;及;搬迁地址;?,gcc,linker,ld,Gcc,Linker,Ld,关于ld的AT(…)指令,声明: AT(ldadr) AT关键字后面的表达式ldadr指定节的加载地址。默认设置(如果不使用AT关键字)是使加载地址与重新定位地址相同。此功能旨在使ROM映像的构建变得简单。 我一直在搜索,但没有找到“加载地址”和“重新定位地址”的明确定义 我知道,当对象文件链接在一起时,代码被“重新定位”,跳转地址等被重写,以指向组合机器代码中的正确偏移量。那么,“重新定位地址”是一个区段开始的结果目标代码中的偏移量吗?如果是这样的话,一个节的“加载地址”怎么可能是不同的呢
ld
的AT(…)
指令,声明:
AT(ldadr)
AT关键字后面的表达式ldadr指定节的加载地址。默认设置(如果不使用AT关键字)是使加载地址与重新定位地址相同。此功能旨在使ROM映像的构建变得简单。
我一直在搜索,但没有找到“加载地址”和“重新定位地址”的明确定义
我知道,当对象文件链接在一起时,代码被“重新定位”,跳转地址等被重写,以指向组合机器代码中的正确偏移量。那么,“重新定位地址”是一个区段开始的结果目标代码中的偏移量吗?如果是这样的话,一个节的“加载地址”怎么可能是不同的呢
如果这两个地址不同,链接器的输出会受到什么影响?差异至关重要。重新安置地址添加到第节中的所有重新安置地址。所以,若它和加载地址不同,那个么在这一节中并没有什么真正起作用——这一节中的所有relocs都将被解析为错误的值 那么为什么我们需要这样的技术呢?没有太多的应用程序,但假设()在您的体系结构上有0x1000的极快内存 然后,您可以选择两个部分以获得重新定位地址0x1000:
.text0 0x1000 : AT (0x4000) { o1/*.o(.text) }
__load_start_text0 = LOADADDR (.text0);
__load_stop_text0 = LOADADDR (.text0) + SIZEOF (.text0);
.text1 0x1000 : AT (0x4000 + SIZEOF (.text0)) { o2/*.o(.text) }
__load_start_text1 = LOADADDR (.text1);
__load_stop_text1 = LOADADDR (.text1) + SIZEOF (.text1);
. = 0x1000 + MAX (SIZEOF (.text0), SIZEOF (.text1));
现在,在运行时继续,当您需要text1时,请自行管理它,以便从其实际加载地址复制到正确的地址:
extern char __load_start_text1, __load_stop_text1;
memcpy ((char *) 0x1000, &__load_start_text1,
&__load_stop_text1 - &__load_start_text1);
然后使用它,因为它是在这里自然加载的。这种技术称为叠加
我认为,这个例子非常清楚。经过一些搜索,我找到了一个更好的答案: 每。。。输出部分有两个地址。第一个是VMA,或 虚拟内存地址。这是该节将在何时提供的地址 将运行输出文件。第二个是LMA,或加载内存地址。 这是将加载节的地址。在大多数情况下 这两个地址将是相同的。这是一个关于他们何时可能会出现的例子 不同的是,将数据段加载到ROM中,然后进行复制 当程序启动时(这种技术通常用于 在基于ROM的系统中初始化全局变量)。在这种情况下 ROM地址将是LMA,RAM地址将是VMA 引自: 这意味着在类似以下的章节声明中:
section [address] [(type)] :
[AT(lma)]
[ALIGN(section_align) | ALIGN_WITH_INPUT]
[SUBALIGN(subsection_align)]
[constraint]
{
output-section-command
output-section-command
…
} [>region] [AT>lma_region] [:phdr :phdr …] [=fillexp]
[address]
和[AT(lma)]
Konstantin,谢谢你的例子。我想我能理解:链接代码中的所有跳转、调用等都是按照代码将在“重新定位地址”加载的方式计算的,但在运行时,它实际上是在“加载地址”加载的?那么,“加载地址”实际上是代码出现的对象文件中的偏移量吗?或者对象文件(ELF等)是否包含指令,告诉加载程序在运行时将代码放在内存中的什么位置?为了澄清我的问题,一旦链接器确定了某个节的“加载地址”,这将如何影响输出二进制文件?是的,如果您的目标是UNIX系统,则它是ELF格式的一部分好,我现在明白了。。。对于ELF文件中的每个段,都有一个“程序头”,其中包含文件内的偏移量及其加载地址。查看带有readelf
的vmlinux
Linux内核二进制文件,我可以看到它有3个部分,每个部分超过10个部分。这是否意味着引导加载程序将读取这些ELF头并在指定的“加载地址”加载每个段?实际上从未在os内核中尝试过。我想,内核不使用标准加载程序,引导加载程序可能会忽略ELF头中的某些内容或处理其他内容。我认为试着看看它们在哪里比较简单。非常感谢+1.