From b4966f91396b337dc0ce1c1b9f7a95a62a64c84e Mon Sep 17 00:00:00 2001 From: Corinna Vinschen <corinna@vinschen.de> Date: Fri, 13 May 2011 06:50:20 +0000 Subject: [PATCH] * fhandler_process.cc (struct heap_info::heap): Convert base to uintptr_t. Add heap_id, end, flags members. (heap_info::heap_vm_chunks): Rename from heaps. (heap_info::heap_info): Rearrange using RtlQueryProcessDebugInformation to get information of heap virtual memory blocks. Store heap id and flags, as well as end address of each block. (heap_info::fill_if_match): Check incoming base address against full address range of heap chunks. Convert flag values in extra heap information. (format_process_maps): Change order so that heap check is done before MEM_MAPPED check since there are shareable heaps. * ntdll.h (PDI_HEAP_BLOCKS): Define. (HEAP_FLAG_NOSERIALIZE): Define. (HEAP_FLAG_GROWABLE): Define. (HEAP_FLAG_EXCEPTIONS): Define. (HEAP_FLAG_NONDEFAULT): Define. (HEAP_FLAG_SHAREABLE): Define. (HEAP_FLAG_EXECUTABLE): Define. (HEAP_FLAG_DEBUGGED): Define. (struct _DEBUG_HEAP_ARRAY): Define. (struct _DEBUG_HEAP_BLOCK): Define. --- winsup/cygwin/ChangeLog | 24 +++++++++ winsup/cygwin/fhandler_process.cc | 86 ++++++++++++++++++++++--------- winsup/cygwin/ntdll.h | 24 +++++++++ 3 files changed, 109 insertions(+), 25 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index b3122ab28..0733a86a7 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,27 @@ +2011-05-13 Corinna Vinschen <corinna@vinschen.de> + + * fhandler_process.cc (struct heap_info::heap): Convert base to + uintptr_t. Add heap_id, end, flags members. + (heap_info::heap_vm_chunks): Rename from heaps. + (heap_info::heap_info): Rearrange using RtlQueryProcessDebugInformation + to get information of heap virtual memory blocks. Store heap id and + flags, as well as end address of each block. + (heap_info::fill_if_match): Check incoming base address against full + address range of heap chunks. Convert flag values in extra heap + information. + (format_process_maps): Change order so that heap check is done before + MEM_MAPPED check since there are shareable heaps. + * ntdll.h (PDI_HEAP_BLOCKS): Define. + (HEAP_FLAG_NOSERIALIZE): Define. + (HEAP_FLAG_GROWABLE): Define. + (HEAP_FLAG_EXCEPTIONS): Define. + (HEAP_FLAG_NONDEFAULT): Define. + (HEAP_FLAG_SHAREABLE): Define. + (HEAP_FLAG_EXECUTABLE): Define. + (HEAP_FLAG_DEBUGGED): Define. + (struct _DEBUG_HEAP_ARRAY): Define. + (struct _DEBUG_HEAP_BLOCK): Define. + 2011-05-12 Corinna Vinschen <corinna@vinschen.de> Based on newlib patch to strptime by Peter Rosin <peda@lysator.liu.se>: diff --git a/winsup/cygwin/fhandler_process.cc b/winsup/cygwin/fhandler_process.cc index 3d353096c..1038537ce 100644 --- a/winsup/cygwin/fhandler_process.cc +++ b/winsup/cygwin/fhandler_process.cc @@ -614,34 +614,68 @@ struct heap_info struct heap { heap *next; - void *base; + unsigned heap_id; + uintptr_t base; + uintptr_t end; + unsigned long flags; }; - heap *heaps; + heap *heap_vm_chunks; heap_info (DWORD pid) - : heaps (0) + : heap_vm_chunks (0) { - HANDLE hHeapSnap = CreateToolhelp32Snapshot (TH32CS_SNAPHEAPLIST, pid); - HEAPLIST32 hl; - hl.dwSize = sizeof(hl); + PDEBUG_BUFFER buf; + NTSTATUS status; + PDEBUG_HEAP_ARRAY harray; - if (hHeapSnap != INVALID_HANDLE_VALUE && Heap32ListFirst (hHeapSnap, &hl)) - do - { - heap *h = (heap *) cmalloc (HEAP_FHANDLER, sizeof (heap)); - *h = (heap) {heaps, (void*) hl.th32HeapID}; - heaps = h; - } while (Heap32ListNext (hHeapSnap, &hl)); - CloseHandle (hHeapSnap); + buf = RtlCreateQueryDebugBuffer (0, FALSE); + if (!buf) + return; + status = RtlQueryProcessDebugInformation (pid, PDI_HEAPS | PDI_HEAP_BLOCKS, + buf); + if (NT_SUCCESS (status) + && (harray = (PDEBUG_HEAP_ARRAY) buf->HeapInformation) != NULL) + for (ULONG hcnt = 0; hcnt < harray->Count; ++hcnt) + { + PDEBUG_HEAP_BLOCK barray = (PDEBUG_HEAP_BLOCK) + harray->Heaps[hcnt].Blocks; + if (!barray) + continue; + for (ULONG bcnt = 0; bcnt < harray->Heaps[hcnt].BlockCount; ++bcnt) + if (barray[bcnt].Flags & 2) + { + heap *h = (heap *) cmalloc (HEAP_FHANDLER, sizeof (heap)); + *h = (heap) { heap_vm_chunks, + hcnt, barray[bcnt].Address, + barray[bcnt].Address + barray[bcnt].Size, + harray->Heaps[hcnt].Flags }; + heap_vm_chunks = h; + } + } + RtlDestroyQueryDebugBuffer (buf); } - char *fill_if_match (void *base, char *dest ) + char *fill_if_match (void *base, ULONG type, char *dest ) { - long count = 0; - for (heap *h = heaps; h && ++count; h = h->next) - if (base == h->base) + for (heap *h = heap_vm_chunks; h; h = h->next) + if ((uintptr_t) base >= h->base && (uintptr_t) base < h->end) { - __small_sprintf (dest, "[heap %ld]", count); + char *p; + __small_sprintf (dest, "[heap %ld", h->heap_id); + p = strchr (dest, '\0'); + if (!(h->flags & HEAP_FLAG_NONDEFAULT)) + p = stpcpy (p, " default"); + if ((h->flags & HEAP_FLAG_SHAREABLE) && (type & MEM_MAPPED)) + p = stpcpy (p, " share"); + if (h->flags & HEAP_FLAG_EXECUTABLE) + p = stpcpy (p, " exec"); + if (h->flags & HEAP_FLAG_GROWABLE) + p = stpcpy (p, " grow"); + if (h->flags & HEAP_FLAG_NOSERIALIZE) + p = stpcpy (p, " noserial"); + if (h->flags == HEAP_FLAG_DEBUGGED) + p = stpcpy (p, " debug"); + stpcpy (p, "]"); return dest; } return 0; @@ -650,7 +684,7 @@ struct heap_info ~heap_info () { heap *n = 0; - for (heap *m = heaps; m; m = n) + for (heap *m = heap_vm_chunks; m; m = n) { n = m->next; cfree (m); @@ -777,11 +811,13 @@ format_process_maps (void *data, char *&destbuf) sys_wcstombs (posix_modname, NT_MAX_PATH, dosname); stat64 (posix_modname, &st); } - else if (mb.Type & MEM_MAPPED) - strcpy (posix_modname, "[shareable]"); - else if (!(mb.Type & MEM_PRIVATE - && heaps.fill_if_match (cur.abase, posix_modname))) - posix_modname[0] = 0; + else if (!heaps.fill_if_match (cur.abase, mb.Type, posix_modname)) + { + if (mb.Type & MEM_MAPPED) + strcpy (posix_modname, "[shareable]"); + else + posix_modname[0] = 0; + } } } } diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index df0ae29a3..cb4e6d962 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -63,6 +63,7 @@ #define PDI_MODULES 0x01 #define PDI_HEAPS 0x04 +#define PDI_HEAP_BLOCKS 0x10 #define LDRP_IMAGE_DLL 0x00000004 #define WSLE_PAGE_READONLY 0x001 #define WSLE_PAGE_EXECUTE 0x002 @@ -510,6 +511,15 @@ typedef struct _DEBUG_BUFFER PVOID Reserved[9]; } DEBUG_BUFFER, *PDEBUG_BUFFER; +/* Known debug heap flags */ +#define HEAP_FLAG_NOSERIALIZE 0x1 +#define HEAP_FLAG_GROWABLE 0x2 +#define HEAP_FLAG_EXCEPTIONS 0x4 +#define HEAP_FLAG_NONDEFAULT 0x1000 +#define HEAP_FLAG_SHAREABLE 0x8000 +#define HEAP_FLAG_EXECUTABLE 0x40000 +#define HEAP_FLAG_DEBUGGED 0x40000000 + typedef struct _DEBUG_HEAP_INFORMATION { ULONG Base; @@ -525,6 +535,20 @@ typedef struct _DEBUG_HEAP_INFORMATION PVOID Blocks; } DEBUG_HEAP_INFORMATION, *PDEBUG_HEAP_INFORMATION; +typedef struct _DEBUG_HEAP_ARRAY +{ + ULONG Count; + DEBUG_HEAP_INFORMATION Heaps[1]; +} DEBUG_HEAP_ARRAY, *PDEBUG_HEAP_ARRAY; + +typedef struct _DEBUG_HEAP_BLOCK +{ + ULONG Size; + ULONG Flags; + ULONG Committed; + ULONG Address; +} DEBUG_HEAP_BLOCK, *PDEBUG_HEAP_BLOCK; + typedef struct _DEBUG_MODULE_INFORMATION { ULONG Reserved[2];