From: Vibhav Pant vibhavp@gmail.com
--- configure | 10 ++++++ configure.ac | 1 + dlls/ntdll/unix/virtual.c | 65 ++++++++++++++++++++++++++++++++++++--- include/config.h.in | 3 ++ 4 files changed, 74 insertions(+), 5 deletions(-)
diff --git a/configure b/configure index 15cf8f98459..844ee5409e0 100755 --- a/configure +++ b/configure @@ -21065,6 +21065,16 @@ then : printf "%s\n" "#define HAVE_REQUEST_SENSE 1" >>confdefs.h
+fi + +ac_fn_c_check_type "$LINENO" "struct pm_scan_arg" "ac_cv_type_struct_pm_scan_arg" "#include <linux/fs.h> +" +if test "x$ac_cv_type_struct_pm_scan_arg" = xyes +then : + +printf "%s\n" "#define HAVE_STRUCT_PM_SCAN_ARG 1" >>confdefs.h + + fi
diff --git a/configure.ac b/configure.ac index 8e68a09ad0a..8a03a10aa55 100644 --- a/configure.ac +++ b/configure.ac @@ -2121,6 +2121,7 @@ dnl **** Check for types ****
AC_C_INLINE AC_CHECK_TYPES([request_sense],,,[#include <linux/cdrom.h>]) +AC_CHECK_TYPES([struct pm_scan_arg],,,[#include <linux/fs.h>])
AC_CHECK_TYPES([struct xinpgen],,, [#include <sys/types.h> diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 0e5917403f9..38acadb793c 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -63,6 +63,10 @@ # include <mach/mach_init.h> # include <mach/mach_vm.h> #endif +#ifdef HAVE_STRUCT_PM_SCAN_ARG +#include <linux/fs.h> +#include <sys/ioctl.h> +#endif
#include "ntstatus.h" #define WIN32_NO_STATUS @@ -5272,6 +5276,9 @@ static NTSTATUS get_working_set_ex( HANDLE process, LPCVOID addr, { #if !defined(HAVE_LIBPROCSTAT) static int pagemap_fd = -2; +#ifdef HAVE_STRUCT_PM_SCAN_ARG + BOOL pagemap_ioctl_avail = TRUE; +#endif #endif MEMORY_WORKING_SET_EX_INFORMATION *p; sigset_t sigset; @@ -5359,15 +5366,63 @@ static NTSTATUS get_working_set_ex( HANDLE process, LPCVOID addr, get_committed_size( view, p->VirtualAddress, &vprot, VPROT_COMMITTED ) && (vprot & VPROT_COMMITTED)) { - if (pagemap_fd == -1 || - pread( pagemap_fd, &pagemap, sizeof(pagemap), ((UINT_PTR)p->VirtualAddress >> page_shift) * sizeof(pagemap) ) != sizeof(pagemap)) + if (pagemap_fd != -1) + { +#ifdef HAVE_STRUCT_PM_SCAN_ARG + if (pagemap_ioctl_avail) + { + UINT_PTR addr = (UINT_PTR)(ROUND_ADDR(view->base, page_mask)); + struct page_region output_buf; + int count; + struct pm_scan_arg scan_arg = { + .size = sizeof( scan_arg ), + .flags = 0, + .start = addr, + .end = addr + page_size, + .vec = (UINT_PTR)&output_buf, + .vec_len = 1, + .max_pages = 1, + .category_inverted = 0, + .category_mask = PAGE_IS_PRESENT, + .category_anyof_mask = PAGE_IS_HUGE | PAGE_IS_PRESENT | PAGE_IS_FILE, + .return_mask = PAGE_IS_HUGE | PAGE_IS_PRESENT | PAGE_IS_FILE, + }; + + memset(&output_buf, 0, sizeof(output_buf)); + count = ioctl(pagemap_fd, PAGEMAP_SCAN, &scan_arg); + if (count == -1) + { + WARN("ioctl(PAGEMAP_SCAN, %p) failed: '%s'\n", (void *)addr, strerror(errno)); + pagemap_ioctl_avail = FALSE; + } + else if (count > 0) + { + assert( output_buf.start <= addr && output_buf.end > addr ); + p->VirtualAttributes.Valid = !(vprot & VPROT_GUARD) && (vprot & 0x0f) && (output_buf.categories & PAGE_IS_PRESENT); + p->VirtualAttributes.Shared = !is_view_valloc( view ) && (output_buf.categories & PAGE_IS_FILE); + p->VirtualAttributes.LargePage = p->VirtualAttributes.Valid && (output_buf.categories & PAGE_IS_HUGE) && (view->protect & SEC_LARGE_PAGES); + if (p->VirtualAttributes.LargePage) + p->VirtualAttributes.Locked = TRUE; + } + } + if (!pagemap_ioctl_avail) +#endif + { + if (pread( pagemap_fd, &pagemap, sizeof(pagemap), ((UINT_PTR)p->VirtualAddress >> page_shift) * sizeof(pagemap) ) != sizeof(pagemap)) + { + /* If we don't have pagemap information, default to invalid. */ + pagemap = 0; + } + + p->VirtualAttributes.Valid = !(vprot & VPROT_GUARD) && (vprot & 0x0f) && (pagemap >> 63); + p->VirtualAttributes.Shared = !is_view_valloc( view ) && ((pagemap >> 61) & 1); + } + } + else { - /* If we don't have pagemap information, default to invalid. */ pagemap = 0; }
- p->VirtualAttributes.Valid = !(vprot & VPROT_GUARD) && (vprot & 0x0f) && (pagemap >> 63); - p->VirtualAttributes.Shared = !is_view_valloc( view ) && ((pagemap >> 61) & 1); if (p->VirtualAttributes.Shared && p->VirtualAttributes.Valid) p->VirtualAttributes.ShareCount = 1; /* FIXME */ if (p->VirtualAttributes.Valid) diff --git a/include/config.h.in b/include/config.h.in index bbd5a57a280..54816765623 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -432,6 +432,9 @@ /* Define to 1 if `mt_gstat' is a member of `struct mtget'. */ #undef HAVE_STRUCT_MTGET_MT_GSTAT
+/* Define to 1 if the system has the type `struct pm_scan_arg'. */ +#undef HAVE_STRUCT_PM_SCAN_ARG + /* Define to 1 if `sin6_scope_id' is a member of `struct sockaddr_in6'. */ #undef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID