1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 // Platform specific code for Win32. 29 #ifndef WIN32_LEAN_AND_MEAN 30 // WIN32_LEAN_AND_MEAN implies NOCRYPT and NOGDI. 31 #define WIN32_LEAN_AND_MEAN 32 #endif 33 #ifndef NOMINMAX 34 #define NOMINMAX 35 #endif 36 #ifndef NOKERNEL 37 #define NOKERNEL 38 #endif 39 #ifndef NOUSER 40 #define NOUSER 41 #endif 42 #ifndef NOSERVICE 43 #define NOSERVICE 44 #endif 45 #ifndef NOSOUND 46 #define NOSOUND 47 #endif 48 #ifndef NOMCX 49 #define NOMCX 50 #endif 51 // Require Windows XP or higher (this is required for the RtlCaptureContext 52 // function to be present). 53 #ifndef _WIN32_WINNT 54 #define _WIN32_WINNT 0x501 55 #endif 56 57 #include <windows.h> 58 59 #include <time.h> // For LocalOffset() implementation. 60 #include <mmsystem.h> // For timeGetTime(). 61 #ifdef __MINGW32__ 62 // Require Windows XP or higher when compiling with MinGW. This is for MinGW 63 // header files to expose getaddrinfo. 64 #undef _WIN32_WINNT 65 #define _WIN32_WINNT 0x501 66 #endif // __MINGW32__ 67 #ifndef __MINGW32__ 68 #include <dbghelp.h> // For SymLoadModule64 and al. 69 #endif // __MINGW32__ 70 #include <limits.h> // For INT_MAX and al. 71 #include <tlhelp32.h> // For Module32First and al. 72 73 // These additional WIN32 includes have to be right here as the #undef's below 74 // makes it impossible to have them elsewhere. 75 #include <winsock2.h> 76 #include <ws2tcpip.h> 77 #include <process.h> // for _beginthreadex() 78 #include <stdlib.h> 79 80 #undef VOID 81 #undef DELETE 82 #undef IN 83 #undef THIS 84 #undef CONST 85 #undef NAN 86 #undef GetObject 87 #undef CreateMutex 88 #undef CreateSemaphore 89 90 #include "v8.h" 91 92 #include "platform.h" 93 94 // Extra POSIX/ANSI routines for Win32 when when using Visual Studio C++. Please 95 // refer to The Open Group Base Specification for specification of the correct 96 // semantics for these functions. 97 // (http://www.opengroup.org/onlinepubs/000095399/) 98 #ifdef _MSC_VER 99 100 namespace v8 { 101 namespace internal { 102 103 // Test for finite value - usually defined in math.h 104 int isfinite(double x) { 105 return _finite(x); 106 } 107 108 } // namespace v8 109 } // namespace internal 110 111 // Test for a NaN (not a number) value - usually defined in math.h 112 int isnan(double x) { 113 return _isnan(x); 114 } 115 116 117 // Test for infinity - usually defined in math.h 118 int isinf(double x) { 119 return (_fpclass(x) & (_FPCLASS_PINF | _FPCLASS_NINF)) != 0; 120 } 121 122 123 // Test if x is less than y and both nominal - usually defined in math.h 124 int isless(double x, double y) { 125 return isnan(x) || isnan(y) ? 0 : x < y; 126 } 127 128 129 // Test if x is greater than y and both nominal - usually defined in math.h 130 int isgreater(double x, double y) { 131 return isnan(x) || isnan(y) ? 0 : x > y; 132 } 133 134 135 // Classify floating point number - usually defined in math.h 136 int fpclassify(double x) { 137 // Use the MS-specific _fpclass() for classification. 138 int flags = _fpclass(x); 139 140 // Determine class. We cannot use a switch statement because 141 // the _FPCLASS_ constants are defined as flags. 142 if (flags & (_FPCLASS_PN | _FPCLASS_NN)) return FP_NORMAL; 143 if (flags & (_FPCLASS_PZ | _FPCLASS_NZ)) return FP_ZERO; 144 if (flags & (_FPCLASS_PD | _FPCLASS_ND)) return FP_SUBNORMAL; 145 if (flags & (_FPCLASS_PINF | _FPCLASS_NINF)) return FP_INFINITE; 146 147 // All cases should be covered by the code above. 148 ASSERT(flags & (_FPCLASS_SNAN | _FPCLASS_QNAN)); 149 return FP_NAN; 150 } 151 152 153 // Test sign - usually defined in math.h 154 int signbit(double x) { 155 // We need to take care of the special case of both positive 156 // and negative versions of zero. 157 if (x == 0) 158 return _fpclass(x) & _FPCLASS_NZ; 159 else 160 return x < 0; 161 } 162 163 164 // Case-insensitive bounded string comparisons. Use stricmp() on Win32. Usually 165 // defined in strings.h. 166 int strncasecmp(const char* s1, const char* s2, int n) { 167 return _strnicmp(s1, s2, n); 168 } 169 170 #endif // _MSC_VER 171 172 173 // Extra functions for MinGW. Most of these are the _s functions which are in 174 // the Microsoft Visual Studio C++ CRT. 175 #ifdef __MINGW32__ 176 177 int localtime_s(tm* out_tm, const time_t* time) { 178 tm* posix_local_time_struct = localtime(time); 179 if (posix_local_time_struct == NULL) return 1; 180 *out_tm = *posix_local_time_struct; 181 return 0; 182 } 183 184 185 // Not sure this the correct interpretation of _mkgmtime 186 time_t _mkgmtime(tm* timeptr) { 187 return mktime(timeptr); 188 } 189 190 191 int fopen_s(FILE** pFile, const char* filename, const char* mode) { 192 *pFile = fopen(filename, mode); 193 return *pFile != NULL ? 0 : 1; 194 } 195 196 197 int _vsnprintf_s(char* buffer, size_t sizeOfBuffer, size_t count, 198 const char* format, va_list argptr) { 199 return _vsnprintf(buffer, sizeOfBuffer, format, argptr); 200 } 201 #define _TRUNCATE 0 202 203 204 int strncpy_s(char* strDest, size_t numberOfElements, 205 const char* strSource, size_t count) { 206 strncpy(strDest, strSource, count); 207 return 0; 208 } 209 210 #endif // __MINGW32__ 211 212 // Generate a pseudo-random number in the range 0-2^31-1. Usually 213 // defined in stdlib.h. Missing in both Microsoft Visual Studio C++ and MinGW. 214 int random() { 215 return rand(); 216 } 217 218 219 namespace v8 { 220 namespace internal { 221 222 double ceiling(double x) { 223 return ceil(x); 224 } 225 226 #ifdef _WIN64 227 typedef double (*ModuloFunction)(double, double); 228 229 // Defined in codegen-x64.cc. 230 ModuloFunction CreateModuloFunction(); 231 232 double modulo(double x, double y) { 233 static ModuloFunction function = CreateModuloFunction(); 234 return function(x, y); 235 } 236 #else // Win32 237 238 double modulo(double x, double y) { 239 // Workaround MS fmod bugs. ECMA-262 says: 240 // dividend is finite and divisor is an infinity => result equals dividend 241 // dividend is a zero and divisor is nonzero finite => result equals dividend 242 if (!(isfinite(x) && (!isfinite(y) && !isnan(y))) && 243 !(x == 0 && (y != 0 && isfinite(y)))) { 244 x = fmod(x, y); 245 } 246 return x; 247 } 248 249 #endif // _WIN64 250 251 // ---------------------------------------------------------------------------- 252 // The Time class represents time on win32. A timestamp is represented as 253 // a 64-bit integer in 100 nano-seconds since January 1, 1601 (UTC). JavaScript 254 // timestamps are represented as a doubles in milliseconds since 00:00:00 UTC, 255 // January 1, 1970. 256 257 class Time { 258 public: 259 // Constructors. 260 Time(); 261 explicit Time(double jstime); 262 Time(int year, int mon, int day, int hour, int min, int sec); 263 264 // Convert timestamp to JavaScript representation. 265 double ToJSTime(); 266 267 // Set timestamp to current time. 268 void SetToCurrentTime(); 269 270 // Returns the local timezone offset in milliseconds east of UTC. This is 271 // the number of milliseconds you must add to UTC to get local time, i.e. 272 // LocalOffset(CET) = 3600000 and LocalOffset(PST) = -28800000. This 273 // routine also takes into account whether daylight saving is effect 274 // at the time. 275 int64_t LocalOffset(); 276 277 // Returns the daylight savings time offset for the time in milliseconds. 278 int64_t DaylightSavingsOffset(); 279 280 // Returns a string identifying the current timezone for the 281 // timestamp taking into account daylight saving. 282 char* LocalTimezone(); 283 284 private: 285 // Constants for time conversion. 286 static const int64_t kTimeEpoc = 116444736000000000LL; 287 static const int64_t kTimeScaler = 10000; 288 static const int64_t kMsPerMinute = 60000; 289 290 // Constants for timezone information. 291 static const int kTzNameSize = 128; 292 static const bool kShortTzNames = false; 293 294 // Timezone information. We need to have static buffers for the 295 // timezone names because we return pointers to these in 296 // LocalTimezone(). 297 static bool tz_initialized_; 298 static TIME_ZONE_INFORMATION tzinfo_; 299 static char std_tz_name_[kTzNameSize]; 300 static char dst_tz_name_[kTzNameSize]; 301 302 // Initialize the timezone information (if not already done). 303 static void TzSet(); 304 305 // Guess the name of the timezone from the bias. 306 static const char* GuessTimezoneNameFromBias(int bias); 307 308 // Return whether or not daylight savings time is in effect at this time. 309 bool InDST(); 310 311 // Return the difference (in milliseconds) between this timestamp and 312 // another timestamp. 313 int64_t Diff(Time* other); 314 315 // Accessor for FILETIME representation. 316 FILETIME& ft() { return time_.ft_; } 317 318 // Accessor for integer representation. 319 int64_t& t() { return time_.t_; } 320 321 // Although win32 uses 64-bit integers for representing timestamps, 322 // these are packed into a FILETIME structure. The FILETIME structure 323 // is just a struct representing a 64-bit integer. The TimeStamp union 324 // allows access to both a FILETIME and an integer representation of 325 // the timestamp. 326 union TimeStamp { 327 FILETIME ft_; 328 int64_t t_; 329 }; 330 331 TimeStamp time_; 332 }; 333 334 // Static variables. 335 bool Time::tz_initialized_ = false; 336 TIME_ZONE_INFORMATION Time::tzinfo_; 337 char Time::std_tz_name_[kTzNameSize]; 338 char Time::dst_tz_name_[kTzNameSize]; 339 340 341 // Initialize timestamp to start of epoc. 342 Time::Time() { 343 t() = 0; 344 } 345 346 347 // Initialize timestamp from a JavaScript timestamp. 348 Time::Time(double jstime) { 349 t() = static_cast<int64_t>(jstime) * kTimeScaler + kTimeEpoc; 350 } 351 352 353 // Initialize timestamp from date/time components. 354 Time::Time(int year, int mon, int day, int hour, int min, int sec) { 355 SYSTEMTIME st; 356 st.wYear = year; 357 st.wMonth = mon; 358 st.wDay = day; 359 st.wHour = hour; 360 st.wMinute = min; 361 st.wSecond = sec; 362 st.wMilliseconds = 0; 363 SystemTimeToFileTime(&st, &ft()); 364 } 365 366 367 // Convert timestamp to JavaScript timestamp. 368 double Time::ToJSTime() { 369 return static_cast<double>((t() - kTimeEpoc) / kTimeScaler); 370 } 371 372 373 // Guess the name of the timezone from the bias. 374 // The guess is very biased towards the northern hemisphere. 375 const char* Time::GuessTimezoneNameFromBias(int bias) { 376 static const int kHour = 60; 377 switch (-bias) { 378 case -9*kHour: return "Alaska"; 379 case -8*kHour: return "Pacific"; 380 case -7*kHour: return "Mountain"; 381 case -6*kHour: return "Central"; 382 case -5*kHour: return "Eastern"; 383 case -4*kHour: return "Atlantic"; 384 case 0*kHour: return "GMT"; 385 case +1*kHour: return "Central Europe"; 386 case +2*kHour: return "Eastern Europe"; 387 case +3*kHour: return "Russia"; 388 case +5*kHour + 30: return "India"; 389 case +8*kHour: return "China"; 390 case +9*kHour: return "Japan"; 391 case +12*kHour: return "New Zealand"; 392 default: return "Local"; 393 } 394 } 395 396 397 // Initialize timezone information. The timezone information is obtained from 398 // windows. If we cannot get the timezone information we fall back to CET. 399 // Please notice that this code is not thread-safe. 400 void Time::TzSet() { 401 // Just return if timezone information has already been initialized. 402 if (tz_initialized_) return; 403 404 // Initialize POSIX time zone data. 405 _tzset(); 406 // Obtain timezone information from operating system. 407 memset(&tzinfo_, 0, sizeof(tzinfo_)); 408 if (GetTimeZoneInformation(&tzinfo_) == TIME_ZONE_ID_INVALID) { 409 // If we cannot get timezone information we fall back to CET. 410 tzinfo_.Bias = -60; 411 tzinfo_.StandardDate.wMonth = 10; 412 tzinfo_.StandardDate.wDay = 5; 413 tzinfo_.StandardDate.wHour = 3; 414 tzinfo_.StandardBias = 0; 415 tzinfo_.DaylightDate.wMonth = 3; 416 tzinfo_.DaylightDate.wDay = 5; 417 tzinfo_.DaylightDate.wHour = 2; 418 tzinfo_.DaylightBias = -60; 419 } 420 421 // Make standard and DST timezone names. 422 OS::SNPrintF(Vector<char>(std_tz_name_, kTzNameSize), 423 "%S", 424 tzinfo_.StandardName); 425 std_tz_name_[kTzNameSize - 1] = '\0'; 426 OS::SNPrintF(Vector<char>(dst_tz_name_, kTzNameSize), 427 "%S", 428 tzinfo_.DaylightName); 429 dst_tz_name_[kTzNameSize - 1] = '\0'; 430 431 // If OS returned empty string or resource id (like "@tzres.dll,-211") 432 // simply guess the name from the UTC bias of the timezone. 433 // To properly resolve the resource identifier requires a library load, 434 // which is not possible in a sandbox. 435 if (std_tz_name_[0] == '\0' || std_tz_name_[0] == '@') { 436 OS::SNPrintF(Vector<char>(std_tz_name_, kTzNameSize - 1), 437 "%s Standard Time", 438 GuessTimezoneNameFromBias(tzinfo_.Bias)); 439 } 440 if (dst_tz_name_[0] == '\0' || dst_tz_name_[0] == '@') { 441 OS::SNPrintF(Vector<char>(dst_tz_name_, kTzNameSize - 1), 442 "%s Daylight Time", 443 GuessTimezoneNameFromBias(tzinfo_.Bias)); 444 } 445 446 // Timezone information initialized. 447 tz_initialized_ = true; 448 } 449 450 451 // Return the difference in milliseconds between this and another timestamp. 452 int64_t Time::Diff(Time* other) { 453 return (t() - other->t()) / kTimeScaler; 454 } 455 456 457 // Set timestamp to current time. 458 void Time::SetToCurrentTime() { 459 // The default GetSystemTimeAsFileTime has a ~15.5ms resolution. 460 // Because we're fast, we like fast timers which have at least a 461 // 1ms resolution. 462 // 463 // timeGetTime() provides 1ms granularity when combined with 464 // timeBeginPeriod(). If the host application for v8 wants fast 465 // timers, it can use timeBeginPeriod to increase the resolution. 466 // 467 // Using timeGetTime() has a drawback because it is a 32bit value 468 // and hence rolls-over every ~49days. 469 // 470 // To use the clock, we use GetSystemTimeAsFileTime as our base; 471 // and then use timeGetTime to extrapolate current time from the 472 // start time. To deal with rollovers, we resync the clock 473 // any time when more than kMaxClockElapsedTime has passed or 474 // whenever timeGetTime creates a rollover. 475 476 static bool initialized = false; 477 static TimeStamp init_time; 478 static DWORD init_ticks; 479 static const int64_t kHundredNanosecondsPerSecond = 10000000; 480 static const int64_t kMaxClockElapsedTime = 481 60*kHundredNanosecondsPerSecond; // 1 minute 482 483 // If we are uninitialized, we need to resync the clock. 484 bool needs_resync = !initialized; 485 486 // Get the current time. 487 TimeStamp time_now; 488 GetSystemTimeAsFileTime(&time_now.ft_); 489 DWORD ticks_now = timeGetTime(); 490 491 // Check if we need to resync due to clock rollover. 492 needs_resync |= ticks_now < init_ticks; 493 494 // Check if we need to resync due to elapsed time. 495 needs_resync |= (time_now.t_ - init_time.t_) > kMaxClockElapsedTime; 496 497 // Resync the clock if necessary. 498 if (needs_resync) { 499 GetSystemTimeAsFileTime(&init_time.ft_); 500 init_ticks = ticks_now = timeGetTime(); 501 initialized = true; 502 } 503 504 // Finally, compute the actual time. Why is this so hard. 505 DWORD elapsed = ticks_now - init_ticks; 506 this->time_.t_ = init_time.t_ + (static_cast<int64_t>(elapsed) * 10000); 507 } 508 509 510 // Return the local timezone offset in milliseconds east of UTC. This 511 // takes into account whether daylight saving is in effect at the time. 512 // Only times in the 32-bit Unix range may be passed to this function. 513 // Also, adding the time-zone offset to the input must not overflow. 514 // The function EquivalentTime() in date.js guarantees this. 515 int64_t Time::LocalOffset() { 516 // Initialize timezone information, if needed. 517 TzSet(); 518 519 Time rounded_to_second(*this); 520 rounded_to_second.t() = rounded_to_second.t() / 1000 / kTimeScaler * 521 1000 * kTimeScaler; 522 // Convert to local time using POSIX localtime function. 523 // Windows XP Service Pack 3 made SystemTimeToTzSpecificLocalTime() 524 // very slow. Other browsers use localtime(). 525 526 // Convert from JavaScript milliseconds past 1/1/1970 0:00:00 to 527 // POSIX seconds past 1/1/1970 0:00:00. 528 double unchecked_posix_time = rounded_to_second.ToJSTime() / 1000; 529 if (unchecked_posix_time > INT_MAX || unchecked_posix_time < 0) { 530 return 0; 531 } 532 // Because _USE_32BIT_TIME_T is defined, time_t is a 32-bit int. 533 time_t posix_time = static_cast<time_t>(unchecked_posix_time); 534 535 // Convert to local time, as struct with fields for day, hour, year, etc. 536 tm posix_local_time_struct; 537 if (localtime_s(&posix_local_time_struct, &posix_time)) return 0; 538 // Convert local time in struct to POSIX time as if it were a UTC time. 539 time_t local_posix_time = _mkgmtime(&posix_local_time_struct); 540 Time localtime(1000.0 * local_posix_time); 541 542 return localtime.Diff(&rounded_to_second); 543 } 544 545 546 // Return whether or not daylight savings time is in effect at this time. 547 bool Time::InDST() { 548 // Initialize timezone information, if needed. 549 TzSet(); 550 551 // Determine if DST is in effect at the specified time. 552 bool in_dst = false; 553 if (tzinfo_.StandardDate.wMonth != 0 || tzinfo_.DaylightDate.wMonth != 0) { 554 // Get the local timezone offset for the timestamp in milliseconds. 555 int64_t offset = LocalOffset(); 556 557 // Compute the offset for DST. The bias parameters in the timezone info 558 // are specified in minutes. These must be converted to milliseconds. 559 int64_t dstofs = -(tzinfo_.Bias + tzinfo_.DaylightBias) * kMsPerMinute; 560 561 // If the local time offset equals the timezone bias plus the daylight 562 // bias then DST is in effect. 563 in_dst = offset == dstofs; 564 } 565 566 return in_dst; 567 } 568 569 570 // Return the daylight savings time offset for this time. 571 int64_t Time::DaylightSavingsOffset() { 572 return InDST() ? 60 * kMsPerMinute : 0; 573 } 574 575 576 // Returns a string identifying the current timezone for the 577 // timestamp taking into account daylight saving. 578 char* Time::LocalTimezone() { 579 // Return the standard or DST time zone name based on whether daylight 580 // saving is in effect at the given time. 581 return InDST() ? dst_tz_name_ : std_tz_name_; 582 } 583 584 585 void OS::Setup() { 586 // Seed the random number generator. 587 // Convert the current time to a 64-bit integer first, before converting it 588 // to an unsigned. Going directly can cause an overflow and the seed to be 589 // set to all ones. The seed will be identical for different instances that 590 // call this setup code within the same millisecond. 591 uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); 592 srand(static_cast<unsigned int>(seed)); 593 } 594 595 596 // Returns the accumulated user time for thread. 597 int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) { 598 FILETIME dummy; 599 uint64_t usertime; 600 601 // Get the amount of time that the thread has executed in user mode. 602 if (!GetThreadTimes(GetCurrentThread(), &dummy, &dummy, &dummy, 603 reinterpret_cast<FILETIME*>(&usertime))) return -1; 604 605 // Adjust the resolution to micro-seconds. 606 usertime /= 10; 607 608 // Convert to seconds and microseconds 609 *secs = static_cast<uint32_t>(usertime / 1000000); 610 *usecs = static_cast<uint32_t>(usertime % 1000000); 611 return 0; 612 } 613 614 615 // Returns current time as the number of milliseconds since 616 // 00:00:00 UTC, January 1, 1970. 617 double OS::TimeCurrentMillis() { 618 Time t; 619 t.SetToCurrentTime(); 620 return t.ToJSTime(); 621 } 622 623 // Returns the tickcounter based on timeGetTime. 624 int64_t OS::Ticks() { 625 return timeGetTime() * 1000; // Convert to microseconds. 626 } 627 628 629 // Returns a string identifying the current timezone taking into 630 // account daylight saving. 631 const char* OS::LocalTimezone(double time) { 632 return Time(time).LocalTimezone(); 633 } 634 635 636 // Returns the local time offset in milliseconds east of UTC without 637 // taking daylight savings time into account. 638 double OS::LocalTimeOffset() { 639 // Use current time, rounded to the millisecond. 640 Time t(TimeCurrentMillis()); 641 // Time::LocalOffset inlcudes any daylight savings offset, so subtract it. 642 return static_cast<double>(t.LocalOffset() - t.DaylightSavingsOffset()); 643 } 644 645 646 // Returns the daylight savings offset in milliseconds for the given 647 // time. 648 double OS::DaylightSavingsOffset(double time) { 649 int64_t offset = Time(time).DaylightSavingsOffset(); 650 return static_cast<double>(offset); 651 } 652 653 654 // ---------------------------------------------------------------------------- 655 // Win32 console output. 656 // 657 // If a Win32 application is linked as a console application it has a normal 658 // standard output and standard error. In this case normal printf works fine 659 // for output. However, if the application is linked as a GUI application, 660 // the process doesn't have a console, and therefore (debugging) output is lost. 661 // This is the case if we are embedded in a windows program (like a browser). 662 // In order to be able to get debug output in this case the the debugging 663 // facility using OutputDebugString. This output goes to the active debugger 664 // for the process (if any). Else the output can be monitored using DBMON.EXE. 665 666 enum OutputMode { 667 UNKNOWN, // Output method has not yet been determined. 668 CONSOLE, // Output is written to stdout. 669 ODS // Output is written to debug facility. 670 }; 671 672 static OutputMode output_mode = UNKNOWN; // Current output mode. 673 674 675 // Determine if the process has a console for output. 676 static bool HasConsole() { 677 // Only check the first time. Eventual race conditions are not a problem, 678 // because all threads will eventually determine the same mode. 679 if (output_mode == UNKNOWN) { 680 // We cannot just check that the standard output is attached to a console 681 // because this would fail if output is redirected to a file. Therefore we 682 // say that a process does not have an output console if either the 683 // standard output handle is invalid or its file type is unknown. 684 if (GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE && 685 GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) != FILE_TYPE_UNKNOWN) 686 output_mode = CONSOLE; 687 else 688 output_mode = ODS; 689 } 690 return output_mode == CONSOLE; 691 } 692 693 694 static void VPrintHelper(FILE* stream, const char* format, va_list args) { 695 if (HasConsole()) { 696 vfprintf(stream, format, args); 697 } else { 698 // It is important to use safe print here in order to avoid 699 // overflowing the buffer. We might truncate the output, but this 700 // does not crash. 701 EmbeddedVector<char, 4096> buffer; 702 OS::VSNPrintF(buffer, format, args); 703 OutputDebugStringA(buffer.start()); 704 } 705 } 706 707 708 FILE* OS::FOpen(const char* path, const char* mode) { 709 FILE* result; 710 if (fopen_s(&result, path, mode) == 0) { 711 return result; 712 } else { 713 return NULL; 714 } 715 } 716 717 718 // Open log file in binary mode to avoid /n -> /r/n conversion. 719 const char* OS::LogFileOpenMode = "wb"; 720 721 722 // Print (debug) message to console. 723 void OS::Print(const char* format, ...) { 724 va_list args; 725 va_start(args, format); 726 VPrint(format, args); 727 va_end(args); 728 } 729 730 731 void OS::VPrint(const char* format, va_list args) { 732 VPrintHelper(stdout, format, args); 733 } 734 735 736 // Print error message to console. 737 void OS::PrintError(const char* format, ...) { 738 va_list args; 739 va_start(args, format); 740 VPrintError(format, args); 741 va_end(args); 742 } 743 744 745 void OS::VPrintError(const char* format, va_list args) { 746 VPrintHelper(stderr, format, args); 747 } 748 749 750 int OS::SNPrintF(Vector<char> str, const char* format, ...) { 751 va_list args; 752 va_start(args, format); 753 int result = VSNPrintF(str, format, args); 754 va_end(args); 755 return result; 756 } 757 758 759 int OS::VSNPrintF(Vector<char> str, const char* format, va_list args) { 760 int n = _vsnprintf_s(str.start(), str.length(), _TRUNCATE, format, args); 761 // Make sure to zero-terminate the string if the output was 762 // truncated or if there was an error. 763 if (n < 0 || n >= str.length()) { 764 str[str.length() - 1] = '\0'; 765 return -1; 766 } else { 767 return n; 768 } 769 } 770 771 772 char* OS::StrChr(char* str, int c) { 773 return const_cast<char*>(strchr(str, c)); 774 } 775 776 777 void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) { 778 int result = strncpy_s(dest.start(), dest.length(), src, n); 779 USE(result); 780 ASSERT(result == 0); 781 } 782 783 784 // We keep the lowest and highest addresses mapped as a quick way of 785 // determining that pointers are outside the heap (used mostly in assertions 786 // and verification). The estimate is conservative, ie, not all addresses in 787 // 'allocated' space are actually allocated to our heap. The range is 788 // [lowest, highest), inclusive on the low and and exclusive on the high end. 789 static void* lowest_ever_allocated = reinterpret_cast<void*>(-1); 790 static void* highest_ever_allocated = reinterpret_cast<void*>(0); 791 792 793 static void UpdateAllocatedSpaceLimits(void* address, int size) { 794 lowest_ever_allocated = Min(lowest_ever_allocated, address); 795 highest_ever_allocated = 796 Max(highest_ever_allocated, 797 reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size)); 798 } 799 800 801 bool OS::IsOutsideAllocatedSpace(void* pointer) { 802 if (pointer < lowest_ever_allocated || pointer >= highest_ever_allocated) 803 return true; 804 // Ask the Windows API 805 if (IsBadWritePtr(pointer, 1)) 806 return true; 807 return false; 808 } 809 810 811 // Get the system's page size used by VirtualAlloc() or the next power 812 // of two. The reason for always returning a power of two is that the 813 // rounding up in OS::Allocate expects that. 814 static size_t GetPageSize() { 815 static size_t page_size = 0; 816 if (page_size == 0) { 817 SYSTEM_INFO info; 818 GetSystemInfo(&info); 819 page_size = RoundUpToPowerOf2(info.dwPageSize); 820 } 821 return page_size; 822 } 823 824 825 // The allocation alignment is the guaranteed alignment for 826 // VirtualAlloc'ed blocks of memory. 827 size_t OS::AllocateAlignment() { 828 static size_t allocate_alignment = 0; 829 if (allocate_alignment == 0) { 830 SYSTEM_INFO info; 831 GetSystemInfo(&info); 832 allocate_alignment = info.dwAllocationGranularity; 833 } 834 return allocate_alignment; 835 } 836 837 838 void* OS::Allocate(const size_t requested, 839 size_t* allocated, 840 bool is_executable) { 841 // VirtualAlloc rounds allocated size to page size automatically. 842 size_t msize = RoundUp(requested, static_cast<int>(GetPageSize())); 843 844 // Windows XP SP2 allows Data Excution Prevention (DEP). 845 int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; 846 LPVOID mbase = VirtualAlloc(NULL, msize, MEM_COMMIT | MEM_RESERVE, prot); 847 if (mbase == NULL) { 848 LOG(StringEvent("OS::Allocate", "VirtualAlloc failed")); 849 return NULL; 850 } 851 852 ASSERT(IsAligned(reinterpret_cast<size_t>(mbase), OS::AllocateAlignment())); 853 854 *allocated = msize; 855 UpdateAllocatedSpaceLimits(mbase, static_cast<int>(msize)); 856 return mbase; 857 } 858 859 860 void OS::Free(void* address, const size_t size) { 861 // TODO(1240712): VirtualFree has a return value which is ignored here. 862 VirtualFree(address, 0, MEM_RELEASE); 863 USE(size); 864 } 865 866 867 #ifdef ENABLE_HEAP_PROTECTION 868 869 void OS::Protect(void* address, size_t size) { 870 // TODO(1240712): VirtualProtect has a return value which is ignored here. 871 DWORD old_protect; 872 VirtualProtect(address, size, PAGE_READONLY, &old_protect); 873 } 874 875 876 void OS::Unprotect(void* address, size_t size, bool is_executable) { 877 // TODO(1240712): VirtualProtect has a return value which is ignored here. 878 DWORD new_protect = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; 879 DWORD old_protect; 880 VirtualProtect(address, size, new_protect, &old_protect); 881 } 882 883 #endif 884 885 886 void OS::Sleep(int milliseconds) { 887 ::Sleep(milliseconds); 888 } 889 890 891 void OS::Abort() { 892 if (!IsDebuggerPresent()) { 893 #ifdef _MSC_VER 894 // Make the MSVCRT do a silent abort. 895 _set_abort_behavior(0, _WRITE_ABORT_MSG); 896 _set_abort_behavior(0, _CALL_REPORTFAULT); 897 #endif // _MSC_VER 898 abort(); 899 } else { 900 DebugBreak(); 901 } 902 } 903 904 905 void OS::DebugBreak() { 906 #ifdef _MSC_VER 907 __debugbreak(); 908 #else 909 ::DebugBreak(); 910 #endif 911 } 912 913 914 class Win32MemoryMappedFile : public OS::MemoryMappedFile { 915 public: 916 Win32MemoryMappedFile(HANDLE file, HANDLE file_mapping, void* memory) 917 : file_(file), file_mapping_(file_mapping), memory_(memory) { } 918 virtual ~Win32MemoryMappedFile(); 919 virtual void* memory() { return memory_; } 920 private: 921 HANDLE file_; 922 HANDLE file_mapping_; 923 void* memory_; 924 }; 925 926 927 OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, 928 void* initial) { 929 // Open a physical file 930 HANDLE file = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, 931 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL); 932 if (file == NULL) return NULL; 933 // Create a file mapping for the physical file 934 HANDLE file_mapping = CreateFileMapping(file, NULL, 935 PAGE_READWRITE, 0, static_cast<DWORD>(size), NULL); 936 if (file_mapping == NULL) return NULL; 937 // Map a view of the file into memory 938 void* memory = MapViewOfFile(file_mapping, FILE_MAP_ALL_ACCESS, 0, 0, size); 939 if (memory) memmove(memory, initial, size); 940 return new Win32MemoryMappedFile(file, file_mapping, memory); 941 } 942 943 944 Win32MemoryMappedFile::~Win32MemoryMappedFile() { 945 if (memory_ != NULL) 946 UnmapViewOfFile(memory_); 947 CloseHandle(file_mapping_); 948 CloseHandle(file_); 949 } 950 951 952 // The following code loads functions defined in DbhHelp.h and TlHelp32.h 953 // dynamically. This is to avoid being depending on dbghelp.dll and 954 // tlhelp32.dll when running (the functions in tlhelp32.dll have been moved to 955 // kernel32.dll at some point so loading functions defines in TlHelp32.h 956 // dynamically might not be necessary any more - for some versions of Windows?). 957 958 // Function pointers to functions dynamically loaded from dbghelp.dll. 959 #define DBGHELP_FUNCTION_LIST(V) \ 960 V(SymInitialize) \ 961 V(SymGetOptions) \ 962 V(SymSetOptions) \ 963 V(SymGetSearchPath) \ 964 V(SymLoadModule64) \ 965 V(StackWalk64) \ 966 V(SymGetSymFromAddr64) \ 967 V(SymGetLineFromAddr64) \ 968 V(SymFunctionTableAccess64) \ 969 V(SymGetModuleBase64) 970 971 // Function pointers to functions dynamically loaded from dbghelp.dll. 972 #define TLHELP32_FUNCTION_LIST(V) \ 973 V(CreateToolhelp32Snapshot) \ 974 V(Module32FirstW) \ 975 V(Module32NextW) 976 977 // Define the decoration to use for the type and variable name used for 978 // dynamically loaded DLL function.. 979 #define DLL_FUNC_TYPE(name) _##name##_ 980 #define DLL_FUNC_VAR(name) _##name 981 982 // Define the type for each dynamically loaded DLL function. The function 983 // definitions are copied from DbgHelp.h and TlHelp32.h. The IN and VOID macros 984 // from the Windows include files are redefined here to have the function 985 // definitions to be as close to the ones in the original .h files as possible. 986 #ifndef IN 987 #define IN 988 #endif 989 #ifndef VOID 990 #define VOID void 991 #endif 992 993 // DbgHelp isn't supported on MinGW yet 994 #ifndef __MINGW32__ 995 // DbgHelp.h functions. 996 typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymInitialize))(IN HANDLE hProcess, 997 IN PSTR UserSearchPath, 998 IN BOOL fInvadeProcess); 999 typedef DWORD (__stdcall *DLL_FUNC_TYPE(SymGetOptions))(VOID); 1000 typedef DWORD (__stdcall *DLL_FUNC_TYPE(SymSetOptions))(IN DWORD SymOptions); 1001 typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetSearchPath))( 1002 IN HANDLE hProcess, 1003 OUT PSTR SearchPath, 1004 IN DWORD SearchPathLength); 1005 typedef DWORD64 (__stdcall *DLL_FUNC_TYPE(SymLoadModule64))( 1006 IN HANDLE hProcess, 1007 IN HANDLE hFile, 1008 IN PSTR ImageName, 1009 IN PSTR ModuleName, 1010 IN DWORD64 BaseOfDll, 1011 IN DWORD SizeOfDll); 1012 typedef BOOL (__stdcall *DLL_FUNC_TYPE(StackWalk64))( 1013 DWORD MachineType, 1014 HANDLE hProcess, 1015 HANDLE hThread, 1016 LPSTACKFRAME64 StackFrame, 1017 PVOID ContextRecord, 1018 PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, 1019 PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, 1020 PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, 1021 PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); 1022 typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetSymFromAddr64))( 1023 IN HANDLE hProcess, 1024 IN DWORD64 qwAddr, 1025 OUT PDWORD64 pdwDisplacement, 1026 OUT PIMAGEHLP_SYMBOL64 Symbol); 1027 typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetLineFromAddr64))( 1028 IN HANDLE hProcess, 1029 IN DWORD64 qwAddr, 1030 OUT PDWORD pdwDisplacement, 1031 OUT PIMAGEHLP_LINE64 Line64); 1032 // DbgHelp.h typedefs. Implementation found in dbghelp.dll. 1033 typedef PVOID (__stdcall *DLL_FUNC_TYPE(SymFunctionTableAccess64))( 1034 HANDLE hProcess, 1035 DWORD64 AddrBase); // DbgHelp.h typedef PFUNCTION_TABLE_ACCESS_ROUTINE64 1036 typedef DWORD64 (__stdcall *DLL_FUNC_TYPE(SymGetModuleBase64))( 1037 HANDLE hProcess, 1038 DWORD64 AddrBase); // DbgHelp.h typedef PGET_MODULE_BASE_ROUTINE64 1039 1040 // TlHelp32.h functions. 1041 typedef HANDLE (__stdcall *DLL_FUNC_TYPE(CreateToolhelp32Snapshot))( 1042 DWORD dwFlags, 1043 DWORD th32ProcessID); 1044 typedef BOOL (__stdcall *DLL_FUNC_TYPE(Module32FirstW))(HANDLE hSnapshot, 1045 LPMODULEENTRY32W lpme); 1046 typedef BOOL (__stdcall *DLL_FUNC_TYPE(Module32NextW))(HANDLE hSnapshot, 1047 LPMODULEENTRY32W lpme); 1048 1049 #undef IN 1050 #undef VOID 1051 1052 // Declare a variable for each dynamically loaded DLL function. 1053 #define DEF_DLL_FUNCTION(name) DLL_FUNC_TYPE(name) DLL_FUNC_VAR(name) = NULL; 1054 DBGHELP_FUNCTION_LIST(DEF_DLL_FUNCTION) 1055 TLHELP32_FUNCTION_LIST(DEF_DLL_FUNCTION) 1056 #undef DEF_DLL_FUNCTION 1057 1058 // Load the functions. This function has a lot of "ugly" macros in order to 1059 // keep down code duplication. 1060 1061 static bool LoadDbgHelpAndTlHelp32() { 1062 static bool dbghelp_loaded = false; 1063 1064 if (dbghelp_loaded) return true; 1065 1066 HMODULE module; 1067 1068 // Load functions from the dbghelp.dll module. 1069 module = LoadLibrary(TEXT("dbghelp.dll")); 1070 if (module == NULL) { 1071 return false; 1072 } 1073 1074 #define LOAD_DLL_FUNC(name) \ 1075 DLL_FUNC_VAR(name) = \ 1076 reinterpret_cast<DLL_FUNC_TYPE(name)>(GetProcAddress(module, #name)); 1077 1078 DBGHELP_FUNCTION_LIST(LOAD_DLL_FUNC) 1079 1080 #undef LOAD_DLL_FUNC 1081 1082 // Load functions from the kernel32.dll module (the TlHelp32.h function used 1083 // to be in tlhelp32.dll but are now moved to kernel32.dll). 1084 module = LoadLibrary(TEXT("kernel32.dll")); 1085 if (module == NULL) { 1086 return false; 1087 } 1088 1089 #define LOAD_DLL_FUNC(name) \ 1090 DLL_FUNC_VAR(name) = \ 1091 reinterpret_cast<DLL_FUNC_TYPE(name)>(GetProcAddress(module, #name)); 1092 1093 TLHELP32_FUNCTION_LIST(LOAD_DLL_FUNC) 1094 1095 #undef LOAD_DLL_FUNC 1096 1097 // Check that all functions where loaded. 1098 bool result = 1099 #define DLL_FUNC_LOADED(name) (DLL_FUNC_VAR(name) != NULL) && 1100 1101 DBGHELP_FUNCTION_LIST(DLL_FUNC_LOADED) 1102 TLHELP32_FUNCTION_LIST(DLL_FUNC_LOADED) 1103 1104 #undef DLL_FUNC_LOADED 1105 true; 1106 1107 dbghelp_loaded = result; 1108 return result; 1109 // NOTE: The modules are never unloaded and will stay around until the 1110 // application is closed. 1111 } 1112 1113 1114 // Load the symbols for generating stack traces. 1115 static bool LoadSymbols(HANDLE process_handle) { 1116 static bool symbols_loaded = false; 1117 1118 if (symbols_loaded) return true; 1119 1120 BOOL ok; 1121 1122 // Initialize the symbol engine. 1123 ok = _SymInitialize(process_handle, // hProcess 1124 NULL, // UserSearchPath 1125 FALSE); // fInvadeProcess 1126 if (!ok) return false; 1127 1128 DWORD options = _SymGetOptions(); 1129 options |= SYMOPT_LOAD_LINES; 1130 options |= SYMOPT_FAIL_CRITICAL_ERRORS; 1131 options = _SymSetOptions(options); 1132 1133 char buf[OS::kStackWalkMaxNameLen] = {0}; 1134 ok = _SymGetSearchPath(process_handle, buf, OS::kStackWalkMaxNameLen); 1135 if (!ok) { 1136 int err = GetLastError(); 1137 PrintF("%d\n", err); 1138 return false; 1139 } 1140 1141 HANDLE snapshot = _CreateToolhelp32Snapshot( 1142 TH32CS_SNAPMODULE, // dwFlags 1143 GetCurrentProcessId()); // th32ProcessId 1144 if (snapshot == INVALID_HANDLE_VALUE) return false; 1145 MODULEENTRY32W module_entry; 1146 module_entry.dwSize = sizeof(module_entry); // Set the size of the structure. 1147 BOOL cont = _Module32FirstW(snapshot, &module_entry); 1148 while (cont) { 1149 DWORD64 base; 1150 // NOTE the SymLoadModule64 function has the peculiarity of accepting a 1151 // both unicode and ASCII strings even though the parameter is PSTR. 1152 base = _SymLoadModule64( 1153 process_handle, // hProcess 1154 0, // hFile 1155 reinterpret_cast<PSTR>(module_entry.szExePath), // ImageName 1156 reinterpret_cast<PSTR>(module_entry.szModule), // ModuleName 1157 reinterpret_cast<DWORD64>(module_entry.modBaseAddr), // BaseOfDll 1158 module_entry.modBaseSize); // SizeOfDll 1159 if (base == 0) { 1160 int err = GetLastError(); 1161 if (err != ERROR_MOD_NOT_FOUND && 1162 err != ERROR_INVALID_HANDLE) return false; 1163 } 1164 LOG(SharedLibraryEvent( 1165 module_entry.szExePath, 1166 reinterpret_cast<unsigned int>(module_entry.modBaseAddr), 1167 reinterpret_cast<unsigned int>(module_entry.modBaseAddr + 1168 module_entry.modBaseSize))); 1169 cont = _Module32NextW(snapshot, &module_entry); 1170 } 1171 CloseHandle(snapshot); 1172 1173 symbols_loaded = true; 1174 return true; 1175 } 1176 1177 1178 void OS::LogSharedLibraryAddresses() { 1179 // SharedLibraryEvents are logged when loading symbol information. 1180 // Only the shared libraries loaded at the time of the call to 1181 // LogSharedLibraryAddresses are logged. DLLs loaded after 1182 // initialization are not accounted for. 1183 if (!LoadDbgHelpAndTlHelp32()) return; 1184 HANDLE process_handle = GetCurrentProcess(); 1185 LoadSymbols(process_handle); 1186 } 1187 1188 1189 // Walk the stack using the facilities in dbghelp.dll and tlhelp32.dll 1190 1191 // Switch off warning 4748 (/GS can not protect parameters and local variables 1192 // from local buffer overrun because optimizations are disabled in function) as 1193 // it is triggered by the use of inline assembler. 1194 #pragma warning(push) 1195 #pragma warning(disable : 4748) 1196 int OS::StackWalk(Vector<OS::StackFrame> frames) { 1197 BOOL ok; 1198 1199 // Load the required functions from DLL's. 1200 if (!LoadDbgHelpAndTlHelp32()) return kStackWalkError; 1201 1202 // Get the process and thread handles. 1203 HANDLE process_handle = GetCurrentProcess(); 1204 HANDLE thread_handle = GetCurrentThread(); 1205 1206 // Read the symbols. 1207 if (!LoadSymbols(process_handle)) return kStackWalkError; 1208 1209 // Capture current context. 1210 CONTEXT context; 1211 RtlCaptureContext(&context); 1212 1213 // Initialize the stack walking 1214 STACKFRAME64 stack_frame; 1215 memset(&stack_frame, 0, sizeof(stack_frame)); 1216 #ifdef _WIN64 1217 stack_frame.AddrPC.Offset = context.Rip; 1218 stack_frame.AddrFrame.Offset = context.Rbp; 1219 stack_frame.AddrStack.Offset = context.Rsp; 1220 #else 1221 stack_frame.AddrPC.Offset = context.Eip; 1222 stack_frame.AddrFrame.Offset = context.Ebp; 1223 stack_frame.AddrStack.Offset = context.Esp; 1224 #endif 1225 stack_frame.AddrPC.Mode = AddrModeFlat; 1226 stack_frame.AddrFrame.Mode = AddrModeFlat; 1227 stack_frame.AddrStack.Mode = AddrModeFlat; 1228 int frames_count = 0; 1229 1230 // Collect stack frames. 1231 int frames_size = frames.length(); 1232 while (frames_count < frames_size) { 1233 ok = _StackWalk64( 1234 IMAGE_FILE_MACHINE_I386, // MachineType 1235 process_handle, // hProcess 1236 thread_handle, // hThread 1237 &stack_frame, // StackFrame 1238 &context, // ContextRecord 1239 NULL, // ReadMemoryRoutine 1240 _SymFunctionTableAccess64, // FunctionTableAccessRoutine 1241 _SymGetModuleBase64, // GetModuleBaseRoutine 1242 NULL); // TranslateAddress 1243 if (!ok) break; 1244 1245 // Store the address. 1246 ASSERT((stack_frame.AddrPC.Offset >> 32) == 0); // 32-bit address. 1247 frames[frames_count].address = 1248 reinterpret_cast<void*>(stack_frame.AddrPC.Offset); 1249 1250 // Try to locate a symbol for this frame. 1251 DWORD64 symbol_displacement; 1252 IMAGEHLP_SYMBOL64* symbol = NULL; 1253 symbol = NewArray<IMAGEHLP_SYMBOL64>(kStackWalkMaxNameLen); 1254 if (!symbol) return kStackWalkError; // Out of memory. 1255 memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64) + kStackWalkMaxNameLen); 1256 symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); 1257 symbol->MaxNameLength = kStackWalkMaxNameLen; 1258 ok = _SymGetSymFromAddr64(process_handle, // hProcess 1259 stack_frame.AddrPC.Offset, // Address 1260 &symbol_displacement, // Displacement 1261 symbol); // Symbol 1262 if (ok) { 1263 // Try to locate more source information for the symbol. 1264 IMAGEHLP_LINE64 Line; 1265 memset(&Line, 0, sizeof(Line)); 1266 Line.SizeOfStruct = sizeof(Line); 1267 DWORD line_displacement; 1268 ok = _SymGetLineFromAddr64( 1269 process_handle, // hProcess 1270 stack_frame.AddrPC.Offset, // dwAddr 1271 &line_displacement, // pdwDisplacement 1272 &Line); // Line 1273 // Format a text representation of the frame based on the information 1274 // available. 1275 if (ok) { 1276 SNPrintF(MutableCStrVector(frames[frames_count].text, 1277 kStackWalkMaxTextLen), 1278 "%s %s:%d:%d", 1279 symbol->Name, Line.FileName, Line.LineNumber, 1280 line_displacement); 1281 } else { 1282 SNPrintF(MutableCStrVector(frames[frames_count].text, 1283 kStackWalkMaxTextLen), 1284 "%s", 1285 symbol->Name); 1286 } 1287 // Make sure line termination is in place. 1288 frames[frames_count].text[kStackWalkMaxTextLen - 1] = '\0'; 1289 } else { 1290 // No text representation of this frame 1291 frames[frames_count].text[0] = '\0'; 1292 1293 // Continue if we are just missing a module (for non C/C++ frames a 1294 // module will never be found). 1295 int err = GetLastError(); 1296 if (err != ERROR_MOD_NOT_FOUND) { 1297 DeleteArray(symbol); 1298 break; 1299 } 1300 } 1301 DeleteArray(symbol); 1302 1303 frames_count++; 1304 } 1305 1306 // Return the number of frames filled in. 1307 return frames_count; 1308 } 1309 1310 // Restore warnings to previous settings. 1311 #pragma warning(pop) 1312 1313 #else // __MINGW32__ 1314 void OS::LogSharedLibraryAddresses() { } 1315 int OS::StackWalk(Vector<OS::StackFrame> frames) { return 0; } 1316 #endif // __MINGW32__ 1317 1318 1319 uint64_t OS::CpuFeaturesImpliedByPlatform() { 1320 return 0; // Windows runs on anything. 1321 } 1322 1323 1324 double OS::nan_value() { 1325 #ifdef _MSC_VER 1326 // Positive Quiet NaN with no payload (aka. Indeterminate) has all bits 1327 // in mask set, so value equals mask. 1328 static const __int64 nanval = kQuietNaNMask; 1329 return *reinterpret_cast<const double*>(&nanval); 1330 #else // _MSC_VER 1331 return NAN; 1332 #endif // _MSC_VER 1333 } 1334 1335 1336 int OS::ActivationFrameAlignment() { 1337 #ifdef _WIN64 1338 return 16; // Windows 64-bit ABI requires the stack to be 16-byte aligned. 1339 #else 1340 return 8; // Floating-point math runs faster with 8-byte alignment. 1341 #endif 1342 } 1343 1344 1345 bool VirtualMemory::IsReserved() { 1346 return address_ != NULL; 1347 } 1348 1349 1350 VirtualMemory::VirtualMemory(size_t size) { 1351 address_ = VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS); 1352 size_ = size; 1353 } 1354 1355 1356 VirtualMemory::~VirtualMemory() { 1357 if (IsReserved()) { 1358 if (0 == VirtualFree(address(), 0, MEM_RELEASE)) address_ = NULL; 1359 } 1360 } 1361 1362 1363 bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { 1364 int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; 1365 if (NULL == VirtualAlloc(address, size, MEM_COMMIT, prot)) { 1366 return false; 1367 } 1368 1369 UpdateAllocatedSpaceLimits(address, static_cast<int>(size)); 1370 return true; 1371 } 1372 1373 1374 bool VirtualMemory::Uncommit(void* address, size_t size) { 1375 ASSERT(IsReserved()); 1376 return VirtualFree(address, size, MEM_DECOMMIT) != FALSE; 1377 } 1378 1379 1380 // ---------------------------------------------------------------------------- 1381 // Win32 thread support. 1382 1383 // Definition of invalid thread handle and id. 1384 static const HANDLE kNoThread = INVALID_HANDLE_VALUE; 1385 static const DWORD kNoThreadId = 0; 1386 1387 1388 class ThreadHandle::PlatformData : public Malloced { 1389 public: 1390 explicit PlatformData(ThreadHandle::Kind kind) { 1391 Initialize(kind); 1392 } 1393 1394 void Initialize(ThreadHandle::Kind kind) { 1395 switch (kind) { 1396 case ThreadHandle::SELF: tid_ = GetCurrentThreadId(); break; 1397 case ThreadHandle::INVALID: tid_ = kNoThreadId; break; 1398 } 1399 } 1400 DWORD tid_; // Win32 thread identifier. 1401 }; 1402 1403 1404 // Entry point for threads. The supplied argument is a pointer to the thread 1405 // object. The entry function dispatches to the run method in the thread 1406 // object. It is important that this function has __stdcall calling 1407 // convention. 1408 static unsigned int __stdcall ThreadEntry(void* arg) { 1409 Thread* thread = reinterpret_cast<Thread*>(arg); 1410 // This is also initialized by the last parameter to _beginthreadex() but we 1411 // don't know which thread will run first (the original thread or the new 1412 // one) so we initialize it here too. 1413 thread->thread_handle_data()->tid_ = GetCurrentThreadId(); 1414 thread->Run(); 1415 return 0; 1416 } 1417 1418 1419 // Initialize thread handle to invalid handle. 1420 ThreadHandle::ThreadHandle(ThreadHandle::Kind kind) { 1421 data_ = new PlatformData(kind); 1422 } 1423 1424 1425 ThreadHandle::~ThreadHandle() { 1426 delete data_; 1427 } 1428 1429 1430 // The thread is running if it has the same id as the current thread. 1431 bool ThreadHandle::IsSelf() const { 1432 return GetCurrentThreadId() == data_->tid_; 1433 } 1434 1435 1436 // Test for invalid thread handle. 1437 bool ThreadHandle::IsValid() const { 1438 return data_->tid_ != kNoThreadId; 1439 } 1440 1441 1442 void ThreadHandle::Initialize(ThreadHandle::Kind kind) { 1443 data_->Initialize(kind); 1444 } 1445 1446 1447 class Thread::PlatformData : public Malloced { 1448 public: 1449 explicit PlatformData(HANDLE thread) : thread_(thread) {} 1450 HANDLE thread_; 1451 }; 1452 1453 1454 // Initialize a Win32 thread object. The thread has an invalid thread 1455 // handle until it is started. 1456 1457 Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) { 1458 data_ = new PlatformData(kNoThread); 1459 } 1460 1461 1462 // Close our own handle for the thread. 1463 Thread::~Thread() { 1464 if (data_->thread_ != kNoThread) CloseHandle(data_->thread_); 1465 delete data_; 1466 } 1467 1468 1469 // Create a new thread. It is important to use _beginthreadex() instead of 1470 // the Win32 function CreateThread(), because the CreateThread() does not 1471 // initialize thread specific structures in the C runtime library. 1472 void Thread::Start() { 1473 data_->thread_ = reinterpret_cast<HANDLE>( 1474 _beginthreadex(NULL, 1475 0, 1476 ThreadEntry, 1477 this, 1478 0, 1479 reinterpret_cast<unsigned int*>( 1480 &thread_handle_data()->tid_))); 1481 ASSERT(IsValid()); 1482 } 1483 1484 1485 // Wait for thread to terminate. 1486 void Thread::Join() { 1487 WaitForSingleObject(data_->thread_, INFINITE); 1488 } 1489 1490 1491 Thread::LocalStorageKey Thread::CreateThreadLocalKey() { 1492 DWORD result = TlsAlloc(); 1493 ASSERT(result != TLS_OUT_OF_INDEXES); 1494 return static_cast<LocalStorageKey>(result); 1495 } 1496 1497 1498 void Thread::DeleteThreadLocalKey(LocalStorageKey key) { 1499 BOOL result = TlsFree(static_cast<DWORD>(key)); 1500 USE(result); 1501 ASSERT(result); 1502 } 1503 1504 1505 void* Thread::GetThreadLocal(LocalStorageKey key) { 1506 return TlsGetValue(static_cast<DWORD>(key)); 1507 } 1508 1509 1510 void Thread::SetThreadLocal(LocalStorageKey key, void* value) { 1511 BOOL result = TlsSetValue(static_cast<DWORD>(key), value); 1512 USE(result); 1513 ASSERT(result); 1514 } 1515 1516 1517 1518 void Thread::YieldCPU() { 1519 Sleep(0); 1520 } 1521 1522 1523 // ---------------------------------------------------------------------------- 1524 // Win32 mutex support. 1525 // 1526 // On Win32 mutexes are implemented using CRITICAL_SECTION objects. These are 1527 // faster than Win32 Mutex objects because they are implemented using user mode 1528 // atomic instructions. Therefore we only do ring transitions if there is lock 1529 // contention. 1530 1531 class Win32Mutex : public Mutex { 1532 public: 1533 1534 Win32Mutex() { InitializeCriticalSection(&cs_); } 1535 1536 ~Win32Mutex() { DeleteCriticalSection(&cs_); } 1537 1538 int Lock() { 1539 EnterCriticalSection(&cs_); 1540 return 0; 1541 } 1542 1543 int Unlock() { 1544 LeaveCriticalSection(&cs_); 1545 return 0; 1546 } 1547 1548 private: 1549 CRITICAL_SECTION cs_; // Critical section used for mutex 1550 }; 1551 1552 1553 Mutex* OS::CreateMutex() { 1554 return new Win32Mutex(); 1555 } 1556 1557 1558 // ---------------------------------------------------------------------------- 1559 // Win32 semaphore support. 1560 // 1561 // On Win32 semaphores are implemented using Win32 Semaphore objects. The 1562 // semaphores are anonymous. Also, the semaphores are initialized to have 1563 // no upper limit on count. 1564 1565 1566 class Win32Semaphore : public Semaphore { 1567 public: 1568 explicit Win32Semaphore(int count) { 1569 sem = ::CreateSemaphoreA(NULL, count, 0x7fffffff, NULL); 1570 } 1571 1572 ~Win32Semaphore() { 1573 CloseHandle(sem); 1574 } 1575 1576 void Wait() { 1577 WaitForSingleObject(sem, INFINITE); 1578 } 1579 1580 bool Wait(int timeout) { 1581 // Timeout in Windows API is in milliseconds. 1582 DWORD millis_timeout = timeout / 1000; 1583 return WaitForSingleObject(sem, millis_timeout) != WAIT_TIMEOUT; 1584 } 1585 1586 void Signal() { 1587 LONG dummy; 1588 ReleaseSemaphore(sem, 1, &dummy); 1589 } 1590 1591 private: 1592 HANDLE sem; 1593 }; 1594 1595 1596 Semaphore* OS::CreateSemaphore(int count) { 1597 return new Win32Semaphore(count); 1598 } 1599 1600 1601 // ---------------------------------------------------------------------------- 1602 // Win32 socket support. 1603 // 1604 1605 class Win32Socket : public Socket { 1606 public: 1607 explicit Win32Socket() { 1608 // Create the socket. 1609 socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 1610 } 1611 explicit Win32Socket(SOCKET socket): socket_(socket) { } 1612 virtual ~Win32Socket() { Shutdown(); } 1613 1614 // Server initialization. 1615 bool Bind(const int port); 1616 bool Listen(int backlog) const; 1617 Socket* Accept() const; 1618 1619 // Client initialization. 1620 bool Connect(const char* host, const char* port); 1621 1622 // Shutdown socket for both read and write. 1623 bool Shutdown(); 1624 1625 // Data Transimission 1626 int Send(const char* data, int len) const; 1627 int Receive(char* data, int len) const; 1628 1629 bool SetReuseAddress(bool reuse_address); 1630 1631 bool IsValid() const { return socket_ != INVALID_SOCKET; } 1632 1633 private: 1634 SOCKET socket_; 1635 }; 1636 1637 1638 bool Win32Socket::Bind(const int port) { 1639 if (!IsValid()) { 1640 return false; 1641 } 1642 1643 sockaddr_in addr; 1644 memset(&addr, 0, sizeof(addr)); 1645 addr.sin_family = AF_INET; 1646 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 1647 addr.sin_port = htons(port); 1648 int status = bind(socket_, 1649 reinterpret_cast<struct sockaddr *>(&addr), 1650 sizeof(addr)); 1651 return status == 0; 1652 } 1653 1654 1655 bool Win32Socket::Listen(int backlog) const { 1656 if (!IsValid()) { 1657 return false; 1658 } 1659 1660 int status = listen(socket_, backlog); 1661 return status == 0; 1662 } 1663 1664 1665 Socket* Win32Socket::Accept() const { 1666 if (!IsValid()) { 1667 return NULL; 1668 } 1669 1670 SOCKET socket = accept(socket_, NULL, NULL); 1671 if (socket == INVALID_SOCKET) { 1672 return NULL; 1673 } else { 1674 return new Win32Socket(socket); 1675 } 1676 } 1677 1678 1679 bool Win32Socket::Connect(const char* host, const char* port) { 1680 if (!IsValid()) { 1681 return false; 1682 } 1683 1684 // Lookup host and port. 1685 struct addrinfo *result = NULL; 1686 struct addrinfo hints; 1687 memset(&hints, 0, sizeof(addrinfo)); 1688 hints.ai_family = AF_INET; 1689 hints.ai_socktype = SOCK_STREAM; 1690 hints.ai_protocol = IPPROTO_TCP; 1691 int status = getaddrinfo(host, port, &hints, &result); 1692 if (status != 0) { 1693 return false; 1694 } 1695 1696 // Connect. 1697 status = connect(socket_, 1698 result->ai_addr, 1699 static_cast<int>(result->ai_addrlen)); 1700 freeaddrinfo(result); 1701 return status == 0; 1702 } 1703 1704 1705 bool Win32Socket::Shutdown() { 1706 if (IsValid()) { 1707 // Shutdown socket for both read and write. 1708 int status = shutdown(socket_, SD_BOTH); 1709 closesocket(socket_); 1710 socket_ = INVALID_SOCKET; 1711 return status == SOCKET_ERROR; 1712 } 1713 return true; 1714 } 1715 1716 1717 int Win32Socket::Send(const char* data, int len) const { 1718 int status = send(socket_, data, len, 0); 1719 return status; 1720 } 1721 1722 1723 int Win32Socket::Receive(char* data, int len) const { 1724 int status = recv(socket_, data, len, 0); 1725 return status; 1726 } 1727 1728 1729 bool Win32Socket::SetReuseAddress(bool reuse_address) { 1730 BOOL on = reuse_address ? TRUE : FALSE; 1731 int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, 1732 reinterpret_cast<char*>(&on), sizeof(on)); 1733 return status == SOCKET_ERROR; 1734 } 1735 1736 1737 bool Socket::Setup() { 1738 // Initialize Winsock32 1739 int err; 1740 WSADATA winsock_data; 1741 WORD version_requested = MAKEWORD(1, 0); 1742 err = WSAStartup(version_requested, &winsock_data); 1743 if (err != 0) { 1744 PrintF("Unable to initialize Winsock, err = %d\n", Socket::LastError()); 1745 } 1746 1747 return err == 0; 1748 } 1749 1750 1751 int Socket::LastError() { 1752 return WSAGetLastError(); 1753 } 1754 1755 1756 uint16_t Socket::HToN(uint16_t value) { 1757 return htons(value); 1758 } 1759 1760 1761 uint16_t Socket::NToH(uint16_t value) { 1762 return ntohs(value); 1763 } 1764 1765 1766 uint32_t Socket::HToN(uint32_t value) { 1767 return htonl(value); 1768 } 1769 1770 1771 uint32_t Socket::NToH(uint32_t value) { 1772 return ntohl(value); 1773 } 1774 1775 1776 Socket* OS::CreateSocket() { 1777 return new Win32Socket(); 1778 } 1779 1780 1781 #ifdef ENABLE_LOGGING_AND_PROFILING 1782 1783 // ---------------------------------------------------------------------------- 1784 // Win32 profiler support. 1785 // 1786 // On win32 we use a sampler thread with high priority to sample the program 1787 // counter for the profiled thread. 1788 1789 class Sampler::PlatformData : public Malloced { 1790 public: 1791 explicit PlatformData(Sampler* sampler) { 1792 sampler_ = sampler; 1793 sampler_thread_ = INVALID_HANDLE_VALUE; 1794 profiled_thread_ = INVALID_HANDLE_VALUE; 1795 } 1796 1797 Sampler* sampler_; 1798 HANDLE sampler_thread_; 1799 HANDLE profiled_thread_; 1800 1801 // Sampler thread handler. 1802 void Runner() { 1803 // Context used for sampling the register state of the profiled thread. 1804 CONTEXT context; 1805 memset(&context, 0, sizeof(context)); 1806 // Loop until the sampler is disengaged. 1807 while (sampler_->IsActive()) { 1808 TickSample sample; 1809 1810 // If profiling, we record the pc and sp of the profiled thread. 1811 if (sampler_->IsProfiling() 1812 && SuspendThread(profiled_thread_) != (DWORD)-1) { 1813 context.ContextFlags = CONTEXT_FULL; 1814 if (GetThreadContext(profiled_thread_, &context) != 0) { 1815 #if V8_HOST_ARCH_X64 1816 sample.pc = reinterpret_cast<Address>(context.Rip); 1817 sample.sp = reinterpret_cast<Address>(context.Rsp); 1818 sample.fp = reinterpret_cast<Address>(context.Rbp); 1819 #else 1820 sample.pc = reinterpret_cast<Address>(context.Eip); 1821 sample.sp = reinterpret_cast<Address>(context.Esp); 1822 sample.fp = reinterpret_cast<Address>(context.Ebp); 1823 #endif 1824 sampler_->SampleStack(&sample); 1825 } 1826 ResumeThread(profiled_thread_); 1827 } 1828 1829 // We always sample the VM state. 1830 sample.state = Logger::state(); 1831 // Invoke tick handler with program counter and stack pointer. 1832 sampler_->Tick(&sample); 1833 1834 // Wait until next sampling. 1835 Sleep(sampler_->interval_); 1836 } 1837 } 1838 }; 1839 1840 1841 // Entry point for sampler thread. 1842 static unsigned int __stdcall SamplerEntry(void* arg) { 1843 Sampler::PlatformData* data = 1844 reinterpret_cast<Sampler::PlatformData*>(arg); 1845 data->Runner(); 1846 return 0; 1847 } 1848 1849 1850 // Initialize a profile sampler. 1851 Sampler::Sampler(int interval, bool profiling) 1852 : interval_(interval), profiling_(profiling), active_(false) { 1853 data_ = new PlatformData(this); 1854 } 1855 1856 1857 Sampler::~Sampler() { 1858 delete data_; 1859 } 1860 1861 1862 // Start profiling. 1863 void Sampler::Start() { 1864 // If we are profiling, we need to be able to access the calling 1865 // thread. 1866 if (IsProfiling()) { 1867 // Get a handle to the calling thread. This is the thread that we are 1868 // going to profile. We need to make a copy of the handle because we are 1869 // going to use it in the sampler thread. Using GetThreadHandle() will 1870 // not work in this case. We're using OpenThread because DuplicateHandle 1871 // for some reason doesn't work in Chrome's sandbox. 1872 data_->profiled_thread_ = OpenThread(THREAD_GET_CONTEXT | 1873 THREAD_SUSPEND_RESUME | 1874 THREAD_QUERY_INFORMATION, 1875 FALSE, 1876 GetCurrentThreadId()); 1877 BOOL ok = data_->profiled_thread_ != NULL; 1878 if (!ok) return; 1879 } 1880 1881 // Start sampler thread. 1882 unsigned int tid; 1883 active_ = true; 1884 data_->sampler_thread_ = reinterpret_cast<HANDLE>( 1885 _beginthreadex(NULL, 0, SamplerEntry, data_, 0, &tid)); 1886 // Set thread to high priority to increase sampling accuracy. 1887 SetThreadPriority(data_->sampler_thread_, THREAD_PRIORITY_TIME_CRITICAL); 1888 } 1889 1890 1891 // Stop profiling. 1892 void Sampler::Stop() { 1893 // Seting active to false triggers termination of the sampler 1894 // thread. 1895 active_ = false; 1896 1897 // Wait for sampler thread to terminate. 1898 WaitForSingleObject(data_->sampler_thread_, INFINITE); 1899 1900 // Release the thread handles 1901 CloseHandle(data_->sampler_thread_); 1902 CloseHandle(data_->profiled_thread_); 1903 } 1904 1905 1906 #endif // ENABLE_LOGGING_AND_PROFILING 1907 1908 } } // namespace v8::internal 1909