我怎么知道.data部分需要从哪里获取init数据?(gcc链接器)

Joh*_*han 8 microcontroller linker gcc bare-metal

在构建基于gcc的裸机mcu项目时,您需要在启动期间处理.data和.bss部分的初始化.

.bss部分非常简单,因为我只是将整个部分填充为0.但是.data部分中的变量需要将它们的初始化数据放在rom/flash中并在启动时复制.

如何知道可以在哪里找到具有初始化值的数据?

我们来举个例子吧.

假设我在main.c中创建了两个全局变量

unsigned int my_global_variable_one  = 1;
unsigned int my_global_variable_two  = 2;
Run Code Online (Sandbox Code Playgroud)

然后我可以在目标文件上使用objdump来查看它们将在哪个部分,但是我在objdump out中找不到任何应该放置init数据的内容.

$ arm-none-eabi-objdump --syms main.o | grep my_global_variable
00000000 g     O .data  00000004 my_global_variable_one
00000004 g     O .data  00000004 my_global_variable_two
Run Code Online (Sandbox Code Playgroud)

然后我可以看看整个系统产生的精灵,在本例中是main.elf.

$ arm-none-eabi-nm -n main.elf | grep my_global_variable
20000000 D my_global_variable_one
20000004 D my_global_variable_two
Run Code Online (Sandbox Code Playgroud)

我在哪里可以找到它们的位置,以便我可以复制数据?我需要在链接器脚本中添加什么内容?

它应该像.text或.rodata,但我怎么知道?

如何检查my_global_variable_one的init数据的位置?

我可以使用readelf或objdump等任何binutils命令找到此数据的位置吗?

/谢谢


这是在stm32(Cortex M3)mcu上,使用了CodeBench版本的gcc.

ams*_*ams 11

编译器将所有代码和一些只读数据放在该.text部分中.可能还有一个.rodata部分.您可以将链接描述文件放在ROM地址中,如下所示:

. = <rom-base-address>;
.rodata : { *(.rodata) }
<other read-only sections go here>
.text   : { *(.text) }
Run Code Online (Sandbox Code Playgroud)

编译器将可写数据的所有初始值放入.data节中,并将所有符号放入初始值中.bss.该.bss很容易,你只需将在RAM中.本.data想在运行时内存,但在加载时ROM,并链接脚本可以让你做到这一点与AT关键词:

. = <ram-base-address>;
.bss  : { *(.bss) }
.data : AT ( ADDR (.text) + SIZEOF (.text) )
        { *(.data) }
Run Code Online (Sandbox Code Playgroud)

这意味着数据部分现在具有不同的LMA和VMA(加载存储器地址/虚拟存储器地址).您的程序将期望在VMA(运行时地址)找到数据,但数据实际上将存在于LMA(您可能必须教您的闪存器执行此操作),这是在该.text部分之后.

如果您需要找出要复制到的位置,那么您可以在链接描述文件中创建指针.所以,像这样修改上面的例子:

.data : AT ( ADDR (.text) + SIZEOF (.text) )
        { _data_lma = LOADADDR(.data); _data_vma = .;
          *(.data);
          _data_size = SIZEOF (.data);}
Run Code Online (Sandbox Code Playgroud)

然后memcpy (_data_vma, _data_lma, _data_size),您可以在启动代码中执行(尽管您可能需要在汇编程序中手动编写代码?)这些符号将在程序中显示为在链接时解析的常量全局变量.因此,在汇编程序代码中,您可能会遇到以下情况:

_data_lma_k:
   .long _data_lma
Run Code Online (Sandbox Code Playgroud)

然后将该数字硬编码到该.text部分中.当然,您的平台上的汇编语法可能有所不同.

有关更多信息,请参阅此处的链接器手册