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