Получение указателя на нижнюю часть стека вызовов и разрешение символа по адресу (например, dladdr) под Windows?
Я хочу реализовать аналог утилиты backtrace под windows, чтобы добавить эту информацию в исключение, например.
Мне нужно записать обратные адреса, а затем перевести их в имена символов.
Я знаю о StackWalk64 и о проекте StackWalker, но, к сожалению, у него есть несколько важных недостатков:
- известно, что он очень медленный (StackWalk64), и я не хочу тратить много времени на сбор следов, которые в принципе могут быть сделано так же быстро, как ходить по связанному списку.
- известно, что функция StackWalk64 не является потокобезопасной.
Я хочу поддерживать только x86 и возможные архитектуры x86_64
Основная идея у меня следующая:
- запуск на стеке с использованием регистров esp/ebp аналогично тому, что GCC
__builtin_return_address(x)
/__builtin_frame_address(x)
doe, пока я не достигну нижней части стека (это то, что делает glibc). - перевести адреса в символы
- Demangle их.
Проблемы / Вопросы:
- Как я узнаю, что я достигаю вершины стопки? Например, реализация glibc имеет
__libc_stack_end
, поэтому легко найти, где остановиться. Есть ли аналог такой штуки под окнами? Как я могу получить Нижний адрес стека? - каковы аналоги функциональности dladdr. Теперь я знаю, что в отличие от платформы ELF, которая сохраняет большинство имен символов, формат PE этого не делает. Так что он должен каким-то образом считывать отладочную информацию. Есть идеи?
2 ответа:
- Захват Трассировки Стека: RtlCaptureStackBackTrace
Получение символов: использование библиотеки справки DBG (только MSVC). Ключевые функции:
// Initialization hProcess = GetCurrentProcess() SymSetOptions(SYMOPT_DEFERRED_LOADS) SymInitialize(hProcess, NULL, TRUE) // Fetching symbol SymFromAddr(...)
Реализация может быть найдена там