Различное смещение в libc's backtrace_symbols() и libunwind unw_get_proc_name()
Я делаю трассировку стека в какой-то момент в моей программе. Однажды с libcbacktrace_symbols()
функция и один раз с unw_get_proc_name()
из либунвинда.
Вывод backtrace_symbols():
/home/jj/test/mylib.so(+0x97004)[0x7f6b47ce9004]
Вывод unw_get_proc_name ():
ip: 0x7f6b47ce9004, offset: 0x458e4
Здесь вы видите, что адрес указателя инструкции (0x7f6b47ce9004) является тем же и правильным. Функция смещения 0x97004
из backtrace_symbols() тоже правильно, но не тот, который я получаю от unw_get_proc_name () (0x458e4
).
Кто-нибудь знает, что здесь происходит и что может вызвать эту разницу в смещениях?
Оба метода используют похожий код, как в следующих примерах:
трассировка ():
void *array[10];
size_t size;
size = backtrace(array, 10);
backtrace_symbols_fd(array, size, STDERR_FILENO);
libunwind:
unw_cursor_t cursor;
unw_context_t context;
unw_getcontext(&context);
unw_init_local(&cursor, &context);
while (unw_step(&cursor) > 0) {
unw_word_t offset, pc;
char fname[64];
unw_get_reg(&cursor, UNW_REG_IP, &pc);
fname[0] = '\0';
(void) unw_get_proc_name(&cursor, fname, sizeof(fname), &offset);
printf ("%p : (%s+0x%x) [%p]\n", pc, fname, offset, pc);
}
1 ответ
Я думаю unw_get_proc_name
вычислить смещение от неназванного внутреннего кадра.
Например:
void f() {
int i;
while (...) {
int j;
}
}
Обратите внимание, что внутри блока цикла есть объявление переменной. В этом случае (и в зависимости от уровня оптимизации) компилятор может создать фрейм (и связанную информацию о раскрутке) для цикла. Как следствие, unw_get_proc_name
вычислить смещение из этого цикла вместо начала функции.
Это объясняется в unw_get_proc_name
справочная страница:
Обратите внимание, что на некоторых платформах нет надежного способа отличить имена процедур от обычных меток. Кроме того, если информация о символах была извлечена из программы, имена процедур могут быть полностью недоступны или могут быть ограничены теми, которые экспортируются через динамическую таблицу символов. В таких случаях unw_get_proc_name() может возвращать имя метки или предшествующей (соседней) процедуры.
Вы можете попробовать протестировать снова, но без удаления вашего двоичного файла (так как unw_get_proc_name
не в состоянии найти имя функции, я думаю, что ваш двоичный файл удален).