Получение указателя на нижнюю часть стека вызовов и разрешение символа по адресу (например, dladdr) в Windows?

Я хочу реализовать аналог утилиты backtrace под windows, чтобы добавить эту информацию, например, в исключение.

Мне нужно захватить обратные адреса, а затем перевести их в имена символов.

Мне известно о StackWalk64 и проекте StackWalker, но, к сожалению, у него есть несколько существенных недостатков:

  • Известно, что он очень медленный (StackWalk64), и я не хочу тратить много времени на сбор трассировки, в основном это можно сделать так же быстро, как пройтись по связанному списку.
  • Известно, что функция StackWalk64 не является потокобезопасной.

Я хочу поддерживать только x86 и возможные архитектуры x86_64

Основная идея у меня следующая:

  1. Запуск в стеке с использованием регистров esp/ebp аналогично __builtin_return_address(x)/__builtin_frame_address(x) doe GCC, пока я не достигну нижней части стека (это то, что делает glibc).
  2. Преобразование адресов в символы
  3. Демангл их.

Проблемы/Вопросы:

  1. Как я узнаю, что достиг вершины стека? Например, реализация glibc имеет __libc_stack_end, поэтому легко найти, где остановиться. Есть ли аналог такой штуки под Windows? Как я могу получить нижний адрес стека?
  2. Какие есть аналоги функционала dladdr. Теперь я знаю, что в отличие от платформы ELF, которая хранит большинство имен символов, формат PE этого не делает. Так что он должен как-то читать отладочную информацию. Любые идеи?

person Artyom    schedule 27.09.2010    source источник


Ответы (2)


  • Захват трассировки стека: RtlCaptureStackBackTrace
  • Получение символов: использование библиотеки справки DBG (только для MSVC). Ключевые функции:

    // Initialization
    hProcess = GetCurrentProcess()
    SymSetOptions(SYMOPT_DEFERRED_LOADS)
    SymInitialize(hProcess, NULL, TRUE)
    // Fetching symbol
    SymFromAddr(...)
    

    Реализацию можно найти там

person Artyom    schedule 14.02.2011

Вы используете StackWalk, но разрешаете символы позже.

person Will    schedule 27.09.2010
comment
Я упомянул о своих проблемах с функцией StackWalk - person Artyom; 27.09.2010
comment
в таком случае я бы просто не реализовал, это так как overhead StackWalk64 слишком высок, по сравнению например с хождением по указателям фрейма ebp. - person Artyom; 27.09.2010
comment
По моему опыту, обход стека не такой уж и медленный; он даже используется в профилировщиках образцов моментальных снимков стека. Однако вам нужно избегать поиска символов при сборе данных; это поиск символов, который очень дорог; так что кешируйте их, лениво вычисляйте и так далее. - person Will; 27.09.2010
comment
Даже если производительность не является проблемой, у StackWalk есть другие проблемы — безопасность потоков, полное отсутствие какой-либо полезной документации (которую вы действительно можете прочитать, а не ссылаться на 1001 образец третьей части) и т. д. Если у меня есть указатель на нижнюю часть стек, я могу легко сделать это самостоятельно. Поэтому я действительно хочу избежать этой функции. - person Artyom; 27.09.2010