Electric Fence 2.2.0 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>
p = <not 30 bytes>
Program received signal SIGSEGV, Segmentation fault. /* Снова SIGSEGV */
[Switching to Thread 8192 (LWP 28024)]
0x080485e8 in main (argc=2, argv=0xbffff8a4) at ch15-badmem1.c:21
21 p[0] = 'b';
На системах, которые поддерживают разделяемые библиотеки и переменную окружения
LD_PRELOAD
(в том числе и на GNU/Linux), вам не нужно явным образом компоновать библиотеку
efence
. Вместо этого сценарий оболочки
ef
организует запуск программы с соответствующей настройкой.
Хотя мы не описали механизмы подробно, GNU/Linux (и другие системы Unix) поддерживают разделяемые (shared) библиотеки, особые версии библиотечных процедур, которые хранятся в одном файле на диске, вместо того, чтобы копироваться в каждый отдельный двоичный исполняемый файл программы. Разделяемые библиотеки экономят дисковое пространство и могут сохранить системную память, поскольку все программы, использующие разделяемые библиотеки, используют одну и ту же копию библиотеки в памяти. Платой за это является замедление загрузки программы, поскольку программу и разделяемую библиотеку нужно подключить друг к другу прежде, чем программа сможет начать выполнение. (Обычно это прозрачно для вас, пользователя.)
Переменная окружения
LD_PRELOAD
заставляет системный загрузчик программ (который загружает исполняемые файлы в память) связаться со специальной библиотекой до стандартных библиотек. Сценарий
ef
использует эту особенность для связывания набора функций
malloc
в Electric Fence. [179] Таким образом, повторная компоновка даже не нужна. Этот пример демонстрирует
ef
:
$ cc -g ch15-badmem1.c -о ch15-badmem1 /* Компилировать как обычно */
179
GDB также позволяет определить переменную окружения
LD_PRELOAD
:
set environment LD_PRELOAD=PATH_TO_YOUR_LIBRARY
— Примеч. науч. ред.
$ ef ch15-badmem1 -b /* Запустить с использованием ef, создает дамп ядра */
Electric Fence 2.2.0 Copyright (С) 1987-1999 Bruce Perens <bruce@perens.com>
p = <not 30 bytes>
/usr/bin/ef: line 20: 28005 Segmentation fault (core dumped)
( export LD_PRELOAD=libefence.so.0.0; exec $* )
$ ef ch15-badmem1 -f /*
Запустить с использованием ef, снова создает дамп ядра */
Electric Fence 2.2.0 Copyright (С) 1987-1999 Bruce Perens <bruce@perens.com>
p = <not 30 bytes>
/usr/bin/ef: line 20: 28007 Segmentation fault (core dumped)
( export LD_PRELOAD=libefence.so.0.0; exec $* )
$ ls -l core* /* Linux создает для нас разные файлы core */
– rw------- 1 arnold devel 217088 Aug 28 15:40 core.28005
– rw------- 1 arnold devel 212992 Aug 28 15:40 core.28007
GNU/Linux создает файлы
core
, которые включают в свое имя ID процесса. В данном случае такое поведение полезно, поскольку мы можем отдельно отлаживать каждый файл
core
:
$ gdb ch15-badmem1 core.28005 /* От опции -b */
GNU gdb 5.3
...
Core was generated by 'ch15-badmem1 -b'.
Program terminated with signal 11, Segmentation fault.
...
#0 0x08048466 in main (argc=2, argv=0xbffff8c4) at ch15-badmem1.c:18
18 p[42] = 'a'; /* touch outside the bounds */
(gdb) quit
$ gdb ch15-badmem1 core.28007 /* От опции -f */
GNU gdb 5.3
...
Core was generated by 'ch15-badmem1 -f'.
Program terminated with signal 11, Segmentation fault.
...
#0 0x08048498 in main (argc=2, argv=0xbffff8c4) at ch15-badmem1.с:21
21 p[0] = 'b';
Справочная страница efence(3) описывает несколько переменных окружения, которые должны быть установлены, чтобы настроить поведение Electric Fence. Следующие три наиболее примечательны.
EF_PROTECT_BELOW
Установка этой переменной в 1 заставляет Electric Fence проверять «недоборы» (underruns) вместо «переборов» (overruns) при выходе за пределы отведенной памяти. «Перебор», т.е. доступ к памяти в области за выделенной, был продемонстрирован ранее. «Недобор» является доступом к памяти, расположенной перед выделенной областью памяти.
EF_PROTECT_FREE
Установка этой переменной в 1 предотвращает повторное использование Electric Fence памяти, которая была корректно освобождена. Это полезно, когда вы думаете, что программа может получать доступ к освобожденной памяти; если освобожденная память впоследствии была выделена заново, доступ к ней через предыдущий висячий указатель остался бы в противном случае незамеченным.
EF_ALLOW_MALLOC_0
При наличии ненулевого значения Electric Fence допускает вызовы '
malloc(0)
'. Такие вызовы в стандартном С технически действительны, но могут представлять программную ошибку. Соответственно Electric Fence по умолчанию их запрещает.