gpt4 book ai didi

linker - 提供意外加载地址的 GNU 链接器映射文件

转载 作者:行者123 更新时间:2023-12-05 01:11:54 24 4
gpt4 key购买 nike

我正在开发一个嵌入式程序,其中有一个自定义链接器脚本。该程序可以运行,但我注意到链接器在内存中放置几个​​部分的方式可能存在问题。

以下是链接描述文件的相关部分:

MEMORY {
ROM (rx) : ORIGIN = 0x00100000, LENGTH = 16k
RAM (rwx) : ORIGIN = 0x00200000, LENGTH = 4k
}

SECTIONS {
/* Other sections go here. */
.data : {
...
} >RAM AT>ROM

.bss : {
...
} >RAM

.stack : {
...
} >RAM
...
}

这是 MAP 文件的相关部分:
.data           0x00200040        0x0 load address 0x001003d4
0x001003d4 __data_load = LOADADDR (.data)
0x00200040 __data_start = .
*(.data)
*(.data*)
0x00200040 . = ALIGN (0x4)
0x00200040 _edata = .

.igot.plt 0x00200040 0x0 load address 0x001003d4
.igot.plt 0x00000000 0x0 ./debug/sam7s_startup.o

.bss 0x00200040 0x0 load address 0x001003d4
0x00200040 __bss_start__ = .
*(.bss)
*(.bss*)
*(COMMON)
0x00200040 . = ALIGN (0x4)
0x00200040 _ebss = .
0x00200040 __bss_end__ = .
0x00200040 PROVIDE (end, _ebss)
0x00200040 PROVIDE (_end, _ebss)
0x00200040 PROVIDE (__end__, _ebss)

.stack 0x00200040 0x200 load address 0x001003d4
0x00200040 __stack_start__ = .

因此,从映射文件来看,我认为 .bss 和 .stack 部分正在获取 ROM 中的加载地址。我认为这是因为这两行:
.bss 0x00200040 0x0 load address 0x001003d4 .stack 0x00200040 0x200 load address 0x001003d4
这不好,因为它们没有必要占用 ROM 中的空间。 .bss 部分虽然现在是空的,但将包含未初始化的全局变量,这些变量将在代码中设置为零。堆栈也只是将在代码中初始化的 RAM 的一部分。因此,这些部分中的任何一个都不需要占用 ROM 中的空间。

所以我的问题是,阻止 .bss 和 .stack 加载到 ROM 的正确方法是什么?我是否必须更改 >RAM 中 .bss 和 .stack 部分的结尾?至 >RAM AT>RAM ?这似乎有点多余。

在测试了一些东西后,我发现了以下内容:

(1) 使用 (NOLOAD)属性(例如通过将 .stack : 替换为 .stack (NOLOAD) : )仍然导致映射文件显示 .stack 和 .bss 部分的 ROM 加载地址。

(2) 指定 RAM AT>RAM ,如上所述,确实阻止 map 输出显示 .stack 和 .bss 部分的 ROM 加载地址。

(3) 当映射文件显示 .bss 和 .stack 部分的加载地址时,看起来它们实际上并没有占用 ROM 中的空间。 .stack 部分虽然长 0x200 字节,但似乎实际上并没有占用 ROM 中的空间,即使我为其指定了填充值并在链接描述文件中放置了一个部分。链接描述文件中跟在它后面的部分不会随着不同的堆栈大小移动。

所以也许映射文件输出并不意味着我认为它意味着什么,并且 .stack 和 .bss 部分实际上根本没有在 ROM 中被赋予加载地址。在尝试了一些事情之后,它肯定会以这种方式出现。知道为什么映射输出使它看起来好像这些部分被赋予了 ROM 加载地址仍然会很有趣,尤其是当 (NOLOAD) 时。用来。这可能只是 LD 如何生成其 map 输出文件的错误吗?

另请参阅: Understanding the Location Counter of GNU Linker Scripts

最佳答案

您正在寻找 NOLOAD .见 Gnu LD output section type .我现在读了你的整篇文章,我看到你假设了 NOLOAD .与 NOLOAD ,所有地址都已定义。如果您在“C”代码中使用它们,它们将从该地址加载。您必须提供一些启动代码,通常在清除 BSS 区域的汇编程序中。通常,您不希望您的堆栈被初始化。
NOLOAD部分就像编译/链接时间 malloc() .您可以使用内存,只是不要指望那里有任何东西。对于 BSS,您定义 __bss_start____bss_end__在您的链接器脚本中并编写一个简短的初始化例程以使用这些变量/地址清除此内存。

注:一切都显示在 map 文件中。它不会出现在生成的二进制文件中,也不会在 ELF 中包含数据。只有部分元信息将保存在 ELF 中。

编辑: map 文件中的加载地址就像一个用于加载的位置计数器。加载地址是ld设置放东西。 ld如果它们的尺寸为零,则并没有真正将它们放在那里。 map 输出在语言上没有歧义;我可以看到它是多么令人困惑,但是 ld在创建输出二进制文件时正确地做事情。 BSS 通常标记为 NOLOAD通过目标文件中的 gcc,所以在示例中只有 堆栈部分需要NOLOAD .对于类似 堆栈 , 一个部分并不是真正需要的,只需要一组符号声明就可以了。

关于linker - 提供意外加载地址的 GNU 链接器映射文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14453996/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com