“加载地址”和“重定位地址”有什么区别?

时间:2015-03-26 05:50:32

标签: gcc linker ld

关于AT (...)的{​​{1}}指令,this source州:

ld

我一直在搜索,但没有找到明确的定义是什么意思?#34;加载地址"和"搬迁地址"。

据我所知,当目标文件链接在一起时,代码被重新定位"因为跳转地址等被重写以指向组合机器代码中的正确偏移量。那么"重新安置地址"结果对象代码中的部分开始的偏移量?如果是这样,"加载地址"一节可能是不同的东西?

如果这两个地址不同,链接器的输出会如何影响?

2 个答案:

答案 0 :(得分:1)

差异至关重要。重定位地址是对部分中所有重定位的加数。因此,如果它与加载地址不同,则本节中没有任何内容真正起作用 - 内部的所有重定位将被解析为错误的值。

那么为什么我们需要这样的技术呢?没有那么多的应用程序,但假设(from here)你的架构上的内存非常快,在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);

然后自然地使用它,因为它已经加载。这种技术称为叠加。

我认为,例子很清楚。

答案 1 :(得分:1)

经过一些搜索,我找到了一个更好的答案:

每个...输出节都有两个地址。第一个是VMA,或者 虚拟内存地址。这是该部分将在何时提供的地址 输出文件运行。第二个是LMA,即加载内存地址。 这是将加载该节的地址。在大多数情况下 这两个地址将相同。他们何时可能是一个例子 不同之处在于将数据段加载到ROM中然后进行复制 程序启动时进入RAM(此技术通常用于 在基于ROM的系统中初始化全局变量)。在这种情况下 ROM地址为LMA,RAM地址为VMA。

引用自:https://www.sourceware.org/binutils/docs/ld/Basic-Script-Concepts.html#Basic-Script-Concepts

这意味着在节声明中,如:

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] is the VMA[AT(lma)] is the LMA