public inbox for cygwin-patches@cygwin.com
 help / color / mirror / Atom feed
* [PATCH 0/8] Fix dumper for x86_64
@ 2020-07-01 21:25 Jon Turney
  2020-07-01 21:25 ` [PATCH 1/8] Cygwin: Slightly improve error_start documentation Jon Turney
                   ` (10 more replies)
  0 siblings, 11 replies; 25+ messages in thread
From: Jon Turney @ 2020-07-01 21:25 UTC (permalink / raw)
  To: cygwin-patches; +Cc: Jon Turney

Jon Turney (8):
  Cygwin: Slightly improve error_start documentation
  Cygwin: Update ELF target used by dumper on x86_64
  Cygwin: Add a new win32_pstatus data type for modules on x86_64
  Cygwin: Make dumper scan more than first 4GB of VM on x86_64
  Cygwin: Fix bfd target for parsing PE files on x86_64 in dumper
  Cygwin: Fix dumper region order/overlap checking
  Cygwin: Handle excluded regions more robustly in dumper
  Cygwin: Consider DLL rebasing when computing dumper exclusions

 winsup/cygwin/include/cygwin/core_dump.h | 16 ++++++---
 winsup/doc/cygwinenv.xml                 |  6 +++-
 winsup/utils/dumper.cc                   | 23 ++++++++++---
 winsup/utils/dumper.h                    |  2 +-
 winsup/utils/parse_pe.cc                 | 43 +++++++++++++++++-------
 5 files changed, 66 insertions(+), 24 deletions(-)

-- 
2.27.0


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 1/8] Cygwin: Slightly improve error_start documentation
  2020-07-01 21:25 [PATCH 0/8] Fix dumper for x86_64 Jon Turney
@ 2020-07-01 21:25 ` Jon Turney
  2020-07-01 21:25 ` [PATCH 2/8] Cygwin: Update ELF target used by dumper on x86_64 Jon Turney
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 25+ messages in thread
From: Jon Turney @ 2020-07-01 21:25 UTC (permalink / raw)
  To: cygwin-patches; +Cc: Jon Turney

---
 winsup/doc/cygwinenv.xml | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/winsup/doc/cygwinenv.xml b/winsup/doc/cygwinenv.xml
index f549fee0d..a52b6ac19 100644
--- a/winsup/doc/cygwinenv.xml
+++ b/winsup/doc/cygwinenv.xml
@@ -28,9 +28,13 @@ Defaults to off.</para>
 which is useful for debugging.  <filename>Win32filepath</filename> is
 usually set to the path to <command>gdb</command> or
 <command>dumper</command>, for example
-<filename>C:\cygwin\bin\gdb.exe</filename>. 
+<filename>C:\cygwin\bin\gdb.exe</filename>.
 There is no default set.
 </para>
+<para>
+The filename of the executing program and it's Windows process id are appended
+to the command as arguments.
+</para>
 </listitem>
 
 <listitem>
-- 
2.27.0


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 2/8] Cygwin: Update ELF target used by dumper on x86_64
  2020-07-01 21:25 [PATCH 0/8] Fix dumper for x86_64 Jon Turney
  2020-07-01 21:25 ` [PATCH 1/8] Cygwin: Slightly improve error_start documentation Jon Turney
@ 2020-07-01 21:25 ` Jon Turney
  2020-07-01 21:25 ` [PATCH 3/8] Cygwin: Add a new win32_pstatus data type for modules " Jon Turney
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 25+ messages in thread
From: Jon Turney @ 2020-07-01 21:25 UTC (permalink / raw)
  To: cygwin-patches; +Cc: Jon Turney

Like [1], but actually making the effort to be 'usable' and 'tested'.

[1] https://cygwin.com/pipermail/cygwin/2019-October/242815.html
---
 winsup/utils/dumper.cc | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/winsup/utils/dumper.cc b/winsup/utils/dumper.cc
index 226c2283d..e16d80a36 100644
--- a/winsup/utils/dumper.cc
+++ b/winsup/utils/dumper.cc
@@ -645,7 +645,13 @@ dumper::init_core_dump ()
 {
   bfd_init ();
 
-  core_bfd = bfd_openw (file_name, "elf32-i386");
+#ifdef __x86_64__
+  const char *target = "elf64-x86-64";
+#else
+  const char *target = "elf32-i386";
+#endif
+
+  core_bfd = bfd_openw (file_name, target);
   if (core_bfd == NULL)
     {
       bfd_perror ("opening bfd");
@@ -658,7 +664,7 @@ dumper::init_core_dump ()
       goto failed;
     }
 
-  if (!bfd_set_arch_mach (core_bfd, bfd_arch_i386, 0))
+  if (!bfd_set_arch_mach (core_bfd, bfd_arch_i386, 0 /* = default */))
     {
       bfd_perror ("setting bfd architecture");
       goto failed;
-- 
2.27.0


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 3/8] Cygwin: Add a new win32_pstatus data type for modules on x86_64
  2020-07-01 21:25 [PATCH 0/8] Fix dumper for x86_64 Jon Turney
  2020-07-01 21:25 ` [PATCH 1/8] Cygwin: Slightly improve error_start documentation Jon Turney
  2020-07-01 21:25 ` [PATCH 2/8] Cygwin: Update ELF target used by dumper on x86_64 Jon Turney
@ 2020-07-01 21:25 ` Jon Turney
  2020-07-01 21:25 ` [PATCH 4/8] Cygwin: Make dumper scan more than first 4GB of VM " Jon Turney
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 25+ messages in thread
From: Jon Turney @ 2020-07-01 21:25 UTC (permalink / raw)
  To: cygwin-patches; +Cc: Jon Turney

Take a bit more care with sizes in other data types to ensure they are
the same on x86 and x86_64.

Add some explanatory comments.
---
 winsup/cygwin/include/cygwin/core_dump.h | 16 ++++++++++++----
 winsup/utils/dumper.cc                   |  4 ++++
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/winsup/cygwin/include/cygwin/core_dump.h b/winsup/cygwin/include/cygwin/core_dump.h
index 92ecae7ab..cd218ac45 100644
--- a/winsup/cygwin/include/cygwin/core_dump.h
+++ b/winsup/cygwin/include/cygwin/core_dump.h
@@ -11,17 +11,23 @@ details. */
 #ifndef _CYGWIN_CORE_DUMP_H
 #define _CYGWIN_CORE_DUMP_H
 
+/*
+  Note that elfcore_grok_win32pstatus() in libbfd relies on the precise layout
+  of these structures.
+*/
+
 #include <windows.h>
 
 #define	NOTE_INFO_PROCESS	1
 #define	NOTE_INFO_THREAD	2
 #define	NOTE_INFO_MODULE	3
+#define	NOTE_INFO_MODULE64	4
 
 struct win32_core_process_info
 {
   DWORD pid;
-  int signal;
-  int command_line_size;
+  DWORD signal;
+  DWORD command_line_size;
   char command_line[1];
 }
 #ifdef __GNUC__
@@ -40,10 +46,12 @@ struct win32_core_thread_info
 #endif
 ;
 
+/* Used with data_type NOTE_INFO_MODULE or NOTE_INFO_MODULE64, depending on
+   arch */
 struct win32_core_module_info
 {
   void* base_address;
-  int module_name_size;
+  DWORD module_name_size;
   char module_name[1];
 }
 #ifdef __GNUC__
@@ -53,7 +61,7 @@ struct win32_core_module_info
 
 struct win32_pstatus
 {
-  unsigned long data_type;
+  DWORD data_type;
   union
     {
       struct win32_core_process_info process_info;
diff --git a/winsup/utils/dumper.cc b/winsup/utils/dumper.cc
index e16d80a36..dcf01e800 100644
--- a/winsup/utils/dumper.cc
+++ b/winsup/utils/dumper.cc
@@ -502,7 +502,11 @@ dumper::dump_module (asection * to, process_module * module)
   strncpy (header.elf_note_header.name, "win32module", NOTE_NAME_SIZE);
 #pragma GCC diagnostic pop
 
+#ifdef __x86_64__
+  module_pstatus_ptr->data_type = NOTE_INFO_MODULE64;
+#else
   module_pstatus_ptr->data_type = NOTE_INFO_MODULE;
+#endif
   module_pstatus_ptr->data.module_info.base_address = module->base_address;
   module_pstatus_ptr->data.module_info.module_name_size = strlen (module->name) + 1;
   strcpy (module_pstatus_ptr->data.module_info.module_name, module->name);
-- 
2.27.0


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 4/8] Cygwin: Make dumper scan more than first 4GB of VM on x86_64
  2020-07-01 21:25 [PATCH 0/8] Fix dumper for x86_64 Jon Turney
                   ` (2 preceding siblings ...)
  2020-07-01 21:25 ` [PATCH 3/8] Cygwin: Add a new win32_pstatus data type for modules " Jon Turney
@ 2020-07-01 21:25 ` Jon Turney
  2020-07-01 21:25 ` [PATCH 5/8] Cygwin: Fix bfd target for parsing PE files on x86_64 in dumper Jon Turney
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 25+ messages in thread
From: Jon Turney @ 2020-07-01 21:25 UTC (permalink / raw)
  To: cygwin-patches; +Cc: Jon Turney

It's unclear that we need an end address here at all, or can just rely
on VirtualQueryEx() failing when we reach the end of memory regions.
---
 winsup/utils/dumper.cc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/winsup/utils/dumper.cc b/winsup/utils/dumper.cc
index dcf01e800..ccc4bd12f 100644
--- a/winsup/utils/dumper.cc
+++ b/winsup/utils/dumper.cc
@@ -296,7 +296,7 @@ dumper::collect_memory_sections ()
     return 0;
 
   LPBYTE current_page_address;
-  LPBYTE last_base = (LPBYTE) 0xFFFFFFFF;
+  LPBYTE last_base = (LPBYTE) -1;
   SIZE_T last_size = (SIZE_T) 0;
   SIZE_T done;
 
@@ -307,7 +307,7 @@ dumper::collect_memory_sections ()
   if (hProcess == NULL)
     return 0;
 
-  for (current_page_address = 0; current_page_address < (LPBYTE) 0xFFFF0000;)
+  for (current_page_address = 0; current_page_address < (LPBYTE) -1;)
     {
       if (!VirtualQueryEx (hProcess, current_page_address, &mbi, sizeof (mbi)))
 	break;
-- 
2.27.0


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 5/8] Cygwin: Fix bfd target for parsing PE files on x86_64 in dumper
  2020-07-01 21:25 [PATCH 0/8] Fix dumper for x86_64 Jon Turney
                   ` (3 preceding siblings ...)
  2020-07-01 21:25 ` [PATCH 4/8] Cygwin: Make dumper scan more than first 4GB of VM " Jon Turney
@ 2020-07-01 21:25 ` Jon Turney
  2020-07-01 21:25 ` [PATCH 6/8] Cygwin: Fix dumper region order/overlap checking Jon Turney
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 25+ messages in thread
From: Jon Turney @ 2020-07-01 21:25 UTC (permalink / raw)
  To: cygwin-patches; +Cc: Jon Turney

---
 winsup/utils/parse_pe.cc | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/winsup/utils/parse_pe.cc b/winsup/utils/parse_pe.cc
index 90b5c0b0d..d2a510a81 100644
--- a/winsup/utils/parse_pe.cc
+++ b/winsup/utils/parse_pe.cc
@@ -91,7 +91,14 @@ parse_pe (const char *file_name, exclusion * excl_list)
   if (file_name == NULL || excl_list == NULL)
     return 0;
 
-  bfd *abfd = bfd_openr (file_name, "pei-i386");
+#ifdef __x86_64__
+  const char *target = "pei-x86-64";
+#else
+  const char *target = "pei-i386";
+#endif
+
+  bfd *abfd = bfd_openr (file_name, target);
+
   if (abfd == NULL)
     {
       bfd_perror ("failed to open file");
-- 
2.27.0


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 6/8] Cygwin: Fix dumper region order/overlap checking
  2020-07-01 21:25 [PATCH 0/8] Fix dumper for x86_64 Jon Turney
                   ` (4 preceding siblings ...)
  2020-07-01 21:25 ` [PATCH 5/8] Cygwin: Fix bfd target for parsing PE files on x86_64 in dumper Jon Turney
@ 2020-07-01 21:25 ` Jon Turney
  2020-07-01 21:25 ` [PATCH 7/8] Cygwin: Handle excluded regions more robustly in dumper Jon Turney
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 25+ messages in thread
From: Jon Turney @ 2020-07-01 21:25 UTC (permalink / raw)
  To: cygwin-patches; +Cc: Jon Turney

---
 winsup/utils/parse_pe.cc | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/winsup/utils/parse_pe.cc b/winsup/utils/parse_pe.cc
index d2a510a81..653c46dfe 100644
--- a/winsup/utils/parse_pe.cc
+++ b/winsup/utils/parse_pe.cc
@@ -60,11 +60,9 @@ exclusion::sort_and_check ()
   for (process_mem_region * p = region; p < region + last - 1; p++)
     {
       process_mem_region *q = p + 1;
-      if (q == p + 1)
-	continue;
-      if (p->base + size > q->base)
+      if (p->base + p->size > q->base)
 	{
-	  fprintf (stderr, "region error @ (%p + %zd) > %p\n", p->base, size, q->base);
+	  fprintf (stderr, "region error @ (%p + 0x%0llx) > %p\n", p->base, p->size, q->base);
 	  return 0;
 	}
     }
-- 
2.27.0


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 7/8] Cygwin: Handle excluded regions more robustly in dumper
  2020-07-01 21:25 [PATCH 0/8] Fix dumper for x86_64 Jon Turney
                   ` (5 preceding siblings ...)
  2020-07-01 21:25 ` [PATCH 6/8] Cygwin: Fix dumper region order/overlap checking Jon Turney
@ 2020-07-01 21:25 ` Jon Turney
  2020-07-01 21:25 ` [PATCH 8/8] Cygwin: Consider DLL rebasing when computing dumper exclusions Jon Turney
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 25+ messages in thread
From: Jon Turney @ 2020-07-01 21:25 UTC (permalink / raw)
  To: cygwin-patches; +Cc: Jon Turney

Avoid trying to create regions with negative size if there's an error
(duplicate or out-of-order region) in the excluded region list.
---
 winsup/utils/dumper.cc | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/winsup/utils/dumper.cc b/winsup/utils/dumper.cc
index ccc4bd12f..c0b3fd8ff 100644
--- a/winsup/utils/dumper.cc
+++ b/winsup/utils/dumper.cc
@@ -252,6 +252,9 @@ dumper::split_add_mem_region (LPBYTE base, SIZE_T size)
 	  continue;
 	}
 
+      if (p->base < last_base)
+	continue;
+
       add_mem_region (last_base, p->base - last_base);
       last_base = p->base + p->size;
     }
-- 
2.27.0


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 8/8] Cygwin: Consider DLL rebasing when computing dumper exclusions
  2020-07-01 21:25 [PATCH 0/8] Fix dumper for x86_64 Jon Turney
                   ` (6 preceding siblings ...)
  2020-07-01 21:25 ` [PATCH 7/8] Cygwin: Handle excluded regions more robustly in dumper Jon Turney
@ 2020-07-01 21:25 ` Jon Turney
  2020-07-02  7:43   ` Corinna Vinschen
  2020-07-01 21:29 ` [PATCH 0/8] Fix dumper for x86_64 Jon Turney
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 25+ messages in thread
From: Jon Turney @ 2020-07-01 21:25 UTC (permalink / raw)
  To: cygwin-patches; +Cc: Jon Turney

I think this would always have been neeeded, but is essential on x86_64,
as kernel32.dll has an ImageBase of 00000001:80000000 (but is always
rebased when loaded), which is identical to the cygwin DLL, causing
duplicate or overlapping exclusions.
---
 winsup/utils/dumper.cc   |  2 +-
 winsup/utils/dumper.h    |  2 +-
 winsup/utils/parse_pe.cc | 28 ++++++++++++++++++++--------
 3 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/winsup/utils/dumper.cc b/winsup/utils/dumper.cc
index c0b3fd8ff..fa3fe1fbc 100644
--- a/winsup/utils/dumper.cc
+++ b/winsup/utils/dumper.cc
@@ -284,7 +284,7 @@ dumper::add_module (LPVOID base_address)
   new_entity->u.module.base_address = base_address;
   new_entity->u.module.name = module_name;
 
-  parse_pe (module_name, excl_list);
+  parse_pe (module_name, excl_list, base_address);
 
   deb_printf ("added module %p %s\n", base_address, module_name);
   return 1;
diff --git a/winsup/utils/dumper.h b/winsup/utils/dumper.h
index 9367587bf..9c4b1f092 100644
--- a/winsup/utils/dumper.h
+++ b/winsup/utils/dumper.h
@@ -133,7 +133,7 @@ extern int deb_printf ( const char* format, ... );
 
 extern char* psapi_get_module_name ( HANDLE hProcess, LPVOID BaseAddress );
 
-extern int parse_pe ( const char* file_name, exclusion* excl_list );
+extern int parse_pe ( const char* file_name, exclusion* excl_list, LPVOID base_address );
 
 extern BOOL verbose;
 
diff --git a/winsup/utils/parse_pe.cc b/winsup/utils/parse_pe.cc
index 653c46dfe..0256ada53 100644
--- a/winsup/utils/parse_pe.cc
+++ b/winsup/utils/parse_pe.cc
@@ -70,21 +70,21 @@ exclusion::sort_and_check ()
 }
 
 static void
-select_data_section (bfd * abfd, asection * sect, PTR obj)
+select_data_section (bfd * abfd, asection * sect, exclusion *excl_list,
+		     SSIZE_T adj)
 {
-  exclusion *excl_list = (exclusion *) obj;
-
   if ((sect->flags & (SEC_CODE | SEC_DEBUGGING)) &&
       sect->vma && bfd_get_section_size (sect))
     {
-      excl_list->add ((LPBYTE) sect->vma, (SIZE_T) bfd_get_section_size (sect));
-      deb_printf ("excluding section: %20s %08lx\n", sect->name,
-		  bfd_get_section_size (sect));
+      bfd_vma vma = sect->vma + adj;
+      excl_list->add ((LPBYTE) vma, (SIZE_T) bfd_get_section_size (sect));
+      deb_printf ("excluding section: %20s %016lx %016lx %08lx\n", sect->name,
+		  sect->vma, vma, bfd_get_section_size (sect));
     }
 }
 
 int
-parse_pe (const char *file_name, exclusion * excl_list)
+parse_pe (const char *file_name, exclusion * excl_list, LPVOID base_address)
 {
   if (file_name == NULL || excl_list == NULL)
     return 0;
@@ -104,7 +104,19 @@ parse_pe (const char *file_name, exclusion * excl_list)
     }
 
   bfd_check_format (abfd, bfd_object);
-  bfd_map_over_sections (abfd, &select_data_section, (PTR) excl_list);
+
+  /* Compute the relocation offset for this DLL.  Unfortunately, we have to
+     guess at ImageBase (one page before vma of first section), since bfd
+     doesn't let us get at backend-private data */
+  bfd_vma imagebase = abfd->sections->vma - 0x1000;
+  SSIZE_T adj = (bfd_vma)base_address - imagebase;
+  deb_printf("imagebase relocated from %016lx to %016lx (%016lx)\n",
+	     imagebase, base_address, adj);
+
+  asection *p;
+  for (p = abfd->sections; p != NULL; p = p->next)
+    select_data_section(abfd, p, excl_list, adj);
+
   excl_list->sort_and_check ();
 
   bfd_close (abfd);
-- 
2.27.0


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 0/8] Fix dumper for x86_64
  2020-07-01 21:25 [PATCH 0/8] Fix dumper for x86_64 Jon Turney
                   ` (7 preceding siblings ...)
  2020-07-01 21:25 ` [PATCH 8/8] Cygwin: Consider DLL rebasing when computing dumper exclusions Jon Turney
@ 2020-07-01 21:29 ` Jon Turney
  2020-07-02  7:44   ` Corinna Vinschen
  2020-07-02  7:47 ` Corinna Vinschen
  2020-07-05 16:45 ` [PATCH 9/8] Add all memory regions details to dumper debug output Jon Turney
  10 siblings, 1 reply; 25+ messages in thread
From: Jon Turney @ 2020-07-01 21:29 UTC (permalink / raw)
  To: Cygwin Patches


This needs to be aligned with some changes to gdb to consume the dumps 
it produces, so it's probably best to hold off applying this until it's 
more obvious what's going to happen with those.

Random notes:

- objdump identifies the output of dumper on x86_64 as 
'elf64-x86-64-cloudabi' (perhaps due to some over-eager sniffer).

- regions excluded from the dump aren't rounded up to page size, so we 
may end up writing the excess into the dump.

- looking at the loaded modules and inspecting them to determine what 
memory regions don't need to appear in the dump seems odd.  I'm not sure 
we don't just exclude MEMORY_BASIC_INFORMATION.Type == MEM_IMAGE regions 
(assuming they get converted to MEM_PRIVATE regions if written when 
copy-on-write).


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 8/8] Cygwin: Consider DLL rebasing when computing dumper exclusions
  2020-07-01 21:25 ` [PATCH 8/8] Cygwin: Consider DLL rebasing when computing dumper exclusions Jon Turney
@ 2020-07-02  7:43   ` Corinna Vinschen
  2020-07-02  7:48     ` Corinna Vinschen
  0 siblings, 1 reply; 25+ messages in thread
From: Corinna Vinschen @ 2020-07-02  7:43 UTC (permalink / raw)
  To: cygwin-patches

On Jul  1 22:25, Jon Turney wrote:
> I think this would always have been neeeded, but is essential on x86_64,
> as kernel32.dll has an ImageBase of 00000001:80000000 (but is always

Great, but that shouldn't matter much given that system DLLs are
ASLRed all the time.

> +parse_pe (const char *file_name, exclusion * excl_list, LPVOID base_address)
>  {
>    if (file_name == NULL || excl_list == NULL)
>      return 0;
> @@ -104,7 +104,19 @@ parse_pe (const char *file_name, exclusion * excl_list)
>      }
>  
>    bfd_check_format (abfd, bfd_object);
> -  bfd_map_over_sections (abfd, &select_data_section, (PTR) excl_list);
> +
> +  /* Compute the relocation offset for this DLL.  Unfortunately, we have to
> +     guess at ImageBase (one page before vma of first section), since bfd
> +     doesn't let us get at backend-private data */
> +  bfd_vma imagebase = abfd->sections->vma - 0x1000;

VirtualQueryEx?  The AllocationBase is identical to the base address
of the DLL loaded at that address.


Corinna

-- 
Corinna Vinschen
Cygwin Maintainer

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 0/8] Fix dumper for x86_64
  2020-07-01 21:29 ` [PATCH 0/8] Fix dumper for x86_64 Jon Turney
@ 2020-07-02  7:44   ` Corinna Vinschen
  2020-07-05 16:49     ` Jon Turney
  0 siblings, 1 reply; 25+ messages in thread
From: Corinna Vinschen @ 2020-07-02  7:44 UTC (permalink / raw)
  To: cygwin-patches

On Jul  1 22:29, Jon Turney wrote:
> 
> This needs to be aligned with some changes to gdb to consume the dumps it
> produces, so it's probably best to hold off applying this until it's more
> obvious what's going to happen with those.
> 
> Random notes:
> 
> - objdump identifies the output of dumper on x86_64 as
> 'elf64-x86-64-cloudabi' (perhaps due to some over-eager sniffer).
> 
> - regions excluded from the dump aren't rounded up to page size, so we may
> end up writing the excess into the dump.
> 
> - looking at the loaded modules and inspecting them to determine what memory
> regions don't need to appear in the dump seems odd.  I'm not sure we don't
> just exclude MEMORY_BASIC_INFORMATION.Type == MEM_IMAGE regions (assuming
> they get converted to MEM_PRIVATE regions if written when copy-on-write).

Could format_process_maps() in fhandler_process.cc be a role model here?


Corinna

-- 
Corinna Vinschen
Cygwin Maintainer

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 0/8] Fix dumper for x86_64
  2020-07-01 21:25 [PATCH 0/8] Fix dumper for x86_64 Jon Turney
                   ` (8 preceding siblings ...)
  2020-07-01 21:29 ` [PATCH 0/8] Fix dumper for x86_64 Jon Turney
@ 2020-07-02  7:47 ` Corinna Vinschen
  2020-07-05 16:45 ` [PATCH 9/8] Add all memory regions details to dumper debug output Jon Turney
  10 siblings, 0 replies; 25+ messages in thread
From: Corinna Vinschen @ 2020-07-02  7:47 UTC (permalink / raw)
  To: cygwin-patches

On Jul  1 22:25, Jon Turney wrote:
> Jon Turney (8):
>   Cygwin: Slightly improve error_start documentation
>   Cygwin: Update ELF target used by dumper on x86_64
>   Cygwin: Add a new win32_pstatus data type for modules on x86_64
>   Cygwin: Make dumper scan more than first 4GB of VM on x86_64
>   Cygwin: Fix bfd target for parsing PE files on x86_64 in dumper
>   Cygwin: Fix dumper region order/overlap checking
>   Cygwin: Handle excluded regions more robustly in dumper
>   Cygwin: Consider DLL rebasing when computing dumper exclusions
> 
>  winsup/cygwin/include/cygwin/core_dump.h | 16 ++++++---
>  winsup/doc/cygwinenv.xml                 |  6 +++-
>  winsup/utils/dumper.cc                   | 23 ++++++++++---
>  winsup/utils/dumper.h                    |  2 +-
>  winsup/utils/parse_pe.cc                 | 43 +++++++++++++++++-------
>  5 files changed, 66 insertions(+), 24 deletions(-)
> 
> -- 
> 2.27.0

As soon as you're sure the timing is right, feel free to apply
patches as you see fit.  Dumper is all yours :)


Thanks,
Corinna

-- 
Corinna Vinschen
Cygwin Maintainer

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 8/8] Cygwin: Consider DLL rebasing when computing dumper exclusions
  2020-07-02  7:43   ` Corinna Vinschen
@ 2020-07-02  7:48     ` Corinna Vinschen
  2020-07-03 13:10       ` Jon Turney
  0 siblings, 1 reply; 25+ messages in thread
From: Corinna Vinschen @ 2020-07-02  7:48 UTC (permalink / raw)
  To: cygwin-patches

On Jul  2 09:43, Corinna Vinschen wrote:
> On Jul  1 22:25, Jon Turney wrote:
> > I think this would always have been neeeded, but is essential on x86_64,
> > as kernel32.dll has an ImageBase of 00000001:80000000 (but is always
> 
> Great, but that shouldn't matter much given that system DLLs are
> ASLRed all the time.
> 
> > +parse_pe (const char *file_name, exclusion * excl_list, LPVOID base_address)
> >  {
> >    if (file_name == NULL || excl_list == NULL)
> >      return 0;
> > @@ -104,7 +104,19 @@ parse_pe (const char *file_name, exclusion * excl_list)
> >      }
> >  
> >    bfd_check_format (abfd, bfd_object);
> > -  bfd_map_over_sections (abfd, &select_data_section, (PTR) excl_list);
> > +
> > +  /* Compute the relocation offset for this DLL.  Unfortunately, we have to
> > +     guess at ImageBase (one page before vma of first section), since bfd
> > +     doesn't let us get at backend-private data */
> > +  bfd_vma imagebase = abfd->sections->vma - 0x1000;
> 
> VirtualQueryEx?  The AllocationBase is identical to the base address
> of the DLL loaded at that address.

Uhm... right.  Always assuming you get at the Windows process handle
from bfd...


Corinna

-- 
Corinna Vinschen
Cygwin Maintainer

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 8/8] Cygwin: Consider DLL rebasing when computing dumper exclusions
  2020-07-02  7:48     ` Corinna Vinschen
@ 2020-07-03 13:10       ` Jon Turney
  2020-07-03 19:34         ` Corinna Vinschen
  0 siblings, 1 reply; 25+ messages in thread
From: Jon Turney @ 2020-07-03 13:10 UTC (permalink / raw)
  To: Cygwin Patches

On 02/07/2020 08:48, Corinna Vinschen wrote:
> On Jul  2 09:43, Corinna Vinschen wrote:
>> On Jul  1 22:25, Jon Turney wrote:
>>> I think this would always have been neeeded, but is essential on x86_64,
>>> as kernel32.dll has an ImageBase of 00000001:80000000 (but is always
>>
>> Great, but that shouldn't matter much given that system DLLs are
>> ASLRed all the time.
>>
>>> +parse_pe (const char *file_name, exclusion * excl_list, LPVOID base_address)
>>>   {
>>>     if (file_name == NULL || excl_list == NULL)
>>>       return 0;
>>> @@ -104,7 +104,19 @@ parse_pe (const char *file_name, exclusion * excl_list)
>>>       }
>>>   
>>>     bfd_check_format (abfd, bfd_object);
>>> -  bfd_map_over_sections (abfd, &select_data_section, (PTR) excl_list);
>>> +
>>> +  /* Compute the relocation offset for this DLL.  Unfortunately, we have to
>>> +     guess at ImageBase (one page before vma of first section), since bfd
>>> +     doesn't let us get at backend-private data */
>>> +  bfd_vma imagebase = abfd->sections->vma - 0x1000;
>>
>> VirtualQueryEx?  The AllocationBase is identical to the base address
>> of the DLL loaded at that address.
> 
> Uhm... right.  Always assuming you get at the Windows process handle
> from bfd...

The problem is in the opposite direction.

We have the actual base address the DLL was loaded at in the process 
being dumped, and it's filename, from the LOAD_DLL_DEBUG_EVENT event.

(To my amazement) we then read that DLL using bfd, and examine it for 
sections with the 'CODE' or 'DEBUGGING' flags, the address ranges 
corresponding to which we believe we want to exclude from the dump.

Unfortunately, these addresses are based on the ImageBase in the PE header.

If that's different to the actual base address the PE was loaded at, we 
need to adjust these addresses appropriately.  But libbfd doesn't appear 
to provide a public interface to get at the ImageBase.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 8/8] Cygwin: Consider DLL rebasing when computing dumper exclusions
  2020-07-03 13:10       ` Jon Turney
@ 2020-07-03 19:34         ` Corinna Vinschen
  0 siblings, 0 replies; 25+ messages in thread
From: Corinna Vinschen @ 2020-07-03 19:34 UTC (permalink / raw)
  To: cygwin-patches

On Jul  3 14:10, Jon Turney wrote:
> On 02/07/2020 08:48, Corinna Vinschen wrote:
> > On Jul  2 09:43, Corinna Vinschen wrote:
> > > On Jul  1 22:25, Jon Turney wrote:
> > > > I think this would always have been neeeded, but is essential on x86_64,
> > > > as kernel32.dll has an ImageBase of 00000001:80000000 (but is always
> > > 
> > > Great, but that shouldn't matter much given that system DLLs are
> > > ASLRed all the time.
> > > 
> > > > +parse_pe (const char *file_name, exclusion * excl_list, LPVOID base_address)
> > > >   {
> > > >     if (file_name == NULL || excl_list == NULL)
> > > >       return 0;
> > > > @@ -104,7 +104,19 @@ parse_pe (const char *file_name, exclusion * excl_list)
> > > >       }
> > > >     bfd_check_format (abfd, bfd_object);
> > > > -  bfd_map_over_sections (abfd, &select_data_section, (PTR) excl_list);
> > > > +
> > > > +  /* Compute the relocation offset for this DLL.  Unfortunately, we have to
> > > > +     guess at ImageBase (one page before vma of first section), since bfd
> > > > +     doesn't let us get at backend-private data */
> > > > +  bfd_vma imagebase = abfd->sections->vma - 0x1000;
> > > 
> > > VirtualQueryEx?  The AllocationBase is identical to the base address
> > > of the DLL loaded at that address.
> > 
> > Uhm... right.  Always assuming you get at the Windows process handle
> > from bfd...
> 
> The problem is in the opposite direction.
> 
> We have the actual base address the DLL was loaded at in the process being
> dumped, and it's filename, from the LOAD_DLL_DEBUG_EVENT event.
> 
> (To my amazement) we then read that DLL using bfd, and examine it for
> sections with the 'CODE' or 'DEBUGGING' flags, the address ranges
> corresponding to which we believe we want to exclude from the dump.
> 
> Unfortunately, these addresses are based on the ImageBase in the PE header.
> 
> If that's different to the actual base address the PE was loaded at, we need
> to adjust these addresses appropriately.  But libbfd doesn't appear to
> provide a public interface to get at the ImageBase.

Ok, but you have the filename, so you can map the file and read it's
header and thus imagebase.  Still not nice, sure... but it would work
without guessing, I guess? :)


Corinna

-- 
Corinna Vinschen
Cygwin Maintainer

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 9/8] Add all memory regions details to dumper debug output
  2020-07-01 21:25 [PATCH 0/8] Fix dumper for x86_64 Jon Turney
                   ` (9 preceding siblings ...)
  2020-07-02  7:47 ` Corinna Vinschen
@ 2020-07-05 16:45 ` Jon Turney
  2020-07-05 16:45   ` [PATCH 10/8] Remove PE reading for section flags from dumper Jon Turney
                     ` (2 more replies)
  10 siblings, 3 replies; 25+ messages in thread
From: Jon Turney @ 2020-07-05 16:45 UTC (permalink / raw)
  To: cygwin-patches; +Cc: Jon Turney

---
 winsup/utils/dumper.cc | 101 ++++++++++++++++++++++++++++++++---------
 1 file changed, 80 insertions(+), 21 deletions(-)

diff --git a/winsup/utils/dumper.cc b/winsup/utils/dumper.cc
index fa3fe1fbc..04b7aa638 100644
--- a/winsup/utils/dumper.cc
+++ b/winsup/utils/dumper.cc
@@ -292,6 +292,25 @@ dumper::add_module (LPVOID base_address)
 
 #define PAGE_BUFFER_SIZE 4096
 
+void protect_dump(DWORD protect, char *buf)
+{
+  const char *pt[10];
+  pt[0] = (protect & PAGE_READONLY) ? "RO " : "";
+  pt[1] = (protect & PAGE_READWRITE) ? "RW " : "";
+  pt[2] = (protect & PAGE_WRITECOPY) ? "WC " : "";
+  pt[3] = (protect & PAGE_EXECUTE) ? "EX " : "";
+  pt[4] = (protect & PAGE_EXECUTE_READ) ? "EXRO " : "";
+  pt[5] = (protect & PAGE_EXECUTE_READWRITE) ? "EXRW " : "";
+  pt[6] = (protect & PAGE_EXECUTE_WRITECOPY) ? "EXWC " : "";
+  pt[7] = (protect & PAGE_GUARD) ? "GRD " : "";
+  pt[8] = (protect & PAGE_NOACCESS) ? "NA " : "";
+  pt[9] = (protect & PAGE_NOCACHE) ? "NC " : "";
+
+  buf[0] = '\0';
+  for (int i = 0; i < 10; i++)
+    strcat (buf, pt[i]);
+}
+
 int
 dumper::collect_memory_sections ()
 {
@@ -316,10 +335,65 @@ dumper::collect_memory_sections ()
 	break;
 
       int skip_region_p = 0;
+      const char *disposition = "dumped";
 
-      if (mbi.Protect & (PAGE_NOACCESS | PAGE_GUARD) ||
-	  mbi.State != MEM_COMMIT)
-	skip_region_p = 1;
+      if (mbi.Protect & PAGE_NOACCESS)
+	{
+	  skip_region_p = 1;
+	  disposition = "skipped due to noaccess";
+	}
+
+      if (mbi.Protect & PAGE_GUARD)
+	{
+	  skip_region_p = 1;
+	  disposition = "skipped due to guardpage";
+	}
+
+      if (mbi.State != MEM_COMMIT)
+	{
+	  skip_region_p = 1;
+	  disposition = "skipped due to uncommited";
+	}
+
+      {
+	char buf[10 * 6];
+	protect_dump(mbi.Protect, buf);
+
+	const char *state = "";
+	const char *type = "";
+
+	if (mbi.State & MEM_COMMIT)
+	  {
+	    state = "COMMIT";
+	  }
+	else if (mbi.State & MEM_FREE)
+	  {
+	    state = "FREE";
+	    type = "FREE";
+	  }
+	else if (mbi.State & MEM_RESERVE)
+	  {
+	    state = "RESERVE";
+	  }
+
+	if (mbi.Type & MEM_IMAGE)
+	  {
+	    type = "IMAGE";
+	  }
+	else if (mbi.Type & MEM_MAPPED)
+	  {
+	    type = "MAPPED";
+	  }
+	else if (mbi.Type & MEM_PRIVATE)
+	  {
+	    type = "PRIVATE";
+	  }
+
+	deb_printf ("region 0x%016lx-0x%016lx (protect = %-8s, state = %-7s, type = %-7s, %s)\n",
+		    current_page_address,
+		    current_page_address + mbi.RegionSize,
+		    buf, state, type, disposition);
+      }
 
       if (!skip_region_p)
 	{
@@ -329,26 +403,11 @@ dumper::collect_memory_sections ()
 	  if (!ReadProcessMemory (hProcess, current_page_address, mem_buf, sizeof (mem_buf), &done))
 	    {
 	      DWORD err = GetLastError ();
-	      const char *pt[10];
-	      pt[0] = (mbi.Protect & PAGE_READONLY) ? "RO " : "";
-	      pt[1] = (mbi.Protect & PAGE_READWRITE) ? "RW " : "";
-	      pt[2] = (mbi.Protect & PAGE_WRITECOPY) ? "WC " : "";
-	      pt[3] = (mbi.Protect & PAGE_EXECUTE) ? "EX " : "";
-	      pt[4] = (mbi.Protect & PAGE_EXECUTE_READ) ? "EXRO " : "";
-	      pt[5] = (mbi.Protect & PAGE_EXECUTE_READWRITE) ? "EXRW " : "";
-	      pt[6] = (mbi.Protect & PAGE_EXECUTE_WRITECOPY) ? "EXWC " : "";
-	      pt[7] = (mbi.Protect & PAGE_GUARD) ? "GRD " : "";
-	      pt[8] = (mbi.Protect & PAGE_NOACCESS) ? "NA " : "";
-	      pt[9] = (mbi.Protect & PAGE_NOCACHE) ? "NC " : "";
-	      char buf[10 * 6];
-	      buf[0] = '\0';
-	      for (int i = 0; i < 10; i++)
-		strcat (buf, pt[i]);
-
-	      deb_printf ("warning: failed to read memory at %p-%p (protect = %s), error %ld.\n",
+
+	      deb_printf ("warning: failed to read memory at %p-%p, error %ld.\n",
 			  current_page_address,
 			  current_page_address + mbi.RegionSize,
-			  buf, err);
+			  err);
 	      skip_region_p = 1;
 	    }
 	}
-- 
2.27.0


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 10/8] Remove PE reading for section flags from dumper
  2020-07-05 16:45 ` [PATCH 9/8] Add all memory regions details to dumper debug output Jon Turney
@ 2020-07-05 16:45   ` Jon Turney
  2020-07-05 16:45   ` [PATCH 11/8] Drop excluded regions list " Jon Turney
  2020-07-05 16:45   ` [PATCH 12/8] Don't dump non-writable image regions Jon Turney
  2 siblings, 0 replies; 25+ messages in thread
From: Jon Turney @ 2020-07-05 16:45 UTC (permalink / raw)
  To: cygwin-patches; +Cc: Jon Turney

---
 winsup/utils/Makefile.in |   6 +-
 winsup/utils/dumper.cc   |   2 -
 winsup/utils/dumper.h    |   2 -
 winsup/utils/parse_pe.cc | 124 ---------------------------------------
 4 files changed, 3 insertions(+), 131 deletions(-)
 delete mode 100644 winsup/utils/parse_pe.cc

diff --git a/winsup/utils/Makefile.in b/winsup/utils/Makefile.in
index 5bb62bc6f..f9892fa1d 100644
--- a/winsup/utils/Makefile.in
+++ b/winsup/utils/Makefile.in
@@ -113,9 +113,9 @@ build_dumper := $(shell test -r "$(libbfd)" && echo 1)
 
 ifdef build_dumper
 CYGWIN_BINS += dumper.exe
-dumper.o module_info.o parse_pe.o: CXXFLAGS += -I$(top_srcdir)/include
-dumper.o parse_pe.o: dumper.h
-dumper.exe: module_info.o parse_pe.o
+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}
 else
 all: warn_dumper
diff --git a/winsup/utils/dumper.cc b/winsup/utils/dumper.cc
index 04b7aa638..d9d07c055 100644
--- a/winsup/utils/dumper.cc
+++ b/winsup/utils/dumper.cc
@@ -284,8 +284,6 @@ dumper::add_module (LPVOID base_address)
   new_entity->u.module.base_address = base_address;
   new_entity->u.module.name = module_name;
 
-  parse_pe (module_name, excl_list, base_address);
-
   deb_printf ("added module %p %s\n", base_address, module_name);
   return 1;
 }
diff --git a/winsup/utils/dumper.h b/winsup/utils/dumper.h
index 9c4b1f092..78592b61e 100644
--- a/winsup/utils/dumper.h
+++ b/winsup/utils/dumper.h
@@ -133,8 +133,6 @@ extern int deb_printf ( const char* format, ... );
 
 extern char* psapi_get_module_name ( HANDLE hProcess, LPVOID BaseAddress );
 
-extern int parse_pe ( const char* file_name, exclusion* excl_list, LPVOID base_address );
-
 extern BOOL verbose;
 
 #endif
diff --git a/winsup/utils/parse_pe.cc b/winsup/utils/parse_pe.cc
deleted file mode 100644
index 0256ada53..000000000
--- a/winsup/utils/parse_pe.cc
+++ /dev/null
@@ -1,124 +0,0 @@
-/* parse_pe.cc
-
-   Written by Egor Duda <deo@logos-m.ru>
-
-   This file is part of Cygwin.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License (file COPYING.dumper) for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
-
-#define PACKAGE
-#include <bfd.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "dumper.h"
-
-#ifndef bfd_get_section_size
-#define bfd_get_section_size(sect) bfd_section_size(sect)
-#endif
-
-int
-exclusion::add (LPBYTE mem_base, SIZE_T mem_size)
-{
-  while (last >= size)
-    size += step;
-  region = (process_mem_region *) realloc (region, size * sizeof (process_mem_region));
-  if (region == NULL)
-    return 0;
-  region[last].base = mem_base;
-  region[last].size = mem_size;
-  last++;
-  return 1;
-};
-
-int
-cmp_regions (const void *r1, const void *r2)
-{
-  if (((process_mem_region *) r1)->base < ((process_mem_region *) r2)->base)
-    return -1;
-  if (((process_mem_region *) r1)->base > ((process_mem_region *) r2)->base)
-    return 1;
-  return 0;
-}
-
-int
-exclusion::sort_and_check ()
-{
-  qsort (region, last, sizeof (process_mem_region), &cmp_regions);
-  for (process_mem_region * p = region; p < region + last - 1; p++)
-    {
-      process_mem_region *q = p + 1;
-      if (p->base + p->size > q->base)
-	{
-	  fprintf (stderr, "region error @ (%p + 0x%0llx) > %p\n", p->base, p->size, q->base);
-	  return 0;
-	}
-    }
-  return 1;
-}
-
-static void
-select_data_section (bfd * abfd, asection * sect, exclusion *excl_list,
-		     SSIZE_T adj)
-{
-  if ((sect->flags & (SEC_CODE | SEC_DEBUGGING)) &&
-      sect->vma && bfd_get_section_size (sect))
-    {
-      bfd_vma vma = sect->vma + adj;
-      excl_list->add ((LPBYTE) vma, (SIZE_T) bfd_get_section_size (sect));
-      deb_printf ("excluding section: %20s %016lx %016lx %08lx\n", sect->name,
-		  sect->vma, vma, bfd_get_section_size (sect));
-    }
-}
-
-int
-parse_pe (const char *file_name, exclusion * excl_list, LPVOID base_address)
-{
-  if (file_name == NULL || excl_list == NULL)
-    return 0;
-
-#ifdef __x86_64__
-  const char *target = "pei-x86-64";
-#else
-  const char *target = "pei-i386";
-#endif
-
-  bfd *abfd = bfd_openr (file_name, target);
-
-  if (abfd == NULL)
-    {
-      bfd_perror ("failed to open file");
-      return 0;
-    }
-
-  bfd_check_format (abfd, bfd_object);
-
-  /* Compute the relocation offset for this DLL.  Unfortunately, we have to
-     guess at ImageBase (one page before vma of first section), since bfd
-     doesn't let us get at backend-private data */
-  bfd_vma imagebase = abfd->sections->vma - 0x1000;
-  SSIZE_T adj = (bfd_vma)base_address - imagebase;
-  deb_printf("imagebase relocated from %016lx to %016lx (%016lx)\n",
-	     imagebase, base_address, adj);
-
-  asection *p;
-  for (p = abfd->sections; p != NULL; p = p->next)
-    select_data_section(abfd, p, excl_list, adj);
-
-  excl_list->sort_and_check ();
-
-  bfd_close (abfd);
-  return 1;
-}
-- 
2.27.0


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 11/8] Drop excluded regions list from dumper
  2020-07-05 16:45 ` [PATCH 9/8] Add all memory regions details to dumper debug output Jon Turney
  2020-07-05 16:45   ` [PATCH 10/8] Remove PE reading for section flags from dumper Jon Turney
@ 2020-07-05 16:45   ` Jon Turney
  2020-07-05 16:45   ` [PATCH 12/8] Don't dump non-writable image regions Jon Turney
  2 siblings, 0 replies; 25+ messages in thread
From: Jon Turney @ 2020-07-05 16:45 UTC (permalink / raw)
  To: cygwin-patches; +Cc: Jon Turney

Drop excluded regions, now it's always empty
---
 winsup/utils/dumper.cc | 51 ++++--------------------------------------
 winsup/utils/dumper.h  | 17 --------------
 2 files changed, 4 insertions(+), 64 deletions(-)

diff --git a/winsup/utils/dumper.cc b/winsup/utils/dumper.cc
index d9d07c055..2a0c66002 100644
--- a/winsup/utils/dumper.cc
+++ b/winsup/utils/dumper.cc
@@ -83,7 +83,6 @@ dumper::dumper (DWORD pid, DWORD tid, const char *file_name)
   this->pid = pid;
   this->tid = tid;
   core_bfd = NULL;
-  excl_list = new exclusion (20);
 
   list = last = NULL;
 
@@ -125,19 +124,16 @@ dumper::close ()
 {
   if (core_bfd)
     bfd_close (core_bfd);
-  if (excl_list)
-    delete excl_list;
   if (hProcess)
     CloseHandle (hProcess);
   core_bfd = NULL;
   hProcess = NULL;
-  excl_list = NULL;
 }
 
 int
 dumper::sane ()
 {
-  if (hProcess == NULL || core_bfd == NULL || excl_list == NULL)
+  if (hProcess == NULL || core_bfd == NULL)
     return 0;
   return 1;
 }
@@ -226,45 +222,6 @@ dumper::add_mem_region (LPBYTE base, SIZE_T size)
   return 1;
 }
 
-/* split_add_mem_region scans list of regions to be excluded from dumping process
-   (excl_list) and removes all "excluded" parts from given region. */
-int
-dumper::split_add_mem_region (LPBYTE base, SIZE_T size)
-{
-  if (!sane ())
-    return 0;
-
-  if (base == NULL || size == 0)
-    return 1;			// just ignore empty regions
-
-  LPBYTE last_base = base;
-
-  for (process_mem_region * p = excl_list->region;
-       p < excl_list->region + excl_list->last;
-       p++)
-    {
-      if (p->base >= base + size || p->base + p->size <= base)
-	continue;
-
-      if (p->base <= base)
-	{
-	  last_base = p->base + p->size;
-	  continue;
-	}
-
-      if (p->base < last_base)
-	continue;
-
-      add_mem_region (last_base, p->base - last_base);
-      last_base = p->base + p->size;
-    }
-
-  if (last_base < base + size)
-    add_mem_region (last_base, base + size - last_base);
-
-  return 1;
-}
-
 int
 dumper::add_module (LPVOID base_address)
 {
@@ -416,14 +373,14 @@ dumper::collect_memory_sections ()
 	    last_size += mbi.RegionSize;
 	  else
 	    {
-	      split_add_mem_region (last_base, last_size);
+	      add_mem_region (last_base, last_size);
 	      last_base = (LPBYTE) mbi.BaseAddress;
 	      last_size = mbi.RegionSize;
 	    }
 	}
       else
 	{
-	  split_add_mem_region (last_base, last_size);
+	  add_mem_region (last_base, last_size);
 	  last_base = NULL;
 	  last_size = 0;
 	}
@@ -432,7 +389,7 @@ dumper::collect_memory_sections ()
     }
 
   /* dump last sections, if any */
-  split_add_mem_region (last_base, last_size);
+  add_mem_region (last_base, last_size);
   return 1;
 };
 
diff --git a/winsup/utils/dumper.h b/winsup/utils/dumper.h
index 78592b61e..6e624a983 100644
--- a/winsup/utils/dumper.h
+++ b/winsup/utils/dumper.h
@@ -62,22 +62,6 @@ typedef struct _process_entity
   struct _process_entity* next;
 } process_entity;
 
-class exclusion
-{
-public:
-  size_t last;
-  size_t size;
-  size_t step;
-  process_mem_region* region;
-
-  exclusion ( size_t step ) { last = size = 0;
-			      this->step = step;
-			      region = NULL; }
-  ~exclusion () { free ( region ); }
-  int add ( LPBYTE mem_base, SIZE_T mem_size );
-  int sort_and_check ();
-};
-
 #define PAGE_BUFFER_SIZE 4096
 
 class dumper
@@ -87,7 +71,6 @@ class dumper
   HANDLE hProcess;
   process_entity* list;
   process_entity* last;
-  exclusion* excl_list;
 
   char* file_name;
   bfd* core_bfd;
-- 
2.27.0


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 12/8] Don't dump non-writable image regions
  2020-07-05 16:45 ` [PATCH 9/8] Add all memory regions details to dumper debug output Jon Turney
  2020-07-05 16:45   ` [PATCH 10/8] Remove PE reading for section flags from dumper Jon Turney
  2020-07-05 16:45   ` [PATCH 11/8] Drop excluded regions list " Jon Turney
@ 2020-07-05 16:45   ` Jon Turney
  2 siblings, 0 replies; 25+ messages in thread
From: Jon Turney @ 2020-07-05 16:45 UTC (permalink / raw)
  To: cygwin-patches; +Cc: Jon Turney

After this, we will end up dumping memory regions where:

- state is MEM_COMMIT (i.e. is not MEM_RESERVE or MEM_FREE), and
-- type is MEM_PRIVATE and protection allows reads (i.e. not a guardpage), or
-- type is MEM_IMAGE and protection allows writes

Making this decision based on the current protection isn't 100% correct,
because it may have been changed using VirtualProtect().  But we don't
know how to determine if a region is shareable.

(As a practical matter, anything which gets us the stack (MEM_PRIVATE)
and .data/.bss (RW MEM_IMAGE) is going to be enough for 99% of cases)
---
 winsup/utils/dumper.cc | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/winsup/utils/dumper.cc b/winsup/utils/dumper.cc
index 2a0c66002..b96ee54cc 100644
--- a/winsup/utils/dumper.cc
+++ b/winsup/utils/dumper.cc
@@ -292,6 +292,12 @@ 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)))
+	{
+	  skip_region_p = 1;
+	  disposition = "skipped due to non-writeable MEM_IMAGE";
+	}
+
       if (mbi.Protect & PAGE_NOACCESS)
 	{
 	  skip_region_p = 1;
-- 
2.27.0


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 0/8] Fix dumper for x86_64
  2020-07-02  7:44   ` Corinna Vinschen
@ 2020-07-05 16:49     ` Jon Turney
  2020-07-06  8:12       ` Corinna Vinschen
  0 siblings, 1 reply; 25+ messages in thread
From: Jon Turney @ 2020-07-05 16:49 UTC (permalink / raw)
  To: Cygwin Patches

On 02/07/2020 08:44, Corinna Vinschen wrote:
> On Jul  1 22:29, Jon Turney wrote:
>>
>> This needs to be aligned with some changes to gdb to consume the dumps it
>> produces, so it's probably best to hold off applying this until it's more
>> obvious what's going to happen with those.
>>
>> Random notes:
>>
>> - objdump identifies the output of dumper on x86_64 as
>> 'elf64-x86-64-cloudabi' (perhaps due to some over-eager sniffer).
>>
>> - regions excluded from the dump aren't rounded up to page size, so we may
>> end up writing the excess into the dump.
>>
>> - looking at the loaded modules and inspecting them to determine what memory
>> regions don't need to appear in the dump seems odd.  I'm not sure we don't
>> just exclude MEMORY_BASIC_INFORMATION.Type == MEM_IMAGE regions (assuming
>> they get converted to MEM_PRIVATE regions if written when copy-on-write).

Unfortunately, that doesn't happen, and the region appears to stay 
MEM_IMAGE, even if it's been modified.

I'm inclined to just dump MEM_IMAGE regions if they are writable 
(although using the current protection isn't 100% correct, because it 
may have been changed using VirtualProtect())

I suspect there's probably some undocumented MemoryInformationClass for 
NtQueryVirtualMemory() that would let us determine if a region is 
sharable or not, but ...

> Could format_process_maps() in fhandler_process.cc be a role model here?

Thanks for pointing that out.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 0/8] Fix dumper for x86_64
  2020-07-05 16:49     ` Jon Turney
@ 2020-07-06  8:12       ` Corinna Vinschen
  2020-07-06 13:34         ` Jon Turney
  0 siblings, 1 reply; 25+ messages in thread
From: Corinna Vinschen @ 2020-07-06  8:12 UTC (permalink / raw)
  To: cygwin-patches

On Jul  5 17:49, Jon Turney wrote:
> On 02/07/2020 08:44, Corinna Vinschen wrote:
> > On Jul  1 22:29, Jon Turney wrote:
> > > 
> > > This needs to be aligned with some changes to gdb to consume the dumps it
> > > produces, so it's probably best to hold off applying this until it's more
> > > obvious what's going to happen with those.
> > > 
> > > Random notes:
> > > 
> > > - objdump identifies the output of dumper on x86_64 as
> > > 'elf64-x86-64-cloudabi' (perhaps due to some over-eager sniffer).
> > > 
> > > - regions excluded from the dump aren't rounded up to page size, so we may
> > > end up writing the excess into the dump.
> > > 
> > > - looking at the loaded modules and inspecting them to determine what memory
> > > regions don't need to appear in the dump seems odd.  I'm not sure we don't
> > > just exclude MEMORY_BASIC_INFORMATION.Type == MEM_IMAGE regions (assuming
> > > they get converted to MEM_PRIVATE regions if written when copy-on-write).
> 
> Unfortunately, that doesn't happen, and the region appears to stay
> MEM_IMAGE, even if it's been modified.
> 
> I'm inclined to just dump MEM_IMAGE regions if they are writable (although
> using the current protection isn't 100% correct, because it may have been
> changed using VirtualProtect())
> 
> I suspect there's probably some undocumented MemoryInformationClass for
> NtQueryVirtualMemory() that would let us determine if a region is sharable
> or not, but ...

Surprisingly, there's nothing undocumented in NtQueryVirtualMemory and
the API is fully exposed by VirtualQuery(Ex).

What about the two protection fields in MEMORY_BASIC_INFORMATION?  If
something changed, Protect != AllocationProtect.  Is that insufficient
to handle your case?


Corinna

-- 
Corinna Vinschen
Cygwin Maintainer

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 0/8] Fix dumper for x86_64
  2020-07-06  8:12       ` Corinna Vinschen
@ 2020-07-06 13:34         ` Jon Turney
  2020-07-06 18:10           ` Corinna Vinschen
  2020-07-12 14:47           ` Jon Turney
  0 siblings, 2 replies; 25+ messages in thread
From: Jon Turney @ 2020-07-06 13:34 UTC (permalink / raw)
  To: Cygwin Patches

On 06/07/2020 09:12, Corinna Vinschen wrote:
> On Jul  5 17:49, Jon Turney wrote:
>> On 02/07/2020 08:44, Corinna Vinschen wrote:
>>> On Jul  1 22:29, Jon Turney wrote:
>>>>
>>>> This needs to be aligned with some changes to gdb to consume the dumps it
>>>> produces, so it's probably best to hold off applying this until it's more
>>>> obvious what's going to happen with those.
>>>>
>>>> Random notes:
>>>>
>>>> - objdump identifies the output of dumper on x86_64 as
>>>> 'elf64-x86-64-cloudabi' (perhaps due to some over-eager sniffer).
>>>>
>>>> - regions excluded from the dump aren't rounded up to page size, so we may
>>>> end up writing the excess into the dump.
>>>>
>>>> - looking at the loaded modules and inspecting them to determine what memory
>>>> regions don't need to appear in the dump seems odd.  I'm not sure we don't
>>>> just exclude MEMORY_BASIC_INFORMATION.Type == MEM_IMAGE regions (assuming
>>>> they get converted to MEM_PRIVATE regions if written when copy-on-write).
>>
>> Unfortunately, that doesn't happen, and the region appears to stay
>> MEM_IMAGE, even if it's been modified.
>>
>> I'm inclined to just dump MEM_IMAGE regions if they are writable (although
>> using the current protection isn't 100% correct, because it may have been
>> changed using VirtualProtect())
>>
>> I suspect there's probably some undocumented MemoryInformationClass for
>> NtQueryVirtualMemory() that would let us determine if a region is sharable
>> or not, but ...
> 
> Surprisingly, there's nothing undocumented in NtQueryVirtualMemory and
> the API is fully exposed by VirtualQuery(Ex).

I came across [1], which seems to use some MemoryInformationClass values 
I can't find any MSDN documentation on, but perhaps I'm getting lost.

[1] 
https://github.com/processhacker/processhacker/blob/master/phnt/include/ntmmapi.h#L87

> What about the two protection fields in MEMORY_BASIC_INFORMATION?  If
> something changed, Protect != AllocationProtect.  Is that insufficient
> to handle your case?

Unfortunately that doesn't seem to provide any additional information. 
The Windows loader seems to allocate all regions with EXWC protection, 
then change it to match the section. (Not that there are any guarantees 
about it's behaviour)

I wasn't able to observe a region corresponding to an unmodified .data 
section with WC protection, which is somewhat confusing.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 0/8] Fix dumper for x86_64
  2020-07-06 13:34         ` Jon Turney
@ 2020-07-06 18:10           ` Corinna Vinschen
  2020-07-12 14:47           ` Jon Turney
  1 sibling, 0 replies; 25+ messages in thread
From: Corinna Vinschen @ 2020-07-06 18:10 UTC (permalink / raw)
  To: cygwin-patches

On Jul  6 14:34, Jon Turney wrote:
> On 06/07/2020 09:12, Corinna Vinschen wrote:
> > On Jul  5 17:49, Jon Turney wrote:
> > > On 02/07/2020 08:44, Corinna Vinschen wrote:
> > > > On Jul  1 22:29, Jon Turney wrote:
> > > > > 
> > > > > This needs to be aligned with some changes to gdb to consume the dumps it
> > > > > produces, so it's probably best to hold off applying this until it's more
> > > > > obvious what's going to happen with those.
> > > > > 
> > > > > Random notes:
> > > > > 
> > > > > - objdump identifies the output of dumper on x86_64 as
> > > > > 'elf64-x86-64-cloudabi' (perhaps due to some over-eager sniffer).
> > > > > 
> > > > > - regions excluded from the dump aren't rounded up to page size, so we may
> > > > > end up writing the excess into the dump.
> > > > > 
> > > > > - looking at the loaded modules and inspecting them to determine what memory
> > > > > regions don't need to appear in the dump seems odd.  I'm not sure we don't
> > > > > just exclude MEMORY_BASIC_INFORMATION.Type == MEM_IMAGE regions (assuming
> > > > > they get converted to MEM_PRIVATE regions if written when copy-on-write).
> > > 
> > > Unfortunately, that doesn't happen, and the region appears to stay
> > > MEM_IMAGE, even if it's been modified.
> > > 
> > > I'm inclined to just dump MEM_IMAGE regions if they are writable (although
> > > using the current protection isn't 100% correct, because it may have been
> > > changed using VirtualProtect())
> > > 
> > > I suspect there's probably some undocumented MemoryInformationClass for
> > > NtQueryVirtualMemory() that would let us determine if a region is sharable
> > > or not, but ...
> > 
> > Surprisingly, there's nothing undocumented in NtQueryVirtualMemory and
> > the API is fully exposed by VirtualQuery(Ex).
> 
> I came across [1], which seems to use some MemoryInformationClass values I
> can't find any MSDN documentation on, but perhaps I'm getting lost.
> 
> [1] https://github.com/processhacker/processhacker/blob/master/phnt/include/ntmmapi.h#L87

Uh, sorry.  I confused NtQueryVirtualMemory with just the
MemoryBasicInformation class.  Looking into the above, the
MEMORY_REGION_INFORMATION struct looks pretty interesting
but I doubt it helps...


Corinna

-- 
Corinna Vinschen
Cygwin Maintainer

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 0/8] Fix dumper for x86_64
  2020-07-06 13:34         ` Jon Turney
  2020-07-06 18:10           ` Corinna Vinschen
@ 2020-07-12 14:47           ` Jon Turney
  1 sibling, 0 replies; 25+ messages in thread
From: Jon Turney @ 2020-07-12 14:47 UTC (permalink / raw)
  To: Cygwin Patches

On 06/07/2020 14:34, Jon Turney wrote:
> On 06/07/2020 09:12, Corinna Vinschen wrote: 
> 
>> What about the two protection fields in MEMORY_BASIC_INFORMATION?  If
>> something changed, Protect != AllocationProtect.  Is that insufficient
>> to handle your case?
> 
> Unfortunately that doesn't seem to provide any additional information. 
> The Windows loader seems to allocate all regions with EXWC protection, 
> then change it to match the section. (Not that there are any guarantees 
> about it's behaviour)
> 
> I wasn't able to observe a region corresponding to an unmodified .data 
> section with WC protection, which is somewhat confusing.

I guess that might be due to something in crt0 modifying .data, since 
testing with something like:

      1  #include <windows.h>
      2
      3  int __attribute__ ((section (".special"))) mutable = 2;
      4
      5  int main()
      6  {
      7    // modify rw data
      8    // mutable = 0;
      9
     10    // deref null pointer
     11    *(int *)0 = 1;
     12  }

The memory region corresponding to the '.special' section has WC 
protection, which changes to RW if it gets modified (as expected).

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2020-07-12 14:47 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-01 21:25 [PATCH 0/8] Fix dumper for x86_64 Jon Turney
2020-07-01 21:25 ` [PATCH 1/8] Cygwin: Slightly improve error_start documentation Jon Turney
2020-07-01 21:25 ` [PATCH 2/8] Cygwin: Update ELF target used by dumper on x86_64 Jon Turney
2020-07-01 21:25 ` [PATCH 3/8] Cygwin: Add a new win32_pstatus data type for modules " Jon Turney
2020-07-01 21:25 ` [PATCH 4/8] Cygwin: Make dumper scan more than first 4GB of VM " Jon Turney
2020-07-01 21:25 ` [PATCH 5/8] Cygwin: Fix bfd target for parsing PE files on x86_64 in dumper Jon Turney
2020-07-01 21:25 ` [PATCH 6/8] Cygwin: Fix dumper region order/overlap checking Jon Turney
2020-07-01 21:25 ` [PATCH 7/8] Cygwin: Handle excluded regions more robustly in dumper Jon Turney
2020-07-01 21:25 ` [PATCH 8/8] Cygwin: Consider DLL rebasing when computing dumper exclusions Jon Turney
2020-07-02  7:43   ` Corinna Vinschen
2020-07-02  7:48     ` Corinna Vinschen
2020-07-03 13:10       ` Jon Turney
2020-07-03 19:34         ` Corinna Vinschen
2020-07-01 21:29 ` [PATCH 0/8] Fix dumper for x86_64 Jon Turney
2020-07-02  7:44   ` Corinna Vinschen
2020-07-05 16:49     ` Jon Turney
2020-07-06  8:12       ` Corinna Vinschen
2020-07-06 13:34         ` Jon Turney
2020-07-06 18:10           ` Corinna Vinschen
2020-07-12 14:47           ` Jon Turney
2020-07-02  7:47 ` Corinna Vinschen
2020-07-05 16:45 ` [PATCH 9/8] Add all memory regions details to dumper debug output Jon Turney
2020-07-05 16:45   ` [PATCH 10/8] Remove PE reading for section flags from dumper Jon Turney
2020-07-05 16:45   ` [PATCH 11/8] Drop excluded regions list " Jon Turney
2020-07-05 16:45   ` [PATCH 12/8] Don't dump non-writable image regions Jon Turney

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).