24

I mean whether gcc can insert some source code version infor into ELF binary as section or something similar. I do not want to change my source file, but add some info with gcc option in Makefile.

Lane
  • 391
  • 1
  • 2
  • 6

4 Answers4

11

If you don't mind changing your source file just once, add something like this:

const volatile static char version[] = VERSION;

and compile with:

gcc -c -DVERSION='"1.2.3"'

The volatile keeps gcc from removing the string at higher optimization levels.

As written, this won't compile if you forget the -D option, which may be either good or bad depending on your requirements.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • how do you read this version code from Linux command line or bash script? Thanks – George Oct 08 '21 at 10:17
  • @George There's no straightforward way to do that. The `version` string should be *somewhere* in the executable file, but you don't know where. One possibility is to add some unique string that can be searched for (but that assumes that string doesn't happen to appear elsewhere). – Keith Thompson Oct 08 '21 at 19:06
7

You can emit your version info into a text file, then turn that text file into an object file which you then statically link into your executable.

The first step is simple but you have to write some code: a script or something to write your version info in any format you like as a plain text file. Then write a makefile rule to produce say version.o from version.txt, using objcopy. Now you'll have an object file with two useful symbols defined in it: the beginning and end of the textual version info. Add that generated object to your executable, and you'll be able to access the version two ways: by running strings on the binary, or by writing code in the application to print the version string (you'll need to declare the start and end symbols as variables in some header file).

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • 4
    Thanks. I find that there is better method wiith objcopy: objcopy --add-section versection=version_text main main_version. And with "objdump -s -j versection main_version", the version can be retrieved. – Lane May 03 '13 at 06:36
  • 2
    Hi John, I see you're active member, even if this answer is old. Do you care to update it with some very basic/simple example of how to compile a text file to an object? Say "version 1.1.1" or something. This is exact the question I was going to make, and, well, it would be a (more/less) "duplicate"... – DrBeco Jul 11 '15 at 03:35
  • 1
    @DrBeco: on Linux you can use `objcopy` with the `--input binary` and `--output` formats explicitly specified. There is a full tutorial on this here: http://www.linuxjournal.com/content/embedding-file-executable-aka-hello-world-version-5967 . You can also use `ld` with some options, I think `-b` to do about the same thing, perhaps even easier depending on your exact scenario. – John Zwinck Aug 05 '15 at 10:54
7

Even if you don't have access to your source anymore, you can link the object with this option:

gcc -Wl,--defsym,VERSION_1_2_3=0 prog.o -o prog

You can check it with hexdump -C prog | less and look for VERSION


Add this to your makefile and be sure to always know when a program was compiled:

BUILD = $(shell date +"%Y%m%d_%H%M%S")
LDLIBS = -Wl,--defsym,BUILD_$(BUILD)=0
DrBeco
  • 11,237
  • 9
  • 59
  • 76
2

With the GNU linker ld You can use

--version-script=version-scriptfile

Read more about the command-line options at: Using LD, the GNU linker - Options

Read more about creating version scripts at: Using LD, the GNU linker - Version Script

Let me warn you though, that it is not for the weak-hearted!

mdk
  • 6,225
  • 1
  • 25
  • 30
  • 3
    Version scripts are intended for different purposes than just recording compiler settings. – o11c Jun 13 '15 at 07:27