Различное смещение в 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 не в состоянии найти имя функции, я думаю, что ваш двоичный файл удален).

Другие вопросы по тегам