简体   繁体   English

阻止GCC优化全局变量的问题

[英]Issue preventing GCC from optimizing out global variable

I am using ARM-GCC v4.9 (released 2015-06-23) for a STM32F105RC processor. 我正在使用ARM-GCC v4.9(2015-06-23发布)用于STM32F105RC处理器。
I've searched stackoverflow.com and I've found this in order to try to convince gcc not to optimize out a global variable, as you may see below: 我搜索了stackoverflow.com,我发现这是为了试图说服gcc 不要优化全局变量,如下所示:

static const char AppVersion[] __attribute__((used)) = "v3.05/10.oct.2015";

Yet, to my real surprise , the compiler optimized away the AppVersion variable! 然而, 令我惊讶的是 ,编译器优化了AppVersion变量!
BTW: I am using the optimize level -O0 (default). 顺便说一句:我正在使用优化级别-O0 (默认)。
I also tried using volatile keyword (as suggested on other thread), but it didn't work either :( 我也尝试使用volatile关键字(如其他线程所示),但它也不起作用:(
I already tried (void)AppVersion; 我已经尝试过(void)AppVersion; but it doesn't work... 但它不起作用......
Smart compiler!? 智能编译器!? Too smart I suppose... 我觉得太聪明了......

In the meantime, I use a printf(AppVersion); 在此期间,我使用printf(AppVersion); some place in my code, just to be able to keep the version... But this is a boorish solution :( 在我的代码中的一些地方,只是为了能够保持版本......但这是一个粗野的解决方案:(
So, the question is: Is there any other trick that does the job, ie keep the version from being optimized away by GCC? 所以,问题是:是否有其他技巧可以完成这项工作,即保持版本不被GCC优化掉?

[EDIT]: [编辑]:
I also tried like this (ie without static ): 我也试过这样(即没有static ):

const char AppVersion[] __attribute__((used)) = "v3.05/10.oct.2015";

... and it didn't work either :( ......它也不起作用:(

Given the presence of "static", all your declaration does is ask the compiler to include the bytes representing characters of the string "v3.05/10.oct.2015" in some order at some arbitrary location within the file, but not bother to tell anyone where it put them. 鉴于存在“静态”,所有声明都要求编译器在文件中的某个任意位置以某种顺序包含表示字符串“v3.05 / 10.oct.2015”字符的字节,但不要打扰告诉任何人把它们放在哪里。 Given that the compiler could legitimately write that sequence of bytes somewhere in the code image file whether or not it appeared anywhere in the code such a declaration really isn't very useful. 鉴于编译器可以合法地在代码图像文件中的某处写入该字节序列, 无论它是否出现在代码中的任何地方,这样的声明实际上并不是非常有用。 To be sure, it would be unlikely that such a sequence would appear in the code entirely by chance, and so scanning the binary image for it might be a somewhat reliable way to determine that it appeared in the code, but in general it's much better to have some means of affirmatively determining where the string may be found. 可以肯定的是,这样的序列不可能完全偶然地出现在代码中,因此扫描二进制图像可能是一种可靠的方法来确定它出现在代码中,但总的来说它更好一些有一些肯定地确定可以找到字符串的方法。

If the string isn't declared static, then the compiler is required to tell the linker where it is. 如果字符串未声明为static,则需要编译器告诉链接器它在哪里。 Since the linker generally outputs the names and addresses of all symbols in a variety of places including symbol tables, debug-information files, etc. which may be used in a variety of ways that the linker knows nothing about, it may be able to tell that a symbol isn't used within the code, but can generally have no clue about whether some other utility may be expecting to find it in the symbol table and make use of it. 由于链接器通常输出各种位置的所有符号的名称和地址,包括符号表,调试信息文件等,它们可以以链接器一无所知的各种方式使用,它可能能够分辨代码中没有使用符号,但通常不知道某个其他实用程序是否可能期望在符号表中找到它并使用它。 A directive saying the symbol is "used" will tell the linker that even though it doesn't know of anything that's interested in that symbol, something out in the larger universe the linker knows nothing about is interested in it. 一个说明符号被“使用”的指令将告诉链接器即使它不知道任何对该符号感兴趣的东西,但是在更大的宇宙中,链接器一无所知对它感兴趣。

It's typical for each compilation unit to give a blob of information to the linker and say "Here's some stuff; I need a symbol for the start of it, but I can compute all the addresses of all the internals from that". 每个编译单元通常会向链接器提供一些信息并说“这是一些东西;我需要一个符号来开始它,但我可以从中计算所有内部的所有地址”。 The linker has no way of knowing which parts of such a blob are actually used, so it has no choice but to accept the whole thing verbatim. 链接器无法知道这些blob的哪些部分实际被使用,所以它别无选择,只能逐字接受整个事物。 If the compiler were to include unused static declarations in its blob, they'd make it through to the output file. 如果编译器在其blob中包含未使用的静态声明,则它们会将其传递给输出文件。 On the other hand, the compiler knows that if it doesn't export a symbol for something within that blob, nobody else downstream would be able to find it whether or not the object was included; 另一方面,编译器知道如果它没有为该blob中的某些东西导出符号,那么下游的任何其他人都无法找到它,无论该对象是否被包含在内; thus, there would typically be little benefit to being able to include such a blob and compiler writers generally have to reason to provide a feature to force such inclusion. 因此,能够包括这样的blob通常没什么好处,并且编译器编写者通常必须推理提供强制这种包含的特征。

Unfortunately I am not aware of a pragma to do this. 不幸的是,我不知道这样做的实用工具。
There is however another solution. 然而,有另一种解决方案。 Change AppVersion to: 将AppVersion更改为:

static char * AppVersion = "v3.05/10.oct.2015";

and add: 并添加:

__asm__ ("" : : "" (AppVersion));

to your main function. 到你的主要功能。

You see I dropped the 'used' attribute, according to the documentation this is a function attribute. 您看到我删除了'used'属性,根据文档这是一个函数属性。

Other solutions: Does gcc have any options to add version info in ELF binary file? 其他解决方案: gcc是否有任何选项可以在ELF二进制文件中添加版本信息?

Though I found this one to be the easiest. 虽然我觉得这个最容易。 This basically won't let the compiler and linker remove AppVersion since we told it that this piece of inline assembly uses it, even though we don't actually insert any inline assembly. 这基本上不会让编译器和链接器删除AppVersion,因为我们告诉它这段内联汇编使用它,即使我们实际上没有插入任何内联汇编。

Hopefully that will be satisfactory to you. 希望这对您来说是令人满意的。

Author: Andre Simoes Dias Vieira 作者: Andre Simoes Dias Vieira
Original link : https://answers.launchpad.net/gcc-arm-embedded/+question/280104 原始链接https//answers.launchpad.net/gcc-arm-embedded/+question/280104

It seems that using a custom section also works. 似乎使用自定义部分也有效。

Instead of 代替

__attribute__((used))

try with 尝试

__attribute__((section(".your.section.name.here")))

The linker won't touch it, nor will the strip command. 链接器不会触及它, strip命令也不会触及它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM