Описание архитектуры библиотеки libbacktrace и примеры использования
Библиотека libbacktrace предоставляет возможность программно выполнить обратную трассировку выполняемого процесса извне. Возможно использование обратной трассировки как для отладки, так и для диагностики или ведения логов. В большинстве случаев следует использовать gdb для производства отладки.
Библиотека backtrace позволяет:
Обратите внимание:
SIGSEGV
. SIGSEGV
и SIGBUS
, но обычно эти сигналы ловит gdb. При использовании gdb на той же программе, что использует libbacktrace,следует сообщить gdb о том, чтобы он передавал эти сигналы программе для выполнения корректной операции: Следующие замечания относятся только к целевым системам с PowerPC:
lr
(регистра ссылки) на PPC. BT_SELF
, вторая запись обратной трассировки будет корректна.
![]() | Библиотека обратной трассировки не поддерживается из-за ее недостаточной надежности. Предлагаемые ею функции доступны через gdb более безопасным и стабильным способом; gdb использует отладочную информацию для трассировки, тогда как backtrace использует угадывание - он декодирует инструкции/стек/регистры, чтобы вычислить адрес возврата, и это подвержено ошибкам. GDB использует такое предположение только как запасной вариант, когда символы недоступны.
Ввиду разнообразия версий gcc, и различий в оптимизации каждой из них, напрямую затрагивается точность backtrace; почти наверняка backtrace не будет работать в большинстве случаев. |
Библиотека libbacktrace определяет следующие переменные и типы данных:
BT_SELF
. Данная библиотека также определяет следующие функции:
В целом, данные функции следует использовать следующим образом:
Список примеров:
![]() | Для сокращения объема текста, данные примеры не обрабатывают каких-либо ошибок. |
Используйте следующий фрагмент кода чтобы получить и затем вывести содержимое отображаемой памяти:
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 );
Дополнительные замечания касательно памяти:
(16 + strlen( filename )) * num_files
40
символов, и исключая издержки malloc()), займет приблизительно 224
байта.
![]() | Не существует явных ссылок между отображаемой памятью и обратной трассировкой. Следовательно, пользователь несет ответственность за то, чтобы отображаемая память была перечитана, чтобы учесть правильное обращение с удалением процессов dlopen() и dlclose(), а также с перераспределением идентификаторов процессов. |
Используйте следующий фрагмент кода для цикличной обратной трассировки потока в другом процессе, используя 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 );
Обратная трассировка другого потока в текущем процессе аналогична обратной трассировке потока в другом процессе (см. пример выше). Единственным отличием является то, как следует инициализировать структуру метода доступа. Флаги, переданные bt_init_accessor() определяют, какой процесс нуждается в обратной трассировке. Если установить BT_THREAD
, другой поток в текущем процессе будет подготовлен к обратной трассировке:
bt_init_accessor( &acc, BT_THREAD, tid );
Для отладки потока в другом процессе, установите флаг BT_PROCESS
и передайте pid и tid для обратной трассировки:
bt_init_accessor( &acc, BT_PROCESS, getpid(), tid );
Для обратной трассировки выполняемого в даный момент потока, можно выполнить следующее::
BT_PROCES
, как описано в Обратная трассировка потока в другом процессе но задать текущие pid и tid. BT_THREAD
и выбрать выполняемый в данный момент поток. BT_SELF
. Это лучший способ убедиться что активный поток отслеживается: bt_init_accessor( &acc, BT_SELF );
Вы также можете использовать предварительно инициализированный метод доступа под названием bt_acc_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 );...}
Иногда может быть полезно отслеживать несколько потоков согласованно. Этого можно достичь, приостановив все потоки, выполнив обратную трассировку потоков, и затем запустить их вновь. Например:
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