ОС: Linux/Debian/Sid/x86_64 (и Linux/Debian/тестирование/x86_64); моя система GCC, используемая для компиляции, - 6.1.1 (и 5.3 с Debian/Testing). Gnu libc - 2,22; Ядро Linux - 4,5; GDB является системой 7,10 или мой собственный, построенный из источника FSF, 7,11охота (память, связанная с GC) heisenbug исчезает без ASLR
Я охочусь (так как почти две недели) память & garbage collection связанных heisenbug в MELT экспериментальной ветви НКИ (MELT грубо говоря лисповский -как домена конкретного языка, чтобы настроить GCC компилятор, расплавом диалект переведен на C++ с использованием самого Растопить), который можно восстановить с
svn co -r236207 svn://gcc.gnu.org/svn/gcc/branches/melt-branch gcc-melt
тогда (как и для каждого варианта GCC или ветви) построить его в снаружи, например.
mkdir _ObjMelt
cd _ObjMelt
../gcc-melt/configure --disable-bootstrap --enable-checks=gc \
--enable-plugins --disable-multilib --enable-languages=c,c++,lto
(вы можете передать другие варианты ../gcc-melt/configure
, например CXXFLAGS='-g3 -O0 -DMELT_HAVE_RUNTIME_DEBUG=1'
, если вы хотите, вы можете удалить опцию --enable-checks=gc
)
и конечно make
(или make -j4
); что сборка может занять больше чем полчаса (и, вероятно, потерпит неудачу с ASLR, смотрите ниже)
MELT имеет поколения копирование сборщика мусора (и я подозреваю, что ошибка будет угловой случаем в нем) и использует лот metaprogramming (в частности, большинство кодов сканирования и пересылки для копирования GC генерируется MELT).
(valgrind
здесь не поможет: мы реализации копировального GC, а сам GCC является -Дажа без утечки памяти талой)
MELT загрузилось. Обычная процедура сборки регенерирует дважды испускаемый код C++ из исходного кода MELT. Обычный способ состоит в том, чтобы испускать некоторый код на C++, fork some make
, чтобы получить общий объект, и dlopen
, что и общий объект, и снова.
БезASLR, сборка всегда успех (и это работает значительное испытание: начальной загрузки талой и анализ РАСПЛАВНЫХ выполнения путем компиляции расширенной талой). И я мог бы даже восстановить код времени выполнения с помощью make upgrade-warmelt
.
Но с ASLR включена, сборка не удается, сбой всегда таким же образом (заметьте, что cc1plus
является MELT один):
cc1plus: note: MELT got fatal failure from ../../gcc-melt/gcc/melt-runtime.h:900
cc1plus: fatal error: corrupted memory heap with null magic discriminant
in 0x2bab6a8; GC#11
compilation terminated.
MELT BUILD SCRIPT FAILURE:
melt-build-script.tpl:382/307-melt-build-script.tpl:459/382 failed
with arguments @meltbuild-stage2/warmelt-normatch.args
Я отключить ASLR например с exec setarch $(uname -m) -R /bin/bash
; и, конечно, при запуске uder gdb
ASLR отключен по умолчанию (если только я не делаю set disable-randomization 0
в качестве команды GDB).
Мой коллега Франк Ведрин предложил мне использовать reverse execution объекты gdb
; в принципе, это должно быть так же просто, как установить контрольную точку в моем GC (и в fatal_error
& melt_fatal_info
, вызываемый макросом melt_fatal_error
...), достигните состояния GC#11
, сделайте record
для следующего обратного выполнения, запустите неисправный футляр (с set disable-randomization 0
, чтобы отключить ASLR) до «аварии», затем reverse-cont
до точки останова в GC и используйте с осторожностью watch
. К сожалению, это вызывает широко известный GDB ошибка (Sourceware#19365, Ubuntu#1573786, Redhat#1136403, ...) - что недавние снимки GDB как gdb-7.11.50.20160514
не правиль-
(я сейчас соблазн попытаться избежать этого GDB ошибка, возможно, имея свои собственные memset
& memcpy
процедуры с #pragma GCC optimize ("-Og")
перед ними, но это выглядит слишком далеко)
Для чего это стоит, сообщение грохот задается следующим кодом (около линии 900 моего melt-runtime.h
):
static inline int
melt_magic_discr (melt_ptr_t p)
{
if (!p)
return 0;
#if MELT_HAVE_DEBUG > 0 || MELT_HAVE_RUNTIME_DEBUG > 0
if (MELT_UNLIKELY(!p->u_discr))
{
/* This should never happen, we are asking the discriminant of a
not yet filled, since cleared, memory zone. */
melt_fatal_error
("corrupted memory heap with null discriminant in %p; GC#%ld",
(void*) p, melt_nb_garbcoll);
}
#endif /*MELT_HAVE_DEBUG or MELT_HAVE_RUNTIME_DEBUG */
gcc_assert (p->u_discr != NULL);
return p->u_discr->meltobj_magic;
}
Я думаю, что ошибка может быть трудным GC ошибка вокруг экспедированию «дискриминант» (своего рода «типа» или «класс» или поле «метаданных» в каждый MELT значение) в редком случае, когда этот дискриминант все еще находится в молодом поколении ... Добавляя некоторый код, чтобы избежать этого, действительно, ошибка произошла позже, но я совсем не уверен.
Любые подсказки или рекомендации по отладке гейзенбуга, связанного с фактическими виртуальными адресами (отсюда разумный для ASLR!), Приветствуются.
Я даже добавил некоторый код инициализации, чтобы иметь возможность необязательноmmap
или sbrk
несколько мегабайта бесполезного, в надежде «воспроизвести» рандомизированный адрес, выданный mmap
(вызывается calloc
используемого расплава и его GC). Это еще не помогло!
Я не могу сказать, сможет ли Базиле использовать эту технику для хорошего использования, но я могу сказать, что это умная техника. –