I recently created two executables from the exact same source code and the exact same path on my computer using GCC version 2.9-gnupro-98r2. When I do a binary compare of the two executables there are differences in the .data section of the executable. Does anyone know why this would happen? I need to produce a consistent executable every time.
Thanks!
It's probably related to timestamp information in the executable. If any of your sources use the __TIME__ macro, the binary executables will be different if you compile at different times.
Related
For example, I have a "helloworld" cpp file named main.cpp.
If I compile it with flag -std=c++11. And I compile it again with flag -std=c++03.
How can I specify which is compiled with c++11 flag between this two?
extra: My specific problem is that I have a third-party lib file, I used it in my code, but I don't know which "-std" flag should I use.
If it is a third party library, then there must be some documentation stating the compilation steps to build from source. Please refer that.
If there is no such thing available, I am assuming that you at least have access to the source code, please look into the implementation (the header files or the source files), you will probably get more than enough information to figure out if it uses code conforming to C++ 11 standard.
#πάνταῥεῖ,I mean compile with different c++ standard won't leave something in the binary filie? - Riopho
If you want to figure out from binary, then I would probably use objdump and disassemble the binary with demangling turned on - objdump -dC <binary_name> - (assuming that you are on Linux, don't know much windows though). you should be able to get some hint from that.
I am not sure if the compiler leaves any traces in the binary though.
I have seen that eclipse provides a feature to load an existing executable in order to debug it, so I was following the guidelines described in here to do so. I have to say that I didn't compile the binary in eclipse, I was using my own makes files though.
However, although I can import my binary I cannot set breakpoints into the libraries( shared or not) which the binary has, as is stated in the last point of the guideline, and I don't know exactly the reason. Instead of having the content of the library, I get nothing, even if I click on the associated plus icon to the lib, see figures below
At the beginning I thought it was due to the fact that my binary didn't have the debugging flags enabled, but i checked the binary with the commands below, getting an expected output, which means that debugging flags are enables, aren't they?
readelf --debug-dump=decodedline AudioControlApp
objdump --debugging AudioControlApp
Then, I was wondering, why cannot I set the breakpoints on those libraries? Does my binary miss some compilation option?
thanks in advance,
Regards
If I build the same source code, link to the same version of the same libraries, with the same tool chain ( same compiler, linker etc , GCC 4.4), with the same version of the same operating system, ( Centos 5 Linux in my case) but on two different machines;
Is it reasonable to assume that binaries produced should be identical?
The context behind this is my code has 'undefined behaviour' which 'works' on one configuration but not the other, the obvious answer is to fix this, but I would be interested to know if my assumption that binaries produced should be the identical is correct.
I notice a few hundred bytes difference in size, the location of the symbols shown with the 'nm' command differ slightly, even though the symbols are the same.
Normally I would expect a date and/or meta data to vary slightly even between builds on the same host.
You also neglected to mention compiler flags, (optimization and #defines from the command line for example).
I would however initially suspect the files should come out to the same size, which leads us to the conclusion that something is not the same across the two systems. The most likely candidates are system headers (just one root-level feature in the OS install could cause an entirely different view of these files) and any dependent libraries.
You can check that the headers are the same by preprocessing with g++ -E or similar. You can also follow the library path and confirm that the linked-to files are identical on each system.
From a compiled file, can I see which compiler has been used to generate the file?
There's also the good old 'strings' utility. Dumps all ascii-ish looking strings it finds in the binary. Different compilers embed different amounts of information in the binaries they produce, but many will actually include obviously identifying strings.
Many compilers/linkers insert a .comment section in the output file which identifies them. There are also a number of more subtle behaviors you could create compiler fingerprints off of, but I know of no existing tools for this.
If you have the source, the easiest solution would be to try compiling with each compiler in question until you get a binary that matches byte-for-byte (or even closely).
In some cases you can run ldd on the binary and find out which standard library it's linked against. For example on Solaris gcc vs Sun CC vs whatever.
For C++ code, you can also dump some of the symbols, find a mangled function name, and then figure out which demangler generates the correct original name.
Try, IDA Pro which identifies the libraries and tools used to build up executable file.
I was answering a quiz in a Blue Team website, and this was a question. I found the solution using a tool called PE Detective, he looks for signatures on the EXE, works really fine
https://www.softpedia.com/get/System/File-Management/PE-Detective.shtml
I want to compile a bunch of C++ files into raw machine code and the run it with a platform-dependent starter written in C. Something like
fread(buffer, 1, len, file);
a=((*int(*)(int))buffer)(b);
How can I tell g++ to output raw code?
Will function calls work? How can I make it work?
I think the calling conventions of Linux and Windows differ. Is this a problem? How can I solve it?
EDIT: I know that PE and ELF prevent the DIRECT starting of the executable. But that's what I have the starter for.
There is one (relatively) simple way of achieving some of this, and that's called "position independent code". See your compiler documentation for this.
Meaning you can compile some sources into a binary which will execute no matter where in the address space you place it. If you have such a piece of x86 binary code in a file and mmap() it (or the Windows equivalent) it is possible to invoke it from both Linux and Windows.
Limitations already mentioned are of course still present - namely, the binary code must restrict itself to using a calling convention that's identical on both platforms / can be represented on both platforms (for 32bit x86, that'd be passing args on the stack and returning values in EAX), and of course the code must be fully self-contained - no DLL function calls as resolving these is system dependent, no system calls either.
I.e.:
You need position-independent code
You must create self-contained code without any external dependencies
You must extract the machine code from the object file.
Then mmap() that file, initialize a function pointer, and (*myblob)(someArgs) may do.
If you're using gcc, the -ffreestanding -nostdinc -fPIC options should give you most of what you want regarding the first two, then use objdump to extract the binary blob from the ELF object file afterwards.
Theoretically, some of this is achievable. However there are so many gotchas along the way that it's not really a practical solution for anything.
System call formats are totally incompatible
DEP will prevent data executing as code
Memory layouts are different
You need to effectively dynamically 'relink' the code before you can run it.
.. and so forth...
The same executable cannot be run on both Windows and Linux.
You write your code platform independently (STL, Boost & Qt can help with this), then compile in G++ on Linux to output a linux-binary, and similarly on a compiler on the windows platform.
EDIT: Also, perhaps these two posts might help you:
One
Two
Why don't you take a look at wine? It's for using windows executables on Linux. Another solution for that is using Java or .NET bytecode.
You can run .NET executables on Linux (requires mono runtime)
Also have a look at Agner's objconv (disassembling, converting PE executable to ELF etc.)
http://www.agner.org/optimize/#objconv
Someone actually figured this out. It’s called αcτµαlly pδrταblε εxεcµταblε (APE) and you use the Cosmopolitan C library. The gist is that there’s a way to cause Windows PE executable headers to be ignored and treated as a shell script. Same goes for MacOS allowing you to define a single executable. Additionally, they also figured out how to smuggle ZIP into it so that it can incrementally compress the various sections of the file / decompress on run.
https://justine.lol/ape.html
https://github.com/jart/cosmopolitan
Example of a single identical Lua binary running on Linux and Windows:
https://ahgamut.github.io/2021/02/27/ape-cosmo/
Doing such a thing would be rather complicated. It isn't just a matter of the cpu commands being issued, the compiler has dependencies on many libraries that will be linked into the code. Those libraries will have to match at run-time or it won't work.
For example, the STL library is a series of templates and library functions. The compiler will inline some constructs and call the library for others. It'd have to be the exact same library to work.
Now, in theory you could avoid using any library and just write in fundamentals, but even there the compiler may make assumptions about how they work, what type of data alignment is involved, calling convention, etc.
Don't get me wrong, it can work. Look at the WINE project and other native drivers from windows being used on Linux. I'm just saying it isn't something you can quickly and easily do.
Far better would be to recompile on each platform.
That is achievable only if you have WINE available on your Linux system. Otherwise, the difference in the executable file format will prevent you from running Windows code on Linux.