1 /* 2 * PROJECT: MSVC runtime check support library 3 * LICENSE: BSD - See COPYING.ARM in the top level directory 4 * PURPOSE: Provides support functions for MSVC runtime checks 5 * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) 6 */ 7 8 #include <rtcapi.h> 9 10 #if defined(_M_IX86) 11 #pragma comment(linker, "/alternatename:__CRT_RTC_INITW=__CRT_RTC_INITW0") 12 #elif defined(_M_IA64) || defined(_M_AMD64) || defined(_M_ARM) || defined(_M_ARM64) 13 #pragma comment(linker, "/alternatename:_CRT_RTC_INITW=_CRT_RTC_INITW0") 14 #else 15 #error Unsupported platform 16 #endif 17 18 // Provide a fallback memset for libraries like kbdrost.dll 19 #if defined(_M_ARM) || defined(_M_ARM64) 20 void* __cdecl memset_fallback(void* src, int val, size_t count) 21 { 22 char *char_src = (char *)src; 23 while(count > 0) 24 { 25 *char_src = val; 26 char_src++; 27 count--; 28 } 29 return src; 30 } 31 #pragma comment(linker, "/alternatename:memset=memset_fallback") 32 #pragma comment(linker, "/alternatename:__RTC_memset=memset_fallback") 33 #endif 34 35 int 36 __cdecl 37 _RTC_DefaultErrorFuncW( 38 int errType, 39 const wchar_t *file, 40 int line, 41 const wchar_t *module, 42 const wchar_t *format, 43 ...) 44 { 45 /* Simple fallback function */ 46 __debugbreak(); 47 return 0; 48 } 49 50 _RTC_error_fnW _RTC_pErrorFuncW = _RTC_DefaultErrorFuncW; 51 52 /* 53 Default CRT RTC init, if we don't link to CRT 54 */ 55 _RTC_error_fnW 56 __cdecl 57 _CRT_RTC_INITW0( 58 void *_Res0, 59 void **_Res1, 60 int _Res2, 61 int _Res3, 62 int _Res4) 63 { 64 return &_RTC_DefaultErrorFuncW; 65 } 66 67 void 68 __cdecl 69 _RTC_InitBase(void) 70 { 71 static char initialized = 0; 72 _RTC_error_fnW errorFunc; 73 74 if (!initialized) 75 { 76 errorFunc = _CRT_RTC_INITW(0, 0, 0, 1, 0); 77 _RTC_SetErrorFuncW(errorFunc); 78 initialized = 1; 79 } 80 } 81 82 void 83 __cdecl 84 _RTC_Shutdown(void) 85 { 86 __debugbreak(); 87 } 88 89 void 90 __cdecl 91 _RTC_Initialize(void) 92 { 93 /* Usually this function would walk an array of function pointers and call 94 each of these, like done with global ctors, but since these are currently 95 only _RTC_InitBase, we simply call that function once. */ 96 _RTC_InitBase(); 97 } 98 99 void 100 __cdecl 101 _RTC_Failure( 102 void* retaddr, 103 int errnum) 104 { 105 _RTC_pErrorFuncW(errnum, 106 L"unknown file", 107 -1, 108 L"unknown module", 109 L"Invalid stack pointer value caught at %p, error %d\n", 110 retaddr, 111 errnum); 112 } 113 114 void 115 __cdecl 116 _RTC_UninitUse( 117 const char *_Varname) 118 { 119 _RTC_pErrorFuncW(_RTC_UNINIT_LOCAL_USE, 120 L"unknown file", 121 -1, 122 L"unknown module", 123 L"Use of uninitialized variable %S!\n", 124 _Varname); 125 } 126 127 void 128 __fastcall 129 _RTC_CheckStackVars( 130 void *_Esp, 131 _RTC_framedesc *_Fd) 132 { 133 int i, *guard1, *guard2; 134 135 /* Loop all variables in the descriptor */ 136 for (i = 0; i < _Fd->varCount; i++) 137 { 138 /* Get the 2 guards below and above the variable */ 139 guard1 = (int*)((char*)_Esp + _Fd->variables[i].addr - sizeof(*guard1)); 140 guard2 = (int*)((char*)_Esp + _Fd->variables[i].addr +_Fd->variables[i].size); 141 142 /* Check if they contain the guard bytes */ 143 if ((*guard1 != 0xCCCCCCCC) || (*guard2 != 0xCCCCCCCC)) 144 { 145 _RTC_pErrorFuncW(_RTC_CORRUPT_STACK, 146 L"unknown file", 147 -1, 148 L"unknown module", 149 L"Stack corruption near '%s'\n", 150 _Fd->variables[i].name); 151 } 152 } 153 } 154 155 void 156 __fastcall 157 _RTC_CheckStackVars2( 158 void *_Esp, 159 _RTC_framedesc *_Fd, 160 _RTC_ALLOCA_NODE *_AllocaList) 161 { 162 _RTC_ALLOCA_NODE *current; 163 int *guard; 164 165 /* Process normal variables */ 166 _RTC_CheckStackVars(_Esp, _Fd); 167 168 /* Process the alloca list */ 169 for (current = _AllocaList; current != 0; current = current->next) 170 { 171 /* Get the upper guard */ 172 guard = (int*)((char*)current + current->allocaSize - sizeof(*guard)); 173 174 /* Check if all guard locations are still ok */ 175 if ((current->guard1 != 0xCCCCCCCC) || 176 (current->guard2[0] != 0xCCCCCCCC) || 177 (current->guard2[1] != 0xCCCCCCCC) || 178 (current->guard2[2] != 0xCCCCCCCC) || 179 (*guard != 0xCCCCCCCC)) 180 { 181 _RTC_pErrorFuncW(_RTC_CORRUPTED_ALLOCA, 182 L"unknown file", 183 -1, 184 L"unknown module", 185 L"Stack corruption in alloca frame\n"); 186 } 187 } 188 } 189 190 void 191 __fastcall 192 _RTC_AllocaHelper( 193 _RTC_ALLOCA_NODE *_PAllocaBase, 194 size_t _CbSize, 195 _RTC_ALLOCA_NODE **_PAllocaInfoList) 196 { 197 unsigned long i; 198 199 /* Check if we got any allocation */ 200 if ((_PAllocaBase != 0) && 201 (_CbSize != 0) && 202 (_PAllocaInfoList != 0)) 203 { 204 /* Mark the whole range */ 205 char *guard = (char*)_PAllocaBase; 206 for (i = 0; i < _CbSize; i++) 207 { 208 guard[i] = 0xCC; 209 } 210 211 /* Initialize the alloca base frame */ 212 _PAllocaBase->allocaSize = _CbSize; 213 214 /* Insert this frame into the alloca list */ 215 _PAllocaBase->next = *_PAllocaInfoList; 216 *_PAllocaInfoList = _PAllocaBase; 217 } 218 } 219 220