Моя команда компиляции
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
Когда я запускаю эту команду дважды подряд, два .obj
файлы отличаются, а не только несколько байтов от отметки времени.
Мы переключаем системы сборки, поэтому мы хотим, чтобы наши сборки были двоично-совместимыми. Подавляющее большинство моих объектных файлов являются двоичными идентичными. Некоторые, которые используют __DATE__
а также __TIME__
Макросы отличаются на несколько байтов, но этот дико отличается!
Я использовал утилиту elf-dump и обнаружил, что раздел между двумя компиляциями сильно отличается
[544] .debug_info
PROGBITS 00000000 047d70 1021ed 00 0 0 1
[00000000]:
Но я не знаю что PROGBITS
содержит и почему он содержит различные элементы для последовательных компиляций. Этот сайт просто утверждает, что PROGBITS
это атрибут, но не то, что он указывает (и почему он будет другим для последовательных компиляций).
ВОПРОС
Как мне сделать поколение .obj
бинарный детерминированный?
МЫСЛИ
Каким-то образом компилируемый код фактически изменяет .debug_info
раздел .obj
, это .cpp
использует кучу буст-библиотек; возможно ли это причина?
ОБНОВИТЬ
Я посмотрел на генерируемые файлы сборки, и они разные. Имеет смысл, что в результате .obj
с будет иначе.
Все еще не имеет смысла, почему это происходит.
ОБНОВИТЬ
qcc
Команда выше не является действительной командой компилятора: qcc
компилятор «перенаправитель» в том, что он будет вызывать тот, который соответствует -V
аргумент.
«Настоящий» вызов компилятора таков:
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
ОБНОВИТЬ
Я думаю, что стоит взглянуть на .s
сборочный вывод, так как там есть большие различия.
Помни, я использую -frandom-seed
,
.s
файл имеет размер 1,05 миллиона строк, и разница составляет около 900 тысяч.
Оставил:
.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_»
…
Правильно:
.LASF17764:
.ascii «_ZNKSt8numpunctIcE13decimal_pointEv \ 000»
.LASF10304:
.ascii «cAlpha0 \ 000»
.LASF10222:
.ascii «usWeek \ 000»
.LASF14117:
.ascii «_ZN5boost10shared_ptrI27TnRespTravelEsificationEvent»
.ascii «EaSERKS2_ \ 000»
…
Это продолжается в течение нескольких сотен байтов.
Теперь, когда я тщательно проверяю свое невообразимое сравнение, все разделы различий boost::detail::variant::make_initializer_node
, Эта функция повышения каждый раз генерирует другой код?
РАЗРЕШАЮЩАЯ СПОСОБНОСТЬ
Оказывается, это gcc
ошибка. Я собрал свой .cpp
со всеми перестановками -O<X> -ggdb<Y>
а для Y> = 2 файлы сборки .s
и объекты .obj
являются недетерминированными.
я нашел ошибка gcc который описывает эту проблему.
Мне пришлось удалить другой пост для. , , причины.
Обычные виновники — макросы __DATE__
, __TIME__
, __TIMESTAMP__
который компилятор расширяет до значений, рассчитанных по системному времени.
Одна возможность состоит в том, что отладочная информация, сгенерированная для двоичного файла, написана недетерминированным способом. Это может произойти, например, когда расположение в памяти отладочной информации в процессе компиляции не является детерминированным. Я не знаю внутренностей GCC. Но я думаю, что-то подобное может произойти, когда
Последний источник недетерминизма обычно считается ошибкой в компиляторе (например, GCC PR65015)
Для принудительного воспроизведения воспроизводимых расширений __DATE__
, __TIME__
а также __TIMESTAMP__
макросами, нужно эмулировать и подделывать системное время (например, используя libfaketime / faketime) к компилятору. -Wdate-time
Опция командной строки для GCC может использоваться для предупреждения всякий раз, когда используются эти предопределенные макросы.
Чтобы вызвать воспроизводимую «случайность» для GUID и искажения, вы можете попробовать скомпилировать -frandom-seed=<somestring>
где <somestring>
является уникальной строкой для вашей сборки (например, это должен делать хеш содержимого исходного файла, который вы компилируете).
В качестве альтернативы вы можете попытаться скомпилировать без отладочной информации (например, без -ggdb
и т. д.) или используйте какой-либо инструмент для удаления полос, чтобы позже удалить раздел с информацией об отладке.
Других решений пока нет …