Skip to content

Commit

Permalink
windows: add QueryWorkingSetEx
Browse files Browse the repository at this point in the history
This change adds the QueryWorkingSetEx function for inspecting
the virtual memory details of pointers.

https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-queryworkingsetex

Change-Id: I2bc92bb0b65d34ed1caf88e4d368d64946dfcc5c
GitHub-Last-Rev: c5ac004
GitHub-Pull-Request: #124
Reviewed-on: https://go-review.googlesource.com/c/sys/+/402494
Run-TryBot: Alex Brainman <alex.brainman@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
  • Loading branch information
fumin authored and alexbrainman committed Jul 30, 2022
1 parent 3c1f352 commit 1609e55
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 0 deletions.
69 changes: 69 additions & 0 deletions windows/syscall_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys GetModuleInformation(process Handle, module Handle, modinfo *ModuleInfo, cb uint32) (err error) = psapi.GetModuleInformation
//sys GetModuleFileNameEx(process Handle, module Handle, filename *uint16, size uint32) (err error) = psapi.GetModuleFileNameExW
//sys GetModuleBaseName(process Handle, module Handle, baseName *uint16, size uint32) (err error) = psapi.GetModuleBaseNameW
//sys QueryWorkingSetEx(process Handle, pv uintptr, cb uint32) (err error) = psapi.QueryWorkingSetEx

// NT Native APIs
//sys rtlNtStatusToDosErrorNoTeb(ntstatus NTStatus) (ret syscall.Errno) = ntdll.RtlNtStatusToDosErrorNoTeb
Expand Down Expand Up @@ -1707,3 +1708,71 @@ func LoadResourceData(module, resInfo Handle) (data []byte, err error) {
h.Cap = int(size)
return
}

// PSAPI_WORKING_SET_EX_BLOCK contains extended working set information for a page.
type PSAPI_WORKING_SET_EX_BLOCK uint64

// Valid returns the validity of this page.
// If this bit is 1, the subsequent members are valid; otherwise they should be ignored.
func (b PSAPI_WORKING_SET_EX_BLOCK) Valid() bool {
return (b & 1) == 1
}

// ShareCount is the number of processes that share this page. The maximum value of this member is 7.
func (b PSAPI_WORKING_SET_EX_BLOCK) ShareCount() uint64 {
return b.intField(1, 3)
}

// Win32Protection is the memory protection attributes of the page. For a list of values, see
// https://docs.microsoft.com/en-us/windows/win32/memory/memory-protection-constants
func (b PSAPI_WORKING_SET_EX_BLOCK) Win32Protection() uint64 {
return b.intField(4, 11)
}

// Shared returns the shared status of this page.
// If this bit is 1, the page can be shared.
func (b PSAPI_WORKING_SET_EX_BLOCK) Shared() bool {
return (b & (1 << 15)) == 1
}

// Node is the NUMA node. The maximum value of this member is 63.
func (b PSAPI_WORKING_SET_EX_BLOCK) Node() uint64 {
return b.intField(16, 6)
}

// Locked returns the locked status of this page.
// If this bit is 1, the virtual page is locked in physical memory.
func (b PSAPI_WORKING_SET_EX_BLOCK) Locked() bool {
return (b & (1 << 22)) == 1
}

// LargePage returns the large page status of this page.
// If this bit is 1, the page is a large page.
func (b PSAPI_WORKING_SET_EX_BLOCK) LargePage() bool {
return (b & (1 << 23)) == 1
}

// Bad returns the bad status of this page.
// If this bit is 1, the page is has been reported as bad.
func (b PSAPI_WORKING_SET_EX_BLOCK) Bad() bool {
return (b & (1 << 31)) == 1
}

// intField extracts an integer field in the PSAPI_WORKING_SET_EX_BLOCK union.
func (b PSAPI_WORKING_SET_EX_BLOCK) intField(start, length int) uint64 {
var mask PSAPI_WORKING_SET_EX_BLOCK
for pos := start; pos < start+length; pos++ {
mask |= (1 << pos)
}

masked := b & mask
return uint64(masked >> start)
}

// PSAPI_WORKING_SET_EX_INFORMATION contains extended working set information for a process.
type PSAPI_WORKING_SET_EX_INFORMATION struct {
// The virtual address.
VirtualAddress Pointer
// A PSAPI_WORKING_SET_EX_BLOCK union that indicates the attributes of the page at VirtualAddress.
VirtualAttributes PSAPI_WORKING_SET_EX_BLOCK
}
19 changes: 19 additions & 0 deletions windows/syscall_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,25 @@ func TestProcessModules(t *testing.T) {
}
}

func TestQueryWorkingSetEx(t *testing.T) {
var a int

process := windows.CurrentProcess()
information := windows.PSAPI_WORKING_SET_EX_INFORMATION{
VirtualAddress: windows.Pointer(unsafe.Pointer(&a)),
}
infos := []windows.PSAPI_WORKING_SET_EX_INFORMATION{information}

cb := uint32(uintptr(len(infos)) * unsafe.Sizeof(infos[0]))
if err := windows.QueryWorkingSetEx(process, uintptr(unsafe.Pointer(&infos[0])), cb); err != nil {
t.Fatalf("%+v", err)
}

if !infos[0].VirtualAttributes.Valid() {
t.Errorf("memory location not valid")
}
}

func TestReadWriteProcessMemory(t *testing.T) {
testBuffer := []byte{0xBA, 0xAD, 0xF0, 0x0D}

Expand Down
9 changes: 9 additions & 0 deletions windows/zsyscall_windows.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 1609e55

Please sign in to comment.