public inbox for cygwin-patches@cygwin.com
 help / color / mirror / Atom feed
From: Jon Turney <jon.turney@dronecode.org.uk>
To: cygwin-patches@cygwin.com
Cc: Jon Turney <jon.turney@dronecode.org.uk>
Subject: [PATCH 5/5] Cygwin: Use MEMORY_WORKING_SET_EX_INFORMATION in dumper
Date: Sat, 18 Jul 2020 16:00:28 +0100	[thread overview]
Message-ID: <20200718150028.1709-6-jon.turney@dronecode.org.uk> (raw)
In-Reply-To: <20200718150028.1709-1-jon.turney@dronecode.org.uk>

Use the (undocumented) MEMORY_WORKING_SET_EX_INFORMATION in dumper to
determine if a MEM_IMAGE region is unsharable, and hence has been
modified.
---
 winsup/doc/utils.xml     |  8 ++---
 winsup/utils/Makefile.in |  2 +-
 winsup/utils/dumper.cc   | 63 ++++++++++++++++++++++++++++++++++++++--
 3 files changed, 65 insertions(+), 8 deletions(-)

diff --git a/winsup/doc/utils.xml b/winsup/doc/utils.xml
index 5f266bcb1..8b92bfdf1 100644
--- a/winsup/doc/utils.xml
+++ b/winsup/doc/utils.xml
@@ -524,11 +524,11 @@ error_start=x:\path\to\dumper.exe
       <command>dumper</command> exits, the target process is terminated too. </para>
 
     <para> To save space in the core dump, <command>dumper</command> doesn't
-      write those portions of target process' memory space that are loaded from
-      executable and dll files and are unchangeable, such as program code and
-      debug info. Instead, <command>dumper</command> saves paths to files which
+      write those portions of the target process's memory space that are loaded
+      from executable and dll files and are unchanged (e.g. program code).
+      Instead, <command>dumper</command> saves paths to the files which
       contain that data. When a core dump is loaded into gdb, it uses these
-      paths to load appropriate files. That means that if you create a core
+      paths to load the appropriate files. That means that if you create a core
       dump on one machine and try to debug it on another, you'll need to place
       identical copies of the executable and dlls in the same directories as on
       the machine where the core dump was created. </para>
diff --git a/winsup/utils/Makefile.in b/winsup/utils/Makefile.in
index f9892fa1d..6bf4454c5 100644
--- a/winsup/utils/Makefile.in
+++ b/winsup/utils/Makefile.in
@@ -116,7 +116,7 @@ CYGWIN_BINS += dumper.exe
 dumper.o module_info.o: CXXFLAGS += -I$(top_srcdir)/include
 dumper.o: dumper.h
 dumper.exe: module_info.o
-dumper.exe: CYGWIN_LDFLAGS += -lpsapi -lbfd -lintl -liconv -liberty ${ZLIB}
+dumper.exe: CYGWIN_LDFLAGS += -lpsapi -lbfd -lintl -liconv -liberty ${ZLIB} -lntdll
 else
 all: warn_dumper
 endif
diff --git a/winsup/utils/dumper.cc b/winsup/utils/dumper.cc
index b96ee54cc..3af138b9e 100644
--- a/winsup/utils/dumper.cc
+++ b/winsup/utils/dumper.cc
@@ -266,6 +266,46 @@ void protect_dump(DWORD protect, char *buf)
     strcat (buf, pt[i]);
 }
 
+typedef enum _MEMORY_INFORMATION_CLASS
+{
+ MemoryWorkingSetExInformation = 4, // MEMORY_WORKING_SET_EX_INFORMATION
+} MEMORY_INFORMATION_CLASS;
+
+extern "C"
+NTSTATUS
+NtQueryVirtualMemory(HANDLE ProcessHandle,
+		     LPVOID BaseAddress,
+		     MEMORY_INFORMATION_CLASS MemoryInformationClass,
+		     LPVOID MemoryInformation,
+		     SIZE_T MemoryInformationLength,
+		     SIZE_T *ReturnLength);
+
+typedef struct _MEMORY_WORKING_SET_EX_INFORMATION
+{
+  LPVOID VirtualAddress;
+  ULONG_PTR Long;
+} MEMORY_WORKING_SET_EX_INFORMATION;
+
+#define MWSEI_ATTRIB_SHARED (0x1 << 15)
+
+static BOOL
+getRegionAttributes(HANDLE hProcess, LPVOID address, DWORD &attribs)
+{
+  MEMORY_WORKING_SET_EX_INFORMATION mwsei = { address };
+  NTSTATUS status = NtQueryVirtualMemory(hProcess, 0,
+					 MemoryWorkingSetExInformation,
+					 &mwsei, sizeof(mwsei), 0);
+
+  if (!status)
+    {
+      attribs = mwsei.Long;
+      return TRUE;
+    }
+
+  deb_printf("MemoryWorkingSetExInformation failed status %08x\n", status);
+  return FALSE;
+}
+
 int
 dumper::collect_memory_sections ()
 {
@@ -292,10 +332,27 @@ dumper::collect_memory_sections ()
       int skip_region_p = 0;
       const char *disposition = "dumped";
 
-      if ((mbi.Type & MEM_IMAGE) && !(mbi.Protect & (PAGE_EXECUTE_READWRITE | PAGE_READWRITE)))
+      if (mbi.Type & MEM_IMAGE)
 	{
-	  skip_region_p = 1;
-	  disposition = "skipped due to non-writeable MEM_IMAGE";
+	  DWORD attribs = 0;
+	  if (getRegionAttributes(hProcess, current_page_address, attribs))
+	    {
+	      if (attribs & MWSEI_ATTRIB_SHARED)
+		{
+		  skip_region_p = 1;
+		  disposition = "skipped due to shared MEM_IMAGE";
+		}
+	    }
+	  /*
+	    The undocumented MemoryWorkingSetExInformation is allegedly
+	    supported since XP, so should always succeed, but if it fails,
+	    fallback to looking at region protection.
+	   */
+	  else if (!(mbi.Protect & (PAGE_EXECUTE_READWRITE | PAGE_READWRITE)))
+	    {
+	      skip_region_p = 1;
+	      disposition = "skipped due to non-writeable MEM_IMAGE";
+	    }
 	}
 
       if (mbi.Protect & PAGE_NOACCESS)
-- 
2.27.0


  parent reply	other threads:[~2020-07-18 15:01 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-18 15:00 [PATCH 0/5] Improve dumper megion region selection Jon Turney
2020-07-18 15:00 ` [PATCH 1/5] Cygwin: Show details of all memory regions details in dumper debug output Jon Turney
2020-07-18 15:00 ` [PATCH 2/5] Cygwin: Remove reading of PE for section flags from dumper Jon Turney
2020-07-18 15:00 ` [PATCH 3/5] Cygwin: Drop excluded regions list " Jon Turney
2020-07-18 15:00 ` [PATCH 4/5] Cygwin: Don't dump non-writable image regions Jon Turney
2020-07-18 15:00 ` Jon Turney [this message]
2020-07-20  8:15   ` [PATCH 5/5] Cygwin: Use MEMORY_WORKING_SET_EX_INFORMATION in dumper Corinna Vinschen
2020-07-28  2:20   ` Takashi Yano
2020-07-28 21:04     ` Jon Turney

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200718150028.1709-6-jon.turney@dronecode.org.uk \
    --to=jon.turney@dronecode.org.uk \
    --cc=cygwin-patches@cygwin.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).