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