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
15#include "sanitizer_platform.h"
16#if SANITIZER_WINDOWS
17
18#define WIN32_LEAN_AND_MEAN
19#define NOGDI
20#include <windows.h>
21#include <dbghelp.h>
22#include <io.h>
23#include <psapi.h>
24#include <stdlib.h>
25
26#include "sanitizer_common.h"
27#include "sanitizer_libc.h"
28#include "sanitizer_mutex.h"
29#include "sanitizer_placement_new.h"
30#include "sanitizer_stacktrace.h"
31
32namespace __sanitizer {
33
34#include "sanitizer_syscall_generic.inc"
35
36// --------------------- sanitizer_common.h
37uptr GetPageSize() {
38  return 1U << 14;  // FIXME: is this configurable?
39}
40
41uptr GetMmapGranularity() {
42  return 1U << 16;  // FIXME: is this configurable?
43}
44
45uptr GetMaxVirtualAddress() {
46  SYSTEM_INFO si;
47  GetSystemInfo(&si);
48  return (uptr)si.lpMaximumApplicationAddress;
49}
50
51bool FileExists(const char *filename) {
52  UNIMPLEMENTED();
53}
54
55uptr internal_getpid() {
56  return GetProcessId(GetCurrentProcess());
57}
58
59// In contrast to POSIX, on Windows GetCurrentThreadId()
60// returns a system-unique identifier.
61uptr GetTid() {
62  return GetCurrentThreadId();
63}
64
65uptr GetThreadSelf() {
66  return GetTid();
67}
68
69#if !SANITIZER_GO
70void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
71                                uptr *stack_bottom) {
72  CHECK(stack_top);
73  CHECK(stack_bottom);
74  MEMORY_BASIC_INFORMATION mbi;
75  CHECK_NE(VirtualQuery(&mbi /* on stack */, &mbi, sizeof(mbi)), 0);
76  // FIXME: is it possible for the stack to not be a single allocation?
77  // Are these values what ASan expects to get (reserved, not committed;
78  // including stack guard page) ?
79  *stack_top = (uptr)mbi.BaseAddress + mbi.RegionSize;
80  *stack_bottom = (uptr)mbi.AllocationBase;
81}
82#endif  // #if !SANITIZER_GO
83
84void *MmapOrDie(uptr size, const char *mem_type) {
85  void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
86  if (rv == 0) {
87    Report("ERROR: %s failed to "
88           "allocate 0x%zx (%zd) bytes of %s (error code: %d)\n",
89           SanitizerToolName, size, size, mem_type, GetLastError());
90    CHECK("unable to mmap" && 0);
91  }
92  return rv;
93}
94
95void UnmapOrDie(void *addr, uptr size) {
96  if (!size || !addr)
97    return;
98
99  if (VirtualFree(addr, size, MEM_DECOMMIT) == 0) {
100    Report("ERROR: %s failed to "
101           "deallocate 0x%zx (%zd) bytes at address %p (error code: %d)\n",
102           SanitizerToolName, size, size, addr, GetLastError());
103    CHECK("unable to unmap" && 0);
104  }
105}
106
107void *MmapFixedNoReserve(uptr fixed_addr, uptr size) {
108  // FIXME: is this really "NoReserve"? On Win32 this does not matter much,
109  // but on Win64 it does.
110  void *p = VirtualAlloc((LPVOID)fixed_addr, size,
111      MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
112  if (p == 0)
113    Report("ERROR: %s failed to "
114           "allocate %p (%zd) bytes at %p (error code: %d)\n",
115           SanitizerToolName, size, size, fixed_addr, GetLastError());
116  return p;
117}
118
119void *MmapFixedOrDie(uptr fixed_addr, uptr size) {
120  return MmapFixedNoReserve(fixed_addr, size);
121}
122
123void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
124  // FIXME: make this really NoReserve?
125  return MmapOrDie(size, mem_type);
126}
127
128void *MmapNoAccess(uptr fixed_addr, uptr size) {
129  void *res = VirtualAlloc((LPVOID)fixed_addr, size,
130                           MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS);
131  if (res == 0)
132    Report("WARNING: %s failed to "
133           "mprotect %p (%zd) bytes at %p (error code: %d)\n",
134           SanitizerToolName, size, size, fixed_addr, GetLastError());
135  return res;
136}
137
138bool MprotectNoAccess(uptr addr, uptr size) {
139  DWORD old_protection;
140  return VirtualProtect((LPVOID)addr, size, PAGE_NOACCESS, &old_protection);
141}
142
143
144void FlushUnneededShadowMemory(uptr addr, uptr size) {
145  // This is almost useless on 32-bits.
146  // FIXME: add madvise-analog when we move to 64-bits.
147}
148
149void NoHugePagesInRegion(uptr addr, uptr size) {
150  // FIXME: probably similar to FlushUnneededShadowMemory.
151}
152
153void DontDumpShadowMemory(uptr addr, uptr length) {
154  // This is almost useless on 32-bits.
155  // FIXME: add madvise-analog when we move to 64-bits.
156}
157
158bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
159  MEMORY_BASIC_INFORMATION mbi;
160  CHECK(VirtualQuery((void *)range_start, &mbi, sizeof(mbi)));
161  return mbi.Protect == PAGE_NOACCESS &&
162         (uptr)mbi.BaseAddress + mbi.RegionSize >= range_end;
163}
164
165void *MapFileToMemory(const char *file_name, uptr *buff_size) {
166  UNIMPLEMENTED();
167}
168
169void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, uptr offset) {
170  UNIMPLEMENTED();
171}
172
173static const int kMaxEnvNameLength = 128;
174static const DWORD kMaxEnvValueLength = 32767;
175
176namespace {
177
178struct EnvVariable {
179  char name[kMaxEnvNameLength];
180  char value[kMaxEnvValueLength];
181};
182
183}  // namespace
184
185static const int kEnvVariables = 5;
186static EnvVariable env_vars[kEnvVariables];
187static int num_env_vars;
188
189const char *GetEnv(const char *name) {
190  // Note: this implementation caches the values of the environment variables
191  // and limits their quantity.
192  for (int i = 0; i < num_env_vars; i++) {
193    if (0 == internal_strcmp(name, env_vars[i].name))
194      return env_vars[i].value;
195  }
196  CHECK_LT(num_env_vars, kEnvVariables);
197  DWORD rv = GetEnvironmentVariableA(name, env_vars[num_env_vars].value,
198                                     kMaxEnvValueLength);
199  if (rv > 0 && rv < kMaxEnvValueLength) {
200    CHECK_LT(internal_strlen(name), kMaxEnvNameLength);
201    internal_strncpy(env_vars[num_env_vars].name, name, kMaxEnvNameLength);
202    num_env_vars++;
203    return env_vars[num_env_vars - 1].value;
204  }
205  return 0;
206}
207
208const char *GetPwd() {
209  UNIMPLEMENTED();
210}
211
212u32 GetUid() {
213  UNIMPLEMENTED();
214}
215
216namespace {
217struct ModuleInfo {
218  const char *filepath;
219  uptr base_address;
220  uptr end_address;
221};
222
223int CompareModulesBase(const void *pl, const void *pr) {
224  const ModuleInfo *l = (ModuleInfo *)pl, *r = (ModuleInfo *)pr;
225  if (l->base_address < r->base_address)
226    return -1;
227  return l->base_address > r->base_address;
228}
229}  // namespace
230
231#ifndef SANITIZER_GO
232void DumpProcessMap() {
233  Report("Dumping process modules:\n");
234  InternalScopedBuffer<LoadedModule> modules(kMaxNumberOfModules);
235  uptr num_modules =
236      GetListOfModules(modules.data(), kMaxNumberOfModules, nullptr);
237
238  InternalScopedBuffer<ModuleInfo> module_infos(num_modules);
239  for (size_t i = 0; i < num_modules; ++i) {
240    module_infos[i].filepath = modules[i].full_name();
241    module_infos[i].base_address = modules[i].base_address();
242    module_infos[i].end_address = modules[i].ranges().next()->end;
243  }
244  qsort(module_infos.data(), num_modules, sizeof(ModuleInfo),
245        CompareModulesBase);
246
247  for (size_t i = 0; i < num_modules; ++i) {
248    const ModuleInfo &mi = module_infos[i];
249    if (mi.end_address != 0) {
250      Printf("\t%p-%p %s\n", mi.base_address, mi.end_address,
251             mi.filepath[0] ? mi.filepath : "[no name]");
252    } else if (mi.filepath[0]) {
253      Printf("\t??\?-??? %s\n", mi.filepath);
254    } else {
255      Printf("\t???\n");
256    }
257  }
258}
259#endif
260
261void DisableCoreDumperIfNecessary() {
262  // Do nothing.
263}
264
265void ReExec() {
266  UNIMPLEMENTED();
267}
268
269void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
270  (void)args;
271  // Nothing here for now.
272}
273
274bool StackSizeIsUnlimited() {
275  UNIMPLEMENTED();
276}
277
278void SetStackSizeLimitInBytes(uptr limit) {
279  UNIMPLEMENTED();
280}
281
282bool AddressSpaceIsUnlimited() {
283  UNIMPLEMENTED();
284}
285
286void SetAddressSpaceUnlimited() {
287  UNIMPLEMENTED();
288}
289
290char *FindPathToBinary(const char *name) {
291  // Nothing here for now.
292  return 0;
293}
294
295uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
296  // Nothing here for now.
297  return 0;
298}
299
300bool IsPathSeparator(const char c) {
301  return c == '\\' || c == '/';
302}
303
304bool IsAbsolutePath(const char *path) {
305  UNIMPLEMENTED();
306}
307
308void SleepForSeconds(int seconds) {
309  Sleep(seconds * 1000);
310}
311
312void SleepForMillis(int millis) {
313  Sleep(millis);
314}
315
316u64 NanoTime() {
317  return 0;
318}
319
320void Abort() {
321  if (::IsDebuggerPresent())
322    __debugbreak();
323  internal__exit(3);
324}
325
326uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
327                      string_predicate_t filter) {
328  HANDLE cur_process = GetCurrentProcess();
329
330  // Query the list of modules.  Start by assuming there are no more than 256
331  // modules and retry if that's not sufficient.
332  HMODULE *hmodules = 0;
333  uptr modules_buffer_size = sizeof(HMODULE) * 256;
334  DWORD bytes_required;
335  while (!hmodules) {
336    hmodules = (HMODULE *)MmapOrDie(modules_buffer_size, __FUNCTION__);
337    CHECK(EnumProcessModules(cur_process, hmodules, modules_buffer_size,
338                             &bytes_required));
339    if (bytes_required > modules_buffer_size) {
340      // Either there turned out to be more than 256 hmodules, or new hmodules
341      // could have loaded since the last try.  Retry.
342      UnmapOrDie(hmodules, modules_buffer_size);
343      hmodules = 0;
344      modules_buffer_size = bytes_required;
345    }
346  }
347
348  // |num_modules| is the number of modules actually present,
349  // |count| is the number of modules we return.
350  size_t nun_modules = bytes_required / sizeof(HMODULE),
351         count = 0;
352  for (size_t i = 0; i < nun_modules && count < max_modules; ++i) {
353    HMODULE handle = hmodules[i];
354    MODULEINFO mi;
355    if (!GetModuleInformation(cur_process, handle, &mi, sizeof(mi)))
356      continue;
357
358    char module_name[MAX_PATH];
359    bool got_module_name =
360        GetModuleFileNameA(handle, module_name, sizeof(module_name));
361    if (!got_module_name)
362      module_name[0] = '\0';
363
364    if (filter && !filter(module_name))
365      continue;
366
367    uptr base_address = (uptr)mi.lpBaseOfDll;
368    uptr end_address = (uptr)mi.lpBaseOfDll + mi.SizeOfImage;
369    LoadedModule *cur_module = &modules[count];
370    cur_module->set(module_name, base_address);
371    // We add the whole module as one single address range.
372    cur_module->addAddressRange(base_address, end_address, /*executable*/ true);
373    count++;
374  }
375  UnmapOrDie(hmodules, modules_buffer_size);
376
377  return count;
378};
379
380#ifndef SANITIZER_GO
381// We can't use atexit() directly at __asan_init time as the CRT is not fully
382// initialized at this point.  Place the functions into a vector and use
383// atexit() as soon as it is ready for use (i.e. after .CRT$XIC initializers).
384InternalMmapVectorNoCtor<void (*)(void)> atexit_functions;
385
386int Atexit(void (*function)(void)) {
387  atexit_functions.push_back(function);
388  return 0;
389}
390
391static int RunAtexit() {
392  int ret = 0;
393  for (uptr i = 0; i < atexit_functions.size(); ++i) {
394    ret |= atexit(atexit_functions[i]);
395  }
396  return ret;
397}
398
399#pragma section(".CRT$XID", long, read)  // NOLINT
400static __declspec(allocate(".CRT$XID")) int (*__run_atexit)() = RunAtexit;
401#endif
402
403// ------------------ sanitizer_libc.h
404fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *last_error) {
405  if (mode != WrOnly)
406    UNIMPLEMENTED();
407  fd_t res = CreateFile(filename, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
408                        FILE_ATTRIBUTE_NORMAL, nullptr);
409  CHECK(res != kStdoutFd || kStdoutFd == kInvalidFd);
410  CHECK(res != kStderrFd || kStderrFd == kInvalidFd);
411  return res;
412}
413
414void CloseFile(fd_t fd) {
415  CloseHandle(fd);
416}
417
418bool ReadFromFile(fd_t fd, void *buff, uptr buff_size, uptr *bytes_read,
419                  error_t *error_p) {
420  UNIMPLEMENTED();
421}
422
423bool SupportsColoredOutput(fd_t fd) {
424  // FIXME: support colored output.
425  return false;
426}
427
428bool WriteToFile(fd_t fd, const void *buff, uptr buff_size, uptr *bytes_written,
429                 error_t *error_p) {
430  CHECK(fd != kInvalidFd);
431
432  if (fd == kStdoutFd) {
433    fd = GetStdHandle(STD_OUTPUT_HANDLE);
434    if (fd == 0) fd = kInvalidFd;
435  } else if (fd == kStderrFd) {
436    fd = GetStdHandle(STD_ERROR_HANDLE);
437    if (fd == 0) fd = kInvalidFd;
438  }
439
440  DWORD internal_bytes_written;
441  if (fd == kInvalidFd ||
442      WriteFile(fd, buff, buff_size, &internal_bytes_written, 0)) {
443    if (error_p) *error_p = GetLastError();
444    return false;
445  } else {
446    if (bytes_written) *bytes_written = internal_bytes_written;
447    return true;
448  }
449}
450
451bool RenameFile(const char *oldpath, const char *newpath, error_t *error_p) {
452  UNIMPLEMENTED();
453}
454
455uptr internal_sched_yield() {
456  Sleep(0);
457  return 0;
458}
459
460void internal__exit(int exitcode) {
461  ExitProcess(exitcode);
462}
463
464uptr internal_ftruncate(fd_t fd, uptr size) {
465  UNIMPLEMENTED();
466}
467
468uptr GetRSS() {
469  return 0;
470}
471
472void *internal_start_thread(void (*func)(void *arg), void *arg) { return 0; }
473void internal_join_thread(void *th) { }
474
475// ---------------------- BlockingMutex ---------------- {{{1
476const uptr LOCK_UNINITIALIZED = 0;
477const uptr LOCK_READY = (uptr)-1;
478
479BlockingMutex::BlockingMutex(LinkerInitialized li) {
480  // FIXME: see comments in BlockingMutex::Lock() for the details.
481  CHECK(li == LINKER_INITIALIZED || owner_ == LOCK_UNINITIALIZED);
482
483  CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_));
484  InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
485  owner_ = LOCK_READY;
486}
487
488BlockingMutex::BlockingMutex() {
489  CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_));
490  InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
491  owner_ = LOCK_READY;
492}
493
494void BlockingMutex::Lock() {
495  if (owner_ == LOCK_UNINITIALIZED) {
496    // FIXME: hm, global BlockingMutex objects are not initialized?!?
497    // This might be a side effect of the clang+cl+link Frankenbuild...
498    new(this) BlockingMutex((LinkerInitialized)(LINKER_INITIALIZED + 1));
499
500    // FIXME: If it turns out the linker doesn't invoke our
501    // constructors, we should probably manually Lock/Unlock all the global
502    // locks while we're starting in one thread to avoid double-init races.
503  }
504  EnterCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
505  CHECK_EQ(owner_, LOCK_READY);
506  owner_ = GetThreadSelf();
507}
508
509void BlockingMutex::Unlock() {
510  CHECK_EQ(owner_, GetThreadSelf());
511  owner_ = LOCK_READY;
512  LeaveCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
513}
514
515void BlockingMutex::CheckLocked() {
516  CHECK_EQ(owner_, GetThreadSelf());
517}
518
519uptr GetTlsSize() {
520  return 0;
521}
522
523void InitTlsSize() {
524}
525
526void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
527                          uptr *tls_addr, uptr *tls_size) {
528#ifdef SANITIZER_GO
529  *stk_addr = 0;
530  *stk_size = 0;
531  *tls_addr = 0;
532  *tls_size = 0;
533#else
534  uptr stack_top, stack_bottom;
535  GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
536  *stk_addr = stack_bottom;
537  *stk_size = stack_top - stack_bottom;
538  *tls_addr = 0;
539  *tls_size = 0;
540#endif
541}
542
543#if !SANITIZER_GO
544void BufferedStackTrace::SlowUnwindStack(uptr pc, u32 max_depth) {
545  CHECK_GE(max_depth, 2);
546  // FIXME: CaptureStackBackTrace might be too slow for us.
547  // FIXME: Compare with StackWalk64.
548  // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc
549  size = CaptureStackBackTrace(2, Min(max_depth, kStackTraceMax),
550                               (void**)trace, 0);
551  if (size == 0)
552    return;
553
554  // Skip the RTL frames by searching for the PC in the stacktrace.
555  uptr pc_location = LocatePcInTrace(pc);
556  PopStackFrames(pc_location);
557}
558
559void BufferedStackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
560                                                    u32 max_depth) {
561  CONTEXT ctx = *(CONTEXT *)context;
562  STACKFRAME64 stack_frame;
563  memset(&stack_frame, 0, sizeof(stack_frame));
564  size = 0;
565#if defined(_WIN64)
566  int machine_type = IMAGE_FILE_MACHINE_AMD64;
567  stack_frame.AddrPC.Offset = ctx.Rip;
568  stack_frame.AddrFrame.Offset = ctx.Rbp;
569  stack_frame.AddrStack.Offset = ctx.Rsp;
570#else
571  int machine_type = IMAGE_FILE_MACHINE_I386;
572  stack_frame.AddrPC.Offset = ctx.Eip;
573  stack_frame.AddrFrame.Offset = ctx.Ebp;
574  stack_frame.AddrStack.Offset = ctx.Esp;
575#endif
576  stack_frame.AddrPC.Mode = AddrModeFlat;
577  stack_frame.AddrFrame.Mode = AddrModeFlat;
578  stack_frame.AddrStack.Mode = AddrModeFlat;
579  while (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(),
580                     &stack_frame, &ctx, NULL, &SymFunctionTableAccess64,
581                     &SymGetModuleBase64, NULL) &&
582         size < Min(max_depth, kStackTraceMax)) {
583    trace_buffer[size++] = (uptr)stack_frame.AddrPC.Offset;
584  }
585}
586#endif  // #if !SANITIZER_GO
587
588void ReportFile::Write(const char *buffer, uptr length) {
589  SpinMutexLock l(mu);
590  ReopenIfNecessary();
591  if (!WriteToFile(fd, buffer, length)) {
592    // stderr may be closed, but we may be able to print to the debugger
593    // instead.  This is the case when launching a program from Visual Studio,
594    // and the following routine should write to its console.
595    OutputDebugStringA(buffer);
596  }
597}
598
599void SetAlternateSignalStack() {
600  // FIXME: Decide what to do on Windows.
601}
602
603void UnsetAlternateSignalStack() {
604  // FIXME: Decide what to do on Windows.
605}
606
607void InstallDeadlySignalHandlers(SignalHandlerType handler) {
608  (void)handler;
609  // FIXME: Decide what to do on Windows.
610}
611
612bool IsDeadlySignal(int signum) {
613  // FIXME: Decide what to do on Windows.
614  return false;
615}
616
617bool IsAccessibleMemoryRange(uptr beg, uptr size) {
618  // FIXME: Actually implement this function.
619  return true;
620}
621
622SignalContext SignalContext::Create(void *siginfo, void *context) {
623  EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD*)siginfo;
624  CONTEXT *context_record = (CONTEXT*)context;
625
626  uptr pc = (uptr)exception_record->ExceptionAddress;
627#ifdef _WIN64
628  uptr bp = (uptr)context_record->Rbp;
629  uptr sp = (uptr)context_record->Rsp;
630#else
631  uptr bp = (uptr)context_record->Ebp;
632  uptr sp = (uptr)context_record->Esp;
633#endif
634  uptr access_addr = exception_record->ExceptionInformation[1];
635
636  return SignalContext(context, access_addr, pc, sp, bp);
637}
638
639}  // namespace __sanitizer
640
641#endif  // _WIN32
642