833 // deferred. |
833 // deferred. |
834 // |
834 // |
835 |
835 |
836 #include <winnt.h> |
836 #include <winnt.h> |
837 |
837 |
|
838 // Uncomment the following line to turn on tracing when we examine the call stack |
|
839 // #define DUMP_STACK_BACKTRACE |
|
840 |
|
841 #ifdef DUMP_STACK_BACKTRACE |
|
842 |
|
843 #include <psapi.h> |
|
844 |
|
845 typedef BOOL (WINAPI GMIFunc)(HANDLE hProcess, HMODULE hModule, LPMODULEINFO lpmodinfo, DWORD cb); |
|
846 typedef BOOL (WINAPI EPMFunc)(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded); |
|
847 typedef DWORD (WINAPI GMBNFunc)(HANDLE hProcess, HMODULE hModule, LPSTR lpBaseName, DWORD nSize); |
|
848 |
|
849 void PrintAllModuleInfo() |
|
850 { |
|
851 HMODULE psapiLibrary = LoadLibraryA("psapi.dll"); |
|
852 __NK_ASSERT_ALWAYS(psapiLibrary != NULL); |
|
853 |
|
854 EPMFunc* epmFunc = (EPMFunc*)GetProcAddress(psapiLibrary, "EnumProcessModules"); |
|
855 __NK_ASSERT_ALWAYS(epmFunc != NULL); |
|
856 |
|
857 GMIFunc* gmiFunc = (GMIFunc*)GetProcAddress(psapiLibrary, "GetModuleInformation"); |
|
858 __NK_ASSERT_ALWAYS(gmiFunc != NULL); |
|
859 |
|
860 GMBNFunc* gmbnFunc = (GMBNFunc*)GetProcAddress(psapiLibrary, "GetModuleBaseNameA"); |
|
861 __NK_ASSERT_ALWAYS(gmbnFunc != NULL); |
|
862 |
|
863 const TInt maxModules = 256; |
|
864 HMODULE modules[maxModules]; |
|
865 |
|
866 DWORD spaceNeeded; |
|
867 BOOL r = epmFunc(GetCurrentProcess(), modules, sizeof(HMODULE) * maxModules, &spaceNeeded); |
|
868 __NK_ASSERT_ALWAYS(r); |
|
869 __NK_ASSERT_ALWAYS(spaceNeeded <= sizeof(HMODULE) * maxModules); |
|
870 |
|
871 for (TUint i = 0 ; i < spaceNeeded / sizeof(HMODULE) ; ++i) |
|
872 { |
|
873 HMODULE library = modules[i]; |
|
874 |
|
875 const TUint maxNameLen = 64; |
|
876 char name[maxNameLen]; |
|
877 WORD len = gmbnFunc(GetCurrentProcess(), library, name, sizeof(name)); |
|
878 __NK_ASSERT_ALWAYS(len > 0 && len < maxNameLen); |
|
879 |
|
880 MODULEINFO info; |
|
881 r = gmiFunc(GetCurrentProcess(), library, &info, sizeof(info)); |
|
882 __NK_ASSERT_ALWAYS(r); |
|
883 |
|
884 DEBUGPRINT("Module %s found at %08x to %08x", name, (TUint)info.lpBaseOfDll, (TUint)info.lpBaseOfDll + info.SizeOfImage); |
|
885 } |
|
886 |
|
887 r = FreeLibrary(psapiLibrary); |
|
888 __NK_ASSERT_ALWAYS(r); |
|
889 } |
|
890 |
|
891 #endif |
|
892 |
838 const TInt KWin32NonPreemptibleFunctionCount = 2; |
893 const TInt KWin32NonPreemptibleFunctionCount = 2; |
839 |
894 |
840 struct TWin32FunctionInfo |
895 struct TWin32FunctionInfo |
841 { |
896 { |
842 TUint iStartAddr; |
897 TUint iStartAddr; |
843 TUint iLength; |
898 TUint iLength; |
844 }; |
899 }; |
845 |
900 |
846 static TWin32FunctionInfo Win32NonPreemptibleFunctions[KWin32NonPreemptibleFunctionCount]; |
901 static TWin32FunctionInfo Win32NonPreemptibleFunctions[KWin32NonPreemptibleFunctionCount]; |
847 |
902 |
848 TWin32FunctionInfo Win32FindExportedFunction(const char* aModuleName, const char* aFunctionName) |
903 HMODULE GetFirstLoadedModuleHandleA(const char* aModuleName1, const char* aModuleName2) |
849 { |
904 { |
850 HMODULE library = GetModuleHandleA(aModuleName); |
905 HMODULE result = GetModuleHandleA(aModuleName1); |
|
906 return result ? result : GetModuleHandleA(aModuleName2); |
|
907 } |
|
908 |
|
909 TWin32FunctionInfo Win32FindExportedFunction(const char* aFunctionName, ...) |
|
910 { |
|
911 const char *libname; |
|
912 HMODULE library = NULL; |
|
913 |
|
914 va_list arg; |
|
915 va_start(arg, aFunctionName); |
|
916 |
|
917 // Loop through arguments until we find a library we can get a handle to. List of library names |
|
918 // is NULL-terminated. |
|
919 while ((libname = va_arg(arg, const char *)) != NULL) |
|
920 { |
|
921 library = GetModuleHandleA(libname); |
|
922 if (library != NULL) |
|
923 break; |
|
924 } |
|
925 |
|
926 va_end(arg); |
|
927 |
|
928 // Make sure we did get a valid library |
851 __NK_ASSERT_ALWAYS(library != NULL); |
929 __NK_ASSERT_ALWAYS(library != NULL); |
852 |
930 |
853 // Find the start address of the function |
931 // Find the start address of the function |
854 TUint start = (TUint)GetProcAddress(library, aFunctionName); |
932 TUint start = (TUint)GetProcAddress(library, aFunctionName); |
855 __NK_ASSERT_ALWAYS(start); |
933 __NK_ASSERT_ALWAYS(start != 0); |
856 |
934 |
857 // Now have to check all other exports to find the end of the function |
935 // Now have to check all other exports to find the end of the function |
858 TUint end = 0xffffffff; |
936 TUint end = 0xffffffff; |
859 TInt i = 1; |
937 TInt i = 1; |
860 for (;;) |
938 for (;;) |
865 if (addr > start && addr < end) |
943 if (addr > start && addr < end) |
866 end = addr; |
944 end = addr; |
867 ++i; |
945 ++i; |
868 } |
946 } |
869 __NK_ASSERT_ALWAYS(end != 0xffffffff); |
947 __NK_ASSERT_ALWAYS(end != 0xffffffff); |
870 |
948 |
871 TWin32FunctionInfo result = { start, end - start }; |
949 TWin32FunctionInfo result = { start, end - start }; |
|
950 |
|
951 #ifdef DUMP_STACK_BACKTRACE |
|
952 DEBUGPRINT("Function %s found at %08x to %08x", aFunctionName, start, end); |
|
953 #endif |
|
954 |
872 return result; |
955 return result; |
873 } |
956 } |
874 |
957 |
875 void Win32FindNonPreemptibleFunctions() |
958 void Win32FindNonPreemptibleFunctions() |
876 { |
959 { |
877 Win32NonPreemptibleFunctions[0] = Win32FindExportedFunction("kernel32.dll", "RaiseException"); |
960 #ifdef DUMP_STACK_BACKTRACE |
878 Win32NonPreemptibleFunctions[1] = Win32FindExportedFunction("ntdll.dll", "KiUserExceptionDispatcher"); |
961 PrintAllModuleInfo(); |
|
962 #endif |
|
963 |
|
964 TUint i = 0; |
|
965 Win32NonPreemptibleFunctions[i++] = Win32FindExportedFunction("RaiseException", "kernelbase.dll", "kernel32.dll", NULL); |
|
966 Win32NonPreemptibleFunctions[i++] = Win32FindExportedFunction("KiUserExceptionDispatcher", "ntdll.dll", NULL); |
|
967 __NK_ASSERT_ALWAYS(i == KWin32NonPreemptibleFunctionCount); |
879 } |
968 } |
880 |
969 |
881 TBool Win32IsThreadInNonPreemptibleFunction(HANDLE aWinThread, TLinAddr aStackTop) |
970 TBool Win32IsThreadInNonPreemptibleFunction(HANDLE aWinThread, TLinAddr aStackTop) |
882 { |
971 { |
883 const TInt KMaxSearchDepth = 16; // 12 max observed while handling exceptions |
972 const TInt KMaxSearchDepth = 16; // 12 max observed while handling exceptions |
890 |
979 |
891 TUint eip = c.Eip; |
980 TUint eip = c.Eip; |
892 TUint ebp = c.Ebp; |
981 TUint ebp = c.Ebp; |
893 TUint lastEbp = c.Esp; |
982 TUint lastEbp = c.Esp; |
894 |
983 |
|
984 #ifdef DUMP_STACK_BACKTRACE |
|
985 DEBUGPRINT("Stack backtrace for thread %x", aWinThread); |
|
986 #endif |
|
987 |
895 // Walk the call stack |
988 // Walk the call stack |
896 for (TInt i = 0 ; i < KMaxSearchDepth ; ++i) |
989 for (TInt i = 0 ; i < KMaxSearchDepth ; ++i) |
897 { |
990 { |
|
991 #ifdef DUMP_STACK_BACKTRACE |
|
992 DEBUGPRINT(" %08x", eip); |
|
993 #endif |
|
994 |
898 for (TInt j = 0 ; j < KWin32NonPreemptibleFunctionCount ; ++j) |
995 for (TInt j = 0 ; j < KWin32NonPreemptibleFunctionCount ; ++j) |
899 { |
996 { |
900 const TWin32FunctionInfo& info = Win32NonPreemptibleFunctions[j]; |
997 const TWin32FunctionInfo& info = Win32NonPreemptibleFunctions[j]; |
901 if (TUint(eip - info.iStartAddr) < info.iLength) |
998 if (TUint(eip - info.iStartAddr) < info.iLength) |
902 { |
999 { |