The output of the GCC.obj file is not deterministic (.debug_info, section PROGBITS)

My compilation command is C:\work\PROJ-test\QNX_SDK\host\win32\x86/usr/bin/qcc -c -Wc,-frandom-seed="sadfsasafssadsa" -Wc,-MP,-MT,C:/work/PROJ-test/N_Manag/src/bld/N_Manag//armle-v7/release/nav_event_rcv.cpp.o,-MMD,C:/work/PROJ-test/N_Manag/src/bld/N_Manag//armle-v7/release/nav_event_rcv.cpp.d -Vgcc_ntoarmv7le -w9 -shared -O3 -ggdb3 -DBUILD_VERSION= -DPASLOGOPTIONS=0x02 -DPASLOGAPPZONES=31,23,30,9,8,3 -DNS1_5PORT -DBOARD_TYPE=PRODUCTION C:/work/PROJ-test/N_Manag/src/nav_event_rcv.cpp -o C:/work/PROJ-test/N_Manag/src/bld/N_Manag//armle-v7/release/nav_event_rcv.cpp.o

When I run this command twice in a row, the two .obj files are different, not just a few bytes from the timestamp.

We switch assembly systems, so we want our assemblies to be binary. The vast majority of my object files are binary identical. Some of them using the __DATE__ and __TIME__ macros differ by a few bytes, but this is wildly different!

I used the elf-dump utility and found a section that is very different between the two compilers, this

  [544] .debug_info PROGBITS 00000000 047d70 1021ed 00 0 0 1 [00000000]: 

But I do not know what PROGBITS contains and why it contains different elements for traveling compilers. This site simply claims that PROGBITS is an attribute, but not what it indicates (and why it will be different for consecutive compilations).

Question

How to create binary determinate .obj generation?

THOUGHTS

Be that as it may, the compiled code actually modifies the .debug_info .obj section. This .cpp uses a bunch of boost libraries; is it possible that the reason?

UPDATE

I looked at the generated assembly files, and they are different. It makes sense that the result of .obj will be different.
It still doesn't make sense why this is happening.

UPDATE The above qcc command qcc not a valid compiler command: qcc is a redirector compiler because it calls one that matches the -V argument. The "real" compiler call is:

C:/work/Proj/QNX_SDK/host/win32/x86/usr/lib/gcc/arm-unknown-nto-qnx6.5.0eabi/4.4.2/cc1plus -Wall -O3 -ggdb3 -DBUILD_VERSION= -DPASLOGOPTIONS=0x02 -DPASLOGAPPZONES=31,23,30,9,8,3 -DNS1_5PORT -DBOARD_TYPE=PRODUCTION -quiet -fno-builtin -fpic -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mlittle-endian -nostdinc -nostdinc++ -D__cplusplus -D__QNX__ -D__QNXNTO__ -D__GNUC__=4 -D__GNUC_MINOR__=4 -D__GNUC_PATCHLEVEL__=2 -D__NO_INLINE__ -D__DEPRECATED -D__EXCEPTIONS -D__unix__ -D__unix -D__ELF__ -fpic -DPIC=1 -D__ARM__ -D__arm__ -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=softfp -D__LITTLEENDIAN__ -D__ARMEL__ -U__ARMEB__ -frandom-seed=sadfsasafssadsa -MP -MT C:/work/Proj/N_Manag/src/bld/N_Manag//armle-v7/release/nav_event_rcv.cpp.o -MMD C:/work/Proj/N_Manag/src/bld/N_Manag//armle-v7/release/nav_event_rcv.cpp.d -isystem C:/work/Proj/QNX_SDK/target/qnx6/usr/include -isystem C:/work/Proj/QNX_SDK/host/win32/x86/usr/lib/gcc/arm-unknown-nto-qnx6.5.0eabi/4.4.2/include -isystem C:/work/Proj/QNX_SDK/target/qnx6/usr/include/cpp/c -isystem C:/work/Proj/QNX_SDK/target/qnx6/usr/include/cpp C:/work/Proj/N_Manag/src/nav_event_rcv.cpp -dumpbase C:/work/Proj/N_Manag/src/nav_event_rcv.cpp -o C:\work\Proj\nav_event_rcv.s

UPDATE

I think it's worth looking at the .s assembly, as there are significant differences.

Remember, I use -frandom-seed .

The .s file has a length of 1.05 miles, and on line ~ 900k the difference begins.

Left:

.LASF17345:
.ascii "_ZN5boost6detail7variant21make_initializer_node5app"
.ascii "lyINS_3mpl4pairINS3_INS5_INS3_INS5_INS3_INS5_INS3_I"
.ascii "NS5_INS3_INS5_INS3_INS5_INS3_INS5_INS3_INS5_INS3_IN"
.ascii "S5_INS3_INS5_INS3_INS5_INS3_INS5_INS3_INS5_INS3_INS"
.ascii "5_INS3_INS5_INS3_INS5_INS3_INS5_INS3_INS5_INS1_16in"
.ascii "itializer_rootEN4mpl_4int_ILi0EEEEENS4_6l_iterINS4_"
...

On right:

.LASF17764:
.ascii "_ZNKSt8numpunctIcE13decimal_pointEv \ 000"
.LASF10304:
.ascii "cAlpha0 \ 000"
.LASF10222:
.ascii "usWeek \ 000"
.LASF14117:
.ascii "_ZN5boost10shared_ptrI27TnRespTravelEstimationEvent"
.ascii "EaSERKS2_ \ 000"
...

This goes on for several hundred bytes.

Now, when I carefully study my results, all sections of the differences are related to boost::detail::variant::make_initializer_node . Does this enhancement function generate a different code each time?

Decision

Raises a gcc error. I compiled my .cpp with all permutations -O<X> -ggdb<Y> and for Y> = 2, assembly files .s and .obj objects are not deterministic.

I found a gcc error that describes this problem.


I had to delete another post., Reasons.

+6
source share
1 answer

Reasons for Non-Determinism

The usual culprits are the __DATE__ , __TIME__ , __TIMESTAMP__ , which the compiler extends to values ​​calculated from system time.

One possibility is that debugging information generated for a binary file is recorded in a non-deterministic way. This can happen, for example, when the memory layout in the debugging information in the compiler process is not deterministic. I do not know the internal components of GCC. But I think something like this can happen when

The last source of non-determinism is usually considered a compiler error (e.g. GCC PR65015 )

Softening

To force reproducible macro extensions __DATE__ , __TIME__ and __TIMESTAMP__ , you need to emulate and fake system time (for example, using libfaketime / faketime ) into the compiler. The -Wdate-time command line -Wdate-time for GCC can be used to alert whenever these predefined macros are used.

To force an “accident” for GUID and mangling, you can try to compile with -frandom-seed=<somestring> , where <somestring> is a unique string for your assembly (for example, a hash of the contents of the source file you are compiling should do this).

Alternatively, you can try to compile without debugging information (for example, without the -ggdb flags, etc.) or use some strip tool to delete the section of debugging information later.

see also

+4
source

Source: https://habr.com/ru/post/1014500/


All Articles