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