应用程序在链接描述文件中定义的访问符号 [英] Access symbols defined in the linker script by application

查看:19
本文介绍了应用程序在链接描述文件中定义的访问符号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的链接描述文件中,我定义了两个符号

In my linker script file, I have defined two symbols

define symbol _region_RAM_start__     = 0xC0000000;
define symbol _region_RAM_end__       = 0xC00fffff; 

然后我将它们导出,如下所示

and then I have exported them as well as shown below

export symbol _region_RAM_start__;
export symbol _region_RAM_end__;

从应用程序代码中,我尝试访问这些符号

From the application code, I try to access these symbols

extern const unsigned int _region_RAM_start__;
extern const unsigned int _region_RAM_end__;
....
int GetRAMSize()
{
    int size = 0;
    unsigned int address_1 = _region_RAM_start__;
    unsigned int address_2 = _region_RAM_end__;
    size = address_2 - address_1 + 1U;
    return size;
}

现在,我预计返回值为 0x00100000,但是,我得到的只是 0.因此,当我转向调试器时,我注意到 _region_RAM_start___region_RAM_end__ 的值分别为 0xC0000000 和 0xC00fffff,但 address_1address_2 的值为 0.

Now, I expected the return value to be 0x00100000, however, all I get is 0. So, when I turned to the debugger, I noticed that _region_RAM_start__ and _region_RAM_end__ have the values 0xC0000000 and 0xC00fffff respectively, but address_1 and address_2 have the value 0.

编译器优化设置为无".这一直困扰着我一段时间.是否有一些非常明显的东西我在这里遗漏了(除了我一开始就不应该这样做")?

The compiler optimization is set to "None". This has been bugging me for a while now. Is there something very obvious I am missing here (other than "I should not be doing this in the first place")?

解决方案感谢 n.m.为了答案

Solution Thanks to n.m. for the answer

  unsigned int address_1 = (unsigned int) (&_region_RAM_start__);

否则 address_1address_2 都包含垃圾值(即分别在地址 0xC0000000 和 0xC00fffff 处可用的值,但从这段代码的角度来看是垃圾)

Otherwise address_1 and address_2 both contain garbage values (i.e. values available at the address 0xC0000000 and 0xC00fffff respectivly, but garbage from the point of view of this code)

推荐答案

虽然有点老了,但我还是会回答的……

That's a bit old but i will answer it anyways…

来自 ld 手册:

From the ld manual:

从源代码访问链接描述文件定义的变量是不直观.特别是链接描述文件符号不是相当于高级语言中的变量声明,相反,它是一个没有值的符号.

Accessing a linker script defined variable from source code is not intuitive. In particular a linker script symbol is not equivalent to a variable declaration in a high level language, it is instead a symbol that does not have a value.

在继续之前,重要的是要注意编译器经常将源代码中的名字转换成不同的名字当它们存储在符号表中时.例如,Fortran编译器通常预先或附加下划线和 C++执行广泛的名称修改.因此可能有一个使用的变量名称之间的差异源代码和定义的相同变量的名称在链接描述文件中.例如,在 C 中,链接描述文件变量可以称为:

Before going further, it is important to note that compilers often transform names in the source code into different names when they are stored in the symbol table. For example, Fortran compilers commonly prepend or append an underscore, and C++ performs extensive name mangling. Therefore there might be a discrepancy between the name of a variable as it is used in source code and the name of the same variable as it is defined in a linker script. For example in C a linker script variable might be referred to as:

extern int foo;

但在链接描述文件中它可能被定义为:

But in the linker script it might be defined as:

_foo = 1000;

然而,在其余示例中,假定没有名称转变已经发生.

In the remaining examples however it is assumed that no name transformation has taken place.

当一个符号用 C 等高级语言声明时,发生了两件事.首先是编译器保留程序内存中有足够的空间来保存 value符号.第二个是编译器创建一个入口在包含符号地址的程序符号表中.即符号表包含内存块的地址持有符号的值.所以例如下面的C声明,在文件范围内:

When a symbol is declared in a high level language such as C, two things happen. The first is that the compiler reserves enough space in the program's memory to hold the value of the symbol. The second is that the compiler creates an entry in the program's symbol table which holds the symbol's address. ie the symbol table contains the address of the block of memory holding the symbol's value. So for example the following C declaration, at file scope:

int foo = 1000;

在符号表中创建一个名为foo"的条目.此条目保存一个 int 大小的内存块的地址,其中最初存储数字 1000.

creates a entry called "foo" in the symbol table. This entry holds the address of an int sized block of memory where the number 1000 is initially stored.

当程序引用符号时,编译器会生成代码首先访问符号表以找到符号的内存块,然后代码从中读取值内存块.所以:

When a program references a symbol the compiler generates code that first accesses the symbol table to find the address of the symbol's memory block and then code to read the value from that memory block. So:

foo = 1;

在符号表中查找符号foo,得到地址与此符号关联,然后将值 1 写入那个地址.鉴于:

looks up the symbol foo in the symbol table, gets the address associated with this symbol and then writes the value 1 into that address. Whereas:

int * a = & foo;

在符号表中查找符号foo,得到它的地址然后将此地址复制到关联的内存块中使用变量a".

looks up the symbol foo in the symbol table, gets it address and then copies this address into the block of memory associated with the variable "a".

相比之下,链接器脚本符号声明创建一个条目在符号表中,但不为它们分配任何内存.因此它们是没有值的地址.例如链接器脚本定义:

Linker scripts symbol declarations, by contrast, create an entry in the symbol table but do not assign any memory to them. Thus they are an address without a value. So for example the linker script definition:

foo = 1000;

在符号表中创建一个名为 @samp{foo} 的条目,其中包含内存位置 1000 的地址,但没有存储任何特殊内容在地址 1000.这意味着您无法访问 value链接描述文件定义的符号 - 它没有任何价值 - 你可以做的一切是使用链接描述文件定义符号的地址.

creates an entry in the symbol table called @samp{foo} which holds the address of memory location 1000, but nothing special is stored at address 1000. This means that you cannot access the value of a linker script defined symbol - it has no value - all you can do is use the address of a linker script defined symbol.

因此,当您在源代码中使用链接描述文件定义的符号时代码,您应该始终获取符号的地址,并且永远不要尝试使用它的价值.例如假设你想复制将一段名为 .ROM 的内存的内容放入一个段中称为 .FLASH 并且链接描述文件包含以下声明:

Hence when you are using a linker script defined symbol in source code you should always take the address of the symbol, and never attempt to use its value. For example suppose you want to copy the contents of a section of memory called .ROM into a section called .FLASH and the linker script contains these declarations:

start_of_ROM   = .ROM;
end_of_ROM     = .ROM + sizeof (.ROM);
start_of_FLASH = .FLASH;

那么执行复制的 C 源代码将是:

Then the C source code to perform the copy would be:

extern char start_of_ROM, end_of_ROM, start_of_FLASH;

memcpy (& start_of_FLASH, & start_of_ROM, & end_of_ROM - & start_of_ROM);

注意使用&"运营商.他们是正确的.

Note the use of the "&" operators. They are correct.

这篇关于应用程序在链接描述文件中定义的访问符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆