17f9c5a220b2768a450696bbd157a0e6f2e9ceea3Alexey Samsonov//===-- sanitizer_win.cc --------------------------------------------------===//
2c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov//
3c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov//                     The LLVM Compiler Infrastructure
4c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov//
5c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov// This file is distributed under the University of Illinois Open Source
6c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov// License. See LICENSE.TXT for details.
7c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov//
8c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov//===----------------------------------------------------------------------===//
9c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov//
10c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov// This file is shared between AddressSanitizer and ThreadSanitizer
11c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov// run-time libraries and implements windows-specific functions from
12c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov// sanitizer_libc.h.
13c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov//===----------------------------------------------------------------------===//
1424e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov
1524e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#include "sanitizer_platform.h"
1624e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_WINDOWS
1724e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov
1833b2a94ded8473154553c71ef585b8b2522ce70fDmitry Vyukov#define WIN32_LEAN_AND_MEAN
1933b2a94ded8473154553c71ef585b8b2522ce70fDmitry Vyukov#define NOGDI
20c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <windows.h>
216d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#include <dbghelp.h>
226d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#include <io.h>
2386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include <psapi.h>
246d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#include <stdlib.h>
25c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov
269929ffd1c4737d2c50829dcefcb0b8f1926a05ffAlexey Samsonov#include "sanitizer_common.h"
27c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include "sanitizer_libc.h"
2853833ea8d697c9a92719ab630e605ab590f46193Dmitry Vyukov#include "sanitizer_mutex.h"
29736cf49a46b3cc5aa1856762f85e6f2799c24e5aSergey Matveev#include "sanitizer_placement_new.h"
30736cf49a46b3cc5aa1856762f85e6f2799c24e5aSergey Matveev#include "sanitizer_stacktrace.h"
31c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov
32c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonovnamespace __sanitizer {
33c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov
349578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#include "sanitizer_syscall_generic.inc"
359578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne
36e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// --------------------- sanitizer_common.h
37f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryanyuptr GetPageSize() {
38c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  SYSTEM_INFO si;
39c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  GetSystemInfo(&si);
40c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return si.dwPageSize;
41f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany}
42f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany
43f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryanyuptr GetMmapGranularity() {
44c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  SYSTEM_INFO si;
45c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  GetSystemInfo(&si);
46c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return si.dwAllocationGranularity;
47f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany}
48f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany
49bb7f2d880c843dd5ee1c5e53d2517f7ca9058e66Timur Iskhodzhanovuptr GetMaxVirtualAddress() {
50bb7f2d880c843dd5ee1c5e53d2517f7ca9058e66Timur Iskhodzhanov  SYSTEM_INFO si;
51bb7f2d880c843dd5ee1c5e53d2517f7ca9058e66Timur Iskhodzhanov  GetSystemInfo(&si);
52bb7f2d880c843dd5ee1c5e53d2517f7ca9058e66Timur Iskhodzhanov  return (uptr)si.lpMaximumApplicationAddress;
53bb7f2d880c843dd5ee1c5e53d2517f7ca9058e66Timur Iskhodzhanov}
54bb7f2d880c843dd5ee1c5e53d2517f7ca9058e66Timur Iskhodzhanov
5593b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonovbool FileExists(const char *filename) {
56799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  return ::GetFileAttributesA(filename) != INVALID_FILE_ATTRIBUTES;
5793b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov}
5893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov
590b694fcab9b2f33bdd6691cbea4e80a5c27191b1Peter Collingbourneuptr internal_getpid() {
60230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov  return GetProcessId(GetCurrentProcess());
61230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov}
62230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov
632c969875d823989d401c7de96e310412806ee1efTimur Iskhodzhanov// In contrast to POSIX, on Windows GetCurrentThreadId()
642c969875d823989d401c7de96e310412806ee1efTimur Iskhodzhanov// returns a system-unique identifier.
652c969875d823989d401c7de96e310412806ee1efTimur Iskhodzhanovuptr GetTid() {
66fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov  return GetCurrentThreadId();
67fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov}
68fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov
692c969875d823989d401c7de96e310412806ee1efTimur Iskhodzhanovuptr GetThreadSelf() {
702c969875d823989d401c7de96e310412806ee1efTimur Iskhodzhanov  return GetTid();
712c969875d823989d401c7de96e310412806ee1efTimur Iskhodzhanov}
722c969875d823989d401c7de96e310412806ee1efTimur Iskhodzhanov
736d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_GO
74ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonovvoid GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
75e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov                                uptr *stack_bottom) {
76e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  CHECK(stack_top);
77e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  CHECK(stack_bottom);
78e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  MEMORY_BASIC_INFORMATION mbi;
796985085c4860bf945358f227ddba26511ae770e9Kostya Serebryany  CHECK_NE(VirtualQuery(&mbi /* on stack */, &mbi, sizeof(mbi)), 0);
80e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  // FIXME: is it possible for the stack to not be a single allocation?
81e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  // Are these values what ASan expects to get (reserved, not committed;
82e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  // including stack guard page) ?
83e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  *stack_top = (uptr)mbi.BaseAddress + mbi.RegionSize;
84e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  *stack_bottom = (uptr)mbi.AllocationBase;
85e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov}
866d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif  // #if !SANITIZER_GO
87e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov
88799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
89230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov  void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
90799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (rv == 0)
91799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    ReportMmapFailureAndDie(size, mem_type, "allocate",
92799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                            GetLastError(), raw_report);
93230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov  return rv;
94230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov}
95230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov
96230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonovvoid UnmapOrDie(void *addr, uptr size) {
97259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  if (!size || !addr)
98259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar    return;
99259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar
100c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  MEMORY_BASIC_INFORMATION mbi;
101c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  CHECK(VirtualQuery(addr, &mbi, sizeof(mbi)));
102c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
103c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // MEM_RELEASE can only be used to unmap whole regions previously mapped with
104c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // VirtualAlloc. So we first try MEM_RELEASE since it is better, and if that
105c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // fails try MEM_DECOMMIT.
106c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
107c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    if (VirtualFree(addr, size, MEM_DECOMMIT) == 0) {
108c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      Report("ERROR: %s failed to "
109c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar             "deallocate 0x%zx (%zd) bytes at address %p (error code: %d)\n",
110c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar             SanitizerToolName, size, size, addr, GetLastError());
111c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      CHECK("unable to unmap" && 0);
112c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    }
113c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  }
114c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
115c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
116c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// We want to map a chunk of address space aligned to 'alignment'.
117c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type) {
118c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  CHECK(IsPowerOfTwo(size));
119c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  CHECK(IsPowerOfTwo(alignment));
120c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
121c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // Windows will align our allocations to at least 64K.
122c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  alignment = Max(alignment, GetMmapGranularity());
123c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
124c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  uptr mapped_addr =
125c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      (uptr)VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
126c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (!mapped_addr)
127c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    ReportMmapFailureAndDie(size, mem_type, "allocate aligned", GetLastError());
128c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
129c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // If we got it right on the first try, return. Otherwise, unmap it and go to
130c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // the slow path.
131c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (IsAligned(mapped_addr, alignment))
132c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    return (void*)mapped_addr;
133c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (VirtualFree((void *)mapped_addr, 0, MEM_RELEASE) == 0)
134c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    ReportMmapFailureAndDie(size, mem_type, "deallocate", GetLastError());
135c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
136c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // If we didn't get an aligned address, overallocate, find an aligned address,
137c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // unmap, and try to allocate at that aligned address.
138c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  int retries = 0;
139c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  const int kMaxRetries = 10;
140c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  for (; retries < kMaxRetries &&
141c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar         (mapped_addr == 0 || !IsAligned(mapped_addr, alignment));
142c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar       retries++) {
143c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    // Overallocate size + alignment bytes.
144c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    mapped_addr =
145c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar        (uptr)VirtualAlloc(0, size + alignment, MEM_RESERVE, PAGE_NOACCESS);
146c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    if (!mapped_addr)
147c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      ReportMmapFailureAndDie(size, mem_type, "allocate aligned",
148c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                              GetLastError());
149c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
150c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    // Find the aligned address.
151c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    uptr aligned_addr = RoundUpTo(mapped_addr, alignment);
152c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
153c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    // Free the overallocation.
154c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    if (VirtualFree((void *)mapped_addr, 0, MEM_RELEASE) == 0)
155c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      ReportMmapFailureAndDie(size, mem_type, "deallocate", GetLastError());
156c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
157c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    // Attempt to allocate exactly the number of bytes we need at the aligned
158c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    // address. This may fail for a number of reasons, in which case we continue
159c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    // the loop.
160c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    mapped_addr = (uptr)VirtualAlloc((void *)aligned_addr, size,
161c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                                     MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
1628c53e54ef9e713953ec9495e82e5c330b96e49f3Alexey Samsonov  }
163c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
164c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // Fail if we can't make this work quickly.
165c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (retries == kMaxRetries && mapped_addr == 0)
166c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    ReportMmapFailureAndDie(size, mem_type, "allocate aligned", GetLastError());
167c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
168c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return (void *)mapped_addr;
169230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov}
170230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov
171cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainarvoid *MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
1729bfe78f7d4f9af3cdacb4d34bd7b4fead27dcda5Kostya Serebryany  // FIXME: is this really "NoReserve"? On Win32 this does not matter much,
1739bfe78f7d4f9af3cdacb4d34bd7b4fead27dcda5Kostya Serebryany  // but on Win64 it does.
174c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  (void)name;  // unsupported
175c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if SANITIZER_WINDOWS64
176c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // On Windows64, use MEM_COMMIT would result in error
177c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // 1455:ERROR_COMMITMENT_LIMIT.
178c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // We use exception handler to commit page on demand.
179c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  void *p = VirtualAlloc((LPVOID)fixed_addr, size, MEM_RESERVE, PAGE_READWRITE);
180c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#else
181c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  void *p = VirtualAlloc((LPVOID)fixed_addr, size, MEM_RESERVE | MEM_COMMIT,
182c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                         PAGE_READWRITE);
183c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif
18433b2a94ded8473154553c71ef585b8b2522ce70fDmitry Vyukov  if (p == 0)
1852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    Report("ERROR: %s failed to "
1862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines           "allocate %p (%zd) bytes at %p (error code: %d)\n",
1872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines           SanitizerToolName, size, size, fixed_addr, GetLastError());
18833b2a94ded8473154553c71ef585b8b2522ce70fDmitry Vyukov  return p;
189f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov}
190f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov
191c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Memory space mapped by 'MmapFixedOrDie' must have been reserved by
192c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// 'MmapFixedNoAccess'.
1939bfe78f7d4f9af3cdacb4d34bd7b4fead27dcda5Kostya Serebryanyvoid *MmapFixedOrDie(uptr fixed_addr, uptr size) {
194c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  void *p = VirtualAlloc((LPVOID)fixed_addr, size,
195c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      MEM_COMMIT, PAGE_READWRITE);
196c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (p == 0) {
197c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    char mem_type[30];
198c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx",
199c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                      fixed_addr);
200c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    ReportMmapFailureAndDie(size, mem_type, "allocate", GetLastError());
201c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  }
202c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return p;
2039bfe78f7d4f9af3cdacb4d34bd7b4fead27dcda5Kostya Serebryany}
2049bfe78f7d4f9af3cdacb4d34bd7b4fead27dcda5Kostya Serebryany
2052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid *MmapNoReserveOrDie(uptr size, const char *mem_type) {
2062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // FIXME: make this really NoReserve?
2072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return MmapOrDie(size, mem_type);
2082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
2092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
210c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name) {
211cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  (void)name; // unsupported
21286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *res = VirtualAlloc((LPVOID)fixed_addr, size,
213c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                           MEM_RESERVE, PAGE_NOACCESS);
21486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (res == 0)
21586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    Report("WARNING: %s failed to "
21686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines           "mprotect %p (%zd) bytes at %p (error code: %d)\n",
21786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines           SanitizerToolName, size, size, fixed_addr, GetLastError());
21886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return res;
219f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov}
220f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov
221c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid *MmapNoAccess(uptr size) {
222c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // FIXME: unsupported.
223c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return nullptr;
224c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
225c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
226259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarbool MprotectNoAccess(uptr addr, uptr size) {
227259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  DWORD old_protection;
228259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  return VirtualProtect((LPVOID)addr, size, PAGE_NOACCESS, &old_protection);
229259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar}
230259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar
231259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar
2322b10d3944d911c07f2a10cf248300260ed67454aTimur Iskhodzhanovvoid FlushUnneededShadowMemory(uptr addr, uptr size) {
2332b10d3944d911c07f2a10cf248300260ed67454aTimur Iskhodzhanov  // This is almost useless on 32-bits.
23486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // FIXME: add madvise-analog when we move to 64-bits.
23586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
23686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
23786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid NoHugePagesInRegion(uptr addr, uptr size) {
23886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // FIXME: probably similar to FlushUnneededShadowMemory.
23986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
24086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
24186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid DontDumpShadowMemory(uptr addr, uptr length) {
24286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // This is almost useless on 32-bits.
24386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // FIXME: add madvise-analog when we move to 64-bits.
2442b10d3944d911c07f2a10cf248300260ed67454aTimur Iskhodzhanov}
2452b10d3944d911c07f2a10cf248300260ed67454aTimur Iskhodzhanov
246dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonovbool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
24786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  MEMORY_BASIC_INFORMATION mbi;
24886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK(VirtualQuery((void *)range_start, &mbi, sizeof(mbi)));
24986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return mbi.Protect == PAGE_NOACCESS &&
25086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines         (uptr)mbi.BaseAddress + mbi.RegionSize >= range_end;
251dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov}
252dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov
253a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonovvoid *MapFileToMemory(const char *file_name, uptr *buff_size) {
254a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov  UNIMPLEMENTED();
255a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov}
256a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov
257799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, OFF_T offset) {
2586a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  UNIMPLEMENTED();
2596a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines}
2606a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines
261a3ab1927a8b86536dc29ccaaa49ca65920028224Alexey Samsonovstatic const int kMaxEnvNameLength = 128;
262c5288679cc55c523188a40325d49d97b100cf03cDmitry Vyukovstatic const DWORD kMaxEnvValueLength = 32767;
2631ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov
2641ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonovnamespace {
2651ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov
2661ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonovstruct EnvVariable {
2671ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov  char name[kMaxEnvNameLength];
2681ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov  char value[kMaxEnvValueLength];
2691ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov};
2701ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov
2711ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov}  // namespace
2721ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov
2731ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonovstatic const int kEnvVariables = 5;
2741ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonovstatic EnvVariable env_vars[kEnvVariables];
2751ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonovstatic int num_env_vars;
2761ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov
2773dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonovconst char *GetEnv(const char *name) {
2781ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov  // Note: this implementation caches the values of the environment variables
2791ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov  // and limits their quantity.
2801ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov  for (int i = 0; i < num_env_vars; i++) {
2811ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov    if (0 == internal_strcmp(name, env_vars[i].name))
2821ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov      return env_vars[i].value;
2831ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov  }
2841ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov  CHECK_LT(num_env_vars, kEnvVariables);
2851ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov  DWORD rv = GetEnvironmentVariableA(name, env_vars[num_env_vars].value,
2861ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov                                     kMaxEnvValueLength);
2871ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov  if (rv > 0 && rv < kMaxEnvValueLength) {
2881ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov    CHECK_LT(internal_strlen(name), kMaxEnvNameLength);
2891ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov    internal_strncpy(env_vars[num_env_vars].name, name, kMaxEnvNameLength);
2901ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov    num_env_vars++;
2911ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov    return env_vars[num_env_vars - 1].value;
2921ef94b160c12a2db63daf63af8ab6e1eb2f3cb7cAlexey Samsonov  }
2933dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  return 0;
2943dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov}
2953dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov
2960969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonovconst char *GetPwd() {
2970969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov  UNIMPLEMENTED();
2980969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov}
2990969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov
3000fa691b7ec97d8c3948a637d6263822ed4e738f7Alexey Samsonovu32 GetUid() {
3010fa691b7ec97d8c3948a637d6263822ed4e738f7Alexey Samsonov  UNIMPLEMENTED();
3020fa691b7ec97d8c3948a637d6263822ed4e738f7Alexey Samsonov}
3030fa691b7ec97d8c3948a637d6263822ed4e738f7Alexey Samsonov
30486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesnamespace {
30586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstruct ModuleInfo {
306259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  const char *filepath;
30786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  uptr base_address;
30886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  uptr end_address;
30986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines};
31086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
311799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#ifndef SANITIZER_GO
31286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesint CompareModulesBase(const void *pl, const void *pr) {
313259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  const ModuleInfo *l = (ModuleInfo *)pl, *r = (ModuleInfo *)pr;
314259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  if (l->base_address < r->base_address)
31586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return -1;
316259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  return l->base_address > r->base_address;
31786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
318799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif
31986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}  // namespace
32086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
32186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
322be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonovvoid DumpProcessMap() {
32386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  Report("Dumping process modules:\n");
324c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  ListOfModules modules;
325c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  modules.init();
326c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  uptr num_modules = modules.size();
32786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
328259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  InternalScopedBuffer<ModuleInfo> module_infos(num_modules);
329259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  for (size_t i = 0; i < num_modules; ++i) {
330259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar    module_infos[i].filepath = modules[i].full_name();
331259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar    module_infos[i].base_address = modules[i].base_address();
332c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    module_infos[i].end_address = modules[i].ranges().front()->end;
33386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
334259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  qsort(module_infos.data(), num_modules, sizeof(ModuleInfo),
335259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar        CompareModulesBase);
33686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
33786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  for (size_t i = 0; i < num_modules; ++i) {
338259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar    const ModuleInfo &mi = module_infos[i];
33986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (mi.end_address != 0) {
34086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      Printf("\t%p-%p %s\n", mi.base_address, mi.end_address,
341259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar             mi.filepath[0] ? mi.filepath : "[no name]");
342259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar    } else if (mi.filepath[0]) {
343259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar      Printf("\t??\?-??? %s\n", mi.filepath);
34486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    } else {
34586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      Printf("\t???\n");
34686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
34786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
348be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov}
34986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
350be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov
3516d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesvoid DisableCoreDumperIfNecessary() {
3522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // Do nothing.
353be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov}
354be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov
355d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonovvoid ReExec() {
356d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  UNIMPLEMENTED();
357d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov}
358d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov
3592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid PrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
360cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#if !SANITIZER_GO
361cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  CovPrepareForSandboxing(args);
362cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#endif
36325742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko}
36425742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko
365d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonovbool StackSizeIsUnlimited() {
366d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  UNIMPLEMENTED();
367d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov}
368d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov
369d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonovvoid SetStackSizeLimitInBytes(uptr limit) {
370d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  UNIMPLEMENTED();
371d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov}
372d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov
3736d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesbool AddressSpaceIsUnlimited() {
3746d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  UNIMPLEMENTED();
3756d1862363c88c183b0ed7740fca876342cf0474bStephen Hines}
3766d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
3776d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesvoid SetAddressSpaceUnlimited() {
3786d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  UNIMPLEMENTED();
3796d1862363c88c183b0ed7740fca876342cf0474bStephen Hines}
3806d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
3817c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarbool IsPathSeparator(const char c) {
3827c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  return c == '\\' || c == '/';
3837c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar}
3847c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
3857c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarbool IsAbsolutePath(const char *path) {
3867c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  UNIMPLEMENTED();
3877c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar}
3887c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
389fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonovvoid SleepForSeconds(int seconds) {
390fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov  Sleep(seconds * 1000);
391fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov}
392fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov
3930969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonovvoid SleepForMillis(int millis) {
3940969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov  Sleep(millis);
3950969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov}
3960969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov
397c5288679cc55c523188a40325d49d97b100cf03cDmitry Vyukovu64 NanoTime() {
398c5288679cc55c523188a40325d49d97b100cf03cDmitry Vyukov  return 0;
399c5288679cc55c523188a40325d49d97b100cf03cDmitry Vyukov}
400c5288679cc55c523188a40325d49d97b100cf03cDmitry Vyukov
401fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonovvoid Abort() {
40286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (::IsDebuggerPresent())
40386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    __debugbreak();
40486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  internal__exit(3);
405fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov}
406fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov
407c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#ifndef SANITIZER_GO
408799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// Read the file to extract the ImageBase field from the PE header. If ASLR is
409799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// disabled and this virtual address is available, the loader will typically
410799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// load the image at this address. Therefore, we call it the preferred base. Any
411799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// addresses in the DWARF typically assume that the object has been loaded at
412799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// this address.
413799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarstatic uptr GetPreferredBase(const char *modname) {
414799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  fd_t fd = OpenFile(modname, RdOnly, nullptr);
415799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (fd == kInvalidFd)
416799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    return 0;
417799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  FileCloser closer(fd);
418799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
419799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // Read just the DOS header.
420799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  IMAGE_DOS_HEADER dos_header;
421799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  uptr bytes_read;
422799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (!ReadFromFile(fd, &dos_header, sizeof(dos_header), &bytes_read) ||
423799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      bytes_read != sizeof(dos_header))
424799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    return 0;
425799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
426799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // The file should start with the right signature.
427799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (dos_header.e_magic != IMAGE_DOS_SIGNATURE)
428799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    return 0;
429799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
430799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // The layout at e_lfanew is:
431799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // "PE\0\0"
432799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // IMAGE_FILE_HEADER
433799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // IMAGE_OPTIONAL_HEADER
434799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // Seek to e_lfanew and read all that data.
435799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  char buf[4 + sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER)];
436799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (::SetFilePointer(fd, dos_header.e_lfanew, nullptr, FILE_BEGIN) ==
437799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      INVALID_SET_FILE_POINTER)
438799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    return 0;
439799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (!ReadFromFile(fd, &buf[0], sizeof(buf), &bytes_read) ||
440799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      bytes_read != sizeof(buf))
441799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    return 0;
442799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
443799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // Check for "PE\0\0" before the PE header.
444799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  char *pe_sig = &buf[0];
445799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (internal_memcmp(pe_sig, "PE\0\0", 4) != 0)
446799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    return 0;
447799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
448799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // Skip over IMAGE_FILE_HEADER. We could do more validation here if we wanted.
449799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  IMAGE_OPTIONAL_HEADER *pe_header =
450799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      (IMAGE_OPTIONAL_HEADER *)(pe_sig + 4 + sizeof(IMAGE_FILE_HEADER));
451799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
452799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // Check for more magic in the PE header.
453799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (pe_header->Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
454799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    return 0;
455799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
456799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // Finally, return the ImageBase.
457799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  return (uptr)pe_header->ImageBase;
458799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar}
459799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
460c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid ListOfModules::init() {
461c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  clear();
462259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  HANDLE cur_process = GetCurrentProcess();
463fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov
464259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  // Query the list of modules.  Start by assuming there are no more than 256
465259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  // modules and retry if that's not sufficient.
466259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  HMODULE *hmodules = 0;
467259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  uptr modules_buffer_size = sizeof(HMODULE) * 256;
468259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  DWORD bytes_required;
469259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  while (!hmodules) {
470259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar    hmodules = (HMODULE *)MmapOrDie(modules_buffer_size, __FUNCTION__);
471259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar    CHECK(EnumProcessModules(cur_process, hmodules, modules_buffer_size,
472259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar                             &bytes_required));
473259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar    if (bytes_required > modules_buffer_size) {
474259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar      // Either there turned out to be more than 256 hmodules, or new hmodules
475259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar      // could have loaded since the last try.  Retry.
476259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar      UnmapOrDie(hmodules, modules_buffer_size);
477259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar      hmodules = 0;
478259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar      modules_buffer_size = bytes_required;
479259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar    }
480259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  }
481c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov
482259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  // |num_modules| is the number of modules actually present,
483c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  size_t num_modules = bytes_required / sizeof(HMODULE);
484c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  for (size_t i = 0; i < num_modules; ++i) {
485259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar    HMODULE handle = hmodules[i];
486259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar    MODULEINFO mi;
487259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar    if (!GetModuleInformation(cur_process, handle, &mi, sizeof(mi)))
488259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar      continue;
4891f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov
490799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    // Get the UTF-16 path and convert to UTF-8.
491799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    wchar_t modname_utf16[kMaxPathLength];
492799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    int modname_utf16_len =
493799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar        GetModuleFileNameW(handle, modname_utf16, kMaxPathLength);
494799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    if (modname_utf16_len == 0)
495799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      modname_utf16[0] = '\0';
496799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    char module_name[kMaxPathLength];
497799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    int module_name_len =
498799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar        ::WideCharToMultiByte(CP_UTF8, 0, modname_utf16, modname_utf16_len + 1,
499799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                              &module_name[0], kMaxPathLength, NULL, NULL);
500799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    module_name[module_name_len] = '\0';
501259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar
502259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar    uptr base_address = (uptr)mi.lpBaseOfDll;
503259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar    uptr end_address = (uptr)mi.lpBaseOfDll + mi.SizeOfImage;
504799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
505799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    // Adjust the base address of the module so that we get a VA instead of an
506799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    // RVA when computing the module offset. This helps llvm-symbolizer find the
507799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    // right DWARF CU. In the common case that the image is loaded at it's
508799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    // preferred address, we will now print normal virtual addresses.
509799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    uptr preferred_base = GetPreferredBase(&module_name[0]);
510799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    uptr adjusted_base = base_address - preferred_base;
511799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
512c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    LoadedModule cur_module;
513c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    cur_module.set(module_name, adjusted_base);
514259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar    // We add the whole module as one single address range.
515c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    cur_module.addAddressRange(base_address, end_address, /*executable*/ true);
516c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    modules_.push_back(cur_module);
517259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  }
518259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  UnmapOrDie(hmodules, modules_buffer_size);
519259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar};
52084d57b4ce545d6c19effac01124749a9df0fd0a5Alexey Samsonov
521259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar// We can't use atexit() directly at __asan_init time as the CRT is not fully
522259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar// initialized at this point.  Place the functions into a vector and use
523259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar// atexit() as soon as it is ready for use (i.e. after .CRT$XIC initializers).
524259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga NainarInternalMmapVectorNoCtor<void (*)(void)> atexit_functions;
525ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov
526259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarint Atexit(void (*function)(void)) {
527259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  atexit_functions.push_back(function);
528259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  return 0;
529ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov}
530ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov
531259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarstatic int RunAtexit() {
532259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  int ret = 0;
533259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  for (uptr i = 0; i < atexit_functions.size(); ++i) {
534259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar    ret |= atexit(atexit_functions[i]);
535259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  }
536259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  return ret;
537c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov}
538c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov
539259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar#pragma section(".CRT$XID", long, read)  // NOLINT
540799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar__declspec(allocate(".CRT$XID")) int (*__run_atexit)() = RunAtexit;
541259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar#endif
542a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
543259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar// ------------------ sanitizer_libc.h
544259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarfd_t OpenFile(const char *filename, FileAccessMode mode, error_t *last_error) {
545c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // FIXME: Use the wide variants to handle Unicode filenames.
546799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  fd_t res;
547799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (mode == RdOnly) {
548c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    res = CreateFileA(filename, GENERIC_READ,
549c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                      FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
550c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                      nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
551799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  } else if (mode == WrOnly) {
552c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    res = CreateFileA(filename, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
553c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                      FILE_ATTRIBUTE_NORMAL, nullptr);
554799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  } else {
5558c53e54ef9e713953ec9495e82e5c330b96e49f3Alexey Samsonov    UNIMPLEMENTED();
556799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  }
557259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  CHECK(res != kStdoutFd || kStdoutFd == kInvalidFd);
558259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  CHECK(res != kStderrFd || kStderrFd == kInvalidFd);
559cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  if (res == kInvalidFd && last_error)
560cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    *last_error = GetLastError();
561259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  return res;
562a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
563a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
564259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarvoid CloseFile(fd_t fd) {
565259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  CloseHandle(fd);
5664c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
5674c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
568259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarbool ReadFromFile(fd_t fd, void *buff, uptr buff_size, uptr *bytes_read,
569259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar                  error_t *error_p) {
570799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  CHECK(fd != kInvalidFd);
571799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
572799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // bytes_read can't be passed directly to ReadFile:
573799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // uptr is unsigned long long on 64-bit Windows.
574799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  unsigned long num_read_long;
575799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
576799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  bool success = ::ReadFile(fd, buff, buff_size, &num_read_long, nullptr);
577799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (!success && error_p)
578799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    *error_p = GetLastError();
579799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (bytes_read)
580799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    *bytes_read = num_read_long;
581799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  return success;
5824c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
5834c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
584259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarbool SupportsColoredOutput(fd_t fd) {
585259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  // FIXME: support colored output.
586259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  return false;
5874c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
5884c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
589259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarbool WriteToFile(fd_t fd, const void *buff, uptr buff_size, uptr *bytes_written,
590259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar                 error_t *error_p) {
591259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  CHECK(fd != kInvalidFd);
5928e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
593799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // Handle null optional parameters.
594799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  error_t dummy_error;
595799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  error_p = error_p ? error_p : &dummy_error;
596799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  uptr dummy_bytes_written;
597799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  bytes_written = bytes_written ? bytes_written : &dummy_bytes_written;
598799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
599799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // Initialize output parameters in case we fail.
600799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  *error_p = 0;
601799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  *bytes_written = 0;
602799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
603799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // Map the conventional Unix fds 1 and 2 to Windows handles. They might be
604799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // closed, in which case this will fail.
605799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (fd == kStdoutFd || fd == kStderrFd) {
606799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    fd = GetStdHandle(fd == kStdoutFd ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
607799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    if (fd == 0) {
608799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      *error_p = ERROR_INVALID_HANDLE;
609799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      return false;
610799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    }
611259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  }
612259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar
613799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  DWORD bytes_written_32;
614799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (!WriteFile(fd, buff, buff_size, &bytes_written_32, 0)) {
615799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    *error_p = GetLastError();
616259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar    return false;
617259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  } else {
618799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    *bytes_written = bytes_written_32;
619259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar    return true;
620259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  }
6218e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
6228e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
623259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarbool RenameFile(const char *oldpath, const char *newpath, error_t *error_p) {
624d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov  UNIMPLEMENTED();
625d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov}
626d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov
6279578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_sched_yield() {
62833b2a94ded8473154553c71ef585b8b2522ce70fDmitry Vyukov  Sleep(0);
62933b2a94ded8473154553c71ef585b8b2522ce70fDmitry Vyukov  return 0;
6300969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov}
6310969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov
632f882247088952deed954a19d745c2dd8871e2035Alexey Samsonovvoid internal__exit(int exitcode) {
6332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ExitProcess(exitcode);
634f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov}
635f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov
6366a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesuptr internal_ftruncate(fd_t fd, uptr size) {
6376a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  UNIMPLEMENTED();
6386a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines}
6396a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines
64086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr GetRSS() {
64186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return 0;
64286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
64386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
64486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *internal_start_thread(void (*func)(void *arg), void *arg) { return 0; }
64586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid internal_join_thread(void *th) { }
64686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
647f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov// ---------------------- BlockingMutex ---------------- {{{1
648cf533b6c24c662c9548c25946211f5e1c9d299f9Dmitry Vyukovconst uptr LOCK_UNINITIALIZED = 0;
649cf533b6c24c662c9548c25946211f5e1c9d299f9Dmitry Vyukovconst uptr LOCK_READY = (uptr)-1;
650f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
651f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry VyukovBlockingMutex::BlockingMutex(LinkerInitialized li) {
652f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  // FIXME: see comments in BlockingMutex::Lock() for the details.
653f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  CHECK(li == LINKER_INITIALIZED || owner_ == LOCK_UNINITIALIZED);
654f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
655f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_));
656f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
65793af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov  owner_ = LOCK_READY;
65893af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov}
65993af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov
66093af5948d3e0c5bdc396f432dd0ae782f499c449Alexey SamsonovBlockingMutex::BlockingMutex() {
66193af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov  CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_));
66293af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov  InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
663f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  owner_ = LOCK_READY;
664f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
665f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
666f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Lock() {
667f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  if (owner_ == LOCK_UNINITIALIZED) {
668f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov    // FIXME: hm, global BlockingMutex objects are not initialized?!?
669f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov    // This might be a side effect of the clang+cl+link Frankenbuild...
670f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov    new(this) BlockingMutex((LinkerInitialized)(LINKER_INITIALIZED + 1));
671f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
672f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov    // FIXME: If it turns out the linker doesn't invoke our
673f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov    // constructors, we should probably manually Lock/Unlock all the global
674f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov    // locks while we're starting in one thread to avoid double-init races.
675f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  }
676f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  EnterCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
6778ceeec4f343768b199e7c891865029360b7225dcDmitry Vyukov  CHECK_EQ(owner_, LOCK_READY);
678f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  owner_ = GetThreadSelf();
679f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
680f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
681f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Unlock() {
6828ceeec4f343768b199e7c891865029360b7225dcDmitry Vyukov  CHECK_EQ(owner_, GetThreadSelf());
683f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  owner_ = LOCK_READY;
684f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  LeaveCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
685f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
686f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
687ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonovvoid BlockingMutex::CheckLocked() {
688ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov  CHECK_EQ(owner_, GetThreadSelf());
689ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov}
690ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov
691b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovuptr GetTlsSize() {
692b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  return 0;
693b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov}
694b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov
695b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovvoid InitTlsSize() {
696b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov}
697b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov
69824323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveevvoid GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
69924323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev                          uptr *tls_addr, uptr *tls_size) {
70021b3b1c50662eeb2d9340c51e1837be495cf87b5Dmitry Vyukov#ifdef SANITIZER_GO
70121b3b1c50662eeb2d9340c51e1837be495cf87b5Dmitry Vyukov  *stk_addr = 0;
70221b3b1c50662eeb2d9340c51e1837be495cf87b5Dmitry Vyukov  *stk_size = 0;
70321b3b1c50662eeb2d9340c51e1837be495cf87b5Dmitry Vyukov  *tls_addr = 0;
70421b3b1c50662eeb2d9340c51e1837be495cf87b5Dmitry Vyukov  *tls_size = 0;
70521b3b1c50662eeb2d9340c51e1837be495cf87b5Dmitry Vyukov#else
70624323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  uptr stack_top, stack_bottom;
70724323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
70824323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  *stk_addr = stack_bottom;
70924323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  *stk_size = stack_top - stack_bottom;
71024323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  *tls_addr = 0;
71124323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  *tls_size = 0;
71221b3b1c50662eeb2d9340c51e1837be495cf87b5Dmitry Vyukov#endif
71324323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev}
71424323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev
7156d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_GO
71686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid BufferedStackTrace::SlowUnwindStack(uptr pc, u32 max_depth) {
7172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  CHECK_GE(max_depth, 2);
718736cf49a46b3cc5aa1856762f85e6f2799c24e5aSergey Matveev  // FIXME: CaptureStackBackTrace might be too slow for us.
719736cf49a46b3cc5aa1856762f85e6f2799c24e5aSergey Matveev  // FIXME: Compare with StackWalk64.
720736cf49a46b3cc5aa1856762f85e6f2799c24e5aSergey Matveev  // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc
7217177d2bbb5850fb499d3e8910b2e05f5c6b025b0Timur Iskhodzhanov  size = CaptureStackBackTrace(2, Min(max_depth, kStackTraceMax),
7227177d2bbb5850fb499d3e8910b2e05f5c6b025b0Timur Iskhodzhanov                               (void**)trace, 0);
7232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (size == 0)
7242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return;
7252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
726736cf49a46b3cc5aa1856762f85e6f2799c24e5aSergey Matveev  // Skip the RTL frames by searching for the PC in the stacktrace.
7277177d2bbb5850fb499d3e8910b2e05f5c6b025b0Timur Iskhodzhanov  uptr pc_location = LocatePcInTrace(pc);
7287177d2bbb5850fb499d3e8910b2e05f5c6b025b0Timur Iskhodzhanov  PopStackFrames(pc_location);
729736cf49a46b3cc5aa1856762f85e6f2799c24e5aSergey Matveev}
730736cf49a46b3cc5aa1856762f85e6f2799c24e5aSergey Matveev
7316d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesvoid BufferedStackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
73286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                                                    u32 max_depth) {
7336d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  CONTEXT ctx = *(CONTEXT *)context;
7346d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  STACKFRAME64 stack_frame;
7356d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  memset(&stack_frame, 0, sizeof(stack_frame));
7366d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  size = 0;
7376d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if defined(_WIN64)
7386d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  int machine_type = IMAGE_FILE_MACHINE_AMD64;
7396d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  stack_frame.AddrPC.Offset = ctx.Rip;
7406d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  stack_frame.AddrFrame.Offset = ctx.Rbp;
7416d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  stack_frame.AddrStack.Offset = ctx.Rsp;
7426d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else
7436d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  int machine_type = IMAGE_FILE_MACHINE_I386;
7446d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  stack_frame.AddrPC.Offset = ctx.Eip;
7456d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  stack_frame.AddrFrame.Offset = ctx.Ebp;
7466d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  stack_frame.AddrStack.Offset = ctx.Esp;
7476d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif
7486d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  stack_frame.AddrPC.Mode = AddrModeFlat;
7496d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  stack_frame.AddrFrame.Mode = AddrModeFlat;
7506d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  stack_frame.AddrStack.Mode = AddrModeFlat;
7516d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  while (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(),
7526d1862363c88c183b0ed7740fca876342cf0474bStephen Hines                     &stack_frame, &ctx, NULL, &SymFunctionTableAccess64,
7536d1862363c88c183b0ed7740fca876342cf0474bStephen Hines                     &SymGetModuleBase64, NULL) &&
7546d1862363c88c183b0ed7740fca876342cf0474bStephen Hines         size < Min(max_depth, kStackTraceMax)) {
7556d1862363c88c183b0ed7740fca876342cf0474bStephen Hines    trace_buffer[size++] = (uptr)stack_frame.AddrPC.Offset;
7566d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  }
7572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
7586d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif  // #if !SANITIZER_GO
7592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
76086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid ReportFile::Write(const char *buffer, uptr length) {
76186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  SpinMutexLock l(mu);
76286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ReopenIfNecessary();
763259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  if (!WriteToFile(fd, buffer, length)) {
764923bac7a85d8bd37219b440a6b4c0800ea4bcd21Reid Kleckner    // stderr may be closed, but we may be able to print to the debugger
765923bac7a85d8bd37219b440a6b4c0800ea4bcd21Reid Kleckner    // instead.  This is the case when launching a program from Visual Studio,
766923bac7a85d8bd37219b440a6b4c0800ea4bcd21Reid Kleckner    // and the following routine should write to its console.
767923bac7a85d8bd37219b440a6b4c0800ea4bcd21Reid Kleckner    OutputDebugStringA(buffer);
768923bac7a85d8bd37219b440a6b4c0800ea4bcd21Reid Kleckner  }
769923bac7a85d8bd37219b440a6b4c0800ea4bcd21Reid Kleckner}
770923bac7a85d8bd37219b440a6b4c0800ea4bcd21Reid Kleckner
7712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid SetAlternateSignalStack() {
7722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // FIXME: Decide what to do on Windows.
7732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
7742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
7752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid UnsetAlternateSignalStack() {
7762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // FIXME: Decide what to do on Windows.
7772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
7782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
7792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid InstallDeadlySignalHandlers(SignalHandlerType handler) {
7802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  (void)handler;
7812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // FIXME: Decide what to do on Windows.
7822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
7832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
784c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarbool IsHandledDeadlySignal(int signum) {
7852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // FIXME: Decide what to do on Windows.
7862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return false;
7872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
7882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
7896d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesbool IsAccessibleMemoryRange(uptr beg, uptr size) {
790799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  SYSTEM_INFO si;
791799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  GetNativeSystemInfo(&si);
792799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  uptr page_size = si.dwPageSize;
793799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  uptr page_mask = ~(page_size - 1);
794799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
795799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  for (uptr page = beg & page_mask, end = (beg + size - 1) & page_mask;
796799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar       page <= end;) {
797799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    MEMORY_BASIC_INFORMATION info;
798799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    if (VirtualQuery((LPCVOID)page, &info, sizeof(info)) != sizeof(info))
799799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      return false;
800799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
801799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    if (info.Protect == 0 || info.Protect == PAGE_NOACCESS ||
802799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar        info.Protect == PAGE_EXECUTE)
803799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      return false;
804799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
805799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    if (info.RegionSize == 0)
806799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      return false;
807799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
808799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    page += info.RegionSize;
809799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  }
810799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
8116d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  return true;
8126d1862363c88c183b0ed7740fca876342cf0474bStephen Hines}
8136d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
8147c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga NainarSignalContext SignalContext::Create(void *siginfo, void *context) {
815c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo;
816c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  CONTEXT *context_record = (CONTEXT *)context;
8177c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
8187c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  uptr pc = (uptr)exception_record->ExceptionAddress;
8197c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#ifdef _WIN64
8207c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  uptr bp = (uptr)context_record->Rbp;
8217c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  uptr sp = (uptr)context_record->Rsp;
8227c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#else
8237c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  uptr bp = (uptr)context_record->Ebp;
8247c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  uptr sp = (uptr)context_record->Esp;
8257c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#endif
8267c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  uptr access_addr = exception_record->ExceptionInformation[1];
8277c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
828c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // The contents of this array are documented at
829c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363082(v=vs.85).aspx
830c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // The first element indicates read as 0, write as 1, or execute as 8.  The
831c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // second element is the faulting address.
832c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  WriteFlag write_flag = SignalContext::UNKNOWN;
833c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  switch (exception_record->ExceptionInformation[0]) {
834c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  case 0: write_flag = SignalContext::READ; break;
835c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  case 1: write_flag = SignalContext::WRITE; break;
836c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  case 8: write_flag = SignalContext::UNKNOWN; break;
837c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  }
838c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  bool is_memory_access = write_flag != SignalContext::UNKNOWN;
839c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return SignalContext(context, access_addr, pc, sp, bp, is_memory_access,
840c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                       write_flag);
8417c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar}
8427c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
843cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainaruptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
844cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  // FIXME: Actually implement this function.
845cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  CHECK_GT(buf_len, 0);
846cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  buf[0] = 0;
847cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  return 0;
848cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar}
849cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
850799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainaruptr ReadLongProcessName(/*out*/char *buf, uptr buf_len) {
851799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  return ReadBinaryName(buf, buf_len);
852799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar}
853799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
854799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid CheckVMASize() {
855799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // Do nothing.
856799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar}
857799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
858c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid MaybeReexec() {
859799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // No need to re-exec on Windows.
860799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar}
861799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
862c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarchar **GetArgv() {
863c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // FIXME: Actually implement this function.
864c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return 0;
865c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
866c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
867c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarpid_t StartSubprocess(const char *program, const char *const argv[],
868c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                      fd_t stdin_fd, fd_t stdout_fd, fd_t stderr_fd) {
869c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // FIXME: implement on this platform
870c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // Should be implemented based on
871c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // SymbolizerProcess::StarAtSymbolizerSubprocess
872c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // from lib/sanitizer_common/sanitizer_symbolizer_win.cc.
873c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return -1;
874799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar}
875799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
876c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarbool IsProcessRunning(pid_t pid) {
877c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // FIXME: implement on this platform.
878c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return false;
879c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
880c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
881c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarint WaitForProcess(pid_t pid) { return -1; }
882c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
883c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov}  // namespace __sanitizer
884c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov
885c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#endif  // _WIN32
886