sanitizer_win.cc revision 0969bcf2c936126b1f6e636b978aade8fc207437
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#include <windows.h>
16
17#include "sanitizer_common.h"
18#include "sanitizer_libc.h"
19
20namespace __sanitizer {
21
22// --------------------- sanitizer_common.h
23int GetPid() {
24  return GetProcessId(GetCurrentProcess());
25}
26
27uptr GetThreadSelf() {
28  return GetCurrentThreadId();
29}
30
31void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
32                                uptr *stack_bottom) {
33  CHECK(stack_top);
34  CHECK(stack_bottom);
35  MEMORY_BASIC_INFORMATION mbi;
36  CHECK(VirtualQuery(&mbi /* on stack */, &mbi, sizeof(mbi)) != 0);
37  // FIXME: is it possible for the stack to not be a single allocation?
38  // Are these values what ASan expects to get (reserved, not committed;
39  // including stack guard page) ?
40  *stack_top = (uptr)mbi.BaseAddress + mbi.RegionSize;
41  *stack_bottom = (uptr)mbi.AllocationBase;
42}
43
44
45void *MmapOrDie(uptr size, const char *mem_type) {
46  void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
47  if (rv == 0) {
48    Report("ERROR: Failed to allocate 0x%zx (%zd) bytes of %s\n",
49           size, size, mem_type);
50    CHECK("unable to mmap" && 0);
51  }
52  return rv;
53}
54
55void UnmapOrDie(void *addr, uptr size) {
56  if (VirtualFree(addr, size, MEM_DECOMMIT) == 0) {
57    Report("ERROR: Failed to deallocate 0x%zx (%zd) bytes at address %p\n",
58           size, size, addr);
59    CHECK("unable to unmap" && 0);
60  }
61}
62
63void *MmapFixedNoReserve(uptr fixed_addr, uptr size) {
64  return VirtualAlloc((LPVOID)fixed_addr, size,
65                      MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
66}
67
68void *Mprotect(uptr fixed_addr, uptr size) {
69  return VirtualAlloc((LPVOID)fixed_addr, size,
70                      MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS);
71}
72
73bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
74  // FIXME: shall we do anything here on Windows?
75  return true;
76}
77
78const char *GetEnv(const char *name) {
79  static char env_buffer[32767] = {};
80
81  // Note: this implementation stores the result in a static buffer so we only
82  // allow it to be called just once.
83  static bool called_once = false;
84  if (called_once)
85    UNIMPLEMENTED();
86  called_once = true;
87
88  DWORD rv = GetEnvironmentVariableA(name, env_buffer, sizeof(env_buffer));
89  if (rv > 0 && rv < sizeof(env_buffer))
90    return env_buffer;
91  return 0;
92}
93
94const char *GetPwd() {
95  UNIMPLEMENTED();
96}
97
98void DumpProcessMap() {
99  UNIMPLEMENTED();
100}
101
102void DisableCoreDumper() {
103  UNIMPLEMENTED();
104}
105
106void SleepForSeconds(int seconds) {
107  Sleep(seconds * 1000);
108}
109
110void SleepForMillis(int millis) {
111  Sleep(millis);
112}
113
114void Exit(int exitcode) {
115  _exit(exitcode);
116}
117
118void Abort() {
119  abort();
120  _exit(-1);  // abort is not NORETURN on Windows.
121}
122
123int Atexit(void (*function)(void)) {
124  return atexit(function);
125}
126
127int AtomicInc(int *a) {
128  return InterlockedExchangeAdd((LONG*)a, 1) + 1;
129}
130
131u16 AtomicExchange(u16 *a, u16 new_val) {
132  // InterlockedExchange16 seems unavailable on some MSVS installations.
133  // Everybody stand back, I pretend to know inline assembly!
134  // FIXME: I assume VC is smart enough to save/restore eax/ecx?
135  __asm {
136    mov eax, a
137    mov cx, new_val
138    xchg [eax], cx  ; NOLINT
139    mov new_val, cx
140  }
141  return new_val;
142}
143
144u8 AtomicExchange(u8 *a, u8 new_val) {
145  // FIXME: can we do this with a proper xchg intrinsic?
146  u8 t = *a;
147  *a = new_val;
148  return t;
149}
150
151// ------------------ sanitizer_libc.h
152void *internal_mmap(void *addr, uptr length, int prot, int flags,
153                    int fd, u64 offset) {
154  UNIMPLEMENTED();
155}
156
157int internal_munmap(void *addr, uptr length) {
158  UNIMPLEMENTED();
159}
160
161int internal_close(fd_t fd) {
162  UNIMPLEMENTED();
163}
164
165fd_t internal_open(const char *filename, bool write) {
166  UNIMPLEMENTED();
167}
168
169uptr internal_read(fd_t fd, void *buf, uptr count) {
170  UNIMPLEMENTED();
171}
172
173uptr internal_write(fd_t fd, const void *buf, uptr count) {
174  if (fd != 2)
175    UNIMPLEMENTED();
176  HANDLE err = GetStdHandle(STD_ERROR_HANDLE);
177  if (err == 0)
178    return 0;  // FIXME: this might not work on some apps.
179  DWORD ret;
180  if (!WriteFile(err, buf, count, &ret, 0))
181    return 0;
182  return ret;
183}
184
185uptr internal_filesize(fd_t fd) {
186  UNIMPLEMENTED();
187}
188
189int internal_dup2(int oldfd, int newfd) {
190  UNIMPLEMENTED();
191}
192
193int internal_sched_yield() {
194  UNIMPLEMENTED();
195}
196
197int internal_sscanf(const char *str, const char *format, ...) {
198  UNIMPLEMENTED();
199}
200
201}  // namespace __sanitizer
202
203#endif  // _WIN32
204