Esempio n. 1
0
void *AllocateExecutableMemory(size_t size, bool exec) {
#if defined(_WIN32)
	void *ptr;
#if defined(_M_X64)
	if (exec && (uintptr_t)&hint_location > 0xFFFFFFFFULL) {
		if (sys_info.dwPageSize == 0)
			GetSystemInfo(&sys_info);

		size_t aligned_size = round_page(size);
		ptr = SearchForFreeMem(aligned_size);
		if (!ptr) {
			// Let's try again, from the top.
			// When we deallocate, this doesn't change, so we eventually run out of space.
			last_executable_addr = 0;
			ptr = SearchForFreeMem(aligned_size);
		}
		if (ptr) {
			ptr = VirtualAlloc(ptr, aligned_size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
		} else {
			ERROR_LOG(COMMON, "Unable to find nearby executable memory for jit");
		}
	}
	else
#endif
		ptr = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#elif defined(__SYMBIAN32__)
	//This function may be called more than once, and we want to create only one big
	//memory chunk for all the executable code for the JIT
	if( g_code_chunk == NULL && g_code_heap == NULL)
	{
		g_code_chunk = new RChunk();
		g_code_chunk->CreateLocalCode(CODECHUNK_SIZE, CODECHUNK_SIZE + 3*GetPageSize());
		g_code_heap = UserHeap::ChunkHeap(*g_code_chunk, CODECHUNK_SIZE, 1, CODECHUNK_SIZE + 3*GetPageSize());
		g_next_ptr = reinterpret_cast<u8*>(g_code_heap->AllocZ(CODECHUNK_SIZE));
		g_orig_ptr = g_next_ptr;
	}
	void* ptr = (void*)g_next_ptr;
	g_next_ptr += size;
#else
	static char *map_hint = 0;
#if defined(_M_X64)
	// Try to request one that is close to our memory location if we're in high memory.
	// We use a dummy global variable to give us a good location to start from.
	if (exec && (!map_hint))
	{
		if ((uintptr_t) &hint_location > 0xFFFFFFFFULL)
			map_hint = (char*)round_page(&hint_location) - 0x20000000; // 0.5gb lower than our approximate location
		else
			map_hint = (char*)0x20000000; // 0.5GB mark in memory
	}
	else if (exec && (uintptr_t) map_hint > 0xFFFFFFFFULL)
	{
		map_hint -= round_page(size); /* round down to the next page if we're in high memory */
	}
#endif
	void* ptr = mmap(map_hint, size, PROT_READ | PROT_WRITE	| PROT_EXEC,
		MAP_ANON | MAP_PRIVATE
#if defined(_M_X64) && defined(MAP_32BIT)
		| (exec && (uintptr_t) map_hint == 0 ? MAP_32BIT : 0)
#endif
		, -1, 0);

#endif /* defined(_WIN32) */

#if !defined(_WIN32) && !defined(__SYMBIAN32__)
	static const void *failed_result = MAP_FAILED;
#else
	static const void *failed_result = nullptr;
#endif

	if (ptr == failed_result) {
		ptr = nullptr;
		PanicAlert("Failed to allocate executable memory\n%s", GetLastErrorMsg());
	}
#if defined(_M_X64) && !defined(_WIN32)
	else if (exec && (uintptr_t)map_hint <= 0xFFFFFFFF) {
		// Round up if we're below 32-bit mark, probably allocating sequentially.
		map_hint += round_page(size);

		// If we moved ahead too far, skip backwards and recalculate.
		// When we free, we keep moving forward and eventually move too far.
		if ((uintptr_t)map_hint - (uintptr_t) &hint_location >= 0x70000000) {
			map_hint = 0;
		}
	}
#endif

	return ptr;
}
Esempio n. 2
0
void *AllocateExecutableMemory(size_t size) {
#if defined(_WIN32)
	void *ptr = nullptr;
	DWORD prot = PAGE_EXECUTE_READWRITE;
	if (PlatformIsWXExclusive())
		prot = PAGE_READWRITE;
	if (sys_info.dwPageSize == 0)
		GetSystemInfo(&sys_info);
#if defined(_M_X64)
	if ((uintptr_t)&hint_location > 0xFFFFFFFFULL) {
		size_t aligned_size = round_page(size);
#if 1   // Turn off to hunt for RIP bugs on x86-64.
		ptr = SearchForFreeMem(aligned_size);
		if (!ptr) {
			// Let's try again, from the top.
			// When we deallocate, this doesn't change, so we eventually run out of space.
			last_executable_addr = 0;
			ptr = SearchForFreeMem(aligned_size);
		}
#endif
		if (ptr) {
			ptr = VirtualAlloc(ptr, aligned_size, MEM_RESERVE | MEM_COMMIT, prot);
		} else {
			WARN_LOG(COMMON, "Unable to find nearby executable memory for jit. Proceeding with far memory.");
			// Can still run, thanks to "RipAccessible".
			ptr = VirtualAlloc(nullptr, aligned_size, MEM_RESERVE | MEM_COMMIT, prot);
		}
	}
	else
#endif
	{
#if PPSSPP_PLATFORM(UWP)
		ptr = VirtualAllocFromApp(0, size, MEM_RESERVE | MEM_COMMIT, prot);
#else
		ptr = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, prot);
#endif
	}
#else
	static char *map_hint = 0;
#if defined(_M_X64) && !defined(MAP_32BIT)
	// Try to request one that is close to our memory location if we're in high memory.
	// We use a dummy global variable to give us a good location to start from.
	if (!map_hint) {
		if ((uintptr_t) &hint_location > 0xFFFFFFFFULL)
			map_hint = (char*)round_page(&hint_location) - 0x20000000; // 0.5gb lower than our approximate location
		else
			map_hint = (char*)0x20000000; // 0.5GB mark in memory
	}
	else if ((uintptr_t) map_hint > 0xFFFFFFFFULL)
	{
		map_hint -= round_page(size); /* round down to the next page if we're in high memory */
	}
#endif

	int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
	if (PlatformIsWXExclusive())
		prot = PROT_READ | PROT_WRITE;  // POST_EXEC is added later in this case.

	void* ptr = mmap(map_hint, size, prot,
		MAP_ANON | MAP_PRIVATE
#if defined(_M_X64) && defined(MAP_32BIT)
		| MAP_32BIT
#endif
		, -1, 0);

#endif /* defined(_WIN32) */

#if !defined(_WIN32)
	static const void *failed_result = MAP_FAILED;
#else
	static const void *failed_result = nullptr;
#endif

	if (ptr == failed_result) {
		ptr = nullptr;
		ERROR_LOG(MEMMAP, "Failed to allocate executable memory (%d)", (int)size);
		PanicAlert("Failed to allocate executable memory\n%s", GetLastErrorMsg());
	}
#if defined(_M_X64) && !defined(_WIN32) && !defined(MAP_32BIT)
	else if ((uintptr_t)map_hint <= 0xFFFFFFFF) {
		// Round up if we're below 32-bit mark, probably allocating sequentially.
		map_hint += round_page(size);

		// If we moved ahead too far, skip backwards and recalculate.
		// When we free, we keep moving forward and eventually move too far.
		if ((uintptr_t)map_hint - (uintptr_t) &hint_location >= 0x70000000) {
			map_hint = 0;
		}
	}
#endif
	return ptr;
}
Esempio n. 3
0
void* AllocateExecutableMemory(size_t size, bool exec)
{
#if defined(_WIN32)
	void* ptr;
#if defined(_M_X64)
	if (exec && (uintptr_t) &hint_location > 0xFFFFFFFFULL)
	{
		if (!last_addr)
			GetSystemInfo(&sys_info);

		size_t _size = round_page(size);
		ptr = SearchForFreeMem(_size);
		if (ptr)
			ptr = VirtualAlloc(ptr, _size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	}
	else
#endif
		ptr = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#elif defined(__SYMBIAN32__)
	//This function may be called more than once, and we want to create only one big
	//memory chunk for all the executable code for the JIT
	if( g_code_chunk == NULL && g_code_heap == NULL)
	{
		g_code_chunk = new RChunk();
		g_code_chunk->CreateLocalCode(CODECHUNK_SIZE, CODECHUNK_SIZE + 3*GetPageSize());
		g_code_heap = UserHeap::ChunkHeap(*g_code_chunk, CODECHUNK_SIZE, 1, CODECHUNK_SIZE + 3*GetPageSize());
		g_next_ptr = reinterpret_cast<u8*>(g_code_heap->AllocZ(CODECHUNK_SIZE));
		g_orig_ptr = g_next_ptr;
	}
	void* ptr = (void*)g_next_ptr;
	g_next_ptr += size;
#else
	static char *map_hint = 0;
#if defined(_M_X64)
	// Try to request one that is close to our memory location if we're in high memory.
	// We use a dummy global variable to give us a good location to start from.
	if (exec && (!map_hint))
	{
		if ((uintptr_t) &hint_location > 0xFFFFFFFFULL)
			map_hint = (char*)round_page(&hint_location) - 0x20000000; // 0.5gb lower than our approximate location
		else
			map_hint = (char*)0x20000000; // 0.5GB mark in memory
	}
	else if (exec && (uintptr_t) map_hint > 0xFFFFFFFFULL)
	{
		map_hint -= round_page(size); /* round down to the next page if we're in high memory */
	}
#endif
	void* ptr = mmap(map_hint, size, PROT_READ | PROT_WRITE	| PROT_EXEC,
		MAP_ANON | MAP_PRIVATE
#if defined(_M_X64) && defined(MAP_32BIT)
		| (exec && (uintptr_t) map_hint == 0 ? MAP_32BIT : 0)
#endif
		, -1, 0);

#endif /* defined(_WIN32) */

	// printf("Mapped executable memory at %p (size %ld)\n", ptr,
	//	(unsigned long)size);

#if !defined(_WIN32) && !defined(__SYMBIAN32__)
	if (ptr == MAP_FAILED)
	{
		ptr = NULL;
#else
	if (ptr == NULL)
	{
#endif
		PanicAlert("Failed to allocate executable memory");
	}
#if defined(_M_X64) && !defined(_WIN32)
	else if (exec && (uintptr_t) map_hint <= 0xFFFFFFFF)
	{
		map_hint += round_page(size); /* round up if we're below 32-bit mark, probably allocating sequentially */
	}
#endif

	return ptr;
}

void* AllocateMemoryPages(size_t size)
{
	size = (size + 4095) & (~4095);
#ifdef _WIN32
	void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
#elif defined(__SYMBIAN32__)
	void* ptr = malloc(size);
#else
	void* ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
#endif

	// printf("Mapped memory at %p (size %ld)\n", ptr,
	//	(unsigned long)size);
	if (ptr == NULL)
		PanicAlert("Failed to allocate raw memory");

	return ptr;
}