Ingo Leonhardt
Ingo Leonhardt

Reputation: 9884

prevent gcc from removing an unused variable

In our source files we usually have a version string like that:

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

When that string isn't optimized away, it's quite useful in certain cases, as one can determine the version of each source file linked to an executable by simply calling strings a.out | grep VERSION.

Unfortunately it is optimized away by gcc (using '-O'). So my question is, is there a simple way (a compiler switch would be great) to make gcc keep that variable (its name is always the same) without switching off any other optimizations.

Edit

What, in my opinion, makes the question different from that one, is that I'm was hoping to find a solution for which I wouldn't have to touch thousands of source files.

Upvotes: 31

Views: 38310

Answers (5)

You are concerned about gcc removing an unused static char[] variable. AFAIK, the compiler is right to do so.

Other answers provided suggestion to improve that. But you don't want to change the source code of thousands of files.

Then, you might perhaps change your build (e.g. some Makefile) so that every such source file using your trick (which is slightly wrong, as discussed here...) would not need to be changed. So you might invoke GCC specifically. You want

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

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

 CFLAGS += -include _declare_ver.h

in your Makefile.

BTW, that is a dirty trick. You should consider doing something better (following other answers).

Upvotes: 1

Ber
Ber

Reputation: 41793

As it seems that all the solutions require some kind of decoration of the version string in the source, it may help to define a macro containing all the necessary syntax and then use this macro in the source or header files whenever need:

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

Then in your source just put

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

The macro may be in a central project header file or on the compiler's command line.

That way, at least you do not have to touch all the source files again if you want to change something about the definition.

Note how the macro definition uses string concatenation to build the final version string. Also it contains the final semicolon so you can remove everything by defining an empty macro if needed.

Upvotes: 1

Sam Protsenko
Sam Protsenko

Reputation: 14743

As I understand your question, you need to add version string to every object file without touching sources. It can be done using next way.

Create 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 next gcc flag:

CPPFLAGS += -include include/version.h

Of course it should be passed to gcc, e.g. like this:

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

Now you can observe your _ver string compiled to every object file:

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

Which will show you something like that:

Disassembly of section .rodata._ver:
00000000 <_ver>:

Upvotes: 5

anon
anon

Reputation:

Declaring the variable as volatile can also help. That's why it is used in the first place, preventing any optimizations by the compiler regarding that variable.

Upvotes: 1

Dogbert
Dogbert

Reputation: 222040

You can use __attribute__((used)) gcc (also works in clang) specific (I see that the question is tagged gcc) attributes for this:

This attribute, attached to a function, means that code must be emitted for the function even if it appears that the function is not referenced. This is useful, for example, when the function is referenced only in inline assembly.

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

Demo:

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

You can use some #ifs and #defines to make this terser and also compile on compilers which don't support this extension.

Upvotes: 42

Related Questions