Как декодировать стек вызовов Windows CE? - PullRequest
4 голосов
/ 29 октября 2010

Настольные ОС Windows имеют функцию «StackWalk64», благодаря которой Йохен Кальмбах сделал библиотеку для декодирования стека вызовов в нечто, удобочитаемое человеком.для Windows CE.WinCE имеет функцию для получения стека вызовов, GetThreadCallStack , но когда у меня есть необработанные обратные адреса, как мне

  1. определить модуль (DLL или EXE) из каждой программыcounter?
  2. Определить функцию, содержащую адрес, используя мои файлы .map или .pdb?

PS.Если это кому-нибудь поможет, я также нашел независимый от ОС код для обхода стека вызовов ARM.По-видимому, это действительно трудно сделать надежно!

Ответы [ 3 ]

4 голосов
/ 04 ноября 2010

Ну, я разобрался с половиной. Вам нужно позвонить GetThreadCallStack ...

CallSnapshot frames[100];

HANDLE hThread = GetCurrentThread();
SetLastError(ERROR_SUCCESS);
int funcCount = GetThreadCallStack(hThread, 100, frames, STACKSNAP_RETURN_FRAMES_ON_ERROR, 0);
bool success = GetLastError() == ERROR_SUCCESS;

но по какой-то причине файл заголовка для него не включен в Windows CE SDK. Поэтому вам нужно объявить это вручную:

extern "C" {
    typedef struct _CallSnapshot {
        DWORD dwReturnAddr;
    } CallSnapshot;

    typedef struct _CallSnapshotEx {
        DWORD dwReturnAddr;
        DWORD dwFramePtr;
        DWORD dwCurProc;
        DWORD dwParams[4];
    } CallSnapshotEx;

    ULONG GetThreadCallStack (HANDLE hThrd, ULONG dwMaxFrames, LPVOID lpFrames, DWORD dwFlags, DWORD dwSkip);
    ULONG GetCallStackSnapshot (ULONG dwMaxFrames, CallSnapshot lpFrames[], DWORD dwFlags, DWORD dwSkip);

    #define STACKSNAP_FAIL_IF_INCOMPLETE     1
    #define STACKSNAP_EXTENDED_INFO          2
    #define STACKSNAP_INPROC_ONLY            4
    #define STACKSNAP_RETURN_FRAMES_ON_ERROR 8
}

И затем для декодирования стека вызовов вам необходимо (1) определить модуль (EXE или DLL) каждого адреса возврата и (2) выяснить функцию в этом модуле.

Я задал еще один вопрос о получении модуля с адресом кода ; и теоретически можно было бы проанализировать файл карты, чтобы выяснить, какой функции (в этом модуле) адрес принадлежит (спасибо ctacke за ссылку).

3 голосов
/ 09 декабря 2010

Я также использую GetThreadCallStack, он работает довольно хорошо.В целом, wince - худшая платформа с худшими инструментами, когда дело доходит до отладки.Все BS на MSDN о doctorwatson требуют быть партнером или использовать сборщик платформ.А как насчет обычных разработчиков, которым нужно устранять источник сбоев во время выпуска приложений ?!Во времена цифровой эры и компьютеров эти «крутые» трюки с файлами карт звучат довольно медленно;Такая задача идеально подходит для компьютеров.Единственный способ получить стек вызовов на wince - это GetThreadCallStack.«Код, не зависящий от ОС», упомянутый в оригинальном постере, не работает на Wince.Это было достаточно для автора, чтобы заставить его работать с его комбо компилятором / os / cpu, но это не работает для wince (в частности, он не обрабатывает инструкции LDR, которые восстанавливают реестр ПК).Я потратил некоторое время на то, чтобы заставить этот код работать, в общем, я решил пропустить его и кучу отходов: такой код должен писать производитель ОС или компилятор, очень трудно заставить его работать идеально для всех возможных типов сгенерированныхcode.

Для тех, кто отказывается использовать всю эту путаницу с файлами карт, я могу порекомендовать инструмент, который поможет вам избежать этого шага. CrashFinder.exe Джона Роббинса может сделать эту часть для вас.Кроме того, когда вы получаете callstack от GetThreadCallStack, печатайте адреса с очищенным верхним байтом:

unsigned addr = addr1 & 0x00ffffff;

Затем в поисковике сбоев вам нужно открыть exe-файл вашего приложения wince, и вы можете запросить адреса, и он будетпокажет вам имена функций, если адреса находятся в вашем приложении.Обычно, если сбой происходит где-то внутри winapi, мне нужно вручную вводить каждый адрес из стека вызовов, пока не найду последний, который был в моем приложении.

2 голосов
/ 29 октября 2010

Все эти статьи обсуждают преобразование адреса в строку кода в исходном коде и могут быть полезны:

...