sanitizer_win.cc revision 1dcd1d9d1c86ab9b728386d261fbebe00b32e097
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===-- sanitizer_win.cc --------------------------------------------------===// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This file is shared between AddressSanitizer and ThreadSanitizer 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// run-time libraries and implements windows-specific functions from 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sanitizer_libc.h. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sanitizer_platform.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SANITIZER_WINDOWS 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define WIN32_LEAN_AND_MEAN 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NOGDI 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <io.h> 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sanitizer_common.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sanitizer_libc.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sanitizer_mutex.h" 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sanitizer_placement_new.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sanitizer_stacktrace.h" 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace __sanitizer { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sanitizer_syscall_generic.inc" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --------------------- sanitizer_common.h 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uptr GetPageSize() { 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return 1U << 14; // FIXME: is this configurable? 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uptr GetMmapGranularity() { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1U << 16; // FIXME: is this configurable? 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uptr GetMaxVirtualAddress() { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SYSTEM_INFO si; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetSystemInfo(&si); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (uptr)si.lpMaximumApplicationAddress; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FileExists(const char *filename) { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNIMPLEMENTED(); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uptr internal_getpid() { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetProcessId(GetCurrentProcess()); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In contrast to POSIX, on Windows GetCurrentThreadId() 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// returns a system-unique identifier. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uptr GetTid() { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetCurrentThreadId(); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uptr GetThreadSelf() { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetTid(); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uptr *stack_bottom) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(stack_top); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(stack_bottom); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MEMORY_BASIC_INFORMATION mbi; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_NE(VirtualQuery(&mbi /* on stack */, &mbi, sizeof(mbi)), 0); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: is it possible for the stack to not be a single allocation? 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Are these values what ASan expects to get (reserved, not committed; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // including stack guard page) ? 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *stack_top = (uptr)mbi.BaseAddress + mbi.RegionSize; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *stack_bottom = (uptr)mbi.AllocationBase; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void *MmapOrDie(uptr size, const char *mem_type) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == 0) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Report("ERROR: Failed to allocate 0x%zx (%zd) bytes of %s\n", 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size, size, mem_type); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK("unable to mmap" && 0); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UnmapOrDie(void *addr, uptr size) { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (VirtualFree(addr, size, MEM_DECOMMIT) == 0) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Report("ERROR: Failed to deallocate 0x%zx (%zd) bytes at address %p\n", 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size, size, addr); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK("unable to unmap" && 0); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void *MmapFixedNoReserve(uptr fixed_addr, uptr size) { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: is this really "NoReserve"? On Win32 this does not matter much, 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // but on Win64 it does. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *p = VirtualAlloc((LPVOID)fixed_addr, size, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p == 0) 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Report("ERROR: Failed to allocate 0x%zx (%zd) bytes at %p (%d)\n", 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size, size, fixed_addr, GetLastError()); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void *MmapFixedOrDie(uptr fixed_addr, uptr size) { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MmapFixedNoReserve(fixed_addr, size); 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void *Mprotect(uptr fixed_addr, uptr size) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return VirtualAlloc((LPVOID)fixed_addr, size, 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FlushUnneededShadowMemory(uptr addr, uptr size) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is almost useless on 32-bits. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: add madvice-analog when we move to 64-bits. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: shall we do anything here on Windows? 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void *MapFileToMemory(const char *file_name, uptr *buff_size) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNIMPLEMENTED(); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMaxEnvNameLength = 128; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const DWORD kMaxEnvValueLength = 32767; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct EnvVariable { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char name[kMaxEnvNameLength]; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char value[kMaxEnvValueLength]; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kEnvVariables = 5; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static EnvVariable env_vars[kEnvVariables]; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int num_env_vars; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char *GetEnv(const char *name) { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: this implementation caches the values of the environment variables 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and limits their quantity. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < num_env_vars; i++) { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0 == internal_strcmp(name, env_vars[i].name)) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return env_vars[i].value; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LT(num_env_vars, kEnvVariables); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD rv = GetEnvironmentVariableA(name, env_vars[num_env_vars].value, 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMaxEnvValueLength); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv > 0 && rv < kMaxEnvValueLength) { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LT(internal_strlen(name), kMaxEnvNameLength); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) internal_strncpy(env_vars[num_env_vars].name, name, kMaxEnvNameLength); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_env_vars++; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return env_vars[num_env_vars - 1].value; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char *GetPwd() { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNIMPLEMENTED(); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)u32 GetUid() { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNIMPLEMENTED(); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DumpProcessMap() { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNIMPLEMENTED(); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisableCoreDumper() { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNIMPLEMENTED(); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReExec() { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNIMPLEMENTED(); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrepareForSandboxing() { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Nothing here for now. 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool StackSizeIsUnlimited() { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNIMPLEMENTED(); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetStackSizeLimitInBytes(uptr limit) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNIMPLEMENTED(); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 198 199char *FindPathToBinary(const char *name) { 200 UNIMPLEMENTED(); 201} 202 203void SleepForSeconds(int seconds) { 204 Sleep(seconds * 1000); 205} 206 207void SleepForMillis(int millis) { 208 Sleep(millis); 209} 210 211u64 NanoTime() { 212 return 0; 213} 214 215void Abort() { 216 abort(); 217 _exit(-1); // abort is not NORETURN on Windows. 218} 219 220#ifndef SANITIZER_GO 221int Atexit(void (*function)(void)) { 222 return atexit(function); 223} 224#endif 225 226// ------------------ sanitizer_libc.h 227uptr internal_mmap(void *addr, uptr length, int prot, int flags, 228 int fd, u64 offset) { 229 UNIMPLEMENTED(); 230} 231 232uptr internal_munmap(void *addr, uptr length) { 233 UNIMPLEMENTED(); 234} 235 236uptr internal_close(fd_t fd) { 237 UNIMPLEMENTED(); 238} 239 240int internal_isatty(fd_t fd) { 241 return _isatty(fd); 242} 243 244uptr internal_open(const char *filename, int flags) { 245 UNIMPLEMENTED(); 246} 247 248uptr internal_open(const char *filename, int flags, u32 mode) { 249 UNIMPLEMENTED(); 250} 251 252uptr OpenFile(const char *filename, bool write) { 253 UNIMPLEMENTED(); 254} 255 256uptr internal_read(fd_t fd, void *buf, uptr count) { 257 UNIMPLEMENTED(); 258} 259 260uptr internal_write(fd_t fd, const void *buf, uptr count) { 261 if (fd != kStderrFd) 262 UNIMPLEMENTED(); 263 HANDLE err = GetStdHandle(STD_ERROR_HANDLE); 264 if (err == 0) 265 return 0; // FIXME: this might not work on some apps. 266 DWORD ret; 267 if (!WriteFile(err, buf, count, &ret, 0)) 268 return 0; 269 return ret; 270} 271 272uptr internal_stat(const char *path, void *buf) { 273 UNIMPLEMENTED(); 274} 275 276uptr internal_lstat(const char *path, void *buf) { 277 UNIMPLEMENTED(); 278} 279 280uptr internal_fstat(fd_t fd, void *buf) { 281 UNIMPLEMENTED(); 282} 283 284uptr internal_filesize(fd_t fd) { 285 UNIMPLEMENTED(); 286} 287 288uptr internal_dup2(int oldfd, int newfd) { 289 UNIMPLEMENTED(); 290} 291 292uptr internal_readlink(const char *path, char *buf, uptr bufsize) { 293 UNIMPLEMENTED(); 294} 295 296uptr internal_sched_yield() { 297 Sleep(0); 298 return 0; 299} 300 301void internal__exit(int exitcode) { 302 _exit(exitcode); 303} 304 305// ---------------------- BlockingMutex ---------------- {{{1 306const uptr LOCK_UNINITIALIZED = 0; 307const uptr LOCK_READY = (uptr)-1; 308 309BlockingMutex::BlockingMutex(LinkerInitialized li) { 310 // FIXME: see comments in BlockingMutex::Lock() for the details. 311 CHECK(li == LINKER_INITIALIZED || owner_ == LOCK_UNINITIALIZED); 312 313 CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_)); 314 InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 315 owner_ = LOCK_READY; 316} 317 318BlockingMutex::BlockingMutex() { 319 CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_)); 320 InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 321 owner_ = LOCK_READY; 322} 323 324void BlockingMutex::Lock() { 325 if (owner_ == LOCK_UNINITIALIZED) { 326 // FIXME: hm, global BlockingMutex objects are not initialized?!? 327 // This might be a side effect of the clang+cl+link Frankenbuild... 328 new(this) BlockingMutex((LinkerInitialized)(LINKER_INITIALIZED + 1)); 329 330 // FIXME: If it turns out the linker doesn't invoke our 331 // constructors, we should probably manually Lock/Unlock all the global 332 // locks while we're starting in one thread to avoid double-init races. 333 } 334 EnterCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 335 CHECK_EQ(owner_, LOCK_READY); 336 owner_ = GetThreadSelf(); 337} 338 339void BlockingMutex::Unlock() { 340 CHECK_EQ(owner_, GetThreadSelf()); 341 owner_ = LOCK_READY; 342 LeaveCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 343} 344 345void BlockingMutex::CheckLocked() { 346 CHECK_EQ(owner_, GetThreadSelf()); 347} 348 349uptr GetTlsSize() { 350 return 0; 351} 352 353void InitTlsSize() { 354} 355 356void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, 357 uptr *tls_addr, uptr *tls_size) { 358#ifdef SANITIZER_GO 359 *stk_addr = 0; 360 *stk_size = 0; 361 *tls_addr = 0; 362 *tls_size = 0; 363#else 364 uptr stack_top, stack_bottom; 365 GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom); 366 *stk_addr = stack_bottom; 367 *stk_size = stack_top - stack_bottom; 368 *tls_addr = 0; 369 *tls_size = 0; 370#endif 371} 372 373void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, 374 uptr stack_top, uptr stack_bottom, bool fast) { 375 (void)fast; 376 (void)stack_top; 377 (void)stack_bottom; 378 stack->max_size = max_s; 379 void *tmp[kStackTraceMax]; 380 381 // FIXME: CaptureStackBackTrace might be too slow for us. 382 // FIXME: Compare with StackWalk64. 383 // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc 384 uptr cs_ret = CaptureStackBackTrace(1, stack->max_size, tmp, 0); 385 uptr offset = 0; 386 // Skip the RTL frames by searching for the PC in the stacktrace. 387 // FIXME: this doesn't work well for the malloc/free stacks yet. 388 for (uptr i = 0; i < cs_ret; i++) { 389 if (pc != (uptr)tmp[i]) 390 continue; 391 offset = i; 392 break; 393 } 394 395 stack->size = cs_ret - offset; 396 for (uptr i = 0; i < stack->size; i++) 397 stack->trace[i] = (uptr)tmp[i + offset]; 398} 399 400} // namespace __sanitizer 401 402#endif // _WIN32 403