1 //===-- sanitizer_win.cc --------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is shared between AddressSanitizer and ThreadSanitizer 11 // run-time libraries and implements windows-specific functions from 12 // sanitizer_libc.h. 13 //===----------------------------------------------------------------------===// 14 15 #include "sanitizer_platform.h" 16 #if SANITIZER_WINDOWS 17 18 #define WIN32_LEAN_AND_MEAN 19 #define NOGDI 20 #include <windows.h> 21 #include <dbghelp.h> 22 #include <io.h> 23 #include <psapi.h> 24 #include <stdlib.h> 25 26 #include "sanitizer_common.h" 27 #include "sanitizer_libc.h" 28 #include "sanitizer_mutex.h" 29 #include "sanitizer_placement_new.h" 30 #include "sanitizer_stacktrace.h" 31 32 namespace __sanitizer { 33 34 #include "sanitizer_syscall_generic.inc" 35 36 // --------------------- sanitizer_common.h 37 uptr GetPageSize() { 38 SYSTEM_INFO si; 39 GetSystemInfo(&si); 40 return si.dwPageSize; 41 } 42 43 uptr GetMmapGranularity() { 44 SYSTEM_INFO si; 45 GetSystemInfo(&si); 46 return si.dwAllocationGranularity; 47 } 48 49 uptr GetMaxVirtualAddress() { 50 SYSTEM_INFO si; 51 GetSystemInfo(&si); 52 return (uptr)si.lpMaximumApplicationAddress; 53 } 54 55 bool FileExists(const char *filename) { 56 return ::GetFileAttributesA(filename) != INVALID_FILE_ATTRIBUTES; 57 } 58 59 uptr internal_getpid() { 60 return GetProcessId(GetCurrentProcess()); 61 } 62 63 // In contrast to POSIX, on Windows GetCurrentThreadId() 64 // returns a system-unique identifier. 65 uptr GetTid() { 66 return GetCurrentThreadId(); 67 } 68 69 uptr GetThreadSelf() { 70 return GetTid(); 71 } 72 73 #if !SANITIZER_GO 74 void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, 75 uptr *stack_bottom) { 76 CHECK(stack_top); 77 CHECK(stack_bottom); 78 MEMORY_BASIC_INFORMATION mbi; 79 CHECK_NE(VirtualQuery(&mbi /* on stack */, &mbi, sizeof(mbi)), 0); 80 // FIXME: is it possible for the stack to not be a single allocation? 81 // Are these values what ASan expects to get (reserved, not committed; 82 // including stack guard page) ? 83 *stack_top = (uptr)mbi.BaseAddress + mbi.RegionSize; 84 *stack_bottom = (uptr)mbi.AllocationBase; 85 } 86 #endif // #if !SANITIZER_GO 87 88 void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) { 89 void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 90 if (rv == 0) 91 ReportMmapFailureAndDie(size, mem_type, "allocate", 92 GetLastError(), raw_report); 93 return rv; 94 } 95 96 void UnmapOrDie(void *addr, uptr size) { 97 if (!size || !addr) 98 return; 99 100 MEMORY_BASIC_INFORMATION mbi; 101 CHECK(VirtualQuery(addr, &mbi, sizeof(mbi))); 102 103 // MEM_RELEASE can only be used to unmap whole regions previously mapped with 104 // VirtualAlloc. So we first try MEM_RELEASE since it is better, and if that 105 // fails try MEM_DECOMMIT. 106 if (VirtualFree(addr, 0, MEM_RELEASE) == 0) { 107 if (VirtualFree(addr, size, MEM_DECOMMIT) == 0) { 108 Report("ERROR: %s failed to " 109 "deallocate 0x%zx (%zd) bytes at address %p (error code: %d)\n", 110 SanitizerToolName, size, size, addr, GetLastError()); 111 CHECK("unable to unmap" && 0); 112 } 113 } 114 } 115 116 // We want to map a chunk of address space aligned to 'alignment'. 117 void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type) { 118 CHECK(IsPowerOfTwo(size)); 119 CHECK(IsPowerOfTwo(alignment)); 120 121 // Windows will align our allocations to at least 64K. 122 alignment = Max(alignment, GetMmapGranularity()); 123 124 uptr mapped_addr = 125 (uptr)VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 126 if (!mapped_addr) 127 ReportMmapFailureAndDie(size, mem_type, "allocate aligned", GetLastError()); 128 129 // If we got it right on the first try, return. Otherwise, unmap it and go to 130 // the slow path. 131 if (IsAligned(mapped_addr, alignment)) 132 return (void*)mapped_addr; 133 if (VirtualFree((void *)mapped_addr, 0, MEM_RELEASE) == 0) 134 ReportMmapFailureAndDie(size, mem_type, "deallocate", GetLastError()); 135 136 // If we didn't get an aligned address, overallocate, find an aligned address, 137 // unmap, and try to allocate at that aligned address. 138 int retries = 0; 139 const int kMaxRetries = 10; 140 for (; retries < kMaxRetries && 141 (mapped_addr == 0 || !IsAligned(mapped_addr, alignment)); 142 retries++) { 143 // Overallocate size + alignment bytes. 144 mapped_addr = 145 (uptr)VirtualAlloc(0, size + alignment, MEM_RESERVE, PAGE_NOACCESS); 146 if (!mapped_addr) 147 ReportMmapFailureAndDie(size, mem_type, "allocate aligned", 148 GetLastError()); 149 150 // Find the aligned address. 151 uptr aligned_addr = RoundUpTo(mapped_addr, alignment); 152 153 // Free the overallocation. 154 if (VirtualFree((void *)mapped_addr, 0, MEM_RELEASE) == 0) 155 ReportMmapFailureAndDie(size, mem_type, "deallocate", GetLastError()); 156 157 // Attempt to allocate exactly the number of bytes we need at the aligned 158 // address. This may fail for a number of reasons, in which case we continue 159 // the loop. 160 mapped_addr = (uptr)VirtualAlloc((void *)aligned_addr, size, 161 MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 162 } 163 164 // Fail if we can't make this work quickly. 165 if (retries == kMaxRetries && mapped_addr == 0) 166 ReportMmapFailureAndDie(size, mem_type, "allocate aligned", GetLastError()); 167 168 return (void *)mapped_addr; 169 } 170 171 void *MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) { 172 // FIXME: is this really "NoReserve"? On Win32 this does not matter much, 173 // but on Win64 it does. 174 (void)name; // unsupported 175 #if SANITIZER_WINDOWS64 176 // On Windows64, use MEM_COMMIT would result in error 177 // 1455:ERROR_COMMITMENT_LIMIT. 178 // We use exception handler to commit page on demand. 179 void *p = VirtualAlloc((LPVOID)fixed_addr, size, MEM_RESERVE, PAGE_READWRITE); 180 #else 181 void *p = VirtualAlloc((LPVOID)fixed_addr, size, MEM_RESERVE | MEM_COMMIT, 182 PAGE_READWRITE); 183 #endif 184 if (p == 0) 185 Report("ERROR: %s failed to " 186 "allocate %p (%zd) bytes at %p (error code: %d)\n", 187 SanitizerToolName, size, size, fixed_addr, GetLastError()); 188 return p; 189 } 190 191 // Memory space mapped by 'MmapFixedOrDie' must have been reserved by 192 // 'MmapFixedNoAccess'. 193 void *MmapFixedOrDie(uptr fixed_addr, uptr size) { 194 void *p = VirtualAlloc((LPVOID)fixed_addr, size, 195 MEM_COMMIT, PAGE_READWRITE); 196 if (p == 0) { 197 char mem_type[30]; 198 internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx", 199 fixed_addr); 200 ReportMmapFailureAndDie(size, mem_type, "allocate", GetLastError()); 201 } 202 return p; 203 } 204 205 void *MmapNoReserveOrDie(uptr size, const char *mem_type) { 206 // FIXME: make this really NoReserve? 207 return MmapOrDie(size, mem_type); 208 } 209 210 void *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name) { 211 (void)name; // unsupported 212 void *res = VirtualAlloc((LPVOID)fixed_addr, size, 213 MEM_RESERVE, PAGE_NOACCESS); 214 if (res == 0) 215 Report("WARNING: %s failed to " 216 "mprotect %p (%zd) bytes at %p (error code: %d)\n", 217 SanitizerToolName, size, size, fixed_addr, GetLastError()); 218 return res; 219 } 220 221 void *MmapNoAccess(uptr size) { 222 // FIXME: unsupported. 223 return nullptr; 224 } 225 226 bool MprotectNoAccess(uptr addr, uptr size) { 227 DWORD old_protection; 228 return VirtualProtect((LPVOID)addr, size, PAGE_NOACCESS, &old_protection); 229 } 230 231 232 void FlushUnneededShadowMemory(uptr addr, uptr size) { 233 // This is almost useless on 32-bits. 234 // FIXME: add madvise-analog when we move to 64-bits. 235 } 236 237 void NoHugePagesInRegion(uptr addr, uptr size) { 238 // FIXME: probably similar to FlushUnneededShadowMemory. 239 } 240 241 void DontDumpShadowMemory(uptr addr, uptr length) { 242 // This is almost useless on 32-bits. 243 // FIXME: add madvise-analog when we move to 64-bits. 244 } 245 246 bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) { 247 MEMORY_BASIC_INFORMATION mbi; 248 CHECK(VirtualQuery((void *)range_start, &mbi, sizeof(mbi))); 249 return mbi.Protect == PAGE_NOACCESS && 250 (uptr)mbi.BaseAddress + mbi.RegionSize >= range_end; 251 } 252 253 void *MapFileToMemory(const char *file_name, uptr *buff_size) { 254 UNIMPLEMENTED(); 255 } 256 257 void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, OFF_T offset) { 258 UNIMPLEMENTED(); 259 } 260 261 static const int kMaxEnvNameLength = 128; 262 static const DWORD kMaxEnvValueLength = 32767; 263 264 namespace { 265 266 struct EnvVariable { 267 char name[kMaxEnvNameLength]; 268 char value[kMaxEnvValueLength]; 269 }; 270 271 } // namespace 272 273 static const int kEnvVariables = 5; 274 static EnvVariable env_vars[kEnvVariables]; 275 static int num_env_vars; 276 277 const char *GetEnv(const char *name) { 278 // Note: this implementation caches the values of the environment variables 279 // and limits their quantity. 280 for (int i = 0; i < num_env_vars; i++) { 281 if (0 == internal_strcmp(name, env_vars[i].name)) 282 return env_vars[i].value; 283 } 284 CHECK_LT(num_env_vars, kEnvVariables); 285 DWORD rv = GetEnvironmentVariableA(name, env_vars[num_env_vars].value, 286 kMaxEnvValueLength); 287 if (rv > 0 && rv < kMaxEnvValueLength) { 288 CHECK_LT(internal_strlen(name), kMaxEnvNameLength); 289 internal_strncpy(env_vars[num_env_vars].name, name, kMaxEnvNameLength); 290 num_env_vars++; 291 return env_vars[num_env_vars - 1].value; 292 } 293 return 0; 294 } 295 296 const char *GetPwd() { 297 UNIMPLEMENTED(); 298 } 299 300 u32 GetUid() { 301 UNIMPLEMENTED(); 302 } 303 304 namespace { 305 struct ModuleInfo { 306 const char *filepath; 307 uptr base_address; 308 uptr end_address; 309 }; 310 311 #ifndef SANITIZER_GO 312 int CompareModulesBase(const void *pl, const void *pr) { 313 const ModuleInfo *l = (ModuleInfo *)pl, *r = (ModuleInfo *)pr; 314 if (l->base_address < r->base_address) 315 return -1; 316 return l->base_address > r->base_address; 317 } 318 #endif 319 } // namespace 320 321 #ifndef SANITIZER_GO 322 void DumpProcessMap() { 323 Report("Dumping process modules:\n"); 324 ListOfModules modules; 325 modules.init(); 326 uptr num_modules = modules.size(); 327 328 InternalScopedBuffer<ModuleInfo> module_infos(num_modules); 329 for (size_t i = 0; i < num_modules; ++i) { 330 module_infos[i].filepath = modules[i].full_name(); 331 module_infos[i].base_address = modules[i].base_address(); 332 module_infos[i].end_address = modules[i].ranges().front()->end; 333 } 334 qsort(module_infos.data(), num_modules, sizeof(ModuleInfo), 335 CompareModulesBase); 336 337 for (size_t i = 0; i < num_modules; ++i) { 338 const ModuleInfo &mi = module_infos[i]; 339 if (mi.end_address != 0) { 340 Printf("\t%p-%p %s\n", mi.base_address, mi.end_address, 341 mi.filepath[0] ? mi.filepath : "[no name]"); 342 } else if (mi.filepath[0]) { 343 Printf("\t??\?-??? %s\n", mi.filepath); 344 } else { 345 Printf("\t???\n"); 346 } 347 } 348 } 349 #endif 350 351 void DisableCoreDumperIfNecessary() { 352 // Do nothing. 353 } 354 355 void ReExec() { 356 UNIMPLEMENTED(); 357 } 358 359 void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) { 360 #if !SANITIZER_GO 361 CovPrepareForSandboxing(args); 362 #endif 363 } 364 365 bool StackSizeIsUnlimited() { 366 UNIMPLEMENTED(); 367 } 368 369 void SetStackSizeLimitInBytes(uptr limit) { 370 UNIMPLEMENTED(); 371 } 372 373 bool AddressSpaceIsUnlimited() { 374 UNIMPLEMENTED(); 375 } 376 377 void SetAddressSpaceUnlimited() { 378 UNIMPLEMENTED(); 379 } 380 381 bool IsPathSeparator(const char c) { 382 return c == '\\' || c == '/'; 383 } 384 385 bool IsAbsolutePath(const char *path) { 386 UNIMPLEMENTED(); 387 } 388 389 void SleepForSeconds(int seconds) { 390 Sleep(seconds * 1000); 391 } 392 393 void SleepForMillis(int millis) { 394 Sleep(millis); 395 } 396 397 u64 NanoTime() { 398 return 0; 399 } 400 401 void Abort() { 402 if (::IsDebuggerPresent()) 403 __debugbreak(); 404 internal__exit(3); 405 } 406 407 #ifndef SANITIZER_GO 408 // Read the file to extract the ImageBase field from the PE header. If ASLR is 409 // disabled and this virtual address is available, the loader will typically 410 // load the image at this address. Therefore, we call it the preferred base. Any 411 // addresses in the DWARF typically assume that the object has been loaded at 412 // this address. 413 static uptr GetPreferredBase(const char *modname) { 414 fd_t fd = OpenFile(modname, RdOnly, nullptr); 415 if (fd == kInvalidFd) 416 return 0; 417 FileCloser closer(fd); 418 419 // Read just the DOS header. 420 IMAGE_DOS_HEADER dos_header; 421 uptr bytes_read; 422 if (!ReadFromFile(fd, &dos_header, sizeof(dos_header), &bytes_read) || 423 bytes_read != sizeof(dos_header)) 424 return 0; 425 426 // The file should start with the right signature. 427 if (dos_header.e_magic != IMAGE_DOS_SIGNATURE) 428 return 0; 429 430 // The layout at e_lfanew is: 431 // "PE\0\0" 432 // IMAGE_FILE_HEADER 433 // IMAGE_OPTIONAL_HEADER 434 // Seek to e_lfanew and read all that data. 435 char buf[4 + sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER)]; 436 if (::SetFilePointer(fd, dos_header.e_lfanew, nullptr, FILE_BEGIN) == 437 INVALID_SET_FILE_POINTER) 438 return 0; 439 if (!ReadFromFile(fd, &buf[0], sizeof(buf), &bytes_read) || 440 bytes_read != sizeof(buf)) 441 return 0; 442 443 // Check for "PE\0\0" before the PE header. 444 char *pe_sig = &buf[0]; 445 if (internal_memcmp(pe_sig, "PE\0\0", 4) != 0) 446 return 0; 447 448 // Skip over IMAGE_FILE_HEADER. We could do more validation here if we wanted. 449 IMAGE_OPTIONAL_HEADER *pe_header = 450 (IMAGE_OPTIONAL_HEADER *)(pe_sig + 4 + sizeof(IMAGE_FILE_HEADER)); 451 452 // Check for more magic in the PE header. 453 if (pe_header->Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC) 454 return 0; 455 456 // Finally, return the ImageBase. 457 return (uptr)pe_header->ImageBase; 458 } 459 460 void ListOfModules::init() { 461 clear(); 462 HANDLE cur_process = GetCurrentProcess(); 463 464 // Query the list of modules. Start by assuming there are no more than 256 465 // modules and retry if that's not sufficient. 466 HMODULE *hmodules = 0; 467 uptr modules_buffer_size = sizeof(HMODULE) * 256; 468 DWORD bytes_required; 469 while (!hmodules) { 470 hmodules = (HMODULE *)MmapOrDie(modules_buffer_size, __FUNCTION__); 471 CHECK(EnumProcessModules(cur_process, hmodules, modules_buffer_size, 472 &bytes_required)); 473 if (bytes_required > modules_buffer_size) { 474 // Either there turned out to be more than 256 hmodules, or new hmodules 475 // could have loaded since the last try. Retry. 476 UnmapOrDie(hmodules, modules_buffer_size); 477 hmodules = 0; 478 modules_buffer_size = bytes_required; 479 } 480 } 481 482 // |num_modules| is the number of modules actually present, 483 size_t num_modules = bytes_required / sizeof(HMODULE); 484 for (size_t i = 0; i < num_modules; ++i) { 485 HMODULE handle = hmodules[i]; 486 MODULEINFO mi; 487 if (!GetModuleInformation(cur_process, handle, &mi, sizeof(mi))) 488 continue; 489 490 // Get the UTF-16 path and convert to UTF-8. 491 wchar_t modname_utf16[kMaxPathLength]; 492 int modname_utf16_len = 493 GetModuleFileNameW(handle, modname_utf16, kMaxPathLength); 494 if (modname_utf16_len == 0) 495 modname_utf16[0] = '\0'; 496 char module_name[kMaxPathLength]; 497 int module_name_len = 498 ::WideCharToMultiByte(CP_UTF8, 0, modname_utf16, modname_utf16_len + 1, 499 &module_name[0], kMaxPathLength, NULL, NULL); 500 module_name[module_name_len] = '\0'; 501 502 uptr base_address = (uptr)mi.lpBaseOfDll; 503 uptr end_address = (uptr)mi.lpBaseOfDll + mi.SizeOfImage; 504 505 // Adjust the base address of the module so that we get a VA instead of an 506 // RVA when computing the module offset. This helps llvm-symbolizer find the 507 // right DWARF CU. In the common case that the image is loaded at it's 508 // preferred address, we will now print normal virtual addresses. 509 uptr preferred_base = GetPreferredBase(&module_name[0]); 510 uptr adjusted_base = base_address - preferred_base; 511 512 LoadedModule cur_module; 513 cur_module.set(module_name, adjusted_base); 514 // We add the whole module as one single address range. 515 cur_module.addAddressRange(base_address, end_address, /*executable*/ true); 516 modules_.push_back(cur_module); 517 } 518 UnmapOrDie(hmodules, modules_buffer_size); 519 }; 520 521 // We can't use atexit() directly at __asan_init time as the CRT is not fully 522 // initialized at this point. Place the functions into a vector and use 523 // atexit() as soon as it is ready for use (i.e. after .CRT$XIC initializers). 524 InternalMmapVectorNoCtor<void (*)(void)> atexit_functions; 525 526 int Atexit(void (*function)(void)) { 527 atexit_functions.push_back(function); 528 return 0; 529 } 530 531 static int RunAtexit() { 532 int ret = 0; 533 for (uptr i = 0; i < atexit_functions.size(); ++i) { 534 ret |= atexit(atexit_functions[i]); 535 } 536 return ret; 537 } 538 539 #pragma section(".CRT$XID", long, read) // NOLINT 540 __declspec(allocate(".CRT$XID")) int (*__run_atexit)() = RunAtexit; 541 #endif 542 543 // ------------------ sanitizer_libc.h 544 fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *last_error) { 545 // FIXME: Use the wide variants to handle Unicode filenames. 546 fd_t res; 547 if (mode == RdOnly) { 548 res = CreateFileA(filename, GENERIC_READ, 549 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 550 nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); 551 } else if (mode == WrOnly) { 552 res = CreateFileA(filename, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 553 FILE_ATTRIBUTE_NORMAL, nullptr); 554 } else { 555 UNIMPLEMENTED(); 556 } 557 CHECK(res != kStdoutFd || kStdoutFd == kInvalidFd); 558 CHECK(res != kStderrFd || kStderrFd == kInvalidFd); 559 if (res == kInvalidFd && last_error) 560 *last_error = GetLastError(); 561 return res; 562 } 563 564 void CloseFile(fd_t fd) { 565 CloseHandle(fd); 566 } 567 568 bool ReadFromFile(fd_t fd, void *buff, uptr buff_size, uptr *bytes_read, 569 error_t *error_p) { 570 CHECK(fd != kInvalidFd); 571 572 // bytes_read can't be passed directly to ReadFile: 573 // uptr is unsigned long long on 64-bit Windows. 574 unsigned long num_read_long; 575 576 bool success = ::ReadFile(fd, buff, buff_size, &num_read_long, nullptr); 577 if (!success && error_p) 578 *error_p = GetLastError(); 579 if (bytes_read) 580 *bytes_read = num_read_long; 581 return success; 582 } 583 584 bool SupportsColoredOutput(fd_t fd) { 585 // FIXME: support colored output. 586 return false; 587 } 588 589 bool WriteToFile(fd_t fd, const void *buff, uptr buff_size, uptr *bytes_written, 590 error_t *error_p) { 591 CHECK(fd != kInvalidFd); 592 593 // Handle null optional parameters. 594 error_t dummy_error; 595 error_p = error_p ? error_p : &dummy_error; 596 uptr dummy_bytes_written; 597 bytes_written = bytes_written ? bytes_written : &dummy_bytes_written; 598 599 // Initialize output parameters in case we fail. 600 *error_p = 0; 601 *bytes_written = 0; 602 603 // Map the conventional Unix fds 1 and 2 to Windows handles. They might be 604 // closed, in which case this will fail. 605 if (fd == kStdoutFd || fd == kStderrFd) { 606 fd = GetStdHandle(fd == kStdoutFd ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE); 607 if (fd == 0) { 608 *error_p = ERROR_INVALID_HANDLE; 609 return false; 610 } 611 } 612 613 DWORD bytes_written_32; 614 if (!WriteFile(fd, buff, buff_size, &bytes_written_32, 0)) { 615 *error_p = GetLastError(); 616 return false; 617 } else { 618 *bytes_written = bytes_written_32; 619 return true; 620 } 621 } 622 623 bool RenameFile(const char *oldpath, const char *newpath, error_t *error_p) { 624 UNIMPLEMENTED(); 625 } 626 627 uptr internal_sched_yield() { 628 Sleep(0); 629 return 0; 630 } 631 632 void internal__exit(int exitcode) { 633 ExitProcess(exitcode); 634 } 635 636 uptr internal_ftruncate(fd_t fd, uptr size) { 637 UNIMPLEMENTED(); 638 } 639 640 uptr GetRSS() { 641 return 0; 642 } 643 644 void *internal_start_thread(void (*func)(void *arg), void *arg) { return 0; } 645 void internal_join_thread(void *th) { } 646 647 // ---------------------- BlockingMutex ---------------- {{{1 648 const uptr LOCK_UNINITIALIZED = 0; 649 const uptr LOCK_READY = (uptr)-1; 650 651 BlockingMutex::BlockingMutex(LinkerInitialized li) { 652 // FIXME: see comments in BlockingMutex::Lock() for the details. 653 CHECK(li == LINKER_INITIALIZED || owner_ == LOCK_UNINITIALIZED); 654 655 CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_)); 656 InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 657 owner_ = LOCK_READY; 658 } 659 660 BlockingMutex::BlockingMutex() { 661 CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_)); 662 InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 663 owner_ = LOCK_READY; 664 } 665 666 void BlockingMutex::Lock() { 667 if (owner_ == LOCK_UNINITIALIZED) { 668 // FIXME: hm, global BlockingMutex objects are not initialized?!? 669 // This might be a side effect of the clang+cl+link Frankenbuild... 670 new(this) BlockingMutex((LinkerInitialized)(LINKER_INITIALIZED + 1)); 671 672 // FIXME: If it turns out the linker doesn't invoke our 673 // constructors, we should probably manually Lock/Unlock all the global 674 // locks while we're starting in one thread to avoid double-init races. 675 } 676 EnterCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 677 CHECK_EQ(owner_, LOCK_READY); 678 owner_ = GetThreadSelf(); 679 } 680 681 void BlockingMutex::Unlock() { 682 CHECK_EQ(owner_, GetThreadSelf()); 683 owner_ = LOCK_READY; 684 LeaveCriticalSection((LPCRITICAL_SECTION)opaque_storage_); 685 } 686 687 void BlockingMutex::CheckLocked() { 688 CHECK_EQ(owner_, GetThreadSelf()); 689 } 690 691 uptr GetTlsSize() { 692 return 0; 693 } 694 695 void InitTlsSize() { 696 } 697 698 void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, 699 uptr *tls_addr, uptr *tls_size) { 700 #ifdef SANITIZER_GO 701 *stk_addr = 0; 702 *stk_size = 0; 703 *tls_addr = 0; 704 *tls_size = 0; 705 #else 706 uptr stack_top, stack_bottom; 707 GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom); 708 *stk_addr = stack_bottom; 709 *stk_size = stack_top - stack_bottom; 710 *tls_addr = 0; 711 *tls_size = 0; 712 #endif 713 } 714 715 #if !SANITIZER_GO 716 void BufferedStackTrace::SlowUnwindStack(uptr pc, u32 max_depth) { 717 CHECK_GE(max_depth, 2); 718 // FIXME: CaptureStackBackTrace might be too slow for us. 719 // FIXME: Compare with StackWalk64. 720 // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc 721 size = CaptureStackBackTrace(2, Min(max_depth, kStackTraceMax), 722 (void**)trace, 0); 723 if (size == 0) 724 return; 725 726 // Skip the RTL frames by searching for the PC in the stacktrace. 727 uptr pc_location = LocatePcInTrace(pc); 728 PopStackFrames(pc_location); 729 } 730 731 void BufferedStackTrace::SlowUnwindStackWithContext(uptr pc, void *context, 732 u32 max_depth) { 733 CONTEXT ctx = *(CONTEXT *)context; 734 STACKFRAME64 stack_frame; 735 memset(&stack_frame, 0, sizeof(stack_frame)); 736 size = 0; 737 #if defined(_WIN64) 738 int machine_type = IMAGE_FILE_MACHINE_AMD64; 739 stack_frame.AddrPC.Offset = ctx.Rip; 740 stack_frame.AddrFrame.Offset = ctx.Rbp; 741 stack_frame.AddrStack.Offset = ctx.Rsp; 742 #else 743 int machine_type = IMAGE_FILE_MACHINE_I386; 744 stack_frame.AddrPC.Offset = ctx.Eip; 745 stack_frame.AddrFrame.Offset = ctx.Ebp; 746 stack_frame.AddrStack.Offset = ctx.Esp; 747 #endif 748 stack_frame.AddrPC.Mode = AddrModeFlat; 749 stack_frame.AddrFrame.Mode = AddrModeFlat; 750 stack_frame.AddrStack.Mode = AddrModeFlat; 751 while (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(), 752 &stack_frame, &ctx, NULL, &SymFunctionTableAccess64, 753 &SymGetModuleBase64, NULL) && 754 size < Min(max_depth, kStackTraceMax)) { 755 trace_buffer[size++] = (uptr)stack_frame.AddrPC.Offset; 756 } 757 } 758 #endif // #if !SANITIZER_GO 759 760 void ReportFile::Write(const char *buffer, uptr length) { 761 SpinMutexLock l(mu); 762 ReopenIfNecessary(); 763 if (!WriteToFile(fd, buffer, length)) { 764 // stderr may be closed, but we may be able to print to the debugger 765 // instead. This is the case when launching a program from Visual Studio, 766 // and the following routine should write to its console. 767 OutputDebugStringA(buffer); 768 } 769 } 770 771 void SetAlternateSignalStack() { 772 // FIXME: Decide what to do on Windows. 773 } 774 775 void UnsetAlternateSignalStack() { 776 // FIXME: Decide what to do on Windows. 777 } 778 779 void InstallDeadlySignalHandlers(SignalHandlerType handler) { 780 (void)handler; 781 // FIXME: Decide what to do on Windows. 782 } 783 784 bool IsHandledDeadlySignal(int signum) { 785 // FIXME: Decide what to do on Windows. 786 return false; 787 } 788 789 bool IsAccessibleMemoryRange(uptr beg, uptr size) { 790 SYSTEM_INFO si; 791 GetNativeSystemInfo(&si); 792 uptr page_size = si.dwPageSize; 793 uptr page_mask = ~(page_size - 1); 794 795 for (uptr page = beg & page_mask, end = (beg + size - 1) & page_mask; 796 page <= end;) { 797 MEMORY_BASIC_INFORMATION info; 798 if (VirtualQuery((LPCVOID)page, &info, sizeof(info)) != sizeof(info)) 799 return false; 800 801 if (info.Protect == 0 || info.Protect == PAGE_NOACCESS || 802 info.Protect == PAGE_EXECUTE) 803 return false; 804 805 if (info.RegionSize == 0) 806 return false; 807 808 page += info.RegionSize; 809 } 810 811 return true; 812 } 813 814 SignalContext SignalContext::Create(void *siginfo, void *context) { 815 EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo; 816 CONTEXT *context_record = (CONTEXT *)context; 817 818 uptr pc = (uptr)exception_record->ExceptionAddress; 819 #ifdef _WIN64 820 uptr bp = (uptr)context_record->Rbp; 821 uptr sp = (uptr)context_record->Rsp; 822 #else 823 uptr bp = (uptr)context_record->Ebp; 824 uptr sp = (uptr)context_record->Esp; 825 #endif 826 uptr access_addr = exception_record->ExceptionInformation[1]; 827 828 // The contents of this array are documented at 829 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363082(v=vs.85).aspx 830 // The first element indicates read as 0, write as 1, or execute as 8. The 831 // second element is the faulting address. 832 WriteFlag write_flag = SignalContext::UNKNOWN; 833 switch (exception_record->ExceptionInformation[0]) { 834 case 0: write_flag = SignalContext::READ; break; 835 case 1: write_flag = SignalContext::WRITE; break; 836 case 8: write_flag = SignalContext::UNKNOWN; break; 837 } 838 bool is_memory_access = write_flag != SignalContext::UNKNOWN; 839 return SignalContext(context, access_addr, pc, sp, bp, is_memory_access, 840 write_flag); 841 } 842 843 uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { 844 // FIXME: Actually implement this function. 845 CHECK_GT(buf_len, 0); 846 buf[0] = 0; 847 return 0; 848 } 849 850 uptr ReadLongProcessName(/*out*/char *buf, uptr buf_len) { 851 return ReadBinaryName(buf, buf_len); 852 } 853 854 void CheckVMASize() { 855 // Do nothing. 856 } 857 858 void MaybeReexec() { 859 // No need to re-exec on Windows. 860 } 861 862 char **GetArgv() { 863 // FIXME: Actually implement this function. 864 return 0; 865 } 866 867 pid_t StartSubprocess(const char *program, const char *const argv[], 868 fd_t stdin_fd, fd_t stdout_fd, fd_t stderr_fd) { 869 // FIXME: implement on this platform 870 // Should be implemented based on 871 // SymbolizerProcess::StarAtSymbolizerSubprocess 872 // from lib/sanitizer_common/sanitizer_symbolizer_win.cc. 873 return -1; 874 } 875 876 bool IsProcessRunning(pid_t pid) { 877 // FIXME: implement on this platform. 878 return false; 879 } 880 881 int WaitForProcess(pid_t pid) { return -1; } 882 883 } // namespace __sanitizer 884 885 #endif // _WIN32 886