1//===-- sanitizer_win.cpp -------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file is shared between AddressSanitizer and ThreadSanitizer
10// run-time libraries and implements windows-specific functions from
11// sanitizer_libc.h.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_platform.h"
15#if SANITIZER_WINDOWS
16
17#define WIN32_LEAN_AND_MEAN
18#define NOGDI
19#include <windows.h>
20#include <io.h>
21#include <psapi.h>
22#include <stdlib.h>
23
24#include "sanitizer_common.h"
25#include "sanitizer_file.h"
26#include "sanitizer_libc.h"
27#include "sanitizer_mutex.h"
28#include "sanitizer_placement_new.h"
29#include "sanitizer_win_defs.h"
30
31#if defined(PSAPI_VERSION) && PSAPI_VERSION == 1
32#pragma comment(lib, "psapi")
33#endif
34#if SANITIZER_WIN_TRACE
35#include <traceloggingprovider.h>
36//  Windows trace logging provider init
37#pragma comment(lib, "advapi32.lib")
38TRACELOGGING_DECLARE_PROVIDER(g_asan_provider);
39// GUID must be the same in utils/AddressSanitizerLoggingProvider.wprp
40TRACELOGGING_DEFINE_PROVIDER(g_asan_provider, "AddressSanitizerLoggingProvider",
41                             (0x6c6c766d, 0x3846, 0x4e6a, 0xa4, 0xfb, 0x5b,
42                              0x53, 0x0b, 0xd0, 0xf3, 0xfa));
43#else
44#define TraceLoggingUnregister(x)
45#endif
46
47// A macro to tell the compiler that this part of the code cannot be reached,
48// if the compiler supports this feature. Since we're using this in
49// code that is called when terminating the process, the expansion of the
50// macro should not terminate the process to avoid infinite recursion.
51#if defined(__clang__)
52# define BUILTIN_UNREACHABLE() __builtin_unreachable()
53#elif defined(__GNUC__) && \
54    (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
55# define BUILTIN_UNREACHABLE() __builtin_unreachable()
56#elif defined(_MSC_VER)
57# define BUILTIN_UNREACHABLE() __assume(0)
58#else
59# define BUILTIN_UNREACHABLE()
60#endif
61
62namespace __sanitizer {
63
64#include "sanitizer_syscall_generic.inc"
65
66// --------------------- sanitizer_common.h
67uptr GetPageSize() {
68  SYSTEM_INFO si;
69  GetSystemInfo(&si);
70  return si.dwPageSize;
71}
72
73uptr GetMmapGranularity() {
74  SYSTEM_INFO si;
75  GetSystemInfo(&si);
76  return si.dwAllocationGranularity;
77}
78
79uptr GetMaxUserVirtualAddress() {
80  SYSTEM_INFO si;
81  GetSystemInfo(&si);
82  return (uptr)si.lpMaximumApplicationAddress;
83}
84
85uptr GetMaxVirtualAddress() {
86  return GetMaxUserVirtualAddress();
87}
88
89bool FileExists(const char *filename) {
90  return ::GetFileAttributesA(filename) != INVALID_FILE_ATTRIBUTES;
91}
92
93uptr internal_getpid() {
94  return GetProcessId(GetCurrentProcess());
95}
96
97// In contrast to POSIX, on Windows GetCurrentThreadId()
98// returns a system-unique identifier.
99tid_t GetTid() {
100  return GetCurrentThreadId();
101}
102
103uptr GetThreadSelf() {
104  return GetTid();
105}
106
107#if !SANITIZER_GO
108void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
109                                uptr *stack_bottom) {
110  CHECK(stack_top);
111  CHECK(stack_bottom);
112  MEMORY_BASIC_INFORMATION mbi;
113  CHECK_NE(VirtualQuery(&mbi /* on stack */, &mbi, sizeof(mbi)), 0);
114  // FIXME: is it possible for the stack to not be a single allocation?
115  // Are these values what ASan expects to get (reserved, not committed;
116  // including stack guard page) ?
117  *stack_top = (uptr)mbi.BaseAddress + mbi.RegionSize;
118  *stack_bottom = (uptr)mbi.AllocationBase;
119}
120#endif  // #if !SANITIZER_GO
121
122void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
123  void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
124  if (rv == 0)
125    ReportMmapFailureAndDie(size, mem_type, "allocate",
126                            GetLastError(), raw_report);
127  return rv;
128}
129
130void UnmapOrDie(void *addr, uptr size) {
131  if (!size || !addr)
132    return;
133
134  MEMORY_BASIC_INFORMATION mbi;
135  CHECK(VirtualQuery(addr, &mbi, sizeof(mbi)));
136
137  // MEM_RELEASE can only be used to unmap whole regions previously mapped with
138  // VirtualAlloc. So we first try MEM_RELEASE since it is better, and if that
139  // fails try MEM_DECOMMIT.
140  if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
141    if (VirtualFree(addr, size, MEM_DECOMMIT) == 0) {
142      Report("ERROR: %s failed to "
143             "deallocate 0x%zx (%zd) bytes at address %p (error code: %d)\n",
144             SanitizerToolName, size, size, addr, GetLastError());
145      CHECK("unable to unmap" && 0);
146    }
147  }
148}
149
150static void *ReturnNullptrOnOOMOrDie(uptr size, const char *mem_type,
151                                     const char *mmap_type) {
152  error_t last_error = GetLastError();
153  if (last_error == ERROR_NOT_ENOUGH_MEMORY)
154    return nullptr;
155  ReportMmapFailureAndDie(size, mem_type, mmap_type, last_error);
156}
157
158void *MmapOrDieOnFatalError(uptr size, const char *mem_type) {
159  void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
160  if (rv == 0)
161    return ReturnNullptrOnOOMOrDie(size, mem_type, "allocate");
162  return rv;
163}
164
165// We want to map a chunk of address space aligned to 'alignment'.
166void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
167                                   const char *mem_type) {
168  CHECK(IsPowerOfTwo(size));
169  CHECK(IsPowerOfTwo(alignment));
170
171  // Windows will align our allocations to at least 64K.
172  alignment = Max(alignment, GetMmapGranularity());
173
174  uptr mapped_addr =
175      (uptr)VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
176  if (!mapped_addr)
177    return ReturnNullptrOnOOMOrDie(size, mem_type, "allocate aligned");
178
179  // If we got it right on the first try, return. Otherwise, unmap it and go to
180  // the slow path.
181  if (IsAligned(mapped_addr, alignment))
182    return (void*)mapped_addr;
183  if (VirtualFree((void *)mapped_addr, 0, MEM_RELEASE) == 0)
184    ReportMmapFailureAndDie(size, mem_type, "deallocate", GetLastError());
185
186  // If we didn't get an aligned address, overallocate, find an aligned address,
187  // unmap, and try to allocate at that aligned address.
188  int retries = 0;
189  const int kMaxRetries = 10;
190  for (; retries < kMaxRetries &&
191         (mapped_addr == 0 || !IsAligned(mapped_addr, alignment));
192       retries++) {
193    // Overallocate size + alignment bytes.
194    mapped_addr =
195        (uptr)VirtualAlloc(0, size + alignment, MEM_RESERVE, PAGE_NOACCESS);
196    if (!mapped_addr)
197      return ReturnNullptrOnOOMOrDie(size, mem_type, "allocate aligned");
198
199    // Find the aligned address.
200    uptr aligned_addr = RoundUpTo(mapped_addr, alignment);
201
202    // Free the overallocation.
203    if (VirtualFree((void *)mapped_addr, 0, MEM_RELEASE) == 0)
204      ReportMmapFailureAndDie(size, mem_type, "deallocate", GetLastError());
205
206    // Attempt to allocate exactly the number of bytes we need at the aligned
207    // address. This may fail for a number of reasons, in which case we continue
208    // the loop.
209    mapped_addr = (uptr)VirtualAlloc((void *)aligned_addr, size,
210                                     MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
211  }
212
213  // Fail if we can't make this work quickly.
214  if (retries == kMaxRetries && mapped_addr == 0)
215    return ReturnNullptrOnOOMOrDie(size, mem_type, "allocate aligned");
216
217  return (void *)mapped_addr;
218}
219
220bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
221  // FIXME: is this really "NoReserve"? On Win32 this does not matter much,
222  // but on Win64 it does.
223  (void)name;  // unsupported
224#if !SANITIZER_GO && SANITIZER_WINDOWS64
225  // On asan/Windows64, use MEM_COMMIT would result in error
226  // 1455:ERROR_COMMITMENT_LIMIT.
227  // Asan uses exception handler to commit page on demand.
228  void *p = VirtualAlloc((LPVOID)fixed_addr, size, MEM_RESERVE, PAGE_READWRITE);
229#else
230  void *p = VirtualAlloc((LPVOID)fixed_addr, size, MEM_RESERVE | MEM_COMMIT,
231                         PAGE_READWRITE);
232#endif
233  if (p == 0) {
234    Report("ERROR: %s failed to "
235           "allocate %p (%zd) bytes at %p (error code: %d)\n",
236           SanitizerToolName, size, size, fixed_addr, GetLastError());
237    return false;
238  }
239  return true;
240}
241
242bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size, const char *name) {
243  // FIXME: Windows support large pages too. Might be worth checking
244  return MmapFixedNoReserve(fixed_addr, size, name);
245}
246
247// Memory space mapped by 'MmapFixedOrDie' must have been reserved by
248// 'MmapFixedNoAccess'.
249void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name) {
250  void *p = VirtualAlloc((LPVOID)fixed_addr, size,
251      MEM_COMMIT, PAGE_READWRITE);
252  if (p == 0) {
253    char mem_type[30];
254    internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx",
255                      fixed_addr);
256    ReportMmapFailureAndDie(size, mem_type, "allocate", GetLastError());
257  }
258  return p;
259}
260
261// Uses fixed_addr for now.
262// Will use offset instead once we've implemented this function for real.
263uptr ReservedAddressRange::Map(uptr fixed_addr, uptr size, const char *name) {
264  return reinterpret_cast<uptr>(MmapFixedOrDieOnFatalError(fixed_addr, size));
265}
266
267uptr ReservedAddressRange::MapOrDie(uptr fixed_addr, uptr size,
268                                    const char *name) {
269  return reinterpret_cast<uptr>(MmapFixedOrDie(fixed_addr, size));
270}
271
272void ReservedAddressRange::Unmap(uptr addr, uptr size) {
273  // Only unmap if it covers the entire range.
274  CHECK((addr == reinterpret_cast<uptr>(base_)) && (size == size_));
275  // We unmap the whole range, just null out the base.
276  base_ = nullptr;
277  size_ = 0;
278  UnmapOrDie(reinterpret_cast<void*>(addr), size);
279}
280
281void *MmapFixedOrDieOnFatalError(uptr fixed_addr, uptr size, const char *name) {
282  void *p = VirtualAlloc((LPVOID)fixed_addr, size,
283      MEM_COMMIT, PAGE_READWRITE);
284  if (p == 0) {
285    char mem_type[30];
286    internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx",
287                      fixed_addr);
288    return ReturnNullptrOnOOMOrDie(size, mem_type, "allocate");
289  }
290  return p;
291}
292
293void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
294  // FIXME: make this really NoReserve?
295  return MmapOrDie(size, mem_type);
296}
297
298uptr ReservedAddressRange::Init(uptr size, const char *name, uptr fixed_addr) {
299  base_ = fixed_addr ? MmapFixedNoAccess(fixed_addr, size) : MmapNoAccess(size);
300  size_ = size;
301  name_ = name;
302  (void)os_handle_;  // unsupported
303  return reinterpret_cast<uptr>(base_);
304}
305
306
307void *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name) {
308  (void)name; // unsupported
309  void *res = VirtualAlloc((LPVOID)fixed_addr, size,
310                           MEM_RESERVE, PAGE_NOACCESS);
311  if (res == 0)
312    Report("WARNING: %s failed to "
313           "mprotect %p (%zd) bytes at %p (error code: %d)\n",
314           SanitizerToolName, size, size, fixed_addr, GetLastError());
315  return res;
316}
317
318void *MmapNoAccess(uptr size) {
319  void *res = VirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_NOACCESS);
320  if (res == 0)
321    Report("WARNING: %s failed to "
322           "mprotect %p (%zd) bytes (error code: %d)\n",
323           SanitizerToolName, size, size, GetLastError());
324  return res;
325}
326
327bool MprotectNoAccess(uptr addr, uptr size) {
328  DWORD old_protection;
329  return VirtualProtect((LPVOID)addr, size, PAGE_NOACCESS, &old_protection);
330}
331
332void ReleaseMemoryPagesToOS(uptr beg, uptr end) {
333  // This is almost useless on 32-bits.
334  // FIXME: add madvise-analog when we move to 64-bits.
335}
336
337void SetShadowRegionHugePageMode(uptr addr, uptr size) {
338  // FIXME: probably similar to ReleaseMemoryToOS.
339}
340
341bool DontDumpShadowMemory(uptr addr, uptr length) {
342  // This is almost useless on 32-bits.
343  // FIXME: add madvise-analog when we move to 64-bits.
344  return true;
345}
346
347uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
348                              uptr *largest_gap_found,
349                              uptr *max_occupied_addr) {
350  uptr address = 0;
351  while (true) {
352    MEMORY_BASIC_INFORMATION info;
353    if (!::VirtualQuery((void*)address, &info, sizeof(info)))
354      return 0;
355
356    if (info.State == MEM_FREE) {
357      uptr shadow_address = RoundUpTo((uptr)info.BaseAddress + left_padding,
358                                      alignment);
359      if (shadow_address + size < (uptr)info.BaseAddress + info.RegionSize)
360        return shadow_address;
361    }
362
363    // Move to the next region.
364    address = (uptr)info.BaseAddress + info.RegionSize;
365  }
366  return 0;
367}
368
369bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
370  MEMORY_BASIC_INFORMATION mbi;
371  CHECK(VirtualQuery((void *)range_start, &mbi, sizeof(mbi)));
372  return mbi.Protect == PAGE_NOACCESS &&
373         (uptr)mbi.BaseAddress + mbi.RegionSize >= range_end;
374}
375
376void *MapFileToMemory(const char *file_name, uptr *buff_size) {
377  UNIMPLEMENTED();
378}
379
380void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, OFF_T offset) {
381  UNIMPLEMENTED();
382}
383
384static const int kMaxEnvNameLength = 128;
385static const DWORD kMaxEnvValueLength = 32767;
386
387namespace {
388
389struct EnvVariable {
390  char name[kMaxEnvNameLength];
391  char value[kMaxEnvValueLength];
392};
393
394}  // namespace
395
396static const int kEnvVariables = 5;
397static EnvVariable env_vars[kEnvVariables];
398static int num_env_vars;
399
400const char *GetEnv(const char *name) {
401  // Note: this implementation caches the values of the environment variables
402  // and limits their quantity.
403  for (int i = 0; i < num_env_vars; i++) {
404    if (0 == internal_strcmp(name, env_vars[i].name))
405      return env_vars[i].value;
406  }
407  CHECK_LT(num_env_vars, kEnvVariables);
408  DWORD rv = GetEnvironmentVariableA(name, env_vars[num_env_vars].value,
409                                     kMaxEnvValueLength);
410  if (rv > 0 && rv < kMaxEnvValueLength) {
411    CHECK_LT(internal_strlen(name), kMaxEnvNameLength);
412    internal_strncpy(env_vars[num_env_vars].name, name, kMaxEnvNameLength);
413    num_env_vars++;
414    return env_vars[num_env_vars - 1].value;
415  }
416  return 0;
417}
418
419const char *GetPwd() {
420  UNIMPLEMENTED();
421}
422
423u32 GetUid() {
424  UNIMPLEMENTED();
425}
426
427namespace {
428struct ModuleInfo {
429  const char *filepath;
430  uptr base_address;
431  uptr end_address;
432};
433
434#if !SANITIZER_GO
435int CompareModulesBase(const void *pl, const void *pr) {
436  const ModuleInfo *l = (const ModuleInfo *)pl, *r = (const ModuleInfo *)pr;
437  if (l->base_address < r->base_address)
438    return -1;
439  return l->base_address > r->base_address;
440}
441#endif
442}  // namespace
443
444#if !SANITIZER_GO
445void DumpProcessMap() {
446  Report("Dumping process modules:\n");
447  ListOfModules modules;
448  modules.init();
449  uptr num_modules = modules.size();
450
451  InternalMmapVector<ModuleInfo> module_infos(num_modules);
452  for (size_t i = 0; i < num_modules; ++i) {
453    module_infos[i].filepath = modules[i].full_name();
454    module_infos[i].base_address = modules[i].ranges().front()->beg;
455    module_infos[i].end_address = modules[i].ranges().back()->end;
456  }
457  qsort(module_infos.data(), num_modules, sizeof(ModuleInfo),
458        CompareModulesBase);
459
460  for (size_t i = 0; i < num_modules; ++i) {
461    const ModuleInfo &mi = module_infos[i];
462    if (mi.end_address != 0) {
463      Printf("\t%p-%p %s\n", mi.base_address, mi.end_address,
464             mi.filepath[0] ? mi.filepath : "[no name]");
465    } else if (mi.filepath[0]) {
466      Printf("\t??\?-??? %s\n", mi.filepath);
467    } else {
468      Printf("\t???\n");
469    }
470  }
471}
472#endif
473
474void PrintModuleMap() { }
475
476void DisableCoreDumperIfNecessary() {
477  // Do nothing.
478}
479
480void ReExec() {
481  UNIMPLEMENTED();
482}
483
484void PlatformPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {}
485
486bool StackSizeIsUnlimited() {
487  UNIMPLEMENTED();
488}
489
490void SetStackSizeLimitInBytes(uptr limit) {
491  UNIMPLEMENTED();
492}
493
494bool AddressSpaceIsUnlimited() {
495  UNIMPLEMENTED();
496}
497
498void SetAddressSpaceUnlimited() {
499  UNIMPLEMENTED();
500}
501
502bool IsPathSeparator(const char c) {
503  return c == '\\' || c == '/';
504}
505
506static bool IsAlpha(char c) {
507  c = ToLower(c);
508  return c >= 'a' && c <= 'z';
509}
510
511bool IsAbsolutePath(const char *path) {
512  return path != nullptr && IsAlpha(path[0]) && path[1] == ':' &&
513         IsPathSeparator(path[2]);
514}
515
516void SleepForSeconds(int seconds) {
517  Sleep(seconds * 1000);
518}
519
520void SleepForMillis(int millis) {
521  Sleep(millis);
522}
523
524u64 NanoTime() {
525  static LARGE_INTEGER frequency = {};
526  LARGE_INTEGER counter;
527  if (UNLIKELY(frequency.QuadPart == 0)) {
528    QueryPerformanceFrequency(&frequency);
529    CHECK_NE(frequency.QuadPart, 0);
530  }
531  QueryPerformanceCounter(&counter);
532  counter.QuadPart *= 1000ULL * 1000000ULL;
533  counter.QuadPart /= frequency.QuadPart;
534  return counter.QuadPart;
535}
536
537u64 MonotonicNanoTime() { return NanoTime(); }
538
539void Abort() {
540  internal__exit(3);
541}
542
543#if !SANITIZER_GO
544// Read the file to extract the ImageBase field from the PE header. If ASLR is
545// disabled and this virtual address is available, the loader will typically
546// load the image at this address. Therefore, we call it the preferred base. Any
547// addresses in the DWARF typically assume that the object has been loaded at
548// this address.
549static uptr GetPreferredBase(const char *modname) {
550  fd_t fd = OpenFile(modname, RdOnly, nullptr);
551  if (fd == kInvalidFd)
552    return 0;
553  FileCloser closer(fd);
554
555  // Read just the DOS header.
556  IMAGE_DOS_HEADER dos_header;
557  uptr bytes_read;
558  if (!ReadFromFile(fd, &dos_header, sizeof(dos_header), &bytes_read) ||
559      bytes_read != sizeof(dos_header))
560    return 0;
561
562  // The file should start with the right signature.
563  if (dos_header.e_magic != IMAGE_DOS_SIGNATURE)
564    return 0;
565
566  // The layout at e_lfanew is:
567  // "PE\0\0"
568  // IMAGE_FILE_HEADER
569  // IMAGE_OPTIONAL_HEADER
570  // Seek to e_lfanew and read all that data.
571  char buf[4 + sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER)];
572  if (::SetFilePointer(fd, dos_header.e_lfanew, nullptr, FILE_BEGIN) ==
573      INVALID_SET_FILE_POINTER)
574    return 0;
575  if (!ReadFromFile(fd, &buf[0], sizeof(buf), &bytes_read) ||
576      bytes_read != sizeof(buf))
577    return 0;
578
579  // Check for "PE\0\0" before the PE header.
580  char *pe_sig = &buf[0];
581  if (internal_memcmp(pe_sig, "PE\0\0", 4) != 0)
582    return 0;
583
584  // Skip over IMAGE_FILE_HEADER. We could do more validation here if we wanted.
585  IMAGE_OPTIONAL_HEADER *pe_header =
586      (IMAGE_OPTIONAL_HEADER *)(pe_sig + 4 + sizeof(IMAGE_FILE_HEADER));
587
588  // Check for more magic in the PE header.
589  if (pe_header->Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
590    return 0;
591
592  // Finally, return the ImageBase.
593  return (uptr)pe_header->ImageBase;
594}
595
596void ListOfModules::init() {
597  clearOrInit();
598  HANDLE cur_process = GetCurrentProcess();
599
600  // Query the list of modules.  Start by assuming there are no more than 256
601  // modules and retry if that's not sufficient.
602  HMODULE *hmodules = 0;
603  uptr modules_buffer_size = sizeof(HMODULE) * 256;
604  DWORD bytes_required;
605  while (!hmodules) {
606    hmodules = (HMODULE *)MmapOrDie(modules_buffer_size, __FUNCTION__);
607    CHECK(EnumProcessModules(cur_process, hmodules, modules_buffer_size,
608                             &bytes_required));
609    if (bytes_required > modules_buffer_size) {
610      // Either there turned out to be more than 256 hmodules, or new hmodules
611      // could have loaded since the last try.  Retry.
612      UnmapOrDie(hmodules, modules_buffer_size);
613      hmodules = 0;
614      modules_buffer_size = bytes_required;
615    }
616  }
617
618  // |num_modules| is the number of modules actually present,
619  size_t num_modules = bytes_required / sizeof(HMODULE);
620  for (size_t i = 0; i < num_modules; ++i) {
621    HMODULE handle = hmodules[i];
622    MODULEINFO mi;
623    if (!GetModuleInformation(cur_process, handle, &mi, sizeof(mi)))
624      continue;
625
626    // Get the UTF-16 path and convert to UTF-8.
627    wchar_t modname_utf16[kMaxPathLength];
628    int modname_utf16_len =
629        GetModuleFileNameW(handle, modname_utf16, kMaxPathLength);
630    if (modname_utf16_len == 0)
631      modname_utf16[0] = '\0';
632    char module_name[kMaxPathLength];
633    int module_name_len =
634        ::WideCharToMultiByte(CP_UTF8, 0, modname_utf16, modname_utf16_len + 1,
635                              &module_name[0], kMaxPathLength, NULL, NULL);
636    module_name[module_name_len] = '\0';
637
638    uptr base_address = (uptr)mi.lpBaseOfDll;
639    uptr end_address = (uptr)mi.lpBaseOfDll + mi.SizeOfImage;
640
641    // Adjust the base address of the module so that we get a VA instead of an
642    // RVA when computing the module offset. This helps llvm-symbolizer find the
643    // right DWARF CU. In the common case that the image is loaded at it's
644    // preferred address, we will now print normal virtual addresses.
645    uptr preferred_base = GetPreferredBase(&module_name[0]);
646    uptr adjusted_base = base_address - preferred_base;
647
648    LoadedModule cur_module;
649    cur_module.set(module_name, adjusted_base);
650    // We add the whole module as one single address range.
651    cur_module.addAddressRange(base_address, end_address, /*executable*/ true,
652                               /*writable*/ true);
653    modules_.push_back(cur_module);
654  }
655  UnmapOrDie(hmodules, modules_buffer_size);
656}
657
658void ListOfModules::fallbackInit() { clear(); }
659
660// We can't use atexit() directly at __asan_init time as the CRT is not fully
661// initialized at this point.  Place the functions into a vector and use
662// atexit() as soon as it is ready for use (i.e. after .CRT$XIC initializers).
663InternalMmapVectorNoCtor<void (*)(void)> atexit_functions;
664
665int Atexit(void (*function)(void)) {
666  atexit_functions.push_back(function);
667  return 0;
668}
669
670static int RunAtexit() {
671  TraceLoggingUnregister(g_asan_provider);
672  int ret = 0;
673  for (uptr i = 0; i < atexit_functions.size(); ++i) {
674    ret |= atexit(atexit_functions[i]);
675  }
676  return ret;
677}
678
679#pragma section(".CRT$XID", long, read)
680__declspec(allocate(".CRT$XID")) int (*__run_atexit)() = RunAtexit;
681#endif
682
683// ------------------ sanitizer_libc.h
684fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *last_error) {
685  // FIXME: Use the wide variants to handle Unicode filenames.
686  fd_t res;
687  if (mode == RdOnly) {
688    res = CreateFileA(filename, GENERIC_READ,
689                      FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
690                      nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
691  } else if (mode == WrOnly) {
692    res = CreateFileA(filename, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
693                      FILE_ATTRIBUTE_NORMAL, nullptr);
694  } else {
695    UNIMPLEMENTED();
696  }
697  CHECK(res != kStdoutFd || kStdoutFd == kInvalidFd);
698  CHECK(res != kStderrFd || kStderrFd == kInvalidFd);
699  if (res == kInvalidFd && last_error)
700    *last_error = GetLastError();
701  return res;
702}
703
704void CloseFile(fd_t fd) {
705  CloseHandle(fd);
706}
707
708bool ReadFromFile(fd_t fd, void *buff, uptr buff_size, uptr *bytes_read,
709                  error_t *error_p) {
710  CHECK(fd != kInvalidFd);
711
712  // bytes_read can't be passed directly to ReadFile:
713  // uptr is unsigned long long on 64-bit Windows.
714  unsigned long num_read_long;
715
716  bool success = ::ReadFile(fd, buff, buff_size, &num_read_long, nullptr);
717  if (!success && error_p)
718    *error_p = GetLastError();
719  if (bytes_read)
720    *bytes_read = num_read_long;
721  return success;
722}
723
724bool SupportsColoredOutput(fd_t fd) {
725  // FIXME: support colored output.
726  return false;
727}
728
729bool WriteToFile(fd_t fd, const void *buff, uptr buff_size, uptr *bytes_written,
730                 error_t *error_p) {
731  CHECK(fd != kInvalidFd);
732
733  // Handle null optional parameters.
734  error_t dummy_error;
735  error_p = error_p ? error_p : &dummy_error;
736  uptr dummy_bytes_written;
737  bytes_written = bytes_written ? bytes_written : &dummy_bytes_written;
738
739  // Initialize output parameters in case we fail.
740  *error_p = 0;
741  *bytes_written = 0;
742
743  // Map the conventional Unix fds 1 and 2 to Windows handles. They might be
744  // closed, in which case this will fail.
745  if (fd == kStdoutFd || fd == kStderrFd) {
746    fd = GetStdHandle(fd == kStdoutFd ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
747    if (fd == 0) {
748      *error_p = ERROR_INVALID_HANDLE;
749      return false;
750    }
751  }
752
753  DWORD bytes_written_32;
754  if (!WriteFile(fd, buff, buff_size, &bytes_written_32, 0)) {
755    *error_p = GetLastError();
756    return false;
757  } else {
758    *bytes_written = bytes_written_32;
759    return true;
760  }
761}
762
763uptr internal_sched_yield() {
764  Sleep(0);
765  return 0;
766}
767
768void internal__exit(int exitcode) {
769  TraceLoggingUnregister(g_asan_provider);
770  // ExitProcess runs some finalizers, so use TerminateProcess to avoid that.
771  // The debugger doesn't stop on TerminateProcess like it does on ExitProcess,
772  // so add our own breakpoint here.
773  if (::IsDebuggerPresent())
774    __debugbreak();
775  TerminateProcess(GetCurrentProcess(), exitcode);
776  BUILTIN_UNREACHABLE();
777}
778
779uptr internal_ftruncate(fd_t fd, uptr size) {
780  UNIMPLEMENTED();
781}
782
783uptr GetRSS() {
784  PROCESS_MEMORY_COUNTERS counters;
785  if (!GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters)))
786    return 0;
787  return counters.WorkingSetSize;
788}
789
790void *internal_start_thread(void (*func)(void *arg), void *arg) { return 0; }
791void internal_join_thread(void *th) { }
792
793// ---------------------- BlockingMutex ---------------- {{{1
794
795BlockingMutex::BlockingMutex() {
796  CHECK(sizeof(SRWLOCK) <= sizeof(opaque_storage_));
797  internal_memset(this, 0, sizeof(*this));
798}
799
800void BlockingMutex::Lock() {
801  AcquireSRWLockExclusive((PSRWLOCK)opaque_storage_);
802  CHECK_EQ(owner_, 0);
803  owner_ = GetThreadSelf();
804}
805
806void BlockingMutex::Unlock() {
807  CheckLocked();
808  owner_ = 0;
809  ReleaseSRWLockExclusive((PSRWLOCK)opaque_storage_);
810}
811
812void BlockingMutex::CheckLocked() {
813  CHECK_EQ(owner_, GetThreadSelf());
814}
815
816uptr GetTlsSize() {
817  return 0;
818}
819
820void InitTlsSize() {
821}
822
823void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
824                          uptr *tls_addr, uptr *tls_size) {
825#if SANITIZER_GO
826  *stk_addr = 0;
827  *stk_size = 0;
828  *tls_addr = 0;
829  *tls_size = 0;
830#else
831  uptr stack_top, stack_bottom;
832  GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
833  *stk_addr = stack_bottom;
834  *stk_size = stack_top - stack_bottom;
835  *tls_addr = 0;
836  *tls_size = 0;
837#endif
838}
839
840void ReportFile::Write(const char *buffer, uptr length) {
841  SpinMutexLock l(mu);
842  ReopenIfNecessary();
843  if (!WriteToFile(fd, buffer, length)) {
844    // stderr may be closed, but we may be able to print to the debugger
845    // instead.  This is the case when launching a program from Visual Studio,
846    // and the following routine should write to its console.
847    OutputDebugStringA(buffer);
848  }
849}
850
851void SetAlternateSignalStack() {
852  // FIXME: Decide what to do on Windows.
853}
854
855void UnsetAlternateSignalStack() {
856  // FIXME: Decide what to do on Windows.
857}
858
859void InstallDeadlySignalHandlers(SignalHandlerType handler) {
860  (void)handler;
861  // FIXME: Decide what to do on Windows.
862}
863
864HandleSignalMode GetHandleSignalMode(int signum) {
865  // FIXME: Decide what to do on Windows.
866  return kHandleSignalNo;
867}
868
869// Check based on flags if we should handle this exception.
870bool IsHandledDeadlyException(DWORD exceptionCode) {
871  switch (exceptionCode) {
872    case EXCEPTION_ACCESS_VIOLATION:
873    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
874    case EXCEPTION_STACK_OVERFLOW:
875    case EXCEPTION_DATATYPE_MISALIGNMENT:
876    case EXCEPTION_IN_PAGE_ERROR:
877      return common_flags()->handle_segv;
878    case EXCEPTION_ILLEGAL_INSTRUCTION:
879    case EXCEPTION_PRIV_INSTRUCTION:
880    case EXCEPTION_BREAKPOINT:
881      return common_flags()->handle_sigill;
882    case EXCEPTION_FLT_DENORMAL_OPERAND:
883    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
884    case EXCEPTION_FLT_INEXACT_RESULT:
885    case EXCEPTION_FLT_INVALID_OPERATION:
886    case EXCEPTION_FLT_OVERFLOW:
887    case EXCEPTION_FLT_STACK_CHECK:
888    case EXCEPTION_FLT_UNDERFLOW:
889    case EXCEPTION_INT_DIVIDE_BY_ZERO:
890    case EXCEPTION_INT_OVERFLOW:
891      return common_flags()->handle_sigfpe;
892  }
893  return false;
894}
895
896bool IsAccessibleMemoryRange(uptr beg, uptr size) {
897  SYSTEM_INFO si;
898  GetNativeSystemInfo(&si);
899  uptr page_size = si.dwPageSize;
900  uptr page_mask = ~(page_size - 1);
901
902  for (uptr page = beg & page_mask, end = (beg + size - 1) & page_mask;
903       page <= end;) {
904    MEMORY_BASIC_INFORMATION info;
905    if (VirtualQuery((LPCVOID)page, &info, sizeof(info)) != sizeof(info))
906      return false;
907
908    if (info.Protect == 0 || info.Protect == PAGE_NOACCESS ||
909        info.Protect == PAGE_EXECUTE)
910      return false;
911
912    if (info.RegionSize == 0)
913      return false;
914
915    page += info.RegionSize;
916  }
917
918  return true;
919}
920
921bool SignalContext::IsStackOverflow() const {
922  return (DWORD)GetType() == EXCEPTION_STACK_OVERFLOW;
923}
924
925void SignalContext::InitPcSpBp() {
926  EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo;
927  CONTEXT *context_record = (CONTEXT *)context;
928
929  pc = (uptr)exception_record->ExceptionAddress;
930#ifdef _WIN64
931  bp = (uptr)context_record->Rbp;
932  sp = (uptr)context_record->Rsp;
933#else
934  bp = (uptr)context_record->Ebp;
935  sp = (uptr)context_record->Esp;
936#endif
937}
938
939uptr SignalContext::GetAddress() const {
940  EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo;
941  return exception_record->ExceptionInformation[1];
942}
943
944bool SignalContext::IsMemoryAccess() const {
945  return GetWriteFlag() != SignalContext::UNKNOWN;
946}
947
948bool SignalContext::IsTrueFaultingAddress() const {
949  // FIXME: Provide real implementation for this. See Linux and Mac variants.
950  return IsMemoryAccess();
951}
952
953SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
954  EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo;
955  // The contents of this array are documented at
956  // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363082(v=vs.85).aspx
957  // The first element indicates read as 0, write as 1, or execute as 8.  The
958  // second element is the faulting address.
959  switch (exception_record->ExceptionInformation[0]) {
960    case 0:
961      return SignalContext::READ;
962    case 1:
963      return SignalContext::WRITE;
964    case 8:
965      return SignalContext::UNKNOWN;
966  }
967  return SignalContext::UNKNOWN;
968}
969
970void SignalContext::DumpAllRegisters(void *context) {
971  // FIXME: Implement this.
972}
973
974int SignalContext::GetType() const {
975  return static_cast<const EXCEPTION_RECORD *>(siginfo)->ExceptionCode;
976}
977
978const char *SignalContext::Describe() const {
979  unsigned code = GetType();
980  // Get the string description of the exception if this is a known deadly
981  // exception.
982  switch (code) {
983    case EXCEPTION_ACCESS_VIOLATION:
984      return "access-violation";
985    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
986      return "array-bounds-exceeded";
987    case EXCEPTION_STACK_OVERFLOW:
988      return "stack-overflow";
989    case EXCEPTION_DATATYPE_MISALIGNMENT:
990      return "datatype-misalignment";
991    case EXCEPTION_IN_PAGE_ERROR:
992      return "in-page-error";
993    case EXCEPTION_ILLEGAL_INSTRUCTION:
994      return "illegal-instruction";
995    case EXCEPTION_PRIV_INSTRUCTION:
996      return "priv-instruction";
997    case EXCEPTION_BREAKPOINT:
998      return "breakpoint";
999    case EXCEPTION_FLT_DENORMAL_OPERAND:
1000      return "flt-denormal-operand";
1001    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
1002      return "flt-divide-by-zero";
1003    case EXCEPTION_FLT_INEXACT_RESULT:
1004      return "flt-inexact-result";
1005    case EXCEPTION_FLT_INVALID_OPERATION:
1006      return "flt-invalid-operation";
1007    case EXCEPTION_FLT_OVERFLOW:
1008      return "flt-overflow";
1009    case EXCEPTION_FLT_STACK_CHECK:
1010      return "flt-stack-check";
1011    case EXCEPTION_FLT_UNDERFLOW:
1012      return "flt-underflow";
1013    case EXCEPTION_INT_DIVIDE_BY_ZERO:
1014      return "int-divide-by-zero";
1015    case EXCEPTION_INT_OVERFLOW:
1016      return "int-overflow";
1017  }
1018  return "unknown exception";
1019}
1020
1021uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
1022  // FIXME: Actually implement this function.
1023  CHECK_GT(buf_len, 0);
1024  buf[0] = 0;
1025  return 0;
1026}
1027
1028uptr ReadLongProcessName(/*out*/char *buf, uptr buf_len) {
1029  return ReadBinaryName(buf, buf_len);
1030}
1031
1032void CheckVMASize() {
1033  // Do nothing.
1034}
1035
1036void InitializePlatformEarly() {
1037  // Do nothing.
1038}
1039
1040void MaybeReexec() {
1041  // No need to re-exec on Windows.
1042}
1043
1044void CheckASLR() {
1045  // Do nothing
1046}
1047
1048void CheckMPROTECT() {
1049  // Do nothing
1050}
1051
1052char **GetArgv() {
1053  // FIXME: Actually implement this function.
1054  return 0;
1055}
1056
1057char **GetEnviron() {
1058  // FIXME: Actually implement this function.
1059  return 0;
1060}
1061
1062pid_t StartSubprocess(const char *program, const char *const argv[],
1063                      fd_t stdin_fd, fd_t stdout_fd, fd_t stderr_fd) {
1064  // FIXME: implement on this platform
1065  // Should be implemented based on
1066  // SymbolizerProcess::StarAtSymbolizerSubprocess
1067  // from lib/sanitizer_common/sanitizer_symbolizer_win.cpp.
1068  return -1;
1069}
1070
1071bool IsProcessRunning(pid_t pid) {
1072  // FIXME: implement on this platform.
1073  return false;
1074}
1075
1076int WaitForProcess(pid_t pid) { return -1; }
1077
1078// FIXME implement on this platform.
1079void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) { }
1080
1081void CheckNoDeepBind(const char *filename, int flag) {
1082  // Do nothing.
1083}
1084
1085// FIXME: implement on this platform.
1086bool GetRandom(void *buffer, uptr length, bool blocking) {
1087  UNIMPLEMENTED();
1088}
1089
1090u32 GetNumberOfCPUs() {
1091  SYSTEM_INFO sysinfo = {};
1092  GetNativeSystemInfo(&sysinfo);
1093  return sysinfo.dwNumberOfProcessors;
1094}
1095
1096#if SANITIZER_WIN_TRACE
1097// TODO(mcgov): Rename this project-wide to PlatformLogInit
1098void AndroidLogInit(void) {
1099  HRESULT hr = TraceLoggingRegister(g_asan_provider);
1100  if (!SUCCEEDED(hr))
1101    return;
1102}
1103
1104void SetAbortMessage(const char *) {}
1105
1106void LogFullErrorReport(const char *buffer) {
1107  if (common_flags()->log_to_syslog) {
1108    InternalMmapVector<wchar_t> filename;
1109    DWORD filename_length = 0;
1110    do {
1111      filename.resize(filename.size() + 0x100);
1112      filename_length =
1113          GetModuleFileNameW(NULL, filename.begin(), filename.size());
1114    } while (filename_length >= filename.size());
1115    TraceLoggingWrite(g_asan_provider, "AsanReportEvent",
1116                      TraceLoggingValue(filename.begin(), "ExecutableName"),
1117                      TraceLoggingValue(buffer, "AsanReportContents"));
1118  }
1119}
1120#endif // SANITIZER_WIN_TRACE
1121
1122}  // namespace __sanitizer
1123
1124#endif  // _WIN32
1125