1 //===-- sanitizer_win.cc --------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is shared between AddressSanitizer and ThreadSanitizer 11 // run-time libraries and implements windows-specific functions from 12 // sanitizer_libc.h. 13 //===----------------------------------------------------------------------===// 14 15 #include "sanitizer_platform.h" 16 #if SANITIZER_WINDOWS 17 18 #define WIN32_LEAN_AND_MEAN 19 #define NOGDI 20 #include <stdlib.h> 21 #include <io.h> 22 #include <windows.h> 23 24 #include "sanitizer_common.h" 25 #include "sanitizer_libc.h" 26 #include "sanitizer_mutex.h" 27 #include "sanitizer_placement_new.h" 28 #include "sanitizer_stacktrace.h" 29 30 namespace __sanitizer { 31 32 #include "sanitizer_syscall_generic.inc" 33 34 // --------------------- sanitizer_common.h 35 uptr GetPageSize() { 36 return 1U << 14; // FIXME: is this configurable? 37 } 38 39 uptr GetMmapGranularity() { 40 return 1U << 16; // FIXME: is this configurable? 41 } 42 43 uptr GetMaxVirtualAddress() { 44 SYSTEM_INFO si; 45 GetSystemInfo(&si); 46 return (uptr)si.lpMaximumApplicationAddress; 47 } 48 49 bool FileExists(const char *filename) { 50 UNIMPLEMENTED(); 51 } 52 53 uptr internal_getpid() { 54 return GetProcessId(GetCurrentProcess()); 55 } 56 57 // In contrast to POSIX, on Windows GetCurrentThreadId() 58 // returns a system-unique identifier. 59 uptr GetTid() { 60 return GetCurrentThreadId(); 61 } 62 63 uptr GetThreadSelf() { 64 return GetTid(); 65 } 66 67 void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, 68 uptr *stack_bottom) { 69 CHECK(stack_top); 70 CHECK(stack_bottom); 71 MEMORY_BASIC_INFORMATION mbi; 72 CHECK_NE(VirtualQuery(&mbi /* on stack */, &mbi, sizeof(mbi)), 0); 73 // FIXME: is it possible for the stack to not be a single allocation? 74 // Are these values what ASan expects to get (reserved, not committed; 75 // including stack guard page) ? 76 *stack_top = (uptr)mbi.BaseAddress + mbi.RegionSize; 77 *stack_bottom = (uptr)mbi.AllocationBase; 78 } 79 80 void *MmapOrDie(uptr size, const char *mem_type) { 81 void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 82 if (rv == 0) { 83 Report("ERROR: Failed to allocate 0x%zx (%zd) bytes of %s\n", 84 size, size, mem_type); 85 CHECK("unable to mmap" && 0); 86 } 87 return rv; 88 } 89 90 void UnmapOrDie(void *addr, uptr size) { 91 if (VirtualFree(addr, size, MEM_DECOMMIT) == 0) { 92 Report("ERROR: Failed to deallocate 0x%zx (%zd) bytes at address %p\n", 93 size, size, addr); 94 CHECK("unable to unmap" && 0); 95 } 96 } 97 98 void *MmapFixedNoReserve(uptr fixed_addr, uptr size) { 99 // FIXME: is this really "NoReserve"? On Win32 this does not matter much, 100 // but on Win64 it does. 101 void *p = VirtualAlloc((LPVOID)fixed_addr, size, 102 MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 103 if (p == 0) 104 Report("ERROR: Failed to allocate 0x%zx (%zd) bytes at %p (%d)\n", 105 size, size, fixed_addr, GetLastError()); 106 return p; 107 } 108 109 void *MmapFixedOrDie(uptr fixed_addr, uptr size) { 110 return MmapFixedNoReserve(fixed_addr, size); 111 } 112 113 void *Mprotect(uptr fixed_addr, uptr size) { 114 return VirtualAlloc((LPVOID)fixed_addr, size, 115 MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS); 116 } 117 118 void FlushUnneededShadowMemory(uptr addr, uptr size) { 119 // This is almost useless on 32-bits. 120 // FIXME: add madvice-analog when we move to 64-bits. 121 } 122 123 bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) { 124 // FIXME: shall we do anything here on Windows? 125 return true; 126 } 127 128 void *MapFileToMemory(const char *file_name, uptr *buff_size) { 129 UNIMPLEMENTED(); 130 } 131 132 static const int kMaxEnvNameLength = 128; 133 static const DWORD kMaxEnvValueLength = 32767; 134 135 namespace { 136 137 struct EnvVariable { 138 char name[kMaxEnvNameLength]; 139 char value[kMaxEnvValueLength]; 140 }; 141 142 } // namespace 143 144 static const int kEnvVariables = 5; 145 static EnvVariable env_vars[kEnvVariables]; 146 static int num_env_vars; 147 148 const char *GetEnv(const char *name) { 149 // Note: this implementation caches the values of the environment variables 150 // and limits their quantity. 151 for (int i = 0; i < num_env_vars; i++) { 152 if (0 == internal_strcmp(name, env_vars[i].name)) 153 return env_vars[i].value; 154 } 155 CHECK_LT(num_env_vars, kEnvVariables); 156 DWORD rv = GetEnvironmentVariableA(name, env_vars[num_env_vars].value, 157 kMaxEnvValueLength); 158 if (rv > 0 && rv < kMaxEnvValueLength) { 159 CHECK_LT(internal_strlen(name), kMaxEnvNameLength); 160 internal_strncpy(env_vars[num_env_vars].name, name, kMaxEnvNameLength); 161 num_env_vars++; 162 return env_vars[num_env_vars - 1].value; 163 } 164 return 0; 165 } 166 167 const char *GetPwd() { 168 UNIMPLEMENTED(); 169 } 170 171 u32 GetUid() { 172 UNIMPLEMENTED(); 173 } 174 175 void DumpProcessMap() { 176 UNIMPLEMENTED(); 177 } 178 179 void DisableCoreDumper() { 180 UNIMPLEMENTED(); 181 } 182 183 void ReExec() { 184 UNIMPLEMENTED(); 185 } 186 187 void PrepareForSandboxing() { 188 // Nothing here for now. 189 } 190 191 bool StackSizeIsUnlimited() { 192 UNIMPLEMENTED(); 193 } 194 195 void SetStackSizeLimitInBytes(uptr limit) { 196 UNIMPLEMENTED(); 197 } 198 199 void SleepForSeconds(int seconds) { 200 Sleep(seconds * 1000); 201 } 202 203 void SleepForMillis(int millis) { 204 Sleep(millis); 205 } 206 207 u64 NanoTime() { 208 return 0; 209 } 210 211 void Abort() { 212 abort(); 213 _exit(-1); // abort is not NORETURN on Windows. 214 } 215 216 #ifndef SANITIZER_GO 217 int Atexit(void (*function)(void)) { 218 return atexit(function); 219 } 220 #endif 221 222 // ------------------ sanitizer_libc.h 223 uptr internal_mmap(void *addr, uptr length, int prot, int flags, 224 int fd, u64 offset) { 225 UNIMPLEMENTED(); 226 } 227 228 uptr internal_munmap(void *addr, uptr length) { 229 UNIMPLEMENTED(); 230 } 231 232 uptr internal_close(fd_t fd) { 233 UNIMPLEMENTED(); 234 } 235 236 int internal_isatty(fd_t fd) { 237 return _isatty(fd); 238 } 239 240 uptr internal_open(const char *filename, int flags) { 241 UNIMPLEMENTED(); 242 } 243 244 uptr internal_open(const char *filename, int flags, u32 mode) { 245 UNIMPLEMENTED(); 246 } 247 248 uptr OpenFile(const char *filename, bool write) { 249 UNIMPLEMENTED(); 250 } 251 252 uptr internal_read(fd_t fd, void *buf, uptr count) { 253 UNIMPLEMENTED(); 254 } 255 256 uptr internal_write(fd_t fd, const void *buf, uptr count) { 257 if (fd != kStderrFd) 258 UNIMPLEMENTED(); 259 HANDLE err = GetStdHandle(STD_ERROR_HANDLE); 260 if (err == 0) 261 return 0; // FIXME: this might not work on some apps. 262 DWORD ret; 263 if (!WriteFile(err, buf, count, &ret, 0)) 264 return 0; 265 return ret; 266 } 267 268 uptr internal_stat(const char *path, void *buf) { 269 UNIMPLEMENTED(); 270 } 271 272 uptr internal_lstat(const char *path, void *buf) { 273 UNIMPLEMENTED(); 274 } 275 276 uptr internal_fstat(fd_t fd, void *buf) { 277 UNIMPLEMENTED(); 278 } 279 280 uptr internal_filesize(fd_t fd) { 281 UNIMPLEMENTED(); 282 } 283 284 uptr internal_dup2(int oldfd, int newfd) { 285 UNIMPLEMENTED(); 286 } 287 288 uptr internal_readlink(const char *path, char *buf, uptr bufsize) { 289 UNIMPLEMENTED(); 290 } 291 292 uptr internal_sched_yield() { 293 Sleep(0); 294 return 0; 295 } 296 297 void internal__exit(int exitcode) { 298 _exit(exitcode); 299 } 300 301 // ---------------------- BlockingMutex ---------------- {{{1 302 const uptr LOCK_UNINITIALIZED = 0; 303 const uptr LOCK_READY = (uptr)-1; 304 305 BlockingMutex::BlockingMutex(LinkerInitialized li) { 306 // FIXME: see comments in BlockingMutex::Lock() for the details. 307 CHECK(li == LINKER_INITIALIZED || owner_ == LOCK_UNINITIALIZED); 308 309 CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_)); 310 InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 311 owner_ = LOCK_READY; 312 } 313 314 BlockingMutex::BlockingMutex() { 315 CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_)); 316 InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 317 owner_ = LOCK_READY; 318 } 319 320 void BlockingMutex::Lock() { 321 if (owner_ == LOCK_UNINITIALIZED) { 322 // FIXME: hm, global BlockingMutex objects are not initialized?!? 323 // This might be a side effect of the clang+cl+link Frankenbuild... 324 new(this) BlockingMutex((LinkerInitialized)(LINKER_INITIALIZED + 1)); 325 326 // FIXME: If it turns out the linker doesn't invoke our 327 // constructors, we should probably manually Lock/Unlock all the global 328 // locks while we're starting in one thread to avoid double-init races. 329 } 330 EnterCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 331 CHECK_EQ(owner_, LOCK_READY); 332 owner_ = GetThreadSelf(); 333 } 334 335 void BlockingMutex::Unlock() { 336 CHECK_EQ(owner_, GetThreadSelf()); 337 owner_ = LOCK_READY; 338 LeaveCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 339 } 340 341 void BlockingMutex::CheckLocked() { 342 CHECK_EQ(owner_, GetThreadSelf()); 343 } 344 345 uptr GetTlsSize() { 346 return 0; 347 } 348 349 void InitTlsSize() { 350 } 351 352 void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, 353 uptr *tls_addr, uptr *tls_size) { 354 #ifdef SANITIZER_GO 355 *stk_addr = 0; 356 *stk_size = 0; 357 *tls_addr = 0; 358 *tls_size = 0; 359 #else 360 uptr stack_top, stack_bottom; 361 GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom); 362 *stk_addr = stack_bottom; 363 *stk_size = stack_top - stack_bottom; 364 *tls_addr = 0; 365 *tls_size = 0; 366 #endif 367 } 368 369 void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, 370 uptr stack_top, uptr stack_bottom, bool fast) { 371 (void)fast; 372 (void)stack_top; 373 (void)stack_bottom; 374 stack->max_size = max_s; 375 void *tmp[kStackTraceMax]; 376 377 // FIXME: CaptureStackBackTrace might be too slow for us. 378 // FIXME: Compare with StackWalk64. 379 // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc 380 uptr cs_ret = CaptureStackBackTrace(1, stack->max_size, tmp, 0); 381 uptr offset = 0; 382 // Skip the RTL frames by searching for the PC in the stacktrace. 383 // FIXME: this doesn't work well for the malloc/free stacks yet. 384 for (uptr i = 0; i < cs_ret; i++) { 385 if (pc != (uptr)tmp[i]) 386 continue; 387 offset = i; 388 break; 389 } 390 391 stack->size = cs_ret - offset; 392 for (uptr i = 0; i < stack->size; i++) 393 stack->trace[i] = (uptr)tmp[i + offset]; 394 } 395 396 } // namespace __sanitizer 397 398 #endif // _WIN32 399