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