Библиотека отладчика, используемая MySQL была первоначально написана Фредом Фишом (Fred Fish). Она будет очень полезна, если Вы планируете отлаживать и/или добавлять функциональные возможности к СУБД MySQL.
Автор зачем-то приводит заголовок файла dbug.c из исходников пакета (вместе со всеми комментариями к нему). Приведу его и я, поскольку это может быть продиктовано какими-либо юридическими проблемами с копирайтом. Поскольку я не юрист, привожу этот заголовок без какого-либо перевода (во избежание ошибок или искажения смысла юридического документа при переводе).
/*************************************************************************
* N O T I C E *
* *
* Copyright Abandoned, 1987, Fred Fish *
* *
* This previously copyrighted work has been placed into the public *
* domain by the author and may be freely used for any purpose, *
* private or commercial. *
* *
* Because of the number of inquiries I was receiving about the use *
* of this product in commercially developed works I have decided to *
* simply make it public domain to further its unrestricted use. I *
* specifically would be most happy to see this material become a *
* part of the standard Unix distributions by AT&T and the Berkeley *
* Computer Science Research Group, and a standard part of the GNU *
* system from the Free Software Foundation. *
* *
* I would appreciate it, as a courtesy, if this notice is left in *
* all copies and derivative works. Thank you. *
* *
* The author makes no warranty of any kind with respect to this *
* product and explicitly disclaims any implied warranties of mer- *
* chantability or fitness for any particular purpose. *
*************************************************************************
*/
/*
* FILE
* dbug.c runtime support routines for dbug package
*
* SCCS
* @(#)dbug.c 1.25 7/25/89
*
* DESCRIPTION
* These are the runtime support routines for the dbug package.
* The dbug package has two main components; the user include
* file containing various macro definitions, and the runtime
* support routines which are called from the macro expansions.
*
* Externally visible functions in the runtime support module
* use the naming convention pattern "_db_xx...xx_", thus
* they are unlikely to collide with user defined function names.
*
* AUTHOR(S)
* Fred Fish (base code)
* Enhanced Software Technologies, Tempe, AZ
* asuvax!mcdphx!estinc!fnf
*
* Binayak Banerjee (profiling enhancements)
* seismo!bpa!sjuvax!bbanerje
*
* Michael Widenius:
* DBUG_DUMP - To dump a piece of memory.
* PUSH_FLAG "O" - To be used instead of "o" if we don't
* want flushing (for slow systems)
* Check of malloc on entry/exit (option "S")
*/
Поместить в стек текущее состояние отладчика, и установить новое.
СИНТАКСИС:
VOID _db_push_ (control)
char *control;
ОПИСАНИЕ:
По указателю в параметре "control" на строку управления отладкой помещает в стек текущее состояние отладки, анализирует строку управления и устанавливает новое состояние отладки.
Единственный атрибут нового состояния, унаследованного из предыдущего состояния, это текущая функция вложенного уровня. Это может быть отменено, используя флажок "r" в строке управления.
Строка управления отладкой является последовательностью полей, разделенных двоеточиями:
<field_1><field_2><field_N>
Каждое поле состоит из обязательного символа флажка отладки, сопровождаемого факультативным "," и списком параметров, разделенных запятыми:
flag[,modifier,modifier,...,modifier]
d | Разрешает вывод из макроса DBUG_ |
D | Ждать после каждой выведенной отладчиком строки. Аргумент задает число десятых долей секунды, которое нужно ждать. Например, -#D,20 задает паузу в 2 секунды. |
f | Ограничивает отладку и/или трассировку списком имен функций. Обратите внимание, что пустой список отключит все функции. Соответствующий флажок "d" или "t" должен все же быть дан, поскольку этот флажок только ограничивает их действие, если они включены. |
F | Идентифицируют имя исходного файла для каждой строки отладки или трассирует вывод. |
i | Идентифицируют процесс с pid для каждой строки отладки или трассирует вывод. |
g | Включить профилирование. Создайте файл 'dbugmon.out', содержащий информацию, которая может использоваться, чтобы профилировать программу. Может сопровождаться списком ключевых слов, которые выбирают профилирование только для функций в этом списке. Пустой список подразумевает, что все функции подлежат профилированию. |
L | Идентифицирует номер строки исходного файла для каждой строки отладки или трассирует вывод. |
n | Выводит текущую глубину вложенности функции для каждой строки отладки или трассирует вывод. |
N | Номер каждой строки вывода отладки. |
o | Переназначает выходной поток отладчика в файл. По умолчанию задан stderr. |
O | То же, что и o, но файл сбрасывается между записями. То есть, после каждой записи файл закрывается, и снова открывается только перед следующей записью. Тормозит, конечно, кошмарно, но зато гарантирует сохранность данных в этом файле на случай слета системы. Что при отладке не бесполезно... |
p | Ограничивает действия отладчика определенными процессами. Процесс должен быть указан в макросе DBUG_PROCESS и совпадать с одной из записей в списке действий отладчика. |
P | Выводит имя текущего процесса для каждой строки отладки или трассирует вывод. |
r | При установке нового состояния отладки не наследует предыдущее состояние вложенности функции. Полезно, когда вывод должен начаться в левом поле. |
S | Функция _sanity(_file_, _line_) для каждой отлаживаемой функции до _sanity() возвращает отличное от 0 значение. Обычно используется с safemalloc. Как задается это значение, и что оно вообще значит в документации не сказано (!!!), а опытным путем это установить не удалось. |
t | Включить функцию трассировки строк вызова и выхода (call/exit). Может сопровождаться списком, содержащим число номер максимального уровня трассировки, вне которого никакого вывода не произойдет для отладочных или трассировочных макрокоманд. Умолчание задается при компиляции. |
Некоторые примеры строк управления отладкой:
-#d:t
-#d:f,main,subr1:F:L:t,20
-#d,input,output,files:n
ОПИСАНИЕ:
Извлекает из стека отладки последнее записанное туда состояние отладки и устанавливает в него состояние отладки. Обратите внимание, что извлечение будет терпеть неудачу, если оно удалит последнее имеющее силу состояние из стека. Это предотвращает ошибки пользователя в последовательности действий со стеком из отладчика.
СИНТАКСИС:
VOID _db_enter_ (_func_, _file_, _line_, _sfunc_, _sfile_, _slevel_,
_sframep_)
char *_func_; points to current function name
char *_file_; points to current file name
int _line_; called from source line number
char **_sfunc_; save previous _func_
char **_sfile_; save previous _file_
int *_slevel_; save previous nesting level
char ***_sframep_; save previous frame pointer
ОПИСАНИЕ:
Вызывается в начале каждой функции пользователя, чтобы сообщить отладчику, что была введена новая функция. Обратите внимание, что указатели на предыдущее имя функции пользователя и предыдущее имя файла пользователя сохраняются в стеке вызовов (это причина того, почему макрокоманда ENTER должна быть первым "выполнимым" кодом в функции, так как она распределяет память для этой области. Предыдущий уровень вложения также сохраняется в стеке вызовов для внутренней самопроверки непротиворечивости.
Также печатает строку трассировки, если трассировка включена и увеличивает текущее значение глубины вложения функций.
Обратите внимание, что этот механизм позволяет отладчику знать, какая функция пользователя является текущей, без того, чтобы поддерживать внутренний стек для имен функции.
СИНТАКСИС:
VOID _db_return_ (_line_, _sfunc_, _sfile_, _slevel_)
int _line_; current source line number
char **_sfunc_; where previous _func_ is to be retrieved
char **_sfile_; where previous _file_ is to be retrieved
int *_slevel_; where previous level was stashed
ОПИСАНИЕ:
Вызывается перед тем, как функция пользователя выполняет явный или неявный возврат. Выводит строку трассировки, если трассировка разрешена, уменьшает текущее значение глубины вложения функций и восстанавливает текущую функцию и имена файлов из стека более не существенной функции.
Параметры файла протокола для последующего использования _db_doprnt_().
СИНТАКСИС:
VOID _db_pargs_ (_line_, keyword)
int _line_;
char *keyword;
ОПИСАНИЕ:
Новая универсальная макрокоманда печати DBUG_PRINT, которая заменяет все формы макрокоманд DBUG_N, нуждается в двух обращениях к подпрограммам поддержки во время выполнения. Первая, это функция, которая запоминает параметры, которые используются последующим обращением для _db_doprnt_().
Печать дескриптора строк отладки.
СИНТАКСИС:
VOID _db_doprnt_ (format, va_alist)
char *format;
va_dcl;
ОПИСАНИЕ:
Когда вызывается через одну из DBUG макрокоманд, проверяет текущий набор ключевых слов, вызывая _db_pargs_() чтобы узнать, была ли эта макрокоманда выбрана для обработки через строку управления отладчика, и если так, печатает аргументы с помощью форматированной строки. Номер строки DBUG макрокоманды в источнике найден в u_line.
Обратите внимание, что строка формата (format) НЕ ДОЛЖНА включить завершение строки (\n), это делается автоматически.
Выполняет дамп строки, пока не найдет '\0'.
СИНТАКСИС:
void _db_dump_ (_line_,keyword,memory,length)
int _line_; current source line number
char *keyword;
char *memory; Memory to print
int length; Bytes to print
ОПИСАНИЕ:
Выполняет дамп N символов в двоичный массив. Используется, чтобы исследовать разрушенную память или массивы.
Анализ списка параметров в строке контроля отладки.
СИНТАКСИС:
static struct link *ListParse (ctlp)
char *ctlp;
ОПИСАНИЕ:
Принимает указатель на список строк в "ctlp", разделенный запятыми, анализирует список, формируя список и возвращая указатель на него. Первоначальный список разрушается в процессе формирования связанного списка, таким образом, лучше иметь его дубликат, если он важен.
Обратите внимание что, так как каждая связь добавляется в начало списка, конечный список будет в обратном порядке", который не значителен для нашего использования здесь.
Проверите данную строку на членство в данном списке.
СИНТАКСИС:
static BOOLEAN InList (linkp, cp)
struct link *linkp;
char *cp;
ОПИСАНИЕ:
Проверяет строку, на которую указывает "cp" чтобы определить, находится ли эта строка в списке, на который указывает "linkp". Linkp указывает на первую строку в списке. Если linkp == NULL, то строка обрабатывается, как будто она находится в списке (все строки находятся в пустом списке). Это может казаться довольно странным сначала, но ведет к желательной операции, если никакой список не задан. Результатом является то, что все строки будут приняты, когда не имеется никакого списка, но когда имеется список, будут приняты только те строки, которые есть в списке.
Сохраняет текущее состояние в стеке и устанавливает новое.
СИНТАКСИС:
static VOID PushState()
ОПИСАНИЕ:
Сохраняет текущее состояние в стеке и устанавливает новое. Единственным параметром, унаследованным из предыдущего состояния является уровень вложения функции. Это можно отменить флажком "r".
Стек состояния это связанный список состояний, с новым состоянием, добавленным в начало. Это позволяет стеку расти до самых границ памяти в случае необходимости.
Проверка разрешения на трассировку.
СИНТАКСИС:
static BOOLEAN DoTrace (stack)
ОПИСАНИЕ:
Проверяет разрешена ли трассировка, не достигнута ли еще максимальная глубина трассировки, текущая функция выбрана и текущий процесс выбран. Возвращает TRUE, если все в порядке, и FALSE в противном случае.
Проверяет разрешено ли профилирование.
СИНТАКСИС:
static BOOLEAN DoProfile()
ОПИСАНИЕ:
Проверяет разрешено ли профилирование, не достигнута ли еще максимальная глубина трассировки, текущая функция выбрана и текущий процесс выбран. Возвращает TRUE, если все в порядке, и FALSE в противном случае.
Проверяет ключевое слово на членство в списке ключевых слов.
СИНТАКСИС:
BOOLEAN _db_keyword_ (keyword)
char *keyword;
ОПИСАНИЕ:
Проверяет ключевое слово на членство в списке ключевых слов. Как и в случае со строками, все ключевые слова принадлежат пустому списку. Когда отладка не включена, никакие ключевые слова не принимаются. После того, как максимальный уровень трассировки превышен, никакие ключевые слова тоже не принимаются. Дополнительно, текущая функция и текущий процесс должны входить в соответствующие списки.
Возвращает TRUE, если ключевое слово входит в список, и FALSE в противном случае.
СИНТАКСИС:
static VOID Indent (indent)
int indent;
ОПИСАНИЕ:
Выравнивает строку на заданный уровень indent. Отступ может быть задан во время компиляции пакета в виде количества символов на один уровень вложения.
Освободить всю память, занятую элементами списка.
СИНТАКСИС:
static VOID FreeList (linkp)
struct link *linkp;
ОПИСАНИЕ:
Параметр linkp указывает на первый элемент связанного списка. Освобождается вся память, занятая элементами списка и самим списком.
Создает копию строки в новой области памяти.
СИНТАКСИС:
static char *StrDup (string)
char *string;
ОПИСАНИЕ:
Параметр string задает строку, копия которой нужна. Функция распределяет количество памяти, достаточное для создания копии строки и копирует строку в эту область памяти. Сбой при распределении памяти фатален.
Вывести префикс строки отладки.
СИНТАКСИС:
static VOID DoPrefix (_line_)
int _line_;
ОПИСАНИЕ:
Выводит префикс, общий для всех строк отладки. Выводит такую информацию, как текущее имя процесса, текущее имя исходного файла, номер строки и текущее значение глубины вложения.
Открывает новый поток вывода для вывода отладчика.
СИНТАКСИС:
static VOID OpenFile (name)
char *name;
ОПИСАНИЕ:
Параметр name является именем нового файла (или "-" для stdout). Файл открывается, и в него назначается вывод отладчика.
Открывает новый поток вывода для вывода профайлера.
СИНТАКСИС:
static FILE *OpenProfile (name)
char *name;
ОПИСАНИЕ:
Параметр name задает имя файла, который открывается и назначается в качестве вывода для профайлера.
В настоящее время неясно, должно ли открытие файла усечь любой существующий файл, или просто добавлять записи в него. Последний вариант был бы желателен для сбора хронологии во время выполнения в ходе нескольких разных запусков программы. Это потребует некоторых изменений в программе анализатора.
Закрывает поток вывода отладчика.
СИНТАКСИС:
static VOID CloseFile (fp)
FILE *fp;
ОПИСАНИЕ:
Закрывает поток вывода отладчика, если это не stdout или stderr.
Выводит сообщение об ошибке и завершает работу.
СИНТАКСИС:
static VOID DbugExit (why)
char *why;
ОПИСАНИЕ:
Выводит сообщение об ошибке, используя текущее имя процесса, причина прерывания выполнения (обычно мало памяти), и выходит с 1 состоянием. Это должно быть изменено, чтобы использовать при выходе код состояния, определенный в отладчике пользователя. Но это будет в следующих версиях.
Выделяет память для библиотек поддержки отладчика.
СИНТАКСИС:
static long *DbugMalloc (size)
int size;
ОПИСАНИЕ:
Выделяет дополнительную память для библиотек поддержки отладчика. Сбой при распределении запрошенного число байтов фатален для текущего процесса. Это довольно недружелюбное поведение. Лучше просто печатать предупреждающее сообщение, замораживать текущее состояние отладчика, и продолжать выполнение. Но это в следующей версии (может быть)...
СИНТАКСИС:
static char *static_strtok (s1, separator)
ОПИСАНИЕ:
Аналог strtok, но 2 разделителя в строке заменены на 1 для совместимости с именами каталогов, принятыми в DOS.
Удаляет путь из полного имени файла.
СИНТАКСИС:
static char *BaseName (pathname)
char *pathname;
ОПИСАНИЕ:
Параметр pathname является указателем на полное имя файла. Функция размещает в памяти короткое имя файла и возвращает указатель на него.
Проверяет возможность записи/создания файла.
СИНТАКСИС:
static BOOLEAN Writable (pathname)
char *pathname;
ОПИСАНИЕ
Поскольку отладчик может быть связан и с программой, которая выполняется с битом uid прав доступа (suid), мы должны быть внимательными относительно открытия заданного пользователем файла для вывода отладчика. Это состоит из проверки доступа к файлу на запись с реальным идентификатором пользователя, или проверкой каталога, где файл будет создан.
Вернет TRUE, если все в порядке и FALSE в противном случае.
Меняет владельца на реального пользователя для suid программ.
СИНТАКСИС:
static VOID ChangeOwner (pathname)
ОПИСАНИЕ:
Для Unix-систем, меняет владельца недавно созданного файла отладки на реального владельца. Это нужно в случаях выполнения программ, запущенных с правом доступа set-user-id.
Обратите внимание, что владелец файла уже установлен на момент выдачи этой команды. Так что, если она выполняется без права доступа set-user-id, то эта команда смысла не имеет (но безобидна).
Сохранить окружение отладчика.
СИНТАКСИС:
VOID _db_setjmp_ ()
ОПИСАНИЕ:
Вызывается как часть макрокоманды пользователя DBUG_SETJMP, чтобы сохранить среду отладчика параллельно с сохранением среды пользователя.
Восстановить предварительно сохраненное окружение отладчика.
СИНТАКСИС
VOID _db_longjmp_ ()
ОПИСАНИЕ:
Вызывается как часть макрокоманды пользователя DBUG_LONGJMP, чтобы восстановить среду отладчика параллельно с восстановлением предварительно сохраненной среды пользователя.
Преобразует параметр флажка D к системному стандарту.
СИНТАКСИС:
static int DelayArg (value)
int value;
ОПИСАНИЕ:
Преобразует время задержки, задаваемое в десятых долях секунды, к системному стандарту. Например, на Amiga, имеется системный вызов "Delay()" который получает параметр в импульсах таймера (50 в секунду). На Unix команда sleep работает с числом секунд. Таким образом, значение "10", для задержки в течение одной секунды, преобразуется в 50 на Amiga, и 1 на Unix. Другие системы будут должны использовать цикл синхронизации.
Моделирование perror для систем, которые его не имеют.
СИНТАКСИС:
static VOID perror (s)
char *s;
ОПИСАНИЕ:
Perror выдает сообщение в стандартный поток ошибки, которое обеспечивает большее количество информации относительно библиотеки или ошибки системы. Выводится сообщение, заданное строкой s, затем ': ', сообщение об ошибке и перевод строки (\n).
Недокументированная возможность Unix perror сводится к тому, что если 's' является пустой строкой (но не NULL!), то не выводится ': '.
Эта версия выдает сообщение только о "неизвестной ошибке системы".
В заключение хочется попросить Вас, если Вам понравилась эта страничка или пригодилась изложенная здесь информация, послать благодарность автору. Это поможет мне вести статистику того, скольким людям пригодилось хоть что-то из моих трудов.