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