Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions pkg/callstack/callstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"strconv"
"strings"

"github.com/rabbitstack/fibratus/pkg/sys"
"github.com/rabbitstack/fibratus/pkg/util/va"
"golang.org/x/arch/x86/x86asm"
"golang.org/x/sys/windows"
Expand Down Expand Up @@ -66,23 +67,34 @@ func (f *Frame) AllocationSize(proc windows.Handle) uint64 {
return 0
}

pageCount := r.Size / pageSize
m := make([]sys.MemoryWorkingSetExInformation, pageCount)
for n := range pageCount {
addr := f.Addr.Inc(n * pageSize)
m[n].VirtualAddress = addr.Uintptr()
}

ws := va.QueryWorkingSet(proc, m)
if ws == nil {
return 0
}

var size uint64

// traverse all pages in the region
for n := uint64(0); n < r.Size; n += pageSize {
addr := f.Addr.Inc(n)
ws := va.QueryWorkingSet(proc, addr.Uint64())
if ws == nil || !ws.Valid() {
for _, r := range ws {
attr := r.VirtualAttributes
if !attr.Valid() {
continue
}

// use SharedOriginal after RS3/1709
if buildNumber >= 16299 {
if !ws.SharedOriginal() {
if !attr.SharedOriginal() {
size += pageSize
}
} else {
if !ws.Shared() {
if !attr.Shared() {
size += pageSize
}
}
Expand Down
20 changes: 4 additions & 16 deletions pkg/util/va/region.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ package va

import (
"expvar"
"github.com/rabbitstack/fibratus/pkg/sys"
"golang.org/x/sys/windows"
"golang.org/x/time/rate"
"strconv"
"sync"
"unsafe"

"github.com/rabbitstack/fibratus/pkg/sys"
"golang.org/x/sys/windows"
"golang.org/x/time/rate"
)

const (
Expand Down Expand Up @@ -183,19 +184,6 @@ func VirtualQuery(process windows.Handle, addr uint64) *RegionInfo {
}
}

// QueryWorkingSet retrieves extended information about
// the pages at specific virtual addresses in the address
// space of the specified process.
func QueryWorkingSet(process windows.Handle, addr uint64) *sys.MemoryWorkingSetExBlock {
var ws sys.MemoryWorkingSetExInformation
ws.VirtualAddress = uintptr(addr)
err := sys.QueryWorkingSet(process, &ws, uint32(unsafe.Sizeof(sys.MemoryWorkingSetExInformation{})))
if err != nil {
return nil
}
return &ws.VirtualAttributes
}

// Remove removes the process handle from cache and closes it.
// It returns true if the handle was closed successfully.
func (p *RegionProber) Remove(pid uint32) bool {
Expand Down
20 changes: 4 additions & 16 deletions pkg/util/va/region_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@
package va

import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/sys/windows"
"os"
"testing"
"time"
"unsafe"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/sys/windows"
)

func TestRegionProber(t *testing.T) {
Expand Down Expand Up @@ -125,19 +126,6 @@ func TestReadArea(t *testing.T) {
require.True(t, Zeroed(zeroArea))
}

func TestQueryWorkingSet(t *testing.T) {
addr, err := getModuleBaseAddress(uint32(os.Getpid()))
require.NoError(t, err)

b := QueryWorkingSet(windows.CurrentProcess(), uint64(addr))
require.NotNil(t, b)

require.True(t, b.Valid())
require.False(t, b.Bad())
require.True(t, b.SharedOriginal())
require.True(t, (b.Win32Protection()&windows.PAGE_READONLY) != 0)
}

func getModuleBaseAddress(pid uint32) (uintptr, error) {
var moduleHandles [1024]windows.Handle
var cbNeeded uint32
Expand Down
Loading
Loading