13 #ifdef MINGW_HAS_SECURE_API 14 #undef MINGW_HAS_SECURE_API 15 #endif // MINGW_HAS_SECURE_API 20 #include "src/base/win32-headers.h" 22 #include "src/base/bits.h" 23 #include "src/base/lazy-instance.h" 24 #include "src/base/macros.h" 25 #include "src/base/platform/platform.h" 26 #include "src/base/platform/time.h" 27 #include "src/base/timezone-cache.h" 28 #include "src/base/utils/random-number-generator.h" 30 #include <VersionHelpers.h> 34 #endif // defined(_MSC_VER) 41 #ifndef __MINGW64_VERSION_MAJOR 46 inline void MemoryFence() {
48 __asm__ __volatile__(
"xchgl %%eax,%0 ":
"=r" (barrier));
51 #endif // __MINGW64_VERSION_MAJOR 54 int localtime_s(tm* out_tm,
const time_t* time) {
55 tm* posix_local_time_struct = localtime_r(time, out_tm);
56 if (posix_local_time_struct ==
nullptr)
return 1;
61 int fopen_s(FILE** pFile,
const char* filename,
const char* mode) {
62 *pFile = fopen(filename, mode);
63 return *pFile !=
nullptr ? 0 : 1;
66 int _vsnprintf_s(
char* buffer,
size_t sizeOfBuffer,
size_t count,
67 const char* format, va_list argptr) {
68 DCHECK(count == _TRUNCATE);
69 return _vsnprintf(buffer, sizeOfBuffer, format, argptr);
73 int strncpy_s(
char* dest,
size_t dest_size,
const char* source,
size_t count) {
74 CHECK(source !=
nullptr);
75 CHECK(dest !=
nullptr);
76 CHECK_GT(dest_size, 0);
78 if (count == _TRUNCATE) {
79 while (dest_size > 0 && *source != 0) {
80 *(dest++) = *(source++);
88 while (dest_size > 0 && count > 0 && *source != 0) {
89 *(dest++) = *(source++);
94 CHECK_GT(dest_size, 0);
106 bool g_hard_abort =
false;
116 void Clear()
override { initialized_ =
false; }
118 const char* LocalTimezone(
double time)
override;
120 double LocalTimeOffset(
double time,
bool is_utc)
override;
122 double DaylightSavingsOffset(
double time)
override;
126 void InitializeIfNeeded() {
128 if (initialized_)
return;
133 memset(&tzinfo_, 0,
sizeof(tzinfo_));
134 if (GetTimeZoneInformation(&tzinfo_) == TIME_ZONE_ID_INVALID) {
137 tzinfo_.StandardDate.wMonth = 10;
138 tzinfo_.StandardDate.wDay = 5;
139 tzinfo_.StandardDate.wHour = 3;
140 tzinfo_.StandardBias = 0;
141 tzinfo_.DaylightDate.wMonth = 3;
142 tzinfo_.DaylightDate.wDay = 5;
143 tzinfo_.DaylightDate.wHour = 2;
144 tzinfo_.DaylightBias = -60;
148 WideCharToMultiByte(CP_UTF8, 0, tzinfo_.StandardName, -1, std_tz_name_,
149 kTzNameSize,
nullptr,
nullptr);
150 std_tz_name_[kTzNameSize - 1] =
'\0';
151 WideCharToMultiByte(CP_UTF8, 0, tzinfo_.DaylightName, -1, dst_tz_name_,
152 kTzNameSize,
nullptr,
nullptr);
153 dst_tz_name_[kTzNameSize - 1] =
'\0';
159 if (std_tz_name_[0] ==
'\0' || std_tz_name_[0] ==
'@') {
160 OS::SNPrintF(std_tz_name_, kTzNameSize - 1,
162 GuessTimezoneNameFromBias(tzinfo_.Bias));
164 if (dst_tz_name_[0] ==
'\0' || dst_tz_name_[0] ==
'@') {
165 OS::SNPrintF(dst_tz_name_, kTzNameSize - 1,
167 GuessTimezoneNameFromBias(tzinfo_.Bias));
175 const char* GuessTimezoneNameFromBias(
int bias) {
176 static const int kHour = 60;
178 case -9*kHour:
return "Alaska";
179 case -8*kHour:
return "Pacific";
180 case -7*kHour:
return "Mountain";
181 case -6*kHour:
return "Central";
182 case -5*kHour:
return "Eastern";
183 case -4*kHour:
return "Atlantic";
184 case 0*kHour:
return "GMT";
185 case +1*kHour:
return "Central Europe";
186 case +2*kHour:
return "Eastern Europe";
187 case +3*kHour:
return "Russia";
188 case +5*kHour + 30:
return "India";
189 case +8*kHour:
return "China";
190 case +9*kHour:
return "Japan";
191 case +12*kHour:
return "New Zealand";
192 default:
return "Local";
198 static const int kTzNameSize = 128;
200 char std_tz_name_[kTzNameSize];
201 char dst_tz_name_[kTzNameSize];
202 TIME_ZONE_INFORMATION tzinfo_;
218 Win32Time(
int year,
int mon,
int day,
int hour,
int min,
int sec);
224 void SetToCurrentTime();
242 static const int64_t kTimeEpoc = 116444736000000000LL;
243 static const int64_t kTimeScaler = 10000;
244 static const int64_t kMsPerMinute = 60000;
247 static const bool kShortTzNames =
false;
253 FILETIME& ft() {
return time_.ft_; }
256 int64_t& t() {
return time_.t_; }
273 Win32Time::Win32Time() {
279 Win32Time::Win32Time(
double jstime) {
280 t() =
static_cast<int64_t>(jstime) * kTimeScaler + kTimeEpoc;
285 Win32Time::Win32Time(
int year,
int mon,
int day,
int hour,
int min,
int sec) {
293 st.wMilliseconds = 0;
294 SystemTimeToFileTime(&st, &ft());
299 double Win32Time::ToJSTime() {
300 return static_cast<double>((t() - kTimeEpoc) / kTimeScaler);
305 void Win32Time::SetToCurrentTime() {
323 static bool initialized =
false;
324 static TimeStamp init_time;
325 static DWORD init_ticks;
326 static const int64_t kHundredNanosecondsPerSecond = 10000000;
327 static const int64_t kMaxClockElapsedTime =
328 60*kHundredNanosecondsPerSecond;
331 bool needs_resync = !initialized;
335 GetSystemTimeAsFileTime(&time_now.ft_);
336 DWORD ticks_now = timeGetTime();
339 needs_resync |= ticks_now < init_ticks;
342 needs_resync |= (time_now.t_ - init_time.t_) > kMaxClockElapsedTime;
345 needs_resync |= time_now.t_ < init_time.t_;
349 GetSystemTimeAsFileTime(&init_time.ft_);
350 init_ticks = ticks_now = timeGetTime();
355 DWORD elapsed = ticks_now - init_ticks;
356 this->time_.t_ = init_time.t_ + (
static_cast<int64_t>(elapsed) * 10000);
365 int64_t Win32Time::LocalOffset(WindowsTimezoneCache* cache) {
366 cache->InitializeIfNeeded();
368 Win32Time rounded_to_second(*
this);
369 rounded_to_second.t() =
370 rounded_to_second.t() / 1000 / kTimeScaler * 1000 * kTimeScaler;
377 double unchecked_posix_time = rounded_to_second.ToJSTime() / 1000;
378 if (unchecked_posix_time > INT_MAX || unchecked_posix_time < 0) {
382 time_t posix_time =
static_cast<time_t
>(unchecked_posix_time);
385 tm posix_local_time_struct;
386 if (localtime_s(&posix_local_time_struct, &posix_time))
return 0;
388 if (posix_local_time_struct.tm_isdst > 0) {
389 return (cache->tzinfo_.Bias + cache->tzinfo_.DaylightBias) * -kMsPerMinute;
390 }
else if (posix_local_time_struct.tm_isdst == 0) {
391 return (cache->tzinfo_.Bias + cache->tzinfo_.StandardBias) * -kMsPerMinute;
393 return cache->tzinfo_.Bias * -kMsPerMinute;
399 bool Win32Time::InDST(WindowsTimezoneCache* cache) {
400 cache->InitializeIfNeeded();
404 if (cache->tzinfo_.StandardDate.wMonth != 0 ||
405 cache->tzinfo_.DaylightDate.wMonth != 0) {
407 int64_t offset = LocalOffset(cache);
412 -(cache->tzinfo_.Bias + cache->tzinfo_.DaylightBias) * kMsPerMinute;
416 in_dst = offset == dstofs;
424 int64_t Win32Time::DaylightSavingsOffset(WindowsTimezoneCache* cache) {
425 return InDST(cache) ? 60 * kMsPerMinute : 0;
431 char* Win32Time::LocalTimezone(WindowsTimezoneCache* cache) {
434 return InDST(cache) ? cache->dst_tz_name_ : cache->std_tz_name_;
444 if (!GetThreadTimes(GetCurrentThread(), &dummy, &dummy, &dummy,
445 reinterpret_cast<FILETIME*>(&usertime)))
return -1;
451 *secs =
static_cast<uint32_t>(usertime / 1000000);
452 *usecs =
static_cast<uint32_t>(usertime % 1000000);
459 double OS::TimeCurrentMillis() {
460 return Time::Now().ToJsTime();
465 const char* WindowsTimezoneCache::LocalTimezone(
double time) {
466 return Win32Time(time).LocalTimezone(
this);
471 double WindowsTimezoneCache::LocalTimeOffset(
double time_ms,
bool is_utc) {
475 Win32Time t(OS::TimeCurrentMillis());
477 return static_cast<double>(t.LocalOffset(
this) -
478 t.DaylightSavingsOffset(
this));
483 double WindowsTimezoneCache::DaylightSavingsOffset(
double time) {
484 int64_t offset = Win32Time(time).DaylightSavingsOffset(
this);
485 return static_cast<double>(offset);
488 TimezoneCache* OS::CreateTimezoneCache() {
return new WindowsTimezoneCache(); }
490 int OS::GetLastError() {
491 return ::GetLastError();
495 int OS::GetCurrentProcessId() {
496 return static_cast<int>(::GetCurrentProcessId());
500 int OS::GetCurrentThreadId() {
501 return static_cast<int>(::GetCurrentThreadId());
504 void OS::ExitProcess(
int exit_code) {
509 TerminateProcess(GetCurrentProcess(), exit_code);
530 static OutputMode output_mode = UNKNOWN;
534 static bool HasConsole() {
537 if (output_mode == UNKNOWN) {
542 if (GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE &&
543 GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) != FILE_TYPE_UNKNOWN)
544 output_mode = CONSOLE;
548 return output_mode == CONSOLE;
552 static void VPrintHelper(FILE* stream,
const char* format, va_list args) {
553 if ((stream == stdout || stream == stderr) && !HasConsole()) {
558 OS::VSNPrintF(buffer,
sizeof(buffer), format, args);
559 OutputDebugStringA(buffer);
561 vfprintf(stream, format, args);
566 FILE* OS::FOpen(
const char* path,
const char* mode) {
568 if (fopen_s(&result, path, mode) == 0) {
576 bool OS::Remove(
const char* path) {
577 return (DeleteFileA(path) != 0);
580 char OS::DirectorySeparator() {
return '\\'; }
582 bool OS::isDirectorySeparator(
const char ch) {
583 return ch ==
'/' || ch ==
'\\';
587 FILE* OS::OpenTemporaryFile() {
589 char tempPathBuffer[MAX_PATH];
590 DWORD path_result = 0;
591 path_result = GetTempPathA(MAX_PATH, tempPathBuffer);
592 if (path_result > MAX_PATH || path_result == 0)
return nullptr;
593 UINT name_result = 0;
594 char tempNameBuffer[MAX_PATH];
595 name_result = GetTempFileNameA(tempPathBuffer,
"", 0, tempNameBuffer);
596 if (name_result == 0)
return nullptr;
597 FILE* result = FOpen(tempNameBuffer,
"w+");
598 if (result !=
nullptr) {
599 Remove(tempNameBuffer);
606 const char*
const OS::LogFileOpenMode =
"wb";
610 void OS::Print(
const char* format, ...) {
612 va_start(args, format);
613 VPrint(format, args);
618 void OS::VPrint(
const char* format, va_list args) {
619 VPrintHelper(stdout, format, args);
623 void OS::FPrint(FILE* out,
const char* format, ...) {
625 va_start(args, format);
626 VFPrint(out, format, args);
631 void OS::VFPrint(FILE* out,
const char* format, va_list args) {
632 VPrintHelper(out, format, args);
637 void OS::PrintError(
const char* format, ...) {
639 va_start(args, format);
640 VPrintError(format, args);
645 void OS::VPrintError(
const char* format, va_list args) {
646 VPrintHelper(stderr, format, args);
650 int OS::SNPrintF(
char* str,
int length,
const char* format, ...) {
652 va_start(args, format);
653 int result = VSNPrintF(str, length, format, args);
659 int OS::VSNPrintF(
char* str,
int length,
const char* format, va_list args) {
660 int n = _vsnprintf_s(str, length, _TRUNCATE, format, args);
663 if (n < 0 || n >= length) {
665 str[length - 1] =
'\0';
673 char* OS::StrChr(
char* str,
int c) {
674 return const_cast<char*
>(strchr(str, c));
678 void OS::StrNCpy(
char* dest,
int length,
const char* src,
size_t n) {
680 size_t buffer_size =
static_cast<size_t>(length);
681 if (n + 1 > buffer_size)
683 int result = strncpy_s(dest, length, src, n);
685 DCHECK(result == 0 || (n == _TRUNCATE && result == STRUNCATE));
692 static LazyInstance<RandomNumberGenerator>::type
693 platform_random_number_generator = LAZY_INSTANCE_INITIALIZER;
694 static LazyMutex rng_mutex = LAZY_MUTEX_INITIALIZER;
696 void OS::Initialize(
bool hard_abort,
const char*
const gc_fake_mmap) {
697 g_hard_abort = hard_abort;
701 size_t OS::AllocatePageSize() {
702 static size_t allocate_alignment = 0;
703 if (allocate_alignment == 0) {
705 GetSystemInfo(&info);
706 allocate_alignment = info.dwAllocationGranularity;
708 return allocate_alignment;
712 size_t OS::CommitPageSize() {
713 static size_t page_size = 0;
714 if (page_size == 0) {
716 GetSystemInfo(&info);
717 page_size = info.dwPageSize;
718 DCHECK_EQ(4096, page_size);
724 void OS::SetRandomMmapSeed(
int64_t seed) {
726 MutexGuard guard(rng_mutex.Pointer());
727 platform_random_number_generator.Pointer()->SetSeed(seed);
732 void* OS::GetRandomMmapAddr() {
738 #ifdef V8_HOST_ARCH_64_BIT 739 static const uintptr_t kAllocationRandomAddressMin = 0x0000000080000000;
740 static const uintptr_t kAllocationRandomAddressMax = 0x000003FFFFFF0000;
742 static const uintptr_t kAllocationRandomAddressMin = 0x04000000;
743 static const uintptr_t kAllocationRandomAddressMax = 0x3FFF0000;
747 MutexGuard guard(rng_mutex.Pointer());
748 platform_random_number_generator.Pointer()->NextBytes(&address,
751 address <<= kPageSizeBits;
752 address += kAllocationRandomAddressMin;
753 address &= kAllocationRandomAddressMax;
754 return reinterpret_cast<void*
>(address);
759 DWORD GetProtectionFromMemoryPermission(OS::MemoryPermission access) {
761 case OS::MemoryPermission::kNoAccess:
762 return PAGE_NOACCESS;
763 case OS::MemoryPermission::kRead:
764 return PAGE_READONLY;
765 case OS::MemoryPermission::kReadWrite:
766 return PAGE_READWRITE;
767 case OS::MemoryPermission::kReadWriteExecute:
768 if (IsWindows10OrGreater())
769 return PAGE_EXECUTE_READWRITE | PAGE_TARGETS_INVALID;
770 return PAGE_EXECUTE_READWRITE;
771 case OS::MemoryPermission::kReadExecute:
772 if (IsWindows10OrGreater())
773 return PAGE_EXECUTE_READ | PAGE_TARGETS_INVALID;
774 return PAGE_EXECUTE_READ;
779 uint8_t* RandomizedVirtualAlloc(
size_t size, DWORD flags, DWORD protect,
781 LPVOID base =
nullptr;
782 static BOOL use_aslr = -1;
783 #ifdef V8_HOST_ARCH_32_BIT 786 if (use_aslr == -1 && !IsWow64Process(GetCurrentProcess(), &use_aslr))
792 if (use_aslr && protect != PAGE_READWRITE) {
794 base = VirtualAlloc(hint, size, flags, protect);
798 if (base ==
nullptr) {
799 base = VirtualAlloc(
nullptr, size, flags, protect);
801 return reinterpret_cast<uint8_t*
>(base);
807 void* OS::Allocate(
void* address,
size_t size,
size_t alignment,
808 MemoryPermission access) {
809 size_t page_size = AllocatePageSize();
810 DCHECK_EQ(0, size % page_size);
811 DCHECK_EQ(0, alignment % page_size);
812 DCHECK_LE(page_size, alignment);
813 address = AlignedAddress(address, alignment);
815 DWORD flags = (access == OS::MemoryPermission::kNoAccess)
817 : MEM_RESERVE | MEM_COMMIT;
818 DWORD protect = GetProtectionFromMemoryPermission(access);
821 uint8_t* base = RandomizedVirtualAlloc(size, flags, protect, address);
822 if (base ==
nullptr)
return nullptr;
825 uint8_t* aligned_base =
reinterpret_cast<uint8_t*
>(
826 RoundUp(reinterpret_cast<uintptr_t>(base), alignment));
827 if (base == aligned_base)
return reinterpret_cast<void*
>(base);
830 CHECK(Free(base, size));
837 size_t padded_size = size + (alignment - page_size);
838 const int kMaxAttempts = 3;
839 aligned_base =
nullptr;
840 for (
int i = 0;
i < kMaxAttempts; ++
i) {
841 base = RandomizedVirtualAlloc(padded_size, flags, protect, address);
842 if (base ==
nullptr)
return nullptr;
846 CHECK(Free(base, padded_size));
847 aligned_base =
reinterpret_cast<uint8_t*
>(
848 RoundUp(reinterpret_cast<uintptr_t>(base), alignment));
849 base =
reinterpret_cast<uint8_t*
>(
850 VirtualAlloc(aligned_base, size, flags, protect));
853 if (base !=
nullptr)
break;
855 DCHECK_IMPLIES(base, base == aligned_base);
856 return reinterpret_cast<void*
>(base);
860 bool OS::Free(
void* address,
const size_t size) {
861 DCHECK_EQ(0, reinterpret_cast<uintptr_t>(address) % AllocatePageSize());
862 DCHECK_EQ(0, size % AllocatePageSize());
864 return VirtualFree(address, 0, MEM_RELEASE) != 0;
868 bool OS::Release(
void* address,
size_t size) {
869 DCHECK_EQ(0, reinterpret_cast<uintptr_t>(address) % CommitPageSize());
870 DCHECK_EQ(0, size % CommitPageSize());
871 return VirtualFree(address, size, MEM_DECOMMIT) != 0;
875 bool OS::SetPermissions(
void* address,
size_t size, MemoryPermission access) {
876 DCHECK_EQ(0, reinterpret_cast<uintptr_t>(address) % CommitPageSize());
877 DCHECK_EQ(0, size % CommitPageSize());
878 if (access == MemoryPermission::kNoAccess) {
879 return VirtualFree(address, size, MEM_DECOMMIT) != 0;
881 DWORD protect = GetProtectionFromMemoryPermission(access);
882 return VirtualAlloc(address, size, MEM_COMMIT, protect) !=
nullptr;
886 bool OS::DiscardSystemPages(
void* address,
size_t size) {
889 using DiscardVirtualMemoryFunction =
890 DWORD(WINAPI*)(PVOID virtualAddress, SIZE_T size);
891 static std::atomic<DiscardVirtualMemoryFunction> discard_virtual_memory(
892 reinterpret_cast<DiscardVirtualMemoryFunction>(-1));
893 if (discard_virtual_memory ==
894 reinterpret_cast<DiscardVirtualMemoryFunction>(-1))
895 discard_virtual_memory =
896 reinterpret_cast<DiscardVirtualMemoryFunction
>(GetProcAddress(
897 GetModuleHandle(L
"Kernel32.dll"),
"DiscardVirtualMemory"));
900 DiscardVirtualMemoryFunction discard_function = discard_virtual_memory.load();
901 if (discard_function) {
902 DWORD ret = discard_function(address, size);
903 if (!ret)
return true;
907 void* ptr = VirtualAlloc(address, size, MEM_RESET, PAGE_READWRITE);
913 bool OS::HasLazyCommits() {
918 void OS::Sleep(TimeDelta interval) {
919 ::Sleep(static_cast<DWORD>(interval.InMilliseconds()));
929 V8_IMMEDIATE_CRASH();
939 void OS::DebugBreak() {
956 file_mapping_(file_mapping),
960 void* memory()
const final {
return memory_; }
961 size_t size()
const final {
return size_; }
965 HANDLE
const file_mapping_;
974 HANDLE file = CreateFileA(name, GENERIC_READ | GENERIC_WRITE,
975 FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
976 OPEN_EXISTING, 0,
nullptr);
977 if (file == INVALID_HANDLE_VALUE)
return nullptr;
979 DWORD size = GetFileSize(file,
nullptr);
982 HANDLE file_mapping =
983 CreateFileMapping(file,
nullptr, PAGE_READWRITE, 0, size,
nullptr);
984 if (file_mapping ==
nullptr)
return nullptr;
987 void* memory = MapViewOfFile(file_mapping, FILE_MAP_ALL_ACCESS, 0, 0, size);
993 OS::MemoryMappedFile* OS::MemoryMappedFile::create(
const char* name,
994 size_t size,
void* initial) {
996 HANDLE file = CreateFileA(name, GENERIC_READ | GENERIC_WRITE,
997 FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
998 OPEN_ALWAYS, 0,
nullptr);
999 if (file ==
nullptr)
return nullptr;
1001 HANDLE file_mapping = CreateFileMapping(file,
nullptr, PAGE_READWRITE, 0,
1002 static_cast<DWORD>(size),
nullptr);
1003 if (file_mapping ==
nullptr)
return nullptr;
1005 void* memory = MapViewOfFile(file_mapping, FILE_MAP_ALL_ACCESS, 0, 0, size);
1006 if (memory) memmove(memory, initial, size);
1007 return new Win32MemoryMappedFile(file, file_mapping, memory, size);
1011 Win32MemoryMappedFile::~Win32MemoryMappedFile() {
1012 if (memory_) UnmapViewOfFile(memory_);
1013 CloseHandle(file_mapping_);
1025 #define DBGHELP_FUNCTION_LIST(V) \ 1029 V(SymGetSearchPath) \ 1030 V(SymLoadModule64) \ 1032 V(SymGetSymFromAddr64) \ 1033 V(SymGetLineFromAddr64) \ 1034 V(SymFunctionTableAccess64) \ 1035 V(SymGetModuleBase64) 1038 #define TLHELP32_FUNCTION_LIST(V) \ 1039 V(CreateToolhelp32Snapshot) \ 1045 #define DLL_FUNC_TYPE(name) _##name##_ 1046 #define DLL_FUNC_VAR(name) _##name 1062 typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymInitialize))(IN HANDLE hProcess,
1063 IN PSTR UserSearchPath,
1064 IN BOOL fInvadeProcess);
1065 typedef DWORD (__stdcall *DLL_FUNC_TYPE(SymGetOptions))(VOID);
1066 typedef DWORD (__stdcall *DLL_FUNC_TYPE(SymSetOptions))(IN DWORD SymOptions);
1067 typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetSearchPath))(
1069 OUT PSTR SearchPath,
1070 IN DWORD SearchPathLength);
1071 typedef DWORD64 (__stdcall *DLL_FUNC_TYPE(SymLoadModule64))(
1076 IN DWORD64 BaseOfDll,
1077 IN DWORD SizeOfDll);
1078 typedef BOOL (__stdcall *DLL_FUNC_TYPE(StackWalk64))(
1082 LPSTACKFRAME64 StackFrame,
1083 PVOID ContextRecord,
1084 PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
1085 PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
1086 PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
1087 PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
1088 typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetSymFromAddr64))(
1091 OUT PDWORD64 pdwDisplacement,
1092 OUT PIMAGEHLP_SYMBOL64 Symbol);
1093 typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetLineFromAddr64))(
1096 OUT PDWORD pdwDisplacement,
1097 OUT PIMAGEHLP_LINE64 Line64);
1099 typedef PVOID (__stdcall *DLL_FUNC_TYPE(SymFunctionTableAccess64))(
1102 typedef DWORD64 (__stdcall *DLL_FUNC_TYPE(SymGetModuleBase64))(
1107 typedef HANDLE (__stdcall *DLL_FUNC_TYPE(CreateToolhelp32Snapshot))(
1109 DWORD th32ProcessID);
1110 typedef BOOL (__stdcall *DLL_FUNC_TYPE(Module32FirstW))(HANDLE hSnapshot,
1111 LPMODULEENTRY32W lpme);
1112 typedef BOOL (__stdcall *DLL_FUNC_TYPE(Module32NextW))(HANDLE hSnapshot,
1113 LPMODULEENTRY32W lpme);
1119 #define DEF_DLL_FUNCTION(name) DLL_FUNC_TYPE(name) DLL_FUNC_VAR(name) = nullptr; 1120 DBGHELP_FUNCTION_LIST(DEF_DLL_FUNCTION)
1121 TLHELP32_FUNCTION_LIST(DEF_DLL_FUNCTION)
1122 #undef DEF_DLL_FUNCTION 1127 static bool LoadDbgHelpAndTlHelp32() {
1128 static bool dbghelp_loaded =
false;
1130 if (dbghelp_loaded)
return true;
1135 module = LoadLibrary(TEXT(
"dbghelp.dll"));
1136 if (module ==
nullptr) {
1140 #define LOAD_DLL_FUNC(name) \ 1141 DLL_FUNC_VAR(name) = \ 1142 reinterpret_cast<DLL_FUNC_TYPE(name)>(GetProcAddress(module, #name)); 1144 DBGHELP_FUNCTION_LIST(LOAD_DLL_FUNC)
1146 #undef LOAD_DLL_FUNC 1150 module = LoadLibrary(TEXT(
"kernel32.dll"));
1151 if (module ==
nullptr) {
1155 #define LOAD_DLL_FUNC(name) \ 1156 DLL_FUNC_VAR(name) = \ 1157 reinterpret_cast<DLL_FUNC_TYPE(name)>(GetProcAddress(module, #name)); 1159 TLHELP32_FUNCTION_LIST(LOAD_DLL_FUNC)
1161 #undef LOAD_DLL_FUNC 1165 #define DLL_FUNC_LOADED(name) (DLL_FUNC_VAR(name) != nullptr)&& 1167 DBGHELP_FUNCTION_LIST(DLL_FUNC_LOADED)
1168 TLHELP32_FUNCTION_LIST(DLL_FUNC_LOADED)
1170 #undef DLL_FUNC_LOADED 1173 dbghelp_loaded = result;
1179 #undef DBGHELP_FUNCTION_LIST 1180 #undef TLHELP32_FUNCTION_LIST 1182 #undef DLL_FUNC_TYPE 1186 static std::vector<OS::SharedLibraryAddress> LoadSymbols(
1187 HANDLE process_handle) {
1188 static std::vector<OS::SharedLibraryAddress> result;
1190 static bool symbols_loaded =
false;
1192 if (symbols_loaded)
return result;
1197 ok = _SymInitialize(process_handle,
1200 if (!ok)
return result;
1202 DWORD options = _SymGetOptions();
1203 options |= SYMOPT_LOAD_LINES;
1204 options |= SYMOPT_FAIL_CRITICAL_ERRORS;
1205 options = _SymSetOptions(options);
1207 char buf[OS::kStackWalkMaxNameLen] = {0};
1208 ok = _SymGetSearchPath(process_handle, buf, OS::kStackWalkMaxNameLen);
1210 int err = GetLastError();
1211 OS::Print(
"%d\n", err);
1215 HANDLE snapshot = _CreateToolhelp32Snapshot(
1217 GetCurrentProcessId());
1218 if (snapshot == INVALID_HANDLE_VALUE)
return result;
1219 MODULEENTRY32W module_entry;
1220 module_entry.dwSize =
sizeof(module_entry);
1221 BOOL cont = _Module32FirstW(snapshot, &module_entry);
1226 base = _SymLoadModule64(
1229 reinterpret_cast<PSTR>(module_entry.szExePath),
1230 reinterpret_cast<PSTR>(module_entry.szModule),
1231 reinterpret_cast<DWORD64>(module_entry.modBaseAddr),
1232 module_entry.modBaseSize);
1234 int err = GetLastError();
1235 if (err != ERROR_MOD_NOT_FOUND &&
1236 err != ERROR_INVALID_HANDLE) {
1241 int lib_name_length = WideCharToMultiByte(
1242 CP_UTF8, 0, module_entry.szExePath, -1,
nullptr, 0,
nullptr,
nullptr);
1243 std::string lib_name(lib_name_length, 0);
1244 WideCharToMultiByte(CP_UTF8, 0, module_entry.szExePath, -1, &lib_name[0],
1245 lib_name_length,
nullptr,
nullptr);
1246 result.push_back(OS::SharedLibraryAddress(
1247 lib_name, reinterpret_cast<uintptr_t>(module_entry.modBaseAddr),
1248 reinterpret_cast<uintptr_t>(module_entry.modBaseAddr +
1249 module_entry.modBaseSize)));
1250 cont = _Module32NextW(snapshot, &module_entry);
1252 CloseHandle(snapshot);
1254 symbols_loaded =
true;
1259 std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
1264 if (!LoadDbgHelpAndTlHelp32())
return std::vector<OS::SharedLibraryAddress>();
1265 HANDLE process_handle = GetCurrentProcess();
1266 return LoadSymbols(process_handle);
1269 void OS::SignalCodeMovingGC() {}
1271 #else // __MINGW32__ 1272 std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
1273 return std::vector<OS::SharedLibraryAddress>();
1276 void OS::SignalCodeMovingGC() {}
1277 #endif // __MINGW32__ 1280 int OS::ActivationFrameAlignment() {
1283 #elif defined(__MINGW32__) 1292 #if (defined(_WIN32) || defined(_WIN64)) 1293 void EnsureConsoleOutputWin32() {
1295 SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX;
1296 UINT existing_flags = SetErrorMode(new_flags);
1297 SetErrorMode(existing_flags | new_flags);
1298 #if defined(_MSC_VER) 1299 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
1300 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
1301 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
1302 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
1303 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
1304 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
1305 _set_error_mode(_OUT_TO_STDERR);
1306 #endif // defined(_MSC_VER) 1308 #endif // (defined(_WIN32) || defined(_WIN64)) 1314 static const HANDLE kNoThread = INVALID_HANDLE_VALUE;
1320 static unsigned int __stdcall ThreadEntry(
void* arg) {
1321 Thread* thread =
reinterpret_cast<Thread*
>(arg);
1322 thread->NotifyStartedAndRun();
1327 class Thread::PlatformData {
1329 explicit PlatformData(HANDLE thread) : thread_(thread) {}
1331 unsigned thread_id_;
1338 Thread::Thread(
const Options& options)
1339 : stack_size_(options.stack_size()), start_semaphore_(nullptr) {
1340 data_ =
new PlatformData(kNoThread);
1341 set_name(options.name());
1345 void Thread::set_name(
const char* name) {
1346 OS::StrNCpy(name_,
sizeof(name_), name, strlen(name));
1347 name_[
sizeof(name_) - 1] =
'\0';
1353 if (data_->thread_ != kNoThread) CloseHandle(data_->thread_);
1361 void Thread::Start() {
1362 data_->thread_ =
reinterpret_cast<HANDLE
>(
1363 _beginthreadex(
nullptr, static_cast<unsigned>(stack_size_), ThreadEntry,
1364 this, 0, &data_->thread_id_));
1369 void Thread::Join() {
1370 if (data_->thread_id_ != GetCurrentThreadId()) {
1371 WaitForSingleObject(data_->thread_, INFINITE);
1376 Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
1377 DWORD result = TlsAlloc();
1378 DCHECK(result != TLS_OUT_OF_INDEXES);
1379 return static_cast<LocalStorageKey
>(result);
1383 void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
1384 BOOL result = TlsFree(static_cast<DWORD>(key));
1390 void* Thread::GetThreadLocal(LocalStorageKey key) {
1391 return TlsGetValue(static_cast<DWORD>(key));
1395 void Thread::SetThreadLocal(LocalStorageKey key,
void* value) {
1396 BOOL result = TlsSetValue(static_cast<DWORD>(key), value);