| 894 | static LPVOID s_readMemoryFunction_UserData = NULL; |
| 895 | |
| 896 | BOOL StackWalker::ShowCallstack(HANDLE hThread, const CONTEXT *context, PReadProcessMemoryRoutine readMemoryFunction, LPVOID pUserData) |
| 897 | { |
| 898 | CONTEXT c; |
| 899 | CallstackEntry csEntry; |
| 900 | IMAGEHLP_SYMBOL64 *pSym = NULL; |
| 901 | StackWalkerInternal::IMAGEHLP_MODULE64_V2 Module; |
| 902 | IMAGEHLP_LINE64 Line; |
| 903 | int frameNum; |
| 904 | |
| 905 | if (m_modulesLoaded == FALSE) |
| 906 | this->LoadModules(); // ignore the result... |
| 907 | |
| 908 | if (this->m_sw->m_hDbhHelp == NULL) |
| 909 | { |
| 910 | SetLastError(ERROR_DLL_INIT_FAILED); |
| 911 | return FALSE; |
| 912 | } |
| 913 | |
| 914 | s_readMemoryFunction = readMemoryFunction; |
| 915 | s_readMemoryFunction_UserData = pUserData; |
| 916 | |
| 917 | if (context == NULL) |
| 918 | { |
| 919 | // If no context is provided, capture the context |
| 920 | if (hThread == GetCurrentThread()) |
| 921 | { |
| 922 | GET_CURRENT_CONTEXT(c, USED_CONTEXT_FLAGS); |
| 923 | } |
| 924 | else |
| 925 | { |
| 926 | SuspendThread(hThread); |
| 927 | memset(&c, 0, sizeof(CONTEXT)); |
| 928 | c.ContextFlags = USED_CONTEXT_FLAGS; |
| 929 | if (GetThreadContext(hThread, &c) == FALSE) |
| 930 | { |
| 931 | ResumeThread(hThread); |
| 932 | return FALSE; |
| 933 | } |
| 934 | } |
| 935 | } |
| 936 | else |
| 937 | c = *context; |
| 938 | |
| 939 | // init STACKFRAME for first call |
| 940 | STACKFRAME64 s; // in/out stackframe |
| 941 | memset(&s, 0, sizeof(s)); |
| 942 | DWORD imageType; |
| 943 | #ifdef _M_IX86 |
| 944 | // normally, call ImageNtHeader() and use machine info from PE header |
| 945 | imageType = IMAGE_FILE_MACHINE_I386; |
| 946 | s.AddrPC.Offset = c.Eip; |
| 947 | s.AddrPC.Mode = AddrModeFlat; |
| 948 | s.AddrFrame.Offset = c.Ebp; |
| 949 | s.AddrFrame.Mode = AddrModeFlat; |
| 950 | s.AddrStack.Offset = c.Esp; |
| 951 | s.AddrStack.Mode = AddrModeFlat; |
| 952 | #elif _M_X64 |
| 953 | imageType = IMAGE_FILE_MACHINE_AMD64; |
no test coverage detected