2

I work on some software that loads a set of user specified shared objects. I'd like to add some code to our "loader" component that can query each specified shared object and find out what compiler and what compiler version was used to build/link that shared object.

In the past, I've been able to use a "strings -a | grep " approach as shown below. However, this approach is not working for code compiled with g++ 4.8 on power AIX, and it's not working particularly well for code compiled with g++ 4.8 on x86 linux.

I would also love to find some cleaner way of obtaining this information than grepping for strings if possible.

Can anyone provide advice on how to query a shared object for the name of the compiler that built it and also the version of that compiler?


Here's some example command and output from my current technique:

on an x86 linux g++ 4.1 compiled shared object:

$ strings -a libshareme.so | grep GNU
GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-50)
<etc>

(lots of repetitive output here, but it's clear that the version is GCC 4.1.2)

on a power AIX xlC v11 compiled object

$ strings -a libshareme.so | grep XL
XL  
IBM XL C/C++ for AIX, Version 11.1.0.6
IBM XL C/C++ for AIX, Version 10.1.0.6

(kind of confusing that it shows v11 and v10, but XL C is clear)

on an x86 linux g++ 4.8 compiled shared object:

$ strings -a libshareme.so | grep GNU
GCC: (GNU) 4.4.6 20120305 (Red Hat 4.4.6-4)
GCC: (GNU) 4.8.2 20131111 (Red Hat 4.8.2-4)
GNU C++ 4.8.2 20131111 (Red Hat 4.8.2-4) -m32 -mtune=generic -march=i686 -g -fmessage-length=0 -fPIC

(also kind of confusing here that it shows multiple versions)

on a power AIX g++ 4.8 compiled object

$ strings -a libshareme.so | grep GNU
<no output>

On x86/linux, I usually see a "GNU" type string in 'strings -a' output I can match. However, using strings -a on this libshareme.so compiled on power/aix with g++4.8 doesn't show me anything obvious regarding compiler version.

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
fahrradler
  • 141
  • 1
  • 2
  • 9
  • 1
    The shared libraries are not objects they are libraries of objects and each object in one library could have been compiled with a different compiler. As for the last one why do you expect GNU on a "power AIX g++ 4.8 " – mmmmmm Oct 14 '14 at 22:36
  • 2
    What is the point in doing this? Unless you're an expert in the particular platform ABI & the compilers on that platform, you'll generally want to avoid loading shared libs compiled by random different compilers with random different compiler options. And, you'll not be able to read the exact compiler, version, and options used from the binary object files, because it's not stored there. – Laszlo Valko Oct 14 '14 at 22:51
  • @Laszlo Valko: "you'll generally want to avoid loading shared libs compiled by random different compilers ". This is exactly what I want to avoid. In this software (that I own), users specify which shared objects that they create that they want loaded and the software loads it. I want the software to be able to figure out what compiler was used (here, g++ or xlC) to create these shared objects and emit a clear error if there's a mix. Yes, you get load and other errors in the 'mixing' situation, but those are not too user friendly. – fahrradler Oct 15 '14 at 21:19

2 Answers2

1

I found this way thanks to a coworker to detect if a library is compiled with g++ on AIX:

dump -X32_64 -Tv libshareme.so  | grep libgcc 

[1]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) __cxa_finalize
[2]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) __register_frame_info_table
[3]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) __deregister_frame_info
[4]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) __cmpdi2
[5]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) __gcc_qdiv
[6]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) __udivdi3
[7]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) _Unwind_Resume
[635]   0x20118d70    .data      EXP     DS   Ldef        [noIMid] __init_aix_libgcc_cxa_atex

it

This approach plus the ones in the original question essentially work to let me write code that detects compilers (at least the ones I'm working with) and any potential mismatch of compilers during a load fail.

fahrradler
  • 141
  • 1
  • 2
  • 9
0

It's not possible to foolproofly do what you want to achieve. You may sometimes be able to find random signs of the compiler or some compiler flags, but surely there's no general way to obtain this information. And most of this information is simply not present in the object files (no compiler I know of stores the exact compiler flags used into the object files, for example).

You may look at what the authors of other packages have done, I'd first check Perl. Perl uses its own "./configure" script, which gathers the paths of different tools and the flags to be used with them, and then this information is used when compiling the perl binary and the standard modules supplied there. This information also gets compiled into the perl binary, and can be later printed for convenience (perl -V), or used in order to compile "matching" extra perl modules by perl's own make helper library (see perl Makefile.PL). Even perl's facility is not foolproof, as you may try to load incompatibly compiled/linked shared libs.

Laszlo Valko
  • 2,683
  • 25
  • 29