Общие сведения

Описание архитектуры библиотеки libbacktrace и примеры использования

Обзор
API
Примеры
Пример 1: Получение и печать содержимого отображенной памяти
Пример 2: Обратная трассировка потока в другом процессе
Пример 3: Обратная трассировка другого потока в том же процессе
Пример 4: Обратная трассировка текущего потока
Пример 5: Выполнение обратной трассировки с BT_SELF в обработчике сигнала
Пример 6: Обратная трассировка нескольких потоков

Обзор

Библиотека libbacktrace предоставляет возможность программно выполнить обратную трассировку выполняемого процесса извне. Возможно использование обратной трассировки как для отладки, так и для диагностики или ведения логов. В большинстве случаев следует использовать gdb для производства отладки.

Библиотека backtrace позволяет:

Обратите внимание:

Следующие замечания относятся только к целевым системам с PowerPC:


Note: Библиотека обратной трассировки не поддерживается из-за ее недостаточной надежности. Предлагаемые ею функции доступны через gdb более безопасным и стабильным способом; gdb использует отладочную информацию для трассировки, тогда как backtrace использует угадывание - он декодирует инструкции/стек/регистры, чтобы вычислить адрес возврата, и это подвержено ошибкам. GDB использует такое предположение только как запасной вариант, когда символы недоступны.

Ввиду разнообразия версий gcc, и различий в оптимизации каждой из них, напрямую затрагивается точность backtrace; почти наверняка backtrace не будет работать в большинстве случаев.


API

Библиотека libbacktrace определяет следующие переменные и типы данных:

bt_accessor_t
Непрозрачная структура, в которой хранится идентификатор потока, для которого нужно выполнить обратную трассировку.
bt_memmap_t
Непрозрачная структура, которая содержит отображенную память данного процесса. Отображенная память состоит из списка всех объектных файлов (исполняемых и разделяемых библиотек) в памяти процесса, а также расположения и размера их сегментов кода.
bt_accessor_t bt_acc_self
Заранее инициализированный метод доступа, используемый для обратной трассировки с BT_SELF.

Note: Не вызывайте bt_init_accessor() или bt_release_accessor() для данной глобальной переменной.

Данная библиотека также определяет следующие функции:

bt_get_backtrace()
Получить обратную трассировку
bt_init_accessor()
Инициализировать структуру обратной трассировки
bt_load_memmap()
Выделить память для обратной трассировки
bt_release_accessor()
Очистить структуру обратной трассировки
bt_set_flags()
Установить или сбросить флаги обратной трассировки
bt_sprn_memmap()
Отформатировать информацию в отображенной памяти для обратной трассировки
bt_sprnf_addrs()
Форматировать адреса из обратной трассировки
bt_translate_addrs()
Транслировать адреса из обратной трассировки
bt_unload_memmap()
Освободить память, связанную с обратной трассировкой

В целом, данные функции следует использовать следующим образом:

  1. Вызвать bt_init_accessor() для установки обратной трассировки.
  2. При необходимостм вызвать bt_set_flags() если требуется выполнить обратную трассировку в данный момент. По умолчанию, bt_get_backtrace() приостанавливает поток перед перед сбором обратной трассировки.
  3. Вызвать bt_get_backtrace() для сбора адресов обратной трассировки.
  4. При необходимости загрузить отображаемую память для процесса, вызвав bt_load_memmap(). Это следует сделать в случае, если необходимо форматировать информацию определенныи образом.
  5. При необходимости вызвать bt_sprn_memmap() для генерации строки содержимого отображаемой памяти.
  6. Вызвать bt_sprnf_addrs() или bt_translate_addrs() для форматирования адресов обратной трассировки.
  7. Вызвать bt_unload_memmap() для очистки отображаемой памяти.
  8. Вызвать bt_release_accessor() для освобождения метода доступа.

Примеры

Список примеров:

  1. Получение и печать содержимого отображенной памяти
  2. Обратная трассировка потока в другом процессе
  3. Обратная трассировка другого потока в том же процессе
  4. Обратная трассировка текущего потока
  5. Выполнение обратной трассировки с BT_SELF в обработчике сигнала
  6. Обратная трассировка нескольких потоков


Note: Для сокращения объема текста, данные примеры не обрабатывают каких-либо ошибок.

Пример 1: Получение и печать содержимого отображенной памяти

Используйте следующий фрагмент кода чтобы получить и затем вывести содержимое отображаемой памяти:

char out[1024];
bt_accessor_t acc;
bt_memmap_t memmap;
bt_init_accessor( &acc, BT_SELF );
bt_load_memmap( &acc, &memmap );
bt_sprn_memmap( &memmap, out, sizeof( out ) );
puts( out );
bt_release_accessor( &acc );

Дополнительные замечания касательно памяти:


Note: Не существует явных ссылок между отображаемой памятью и обратной трассировкой. Следовательно, пользователь несет ответственность за то, чтобы отображаемая память была перечитана, чтобы учесть правильное обращение с удалением процессов dlopen() и dlclose(), а также с перераспределением идентификаторов процессов.

Пример 2: Обратная трассировка потока в другом процессе

Используйте следующий фрагмент кода для цикличной обратной трассировки потока в другом процессе, используя pid другого процесса и идентификатор потока tid:

char out[1024];
bt_addr_t pc[16];
bt_accessor_t acc;
bt_init_accessor( &acc, BT_PROCESS, remotepid, remotetid );
bt_load_memmap( &acc, &memmap );
bt_sprn_memmap( &acc, out, sizeof( out ) );
for ( i = 0; i < 10; i++ )
{
cnt = bt_get_backtrace( &acc, pc, sizeof( pc ) / sizeof( bt_addr_t ) );
bt_sprnf_addrs( &memmap, pc, cnt, "%a\n", out, sizeof( out ), 0 );
puts( out );
}
bt_unload_memmap( &memmap );
bt_release_accessor( &acc );

Пример 3: Обратная трассировка другого потока в том же процессе

Обратная трассировка другого потока в текущем процессе аналогична обратной трассировке потока в другом процессе (см. пример выше). Единственным отличием является то, как следует инициализировать структуру метода доступа. Флаги, переданные bt_init_accessor() определяют, какой процесс нуждается в обратной трассировке. Если установить BT_THREAD, другой поток в текущем процессе будет подготовлен к обратной трассировке:

bt_init_accessor( &acc, BT_THREAD, tid );

Для отладки потока в другом процессе, установите флаг BT_PROCESS и передайте pid и tid для обратной трассировки:

bt_init_accessor( &acc, BT_PROCESS, getpid(), tid );

Пример 4: Обратная трассировка текущего потока

Для обратной трассировки выполняемого в даный момент потока, можно выполнить следующее::

Вы также можете использовать предварительно инициализированный метод доступа под названием bt_acc_self.

Пример 5: Выполнение обратной трассировки с BT_SELF в обработчике сигнала

Предоставление обратной трассировки, которая сигнало- и обработчико- безопасна, является особым случаем. Извне обработика сигналов, возможно использование только bt_get_backtrace(), и необходимо убедиться, что доступ к памяти не вызывает конфликтов. Например:

bt_accessor_t acc_sighandler1;
bt_addr_t pc_sighandler1[10];
int cnt_sighandler1;
void sighandler1( int sig )
{
cnt_sighandler1 = bt_get_backtrace( &acc_sighandler1, pc_sighandler1,
sizeof( pc_sighandler1 ) / sizeof( bt_addr_t ) );
}
thread_func()
{
char out[512];
bt_init_accessor( &acc_sighandler1, BT_SELF );
signal( SIGUSR2, sighandler1 );
...
bt_sprnf_addrs( &memmap, pc_sighandler1, cnt_sighandler1, "%a", out, sizeof( out ), 0 );
...
bt_release_accessor( &acc );
...
}

Пример 6: Обратная трассировка нескольких потоков

Иногда может быть полезно отслеживать несколько потоков согласованно. Этого можно достичь, приостановив все потоки, выполнив обратную трассировку потоков, и затем запустить их вновь. Например:

bt_accessor_t acc;
hold_all_threads();
for ( i = 0; i < max_thread; i++ )
{
bt_init_accessor( &acc, BT_PROCESS, pid, i );
bt_set_flags( acc, BT_LIVE_BACKTRACE, 1 );
bt_get_backtrace( &acc, addrs, len );
bt_release_accessor( &acc );
save_addrs( addrs );
}
cont_all_threads();




Предыдущий раздел: Описание API библиотеки asyncmsg