• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
26 namespace __sanitizer {
27 
28 // --------------------- sanitizer_common.h
GetPageSize()29 uptr GetPageSize() {
30   return 1U << 14;  // FIXME: is this configurable?
31 }
32 
GetMmapGranularity()33 uptr GetMmapGranularity() {
34   return 1U << 16;  // FIXME: is this configurable?
35 }
36 
FileExists(const char * filename)37 bool FileExists(const char *filename) {
38   UNIMPLEMENTED();
39 }
40 
GetPid()41 int GetPid() {
42   return GetProcessId(GetCurrentProcess());
43 }
44 
GetThreadSelf()45 uptr GetThreadSelf() {
46   return GetCurrentThreadId();
47 }
48 
GetThreadStackTopAndBottom(bool at_initialization,uptr * stack_top,uptr * stack_bottom)49 void 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 
MmapOrDie(uptr size,const char * mem_type)62 void *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 
UnmapOrDie(void * addr,uptr size)72 void 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 
MmapFixedNoReserve(uptr fixed_addr,uptr size)80 void *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 
MmapFixedOrDie(uptr fixed_addr,uptr size)91 void *MmapFixedOrDie(uptr fixed_addr, uptr size) {
92   return MmapFixedNoReserve(fixed_addr, size);
93 }
94 
Mprotect(uptr fixed_addr,uptr size)95 void *Mprotect(uptr fixed_addr, uptr size) {
96   return VirtualAlloc((LPVOID)fixed_addr, size,
97                       MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS);
98 }
99 
FlushUnneededShadowMemory(uptr addr,uptr size)100 void 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 
MemoryRangeIsAvailable(uptr range_start,uptr range_end)105 bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
106   // FIXME: shall we do anything here on Windows?
107   return true;
108 }
109 
MapFileToMemory(const char * file_name,uptr * buff_size)110 void *MapFileToMemory(const char *file_name, uptr *buff_size) {
111   UNIMPLEMENTED();
112 }
113 
114 static const int kMaxEnvNameLength = 128;
115 static const int kMaxEnvValueLength = 32767;
116 
117 namespace {
118 
119 struct EnvVariable {
120   char name[kMaxEnvNameLength];
121   char value[kMaxEnvValueLength];
122 };
123 
124 }  // namespace
125 
126 static const int kEnvVariables = 5;
127 static EnvVariable env_vars[kEnvVariables];
128 static int num_env_vars;
129 
GetEnv(const char * name)130 const char *GetEnv(const char *name) {
131   // Note: this implementation caches the values of the environment variables
132   // and limits their quantity.
133   for (int i = 0; i < num_env_vars; i++) {
134     if (0 == internal_strcmp(name, env_vars[i].name))
135       return env_vars[i].value;
136   }
137   CHECK_LT(num_env_vars, kEnvVariables);
138   DWORD rv = GetEnvironmentVariableA(name, env_vars[num_env_vars].value,
139                                      kMaxEnvValueLength);
140   if (rv > 0 && rv < kMaxEnvValueLength) {
141     CHECK_LT(internal_strlen(name), kMaxEnvNameLength);
142     internal_strncpy(env_vars[num_env_vars].name, name, kMaxEnvNameLength);
143     num_env_vars++;
144     return env_vars[num_env_vars - 1].value;
145   }
146   return 0;
147 }
148 
GetPwd()149 const char *GetPwd() {
150   UNIMPLEMENTED();
151 }
152 
GetUid()153 u32 GetUid() {
154   UNIMPLEMENTED();
155 }
156 
DumpProcessMap()157 void DumpProcessMap() {
158   UNIMPLEMENTED();
159 }
160 
DisableCoreDumper()161 void DisableCoreDumper() {
162   UNIMPLEMENTED();
163 }
164 
ReExec()165 void ReExec() {
166   UNIMPLEMENTED();
167 }
168 
PrepareForSandboxing()169 void PrepareForSandboxing() {
170   // Nothing here for now.
171 }
172 
StackSizeIsUnlimited()173 bool StackSizeIsUnlimited() {
174   UNIMPLEMENTED();
175 }
176 
SetStackSizeLimitInBytes(uptr limit)177 void SetStackSizeLimitInBytes(uptr limit) {
178   UNIMPLEMENTED();
179 }
180 
SleepForSeconds(int seconds)181 void SleepForSeconds(int seconds) {
182   Sleep(seconds * 1000);
183 }
184 
SleepForMillis(int millis)185 void SleepForMillis(int millis) {
186   Sleep(millis);
187 }
188 
Abort()189 void Abort() {
190   abort();
191   _exit(-1);  // abort is not NORETURN on Windows.
192 }
193 
194 #ifndef SANITIZER_GO
Atexit(void (* function)(void))195 int Atexit(void (*function)(void)) {
196   return atexit(function);
197 }
198 #endif
199 
200 // ------------------ sanitizer_libc.h
internal_mmap(void * addr,uptr length,int prot,int flags,int fd,u64 offset)201 void *internal_mmap(void *addr, uptr length, int prot, int flags,
202                     int fd, u64 offset) {
203   UNIMPLEMENTED();
204 }
205 
internal_munmap(void * addr,uptr length)206 int internal_munmap(void *addr, uptr length) {
207   UNIMPLEMENTED();
208 }
209 
internal_close(fd_t fd)210 int internal_close(fd_t fd) {
211   UNIMPLEMENTED();
212 }
213 
internal_isatty(fd_t fd)214 int internal_isatty(fd_t fd) {
215   return _isatty(fd);
216 }
217 
internal_open(const char * filename,int flags)218 fd_t internal_open(const char *filename, int flags) {
219   UNIMPLEMENTED();
220 }
221 
internal_open(const char * filename,int flags,u32 mode)222 fd_t internal_open(const char *filename, int flags, u32 mode) {
223   UNIMPLEMENTED();
224 }
225 
OpenFile(const char * filename,bool write)226 fd_t OpenFile(const char *filename, bool write) {
227   UNIMPLEMENTED();
228 }
229 
internal_read(fd_t fd,void * buf,uptr count)230 uptr internal_read(fd_t fd, void *buf, uptr count) {
231   UNIMPLEMENTED();
232 }
233 
internal_write(fd_t fd,const void * buf,uptr count)234 uptr internal_write(fd_t fd, const void *buf, uptr count) {
235   if (fd != kStderrFd)
236     UNIMPLEMENTED();
237   HANDLE err = GetStdHandle(STD_ERROR_HANDLE);
238   if (err == 0)
239     return 0;  // FIXME: this might not work on some apps.
240   DWORD ret;
241   if (!WriteFile(err, buf, count, &ret, 0))
242     return 0;
243   return ret;
244 }
245 
internal_stat(const char * path,void * buf)246 int internal_stat(const char *path, void *buf) {
247   UNIMPLEMENTED();
248 }
249 
internal_lstat(const char * path,void * buf)250 int internal_lstat(const char *path, void *buf) {
251   UNIMPLEMENTED();
252 }
253 
internal_fstat(fd_t fd,void * buf)254 int internal_fstat(fd_t fd, void *buf) {
255   UNIMPLEMENTED();
256 }
257 
internal_filesize(fd_t fd)258 uptr internal_filesize(fd_t fd) {
259   UNIMPLEMENTED();
260 }
261 
internal_dup2(int oldfd,int newfd)262 int internal_dup2(int oldfd, int newfd) {
263   UNIMPLEMENTED();
264 }
265 
internal_readlink(const char * path,char * buf,uptr bufsize)266 uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
267   UNIMPLEMENTED();
268 }
269 
internal_sched_yield()270 int internal_sched_yield() {
271   Sleep(0);
272   return 0;
273 }
274 
internal__exit(int exitcode)275 void internal__exit(int exitcode) {
276   _exit(exitcode);
277 }
278 
279 // ---------------------- BlockingMutex ---------------- {{{1
280 const uptr LOCK_UNINITIALIZED = 0;
281 const uptr LOCK_READY = (uptr)-1;
282 
BlockingMutex(LinkerInitialized li)283 BlockingMutex::BlockingMutex(LinkerInitialized li) {
284   // FIXME: see comments in BlockingMutex::Lock() for the details.
285   CHECK(li == LINKER_INITIALIZED || owner_ == LOCK_UNINITIALIZED);
286 
287   CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_));
288   InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
289   owner_ = LOCK_READY;
290 }
291 
BlockingMutex()292 BlockingMutex::BlockingMutex() {
293   CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_));
294   InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
295   owner_ = LOCK_READY;
296 }
297 
Lock()298 void BlockingMutex::Lock() {
299   if (owner_ == LOCK_UNINITIALIZED) {
300     // FIXME: hm, global BlockingMutex objects are not initialized?!?
301     // This might be a side effect of the clang+cl+link Frankenbuild...
302     new(this) BlockingMutex((LinkerInitialized)(LINKER_INITIALIZED + 1));
303 
304     // FIXME: If it turns out the linker doesn't invoke our
305     // constructors, we should probably manually Lock/Unlock all the global
306     // locks while we're starting in one thread to avoid double-init races.
307   }
308   EnterCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
309   CHECK_EQ(owner_, LOCK_READY);
310   owner_ = GetThreadSelf();
311 }
312 
Unlock()313 void BlockingMutex::Unlock() {
314   CHECK_EQ(owner_, GetThreadSelf());
315   owner_ = LOCK_READY;
316   LeaveCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
317 }
318 
CheckLocked()319 void BlockingMutex::CheckLocked() {
320   CHECK_EQ(owner_, GetThreadSelf());
321 }
322 
GetTlsSize()323 uptr GetTlsSize() {
324   return 0;
325 }
326 
InitTlsSize()327 void InitTlsSize() {
328 }
329 
330 }  // namespace __sanitizer
331 
332 #endif  // _WIN32
333