Detect if C++ binary is optimized

Solution 1:

Recent versions of GCC have a way to report which flags were used to compile a binary (third bullet point).

There is a related command line switch (--fverbose-asm) that "only records the information in the assembler output file as comments, so the information never reaches the object file." The --frecord-gcc-switches switch "causes the command line that was used to invoke the compiler to be recorded into the object file that is being created."

Solution 2:

Possible Heuristics Solution

If I would be given this task and it would prove it is a reasonable task (see below), I would perform "a frequency analysis" of the patterns seen in the executable disassembly. As a programmer I am able to distinguish between an optimized and an unoptimized (debug) code at a first glance. I would try to formalize the decision process, with Visual Studio and the x86 platform the typical features seen in an unoptimized exe would be:

  • functions with full prologue/epilogue (ebp based stack frames)
  • a lot of mov-s from/into memory (all variables placed in the memory)

This is definitely not 100 %, but with longer exe I would expect the results to be quite reliable.

I assume for other x86 platforms including GCC the rules will be similar, if not the same, and for other platforms similar rules can be found.

Other heuristics like detection of the runtime library may work as well, depending on compiler settings.

Task sounds silly

That said, I think such task "smells" and under most circumstances it would be sensible to avoid it completely. If you will provide the real reason behind such task, it is very likely some sensible solution will be found.

Solution 3:

The technique we use is simply to create a symbol that appears in every library only if built debug:

// included_by_everything.h
#ifdef (_DEBUG)
extern "C" __declspec( dllexport ) void WasBuiltInDebug() {}
#else
// nothing!
#endif

And then when loading each module at runtime (or in a Perforce trigger) we can ask the binary if it's debug by simply looking for that symbol:

bool IsDebugDLL( HMODULE DllHandle )
{
  // this system call returns a nonzero address if it can 
  // find the symbol, and NULL otherwise:
  return GetProcAddress( DllHandle , "WasBuiltInDebug" );
}

Solution 4:

On Windows you could check if the debug info is stripped from the binary. If you examine the binary image for COFF header, there's a 2 byte flag block called Characteristics at byte offset 18 from COFF header. If the flag

 IMAGE_FILE_DEBUG_STRIPPED = 0x0200

is set then the debugging information is removed from the image file.

This could be done with a trivial 2 byte read from file offset 0x52 and checking if the flag is set.

Flag could be checked as follows

 short flag_block;

 FILE * p_image_file = fopen (...); 

 fseek(p_image_file,0x52,SEEK_SET);

 fread(&flag_block,2,1,p_image_file);

 if(flag_block & 0x0200 > 0)
    then debug info is stripped

You could find the Windows PE format document from Microsoft which describes it in more detail for you to calculate the byte offset to read from etc...