The Compiler Detective - What Compiler and Options Were Used to Build This Application?

("cc CSI")


Performance engineers often look at improving application performance
by getting the compiler to produce more efficient binaries from the
same source. This is done by changing what compiler options are used.
In this modern era of Open Source Software, you can often get your
hands on a number of binary distributions of an application, but if
you really want to roll your sleeves up, the source is there, just
waiting to be compiled with the latest compiler and optimisations.

Now, it might be useful to have as a reference the compiler version and
flags that were originally used on the binary distribution you tried
out, or you just might be interested to know. Read on for details on the
forensic tools.

What architecture was the executable compiled for?

Solaris supports 64 and 32-bit programming models on SPARC and x86.
You may need to know which one an application is using - it's easy
enough to find out.

$ file \*.o
xxx.o: ELF 64-bit LSB relocatable AMD64 Version 1
yyy.o: ELF 32-bit LSB relocatable 80386 Version 1 [SSE2]

Note: yyy.o was built using "-native", informing the compiler
that it can use the SSE2 instruction set extensions supported by the
CPUs on the build system.

Some more examples, including a binary built on a SunOS 4.x system:

$ file gobble.\*
gobble.sunos4: Sun demand paged SPARC executable dynamically linked
gobble.sparcv9: ELF 64-bit MSB executable SPARCV9 Version 1,
dynamically linked, not stripped
gobble.i386: ELF 32-bit LSB executable 80386 Version 1 [FPU],
dynamically linked, not stripped
gobble.amd64: ELF 64-bit LSB executable AMD64 Version 1 [SSE FXSR FPU],
dynamically linked, not stripped

Can I detect what version of whose compiler was used to build a binary,
and on what version of Solaris?

The command to use is:

$ /usr/ccs/bin/mcs -p executable | object

Here are some examples. The "ld:" entries should indicate what
release of Solaris the executable was built on, which is a good
indicator of the oldest version of Solaris it will run on.

  • Sun Studio 11, on Solaris 10:
        acomp: Sun C 5.8 2005/10/13
    iropt: Sun Compiler Common 11 2005/10/13
    as: Sun Compiler Common 11 2005/10/13
    ld: Software Generation Utilities - Solaris Link Editors: 5.10-1.477
  • An old version of GCC (this was built in 1994, looks like Solaris 2.3):
        @(#)SunOS 5.3 Generic September 1993
    GCC: (GNU) 2.5.8
    as: SC3.0 early access 01 Sep 1993
    ld: (SGU) SunOS/ELF (LK-1.3)
  • Sun C 5.0, Solaris???
        @(#)stdio.h     1.78    99/12/08 SMI
    acomp: WorkShop Compilers 5.0 98/12/15 C 5.0
    ld: Software Generation Utilities - Solaris-ELF (4.0)
  • GCC 2.8.1, Solaris 7:
        @(#)SunOS 5.7 Generic October 1998
    as: WorkShop Compilers 5.0 Alpha 03/27/98 Build
    GCC: (GNU) 2.8.1
    ld: Software Generation Utilities - Solaris/ELF (3.0)
  • GCC 3.4.3 (object). The GCC compiler was built on/for "sol210" [sic]
        GCC: (GNU) 3.4.3 (csl-sol210-3_4-branch+sol_rpath)

There is a non-linear relationship between versions of the compiler
("Sun C") and the development suite ("Sun Studio", "Forte Developer",
"Sun WorkShop", etc.). You can figure it out using

Sun Studio Support Matrix

Can I figure out what compiler flags were used?

It depends on what compiler was used, and whether you have objects.

  • For Sun Studio 11, use "dwarfdump -i", and look for
    "DW_AT_SUN_command_line" in the output.
  • For Sun Studio 10 and earlier, use "dumpstabs -s", and look for
    "CMDLINE" in the output.
  • For GCC, you can only figure out what version of GCC was used
    (see above).

"dwarfdump" and "dumpstabs" are available with the Sun Studio suite.

Some examples:

$ dwarfdump -i gobble.sparcv9
DW_AT_name gobble.c
DW_AT_language DW_LANG_C99
DW_AT_comp_dir /home/tc35445/tools/c/gobble
DW_AT_SUN_command_line /usr/dist/share/sunstudio_sparc,
v11.0/SUNWspro/prod/bin/cc -xO3 -xarch=v9 -c gobble.c
DW_AT_SUN_compile_options Xa;O;R=Sun C 5.8 2005/10/13;
$ dumpstabs -s test
5: .stabs "Xa ; g ; V=3.1 ; R=Sun WorkShop 6 2000/04/07 C 5.1
; G=$XAB0qnBB6
6: .stabs "/net/vic/export/home/timc/tools/c/interposition;
/opt/Forte6/SUNWspro/bin/../WS6/bin/cc -g -c test.c
$ dumpstabs -s getwd
1: .stabs "Xa ; V=3.1 ; R=WorkShop Compilers 4.2 30 Oct 1996 C 4.2",
2: .stabs "/home/staff/timc/tools/c/getwd;
/opt/SUNWspro/bin/../SC4.2/bin/cc -c getwd.c -W0,-xp",N_CMDLINE,0x0,0x0,0x0

Can I figure out where the binary will look for shared objects?

If an RPATH has been specified, dumpstabs can find it:
$ dumpstabs mysqladmin | grep RPATH
13: Tag = 15 (RPATH) /usr/sfw/lib/mysql:/usr/sfw/lib

Can I figure out what shared objects the binary needs?

Yes, just use "ldd":

$ ldd mysqladmin
libmysqlclient.so.12 => /usr/sfw/lib/libmysqlclient.so.12
libz.so.1 => /usr/lib/libz.so.1
librt.so.1 => /usr/lib/librt.so.1
libcrypt_i.so.1 => /usr/lib/libcrypt_i.so.1
libgen.so.1 => /usr/lib/libgen.so.1
libsocket.so.1 => /usr/lib/libsocket.so.1
libnsl.so.1 => /usr/lib/libnsl.so.1
libm.so.2 => /usr/lib/libm.so.2
libthread.so.1 => /usr/lib/libthread.so.1
libc.so.1 => /usr/lib/libc.so.1
libaio.so.1 => /usr/lib/libaio.so.1
libmd5.so.1 => /usr/lib/libmd5.so.1
libmp.so.2 => /usr/lib/libmp.so.2
libscf.so.1 => /usr/lib/libscf.so.1
libdoor.so.1 => /usr/lib/libdoor.so.1
libuutil.so.1 => /usr/lib/libuutil.so.1


Join the discussion

Comments ( 2 )
  • henry Wednesday, January 24, 2007
    with command "mcs -p", you focus on the "ld:" entries, but i'm unable to find these lines in my binaries. I have only:
    acomp: Sun C 5.8 Patch 121016-04 2006/10/18
    as: Sun Compiler Common 11 Patch 120759-09 2006/10/24
  • timc Wednesday, January 24, 2007
    henry, were you inspecting an object (.o or .so)? I did focus on "mcs -p" for executables (a.out's), because dumpstabs and dwarfdump are more interesting on objects. /usr/ccs/bin/ccs is available even if you have not installed Sun Studio though.
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.