Prevent gcc from deleting an unused variable

Our source files usually have a version line:

static const char srcvers[] = "VERSION/foo.c/1.01/09.04.15"; 

When this line is not optimized, it is very useful in some cases, since you can determine the version of each source file associated with the executable by simply calling strings a.out | grep VERSION strings a.out | grep VERSION .

Unfortunately, optimized by gcc (using '-O'). So my question is whether there is a simple way (the compiler should work fine) so that gcc saves this variable (its name is always the same) without disabling other optimizations.

Edit

What, in my opinion, distinguishes the question from the fact that I , is that I was hoping to find a solution for which I would not have to touch thousands of source files.

+11
c gcc
source share
5 answers

You can use __attribute__((used)) gcc (also works in clang) (I see this question is marked by gcc ) attributes for this:

This attribute bound to a function means that the code must be emitted for the function, even if it seems that the function is not referenced. This is useful, for example, when a function refers only to an inline assembly.

From https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

Demo:

 $ cat ac static const char srcvers[] __attribute__((used)) = "VERSION/foo.c/1.01/09.04.15"; $ gcc -O3 -c ac $ strings ao VERSION/foo.c/1.01/09.04.15 

You can use some #if and #define to make this terrier, as well as compile compilers that do not support this extension.

+22
source share

As far as I understand your question, you need to add a version line to each object file without touching the sources. This can be done as follows.

Create a header file, for example include/version.h :

 #ifndef VERSION_H #define VERSION_H static const char _ver[] __attribute__((used)) = "VERSION/foo.c/1.01/09.04.15"; #endif /* VERSION_H */ 

Then in your Makefile (or whatever your build system is) add the following gcc flag:

 CPPFLAGS += -include include/version.h 

Of course, it should be passed to gcc , for example. eg:

 %.o: %.c $(CC) $(CFLAGS) $(CPPFLAGS) -o $(*).o -c $(*).c 

Now you can observe the _ver line compiled for each object file:

 $ objdump -DS src/main.o | grep _ver 

What will be shown to you something like this:

 Disassembly of section .rodata._ver: 00000000 <_ver>: 
+4
source share

Declaring a volatile variable can also help. That is why it is used in the first place, preventing any optimizations by the compiler regarding this variable.

+2
source share

It seems that all solutions require some kind of decoration of the version line in the source, this can help determine a macro containing all the necessary syntax, and then use this macro in the source or header files if necessary:

 #define SRCVERSION(file, version, data) static const char _ver[] __attribute__((used)) = "VERSION/" file "/" version "/" date; 

Then just put in your source

 SRCVERSION("foo.c", "1.01", "09.04.15") 

The macro can be in the central project header file or on the compiler command line.

That way, at least you don't have to touch all the source files again if you want to change something in the definition.

Notice how the macro definition uses string concatenation to build the final version. It also contains the end semicolon, so you can delete everything by specifying an empty macro if necessary.

+1
source share

You are concerned about gcc deleting the unused variable static char[] . AFAIK, the compiler is right for this.

Other answers have suggested improving this. But you do not want to change the source code of thousands of files.

Then you can possibly change your build (for example, some Makefile ) so that each such source file using your trick (which is a bit wrong, as discussed here ...), does not need to be changed. So you can specifically specify GCC . Do you want to

  static const char _ver[] __attribute__((used)); 

(this is an announcement, not a definition) to compile before anything else. Put the line above in some _declare_ver.h file and compile with gcc -include _declare_ver.h (instead of gcc ). If make used add

  CFLAGS += -include _declare_ver.h 

in the Makefile .

By the way, this is a dirty trick. You should consider making something better (after the other answers).

0
source share

All Articles