Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

May 64-bit Windows allocate virtual memory over 7FFF'FFFF'FFFF?

Context

I'm working on upgrading a .NET library to support 64-bit. That library performs various operation directly in memory of other processes on Windows. I have to choose between the two types IntPtr (max positive value 7FFF'FFFF'FFFF'FFFF) or UIntPtr (max positive value FFFF'FFFF'FFFF'FFFF) to handle my memory pointers. There is a lot of information on the Web about the two. IntPtr seems to be the de facto agreed choice, as it is CLS-compliant and most of .NET API rely on that (ref Marshal from InteropServices).

The question

I decided to open a 64-bit process and inspect the allocated memory regions, as well as the loaded modules in the process to see if it would be valuable to support unsigned pointers using UIntPtr (addresses > 7FFF'FFFF'FFFF'FFFF). As illustrated in the screenshot below, it seems the memory addresses does not load symbols, nor allocate memory over 7FFF'FFFF'FFFF. Is there a specific reason for doing so ? May Windows allocate memory regions over that value in some cases ?

Memory allocation on Cheat Engine (64-bit)

like image 671
Jämes Avatar asked Mar 26 '19 13:03

Jämes


2 Answers

In Windows each process has only an address space of 8TB, therefore the upper limit for user code is 0x7FF'FFFF'FFFF

The range of virtual addresses that is available to a process is called the virtual address space for the process. Each user-mode process has its own private virtual address space. For a 32-bit process, the virtual address space is usually the 2-gigabyte range 0x00000000 through 0x7FFFFFFF. For a 64-bit process, the virtual address space is the 8-terabyte range 0x000'00000000 through 0x7FF'FFFFFFFF. A range of virtual addresses is sometimes called a range of virtual memory.

This diagram illustrates some of the key features of virtual address spaces.

some of the key features of virtual address spaces

https://docs.microsoft.com/en-us/windows-hardware/drivers/gettingstarted/virtual-address-spaces

The upper 248TB belongs to kernel mode, summing up to 256TB of address space, which is addressed by 48 bits. That means the highest possible positive address is 247-1 = 0x7FFF'FFFF'FFFF

In 64-bit Windows, the theoretical amount of virtual address space is 2^64 bytes (16 exabytes), but only a small portion of the 16-exabyte range is actually used. The 8-terabyte range from 0x000'00000000 through 0x7FF'FFFFFFFF is used for user space, and portions of the 248-terabyte range from 0xFFFF0800'00000000 through 0xFFFFFFFF'FFFFFFFF are used for system space.


Update:

As commented below, in Windows 8.1 and Windows Server 2012 R2 or later the user/kernel address space split is 128/128TB which sums up to the same 256TB space


The significant part is 48-bit wide probably because most current x86-64 implementations use 48-bit virtual address

The original implementation of the AMD64 architecture implemented 40-bit physical addresses and so could address up to 1 TB (240 bytes) of RAM. Current implementations of the AMD64 architecture (starting from AMD 10h microarchitecture) extend this to 48-bit physical addresses and therefore can address up to 256 TB of RAM. The architecture permits extending this to 52 bits in the future (limited by the page table entry format); this would allow addressing of up to 4 PB of RAM.

https://en.wikipedia.org/wiki/X86-64#Architectural_features

like image 136
phuclv Avatar answered Nov 15 '22 07:11

phuclv


Due to specifications on x64 you can depend on userspace pointers always fitting in IntPtr. You cannot depend on a smaller space. The CPU could get more address lines in the future. When this happened between Windows 8 and Windows 8.1, no backwards compatibility flag was added.

In fact you got both positive and negative pointers in x86, but storing pointers in IntPtr worked anyway because of the no-mans-land at 0x7FFF0000 and the null trap range at 0x00000000.

I don't think you're trying to do tagged pointers, but if you are, the only acceptable way to do tagged pointers is the bottom two bits.

like image 35
Joshua Avatar answered Nov 15 '22 08:11

Joshua