105ed9ddc6ff3a1ab3983c50d378cddfa257869b6jkummerow@chromium.org// Copyright 2012 the V8 project authors. All rights reserved. 23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be 33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file. 43a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 5e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org// Platform-specific code for Cygwin goes here. For the POSIX-compatible 6e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org// parts, the implementation is in platform-posix.cc. 73a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 83a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#include <errno.h> 93a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#include <pthread.h> 103a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#include <semaphore.h> 113a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#include <stdarg.h> 123a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#include <strings.h> // index 133a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#include <sys/time.h> 143a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#include <sys/mman.h> // mmap & munmap 153a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#include <unistd.h> // sysconf 163a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 173a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#undef MAP_TYPE 183a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 19196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h" 203a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 211e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#include "src/base/win32-headers.h" 22196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/platform.h" 233a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 243a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgnamespace v8 { 253a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgnamespace internal { 263a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 273a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 286b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgconst char* OS::LocalTimezone(double time, TimezoneCache* cache) { 2977ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org if (std::isnan(time)) return ""; 30e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org time_t tv = static_cast<time_t>(std::floor(time/msPerSecond)); 313a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org struct tm* t = localtime(&tv); 323a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org if (NULL == t) return ""; 333a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org return tzname[0]; // The location of the timezone string on Cygwin. 343a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org} 353a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 363a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 376b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgdouble OS::LocalTimeOffset(TimezoneCache* cache) { 383a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // On Cygwin, struct tm does not contain a tm_gmtoff field. 393a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org time_t utc = time(NULL); 403a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org ASSERT(utc != -1); 413a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org struct tm* loc = localtime(&utc); 423a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org ASSERT(loc != NULL); 433a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // time - localtime includes any daylight savings offset, so subtract it. 443a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org return static_cast<double>((mktime(loc) - utc) * msPerSecond - 453a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org (loc->tm_isdst > 0 ? 3600 * msPerSecond : 0)); 463a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org} 473a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 483a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 493a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgvoid* OS::Allocate(const size_t requested, 503a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org size_t* allocated, 513a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org bool is_executable) { 523a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org const size_t msize = RoundUp(requested, sysconf(_SC_PAGESIZE)); 533a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); 543a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 551845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (mbase == MAP_FAILED) return NULL; 563a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org *allocated = msize; 573a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org return mbase; 583a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org} 593a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 603a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 613a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgclass PosixMemoryMappedFile : public OS::MemoryMappedFile { 623a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org public: 633a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org PosixMemoryMappedFile(FILE* file, void* memory, int size) 643a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org : file_(file), memory_(memory), size_(size) { } 653a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org virtual ~PosixMemoryMappedFile(); 663a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org virtual void* memory() { return memory_; } 673a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org virtual int size() { return size_; } 683a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org private: 693a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org FILE* file_; 703a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org void* memory_; 713a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org int size_; 723a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}; 733a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 743a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 753a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgOS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) { 763a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org FILE* file = fopen(name, "r+"); 773a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org if (file == NULL) return NULL; 783a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 793a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org fseek(file, 0, SEEK_END); 803a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org int size = ftell(file); 813a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 823a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org void* memory = 833a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); 843a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org return new PosixMemoryMappedFile(file, memory, size); 853a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org} 863a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 873a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 883a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgOS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, 893a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org void* initial) { 903a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org FILE* file = fopen(name, "w+"); 913a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org if (file == NULL) return NULL; 923a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org int result = fwrite(initial, size, 1, file); 933a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org if (result < 1) { 943a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org fclose(file); 953a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org return NULL; 963a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org } 973a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org void* memory = 983a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); 993a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org return new PosixMemoryMappedFile(file, memory, size); 1003a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org} 1013a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 1023a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 1033a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgPosixMemoryMappedFile::~PosixMemoryMappedFile() { 1043a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org if (memory_) munmap(memory_, size_); 1053a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org fclose(file_); 1063a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org} 1073a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 1083a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 1091845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgstd::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() { 1101845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org std::vector<SharedLibraryAddresses> result; 1113a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // This function assumes that the layout of the file is as follows: 1123a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name] 1133a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // If we encounter an unexpected situation we abort scanning further entries. 1143a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org FILE* fp = fopen("/proc/self/maps", "r"); 1151845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (fp == NULL) return result; 1163a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 1173a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // Allocate enough room to be able to store a full file name. 1183a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org const int kLibNameLen = FILENAME_MAX + 1; 1193a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen)); 1203a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 1213a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // This loop will terminate once the scanning hits an EOF. 1223a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org while (true) { 1233a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org uintptr_t start, end; 1243a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org char attr_r, attr_w, attr_x, attr_p; 1253a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // Parse the addresses and permission bits at the beginning of the line. 1263a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break; 1273a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break; 1283a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 1293a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org int c; 1303a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') { 1313a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // Found a read-only executable entry. Skip characters until we reach 1323a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // the beginning of the filename or the end of the line. 1333a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org do { 1343a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org c = getc(fp); 1353a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org } while ((c != EOF) && (c != '\n') && (c != '/')); 1363a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org if (c == EOF) break; // EOF: Was unexpected, just exit. 1373a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 1383a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // Process the filename if found. 1393a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org if (c == '/') { 1403a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org ungetc(c, fp); // Push the '/' back into the stream to be read below. 1413a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 1423a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // Read to the end of the line. Exit if the read fails. 1433a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org if (fgets(lib_name, kLibNameLen, fp) == NULL) break; 1443a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 1453a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // Drop the newline character read by fgets. We do not need to check 1463a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // for a zero-length string because we know that we at least read the 1473a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // '/' character. 1483a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org lib_name[strlen(lib_name) - 1] = '\0'; 1493a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org } else { 1503a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // No library name found, just record the raw address range. 1513a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org snprintf(lib_name, kLibNameLen, 1523a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end); 1533a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org } 1541845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org result.push_back(SharedLibraryAddress(lib_name, start, end)); 1553a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org } else { 156f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com // Entry not describing executable data. Skip to end of line to set up 1573a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // reading the next entry. 1583a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org do { 1593a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org c = getc(fp); 1603a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org } while ((c != EOF) && (c != '\n')); 1613a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org if (c == EOF) break; 1623a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org } 1633a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org } 1643a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org free(lib_name); 1653a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org fclose(fp); 1661845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org return result; 1673a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org} 1683a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 1693a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 1703a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgvoid OS::SignalCodeMovingGC() { 1713a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // Nothing to do on Cygwin. 1723a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org} 1733a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 1743a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 175c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org// The VirtualMemory implementation is taken from platform-win32.cc. 176c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org// The mmap-based virtual memory implementation as it is used on most posix 177c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org// platforms does not work well because Cygwin does not support MAP_FIXED. 178c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org// This causes VirtualMemory::Commit to not always commit the memory region 179c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org// specified. 180c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org 181e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgstatic void* GetRandomAddr() { 182e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org Isolate* isolate = Isolate::UncheckedCurrent(); 183e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Note that the current isolate isn't set up in a call path via 184e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // CpuFeatures::Probe. We don't care about randomization in this case because 185e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // the code page is immediately freed. 186e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org if (isolate != NULL) { 187e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // The address range used to randomize RWX allocations in OS::Allocate 188e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Try not to map pages into the default range that windows loads DLLs 189e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Use a multiple of 64k to prevent committing unused memory. 190e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Note: This does not guarantee RWX regions will be within the 191e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // range kAllocationRandomAddressMin to kAllocationRandomAddressMax 192e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org#ifdef V8_HOST_ARCH_64_BIT 193e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org static const intptr_t kAllocationRandomAddressMin = 0x0000000080000000; 194e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org static const intptr_t kAllocationRandomAddressMax = 0x000003FFFFFF0000; 195e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org#else 196e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org static const intptr_t kAllocationRandomAddressMin = 0x04000000; 197e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org static const intptr_t kAllocationRandomAddressMax = 0x3FFF0000; 198e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org#endif 199c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org uintptr_t address = 200c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org (isolate->random_number_generator()->NextInt() << kPageSizeBits) | 201c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org kAllocationRandomAddressMin; 202e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org address &= kAllocationRandomAddressMax; 203e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org return reinterpret_cast<void *>(address); 204e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org } 205e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org return NULL; 206e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org} 207e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 208e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 209e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgstatic void* RandomizedVirtualAlloc(size_t size, int action, int protection) { 210e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org LPVOID base = NULL; 211e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 212e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org if (protection == PAGE_EXECUTE_READWRITE || protection == PAGE_NOACCESS) { 213e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // For exectutable pages try and randomize the allocation address 214e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org for (size_t attempts = 0; base == NULL && attempts < 3; ++attempts) { 215e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org base = VirtualAlloc(GetRandomAddr(), size, action, protection); 216e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org } 217e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org } 218e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 219e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // After three attempts give up and let the OS find an address to use. 220e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org if (base == NULL) base = VirtualAlloc(NULL, size, action, protection); 221e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 222e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org return base; 223c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org} 2243a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 2253a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 226e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgVirtualMemory::VirtualMemory() : address_(NULL), size_(0) { } 227e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 228e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 229e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgVirtualMemory::VirtualMemory(size_t size) 230e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org : address_(ReserveRegion(size)), size_(size) { } 231e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 232e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 233e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgVirtualMemory::VirtualMemory(size_t size, size_t alignment) 234e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org : address_(NULL), size_(0) { 235e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment()))); 236e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org size_t request_size = RoundUp(size + alignment, 237e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org static_cast<intptr_t>(OS::AllocateAlignment())); 238e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org void* address = ReserveRegion(request_size); 239e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org if (address == NULL) return; 240e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org Address base = RoundUp(static_cast<Address>(address), alignment); 241e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Try reducing the size by freeing and then reallocating a specific area. 242e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org bool result = ReleaseRegion(address, request_size); 243e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org USE(result); 244e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org ASSERT(result); 245e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org address = VirtualAlloc(base, size, MEM_RESERVE, PAGE_NOACCESS); 246e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org if (address != NULL) { 247e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org request_size = size; 248e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org ASSERT(base == static_cast<Address>(address)); 249e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org } else { 250e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Resizing failed, just go with a bigger area. 251e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org address = ReserveRegion(request_size); 252e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org if (address == NULL) return; 253e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org } 254e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org address_ = address; 255e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org size_ = request_size; 2563a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org} 2573a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 2583a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 2593a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgVirtualMemory::~VirtualMemory() { 2603a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org if (IsReserved()) { 261e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org bool result = ReleaseRegion(address_, size_); 262e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org ASSERT(result); 263e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org USE(result); 2643a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org } 2653a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org} 2663a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 2673a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 268e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgbool VirtualMemory::IsReserved() { 269e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org return address_ != NULL; 270e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org} 2713a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 272e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 273e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgvoid VirtualMemory::Reset() { 274e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org address_ = NULL; 275e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org size_ = 0; 276e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org} 277e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 278e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 279e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgbool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { 280e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org return CommitRegion(address, size, is_executable); 2813a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org} 2823a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 2833a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 2843a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgbool VirtualMemory::Uncommit(void* address, size_t size) { 285c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org ASSERT(IsReserved()); 286e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org return UncommitRegion(address, size); 287e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org} 288e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 289e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 290e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgvoid* VirtualMemory::ReserveRegion(size_t size) { 291e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org return RandomizedVirtualAlloc(size, MEM_RESERVE, PAGE_NOACCESS); 292e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org} 293e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 294e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 295e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgbool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) { 296e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; 297e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org if (NULL == VirtualAlloc(base, size, MEM_COMMIT, prot)) { 298e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org return false; 299e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org } 300e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org return true; 3013a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org} 3023a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 3033a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 304ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.orgbool VirtualMemory::Guard(void* address) { 305ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org if (NULL == VirtualAlloc(address, 306ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org OS::CommitPageSize(), 307ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org MEM_COMMIT, 308c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org PAGE_NOACCESS)) { 309ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org return false; 310ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org } 311ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org return true; 312ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org} 313ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org 314ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org 315e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgbool VirtualMemory::UncommitRegion(void* base, size_t size) { 316e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org return VirtualFree(base, size, MEM_DECOMMIT) != 0; 317e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org} 318e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 319e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 320e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgbool VirtualMemory::ReleaseRegion(void* base, size_t size) { 321e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org return VirtualFree(base, 0, MEM_RELEASE) != 0; 322e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org} 323e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 324e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 32572204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.orgbool VirtualMemory::HasLazyCommits() { 32672204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org // TODO(alph): implement for the platform. 32772204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org return false; 32872204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org} 32972204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org 3303a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org} } // namespace v8::internal 331