Reputation: 63946
Is there a flag or other reliable method to detect if a compiled C++ binary was compiled with optimizations?
I'm okay with compiler-specific solutions.
Edit: This is for a build deployment system, which could accidentally deploy binaries that were not built properly. A water-tight solution is unlikely, but it will save some pain (and money) if this can be detected some of the time.
The compiler will often be gcc, sometimes sun, and if there's a MSVC solution, I don't want to rule that out for the benefit of the community.
Upvotes: 10
Views: 7878
Reputation: 34443
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:
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.
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.
Upvotes: 8
Reputation: 8881
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...
Upvotes: 4
Reputation: 20047
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."
Upvotes: 12
Reputation: 41482
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" );
}
Upvotes: 8
Reputation: 7760
Perhaps you could use a different indicator to determine if you're deploying the right binary. e.g.
Upvotes: 0
Reputation: 1726
I'd be surprised if you're not already doing something like this, but:
If you "trust" the build system, put the options used to build into a string you can extract from a running program. (ie, from --version or an about dialog)
This won't detect problems with non-optimized object files getting into the build due to a broken build system, but it will let you easily differentiate a developer build from a release build.
Your release process can then include checking the version to make sure it isn't debug/nonoptimized.
Upvotes: 2
Reputation: 5379
In my experience, only reliable way is to examine disassembly itself if you don't know the compiler. First try to dump all strings with your favorite tool and look for clues in the linked library names and exported symbols. Failing that, look for common instruction sequences which are mostly get thrown away after optimizations like stack frame prologue and orderly and easy to understand register usage. If tools like ollydbg get confused about where a function starts and ends, there is a good chance binary is compiled with optimizations on.
Examining a decompiler's output may also help. Last time I checked, they were no better than a disassembler but things may have improved since then.
Upvotes: 2
Reputation: 308520
For Microsoft C++, you may be able to assume that optimization was turned off if the executable is referencing the debug versions of the run-time DLLs. It's not a guarantee, though.
Upvotes: 3
Reputation:
You don't mention a specific platform, so the answer might be yes. But for most common platforms, the answer is no.
Upvotes: 3
Reputation: 62333
I'm pretty sure there is no way. Unless you have specific knowledge of a function inside that you can check to see if the code sequence is optimal or not.
Upvotes: 1