sanitizer_win.cc revision 0fa691b7ec97d8c3948a637d6263822ed4e738f7
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#ifdef _WIN32 15#define WIN32_LEAN_AND_MEAN 16#define NOGDI 17#include <stdlib.h> 18#include <io.h> 19#include <windows.h> 20 21#include "sanitizer_common.h" 22#include "sanitizer_libc.h" 23#include "sanitizer_placement_new.h" 24#include "sanitizer_mutex.h" 25 26namespace __sanitizer { 27 28// --------------------- sanitizer_common.h 29uptr GetPageSize() { 30 return 1U << 14; // FIXME: is this configurable? 31} 32 33uptr GetMmapGranularity() { 34 return 1U << 16; // FIXME: is this configurable? 35} 36 37bool FileExists(const char *filename) { 38 UNIMPLEMENTED(); 39} 40 41int GetPid() { 42 return GetProcessId(GetCurrentProcess()); 43} 44 45uptr GetThreadSelf() { 46 return GetCurrentThreadId(); 47} 48 49void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, 50 uptr *stack_bottom) { 51 CHECK(stack_top); 52 CHECK(stack_bottom); 53 MEMORY_BASIC_INFORMATION mbi; 54 CHECK_NE(VirtualQuery(&mbi /* on stack */, &mbi, sizeof(mbi)), 0); 55 // FIXME: is it possible for the stack to not be a single allocation? 56 // Are these values what ASan expects to get (reserved, not committed; 57 // including stack guard page) ? 58 *stack_top = (uptr)mbi.BaseAddress + mbi.RegionSize; 59 *stack_bottom = (uptr)mbi.AllocationBase; 60} 61 62void *MmapOrDie(uptr size, const char *mem_type) { 63 void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 64 if (rv == 0) { 65 Report("ERROR: Failed to allocate 0x%zx (%zd) bytes of %s\n", 66 size, size, mem_type); 67 CHECK("unable to mmap" && 0); 68 } 69 return rv; 70} 71 72void UnmapOrDie(void *addr, uptr size) { 73 if (VirtualFree(addr, size, MEM_DECOMMIT) == 0) { 74 Report("ERROR: Failed to deallocate 0x%zx (%zd) bytes at address %p\n", 75 size, size, addr); 76 CHECK("unable to unmap" && 0); 77 } 78} 79 80void *MmapFixedNoReserve(uptr fixed_addr, uptr size) { 81 // FIXME: is this really "NoReserve"? On Win32 this does not matter much, 82 // but on Win64 it does. 83 void *p = VirtualAlloc((LPVOID)fixed_addr, size, 84 MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 85 if (p == 0) 86 Report("ERROR: Failed to allocate 0x%zx (%zd) bytes at %p (%d)\n", 87 size, size, fixed_addr, GetLastError()); 88 return p; 89} 90 91void *MmapFixedOrDie(uptr fixed_addr, uptr size) { 92 return MmapFixedNoReserve(fixed_addr, size); 93} 94 95void *Mprotect(uptr fixed_addr, uptr size) { 96 return VirtualAlloc((LPVOID)fixed_addr, size, 97 MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS); 98} 99 100void FlushUnneededShadowMemory(uptr addr, uptr size) { 101 // This is almost useless on 32-bits. 102 // FIXME: add madvice-analog when we move to 64-bits. 103} 104 105bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) { 106 // FIXME: shall we do anything here on Windows? 107 return true; 108} 109 110void *MapFileToMemory(const char *file_name, uptr *buff_size) { 111 UNIMPLEMENTED(); 112} 113 114const char *GetEnv(const char *name) { 115 static char env_buffer[32767] = {}; 116 117 // Note: this implementation stores the result in a static buffer so we only 118 // allow it to be called just once. 119 static bool called_once = false; 120 if (called_once) 121 UNIMPLEMENTED(); 122 called_once = true; 123 124 DWORD rv = GetEnvironmentVariableA(name, env_buffer, sizeof(env_buffer)); 125 if (rv > 0 && rv < sizeof(env_buffer)) 126 return env_buffer; 127 return 0; 128} 129 130const char *GetPwd() { 131 UNIMPLEMENTED(); 132} 133 134u32 GetUid() { 135 UNIMPLEMENTED(); 136} 137 138void DumpProcessMap() { 139 UNIMPLEMENTED(); 140} 141 142void DisableCoreDumper() { 143 UNIMPLEMENTED(); 144} 145 146void ReExec() { 147 UNIMPLEMENTED(); 148} 149 150void PrepareForSandboxing() { 151 // Nothing here for now. 152} 153 154bool StackSizeIsUnlimited() { 155 UNIMPLEMENTED(); 156} 157 158void SetStackSizeLimitInBytes(uptr limit) { 159 UNIMPLEMENTED(); 160} 161 162void SleepForSeconds(int seconds) { 163 Sleep(seconds * 1000); 164} 165 166void SleepForMillis(int millis) { 167 Sleep(millis); 168} 169 170void Exit(int exitcode) { 171 _exit(exitcode); 172} 173 174void Abort() { 175 abort(); 176 _exit(-1); // abort is not NORETURN on Windows. 177} 178 179#ifndef SANITIZER_GO 180int Atexit(void (*function)(void)) { 181 return atexit(function); 182} 183#endif 184 185// ------------------ sanitizer_libc.h 186void *internal_mmap(void *addr, uptr length, int prot, int flags, 187 int fd, u64 offset) { 188 UNIMPLEMENTED(); 189} 190 191int internal_munmap(void *addr, uptr length) { 192 UNIMPLEMENTED(); 193} 194 195int internal_close(fd_t fd) { 196 UNIMPLEMENTED(); 197} 198 199int internal_isatty(fd_t fd) { 200 return _isatty(fd); 201} 202 203fd_t internal_open(const char *filename, int flags) { 204 UNIMPLEMENTED(); 205} 206 207fd_t internal_open(const char *filename, int flags, u32 mode) { 208 UNIMPLEMENTED(); 209} 210 211fd_t OpenFile(const char *filename, bool write) { 212 UNIMPLEMENTED(); 213} 214 215uptr internal_read(fd_t fd, void *buf, uptr count) { 216 UNIMPLEMENTED(); 217} 218 219uptr internal_write(fd_t fd, const void *buf, uptr count) { 220 if (fd != kStderrFd) 221 UNIMPLEMENTED(); 222 HANDLE err = GetStdHandle(STD_ERROR_HANDLE); 223 if (err == 0) 224 return 0; // FIXME: this might not work on some apps. 225 DWORD ret; 226 if (!WriteFile(err, buf, count, &ret, 0)) 227 return 0; 228 return ret; 229} 230 231int internal_stat(const char *path, void *buf) { 232 UNIMPLEMENTED(); 233} 234 235int internal_lstat(const char *path, void *buf) { 236 UNIMPLEMENTED(); 237} 238 239int internal_fstat(fd_t fd, void *buf) { 240 UNIMPLEMENTED(); 241} 242 243uptr internal_filesize(fd_t fd) { 244 UNIMPLEMENTED(); 245} 246 247int internal_dup2(int oldfd, int newfd) { 248 UNIMPLEMENTED(); 249} 250 251uptr internal_readlink(const char *path, char *buf, uptr bufsize) { 252 UNIMPLEMENTED(); 253} 254 255int internal_sched_yield() { 256 Sleep(0); 257 return 0; 258} 259 260// ---------------------- BlockingMutex ---------------- {{{1 261const uptr LOCK_UNINITIALIZED = 0; 262const uptr LOCK_READY = (uptr)-1; 263 264BlockingMutex::BlockingMutex(LinkerInitialized li) { 265 // FIXME: see comments in BlockingMutex::Lock() for the details. 266 CHECK(li == LINKER_INITIALIZED || owner_ == LOCK_UNINITIALIZED); 267 268 CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_)); 269 InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 270 owner_ = LOCK_READY; 271} 272 273void BlockingMutex::Lock() { 274 if (owner_ == LOCK_UNINITIALIZED) { 275 // FIXME: hm, global BlockingMutex objects are not initialized?!? 276 // This might be a side effect of the clang+cl+link Frankenbuild... 277 new(this) BlockingMutex((LinkerInitialized)(LINKER_INITIALIZED + 1)); 278 279 // FIXME: If it turns out the linker doesn't invoke our 280 // constructors, we should probably manually Lock/Unlock all the global 281 // locks while we're starting in one thread to avoid double-init races. 282 } 283 EnterCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 284 CHECK_EQ(owner_, LOCK_READY); 285 owner_ = GetThreadSelf(); 286} 287 288void BlockingMutex::Unlock() { 289 CHECK_EQ(owner_, GetThreadSelf()); 290 owner_ = LOCK_READY; 291 LeaveCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 292} 293 294} // namespace __sanitizer 295 296#endif // _WIN32 297