777
777
// We keep the lowest and highest addresses mapped as a quick way of
778
778
// determining that pointers are outside the heap (used mostly in assertions
779
// and verification). The estimate is conservative, ie, not all addresses in
779
// and verification). The estimate is conservative, i.e., not all addresses in
780
780
// 'allocated' space are actually allocated to our heap. The range is
781
781
// [lowest, highest), inclusive on the low and and exclusive on the high end.
782
782
static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
834
static void* GetRandomAddr() {
835
Isolate* isolate = Isolate::UncheckedCurrent();
836
// Note that the current isolate isn't set up in a call path via
837
// CpuFeatures::Probe. We don't care about randomization in this case because
838
// the code page is immediately freed.
839
if (isolate != NULL) {
840
// The address range used to randomize RWX allocations in OS::Allocate
841
// Try not to map pages into the default range that windows loads DLLs
842
// Use a multiple of 64k to prevent committing unused memory.
843
// Note: This does not guarantee RWX regions will be within the
844
// range kAllocationRandomAddressMin to kAllocationRandomAddressMax
845
#ifdef V8_HOST_ARCH_64_BIT
846
static const intptr_t kAllocationRandomAddressMin = 0x0000000080000000;
847
static const intptr_t kAllocationRandomAddressMax = 0x000003FFFFFF0000;
849
static const intptr_t kAllocationRandomAddressMin = 0x04000000;
850
static const intptr_t kAllocationRandomAddressMax = 0x3FFF0000;
852
uintptr_t address = (V8::RandomPrivate(isolate) << kPageSizeBits)
853
| kAllocationRandomAddressMin;
854
address &= kAllocationRandomAddressMax;
855
return reinterpret_cast<void *>(address);
861
static void* RandomizedVirtualAlloc(size_t size, int action, int protection) {
864
if (protection == PAGE_EXECUTE_READWRITE || protection == PAGE_NOACCESS) {
865
// For exectutable pages try and randomize the allocation address
866
for (size_t attempts = 0; base == NULL && attempts < 3; ++attempts) {
867
base = VirtualAlloc(GetRandomAddr(), size, action, protection);
871
// After three attempts give up and let the OS find an address to use.
872
if (base == NULL) base = VirtualAlloc(NULL, size, action, protection);
834
878
void* OS::Allocate(const size_t requested,
835
879
size_t* allocated,
836
880
bool is_executable) {
837
// The address range used to randomize RWX allocations in OS::Allocate
838
// Try not to map pages into the default range that windows loads DLLs
839
// Use a multiple of 64k to prevent committing unused memory.
840
// Note: This does not guarantee RWX regions will be within the
841
// range kAllocationRandomAddressMin to kAllocationRandomAddressMax
842
#ifdef V8_HOST_ARCH_64_BIT
843
static const intptr_t kAllocationRandomAddressMin = 0x0000000080000000;
844
static const intptr_t kAllocationRandomAddressMax = 0x000003FFFFFF0000;
846
static const intptr_t kAllocationRandomAddressMin = 0x04000000;
847
static const intptr_t kAllocationRandomAddressMax = 0x3FFF0000;
850
881
// VirtualAlloc rounds allocated size to page size automatically.
851
882
size_t msize = RoundUp(requested, static_cast<int>(GetPageSize()));
852
intptr_t address = 0;
854
884
// Windows XP SP2 allows Data Excution Prevention (DEP).
855
885
int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
857
// For exectutable pages try and randomize the allocation address
858
if (prot == PAGE_EXECUTE_READWRITE &&
859
msize >= static_cast<size_t>(Page::kPageSize)) {
860
address = (V8::RandomPrivate(Isolate::Current()) << kPageSizeBits)
861
| kAllocationRandomAddressMin;
862
address &= kAllocationRandomAddressMax;
865
LPVOID mbase = VirtualAlloc(reinterpret_cast<void *>(address),
867
MEM_COMMIT | MEM_RESERVE,
869
if (mbase == NULL && address != 0)
870
mbase = VirtualAlloc(NULL, msize, MEM_COMMIT | MEM_RESERVE, prot);
887
LPVOID mbase = RandomizedVirtualAlloc(msize,
888
MEM_COMMIT | MEM_RESERVE,
872
891
if (mbase == NULL) {
873
892
LOG(ISOLATE, StringEvent("OS::Allocate", "VirtualAlloc failed"));