xref: /netbsd-src/external/gpl3/gcc.old/dist/libsanitizer/sanitizer_common/sanitizer_win.cc (revision d909946ca08dceb44d7d0f22ec9488679695d976)
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