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