1 //===-- sanitizer_win.cc --------------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is shared between AddressSanitizer and ThreadSanitizer
9 // run-time libraries and implements windows-specific functions from
11 //===----------------------------------------------------------------------===//
13 #define WIN32_LEAN_AND_MEAN
19 #include "sanitizer_common.h"
20 #include "sanitizer_libc.h"
21 #include "sanitizer_placement_new.h"
22 #include "sanitizer_mutex.h"
24 namespace __sanitizer
{
26 // --------------------- sanitizer_common.h
28 return 1U << 14; // FIXME: is this configurable?
31 uptr
GetMmapGranularity() {
32 return 1U << 16; // FIXME: is this configurable?
35 bool FileExists(const char *filename
) {
40 return GetProcessId(GetCurrentProcess());
43 uptr
GetThreadSelf() {
44 return GetCurrentThreadId();
47 void GetThreadStackTopAndBottom(bool at_initialization
, uptr
*stack_top
,
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
;
60 void *MmapOrDie(uptr size
, const char *mem_type
) {
61 void *rv
= VirtualAlloc(0, size
, MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
);
63 Report("ERROR: Failed to allocate 0x%zx (%zd) bytes of %s\n",
64 size
, size
, mem_type
);
65 CHECK("unable to mmap" && 0);
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",
74 CHECK("unable to unmap" && 0);
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
);
84 Report("ERROR: Failed to allocate 0x%zx (%zd) bytes at %p (%d)\n",
85 size
, size
, fixed_addr
, GetLastError());
89 void *MmapFixedOrDie(uptr fixed_addr
, uptr size
) {
90 return MmapFixedNoReserve(fixed_addr
, size
);
93 void *Mprotect(uptr fixed_addr
, uptr size
) {
94 return VirtualAlloc((LPVOID
)fixed_addr
, size
,
95 MEM_RESERVE
| MEM_COMMIT
, PAGE_NOACCESS
);
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.
103 bool MemoryRangeIsAvailable(uptr range_start
, uptr range_end
) {
104 // FIXME: shall we do anything here on Windows?
108 void *MapFileToMemory(const char *file_name
, uptr
*buff_size
) {
112 const char *GetEnv(const char *name
) {
113 static char env_buffer
[32767] = {};
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;
122 DWORD rv
= GetEnvironmentVariableA(name
, env_buffer
, sizeof(env_buffer
));
123 if (rv
> 0 && rv
< sizeof(env_buffer
))
128 const char *GetPwd() {
136 void DumpProcessMap() {
140 void DisableCoreDumper() {
148 void PrepareForSandboxing() {
149 // Nothing here for now.
152 bool StackSizeIsUnlimited() {
156 void SetStackSizeLimitInBytes(uptr limit
) {
160 void SleepForSeconds(int seconds
) {
161 Sleep(seconds
* 1000);
164 void SleepForMillis(int millis
) {
170 _exit(-1); // abort is not NORETURN on Windows.
174 int Atexit(void (*function
)(void)) {
175 return atexit(function
);
179 // ------------------ sanitizer_libc.h
180 void *internal_mmap(void *addr
, uptr length
, int prot
, int flags
,
181 int fd
, u64 offset
) {
185 int internal_munmap(void *addr
, uptr length
) {
189 int internal_close(fd_t fd
) {
193 int internal_isatty(fd_t fd
) {
197 fd_t
internal_open(const char *filename
, int flags
) {
201 fd_t
internal_open(const char *filename
, int flags
, u32 mode
) {
205 fd_t
OpenFile(const char *filename
, bool write
) {
209 uptr
internal_read(fd_t fd
, void *buf
, uptr count
) {
213 uptr
internal_write(fd_t fd
, const void *buf
, uptr count
) {
216 HANDLE err
= GetStdHandle(STD_ERROR_HANDLE
);
218 return 0; // FIXME: this might not work on some apps.
220 if (!WriteFile(err
, buf
, count
, &ret
, 0))
225 int internal_stat(const char *path
, void *buf
) {
229 int internal_lstat(const char *path
, void *buf
) {
233 int internal_fstat(fd_t fd
, void *buf
) {
237 uptr
internal_filesize(fd_t fd
) {
241 int internal_dup2(int oldfd
, int newfd
) {
245 uptr
internal_readlink(const char *path
, char *buf
, uptr bufsize
) {
249 int internal_sched_yield() {
254 void internal__exit(int exitcode
) {
258 // ---------------------- BlockingMutex ---------------- {{{1
259 const uptr LOCK_UNINITIALIZED
= 0;
260 const uptr LOCK_READY
= (uptr
)-1;
262 BlockingMutex::BlockingMutex(LinkerInitialized li
) {
263 // FIXME: see comments in BlockingMutex::Lock() for the details.
264 CHECK(li
== LINKER_INITIALIZED
|| owner_
== LOCK_UNINITIALIZED
);
266 CHECK(sizeof(CRITICAL_SECTION
) <= sizeof(opaque_storage_
));
267 InitializeCriticalSection((LPCRITICAL_SECTION
)opaque_storage_
);
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));
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.
281 EnterCriticalSection((LPCRITICAL_SECTION
)opaque_storage_
);
282 CHECK_EQ(owner_
, LOCK_READY
);
283 owner_
= GetThreadSelf();
286 void BlockingMutex::Unlock() {
287 CHECK_EQ(owner_
, GetThreadSelf());
289 LeaveCriticalSection((LPCRITICAL_SECTION
)opaque_storage_
);
292 } // namespace __sanitizer