From 5a755a94719f73c72446508d1f69dd37aeb11305 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 20 May 2011 18:07:52 +0000 Subject: [PATCH] * fhandler_process.cc (struct heap_info): Change type of base and end members to char *. Print "shared" rather than "share". (struct stack_info): New class to fetch process stack information. (format_process_maps): Initialize and check for stack information. --- winsup/cygwin/ChangeLog | 7 ++ winsup/cygwin/fhandler_process.cc | 127 +++++++++++++++++++++++++++--- 2 files changed, 122 insertions(+), 12 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index d7d7e593c..679d9295a 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,10 @@ +2011-05-20 Corinna Vinschen + + * fhandler_process.cc (struct heap_info): Change type of base and end + members to char *. Print "shared" rather than "share". + (struct stack_info): New class to fetch process stack information. + (format_process_maps): Initialize and check for stack information. + 2011-05-20 Corinna Vinschen * miscfuncs.cc (thread_wrapper): Remove statements added for debugging diff --git a/winsup/cygwin/fhandler_process.cc b/winsup/cygwin/fhandler_process.cc index 1038537ce..29044b2ea 100644 --- a/winsup/cygwin/fhandler_process.cc +++ b/winsup/cygwin/fhandler_process.cc @@ -615,14 +615,14 @@ struct heap_info { heap *next; unsigned heap_id; - uintptr_t base; - uintptr_t end; + char *base; + char *end; unsigned long flags; }; heap *heap_vm_chunks; heap_info (DWORD pid) - : heap_vm_chunks (0) + : heap_vm_chunks (NULL) { PDEBUG_BUFFER buf; NTSTATUS status; @@ -646,8 +646,8 @@ struct heap_info { heap *h = (heap *) cmalloc (HEAP_FHANDLER, sizeof (heap)); *h = (heap) { heap_vm_chunks, - hcnt, barray[bcnt].Address, - barray[bcnt].Address + barray[bcnt].Size, + hcnt, (char *) barray[bcnt].Address, + (char *) barray[bcnt].Address + barray[bcnt].Size, harray->Heaps[hcnt].Flags }; heap_vm_chunks = h; } @@ -655,18 +655,16 @@ struct heap_info RtlDestroyQueryDebugBuffer (buf); } - char *fill_if_match (void *base, ULONG type, char *dest ) + char *fill_if_match (char *base, ULONG type, char *dest) { for (heap *h = heap_vm_chunks; h; h = h->next) - if ((uintptr_t) base >= h->base && (uintptr_t) base < h->end) + if (base >= h->base && base < h->end) { - char *p; - __small_sprintf (dest, "[heap %ld", h->heap_id); - p = strchr (dest, '\0'); + char *p = dest + __small_sprintf (dest, "[heap %ld", h->heap_id); if (!(h->flags & HEAP_FLAG_NONDEFAULT)) p = stpcpy (p, " default"); if ((h->flags & HEAP_FLAG_SHAREABLE) && (type & MEM_MAPPED)) - p = stpcpy (p, " share"); + p = stpcpy (p, " shared"); if (h->flags & HEAP_FLAG_EXECUTABLE) p = stpcpy (p, " exec"); if (h->flags & HEAP_FLAG_GROWABLE) @@ -692,6 +690,107 @@ struct heap_info } }; +struct stack_info +{ + struct stack + { + stack *next; + ULONG thread_id; + char *start; + char *end; + }; + stack *stacks; + + stack_info (DWORD pid, HANDLE process) + : stacks (NULL) + { + NTSTATUS status; + PVOID buf = NULL; + size_t size = 50 * (sizeof (SYSTEM_PROCESSES) + + 16 * sizeof (SYSTEM_THREADS)); + PSYSTEM_PROCESSES proc; + PSYSTEM_THREADS thread; + + do + { + buf = realloc (buf, size); + status = NtQuerySystemInformation (SystemProcessesAndThreadsInformation, + buf, size, NULL); + size <<= 1; + } + while (status == STATUS_INFO_LENGTH_MISMATCH); + if (!NT_SUCCESS (status)) + { + if (buf) + free (buf); + debug_printf ("NtQuerySystemInformation, %p", status); + return; + } + proc = (PSYSTEM_PROCESSES) buf; + while (true) + { + if (proc->ProcessId == pid) + break; + if (!proc->NextEntryDelta) + { + free (buf); + return; + } + proc = (PSYSTEM_PROCESSES) ((PBYTE) proc + proc->NextEntryDelta); + } + thread = proc->Threads; + for (ULONG i = 0; i < proc->ThreadCount; ++i) + { + THREAD_BASIC_INFORMATION tbi; + TEB teb; + HANDLE thread_h; + + if (!(thread_h = OpenThread (THREAD_QUERY_INFORMATION, FALSE, + (ULONG) thread[i].ClientId.UniqueThread))) + continue; + status = NtQueryInformationThread (thread_h, ThreadBasicInformation, + &tbi, sizeof tbi, NULL); + CloseHandle (thread_h); + if (!NT_SUCCESS (status)) + continue; + if (!ReadProcessMemory (process, (PVOID) tbi.TebBaseAddress, + &teb, sizeof teb, NULL)) + continue; + stack *s = (stack *) cmalloc (HEAP_FHANDLER, sizeof (stack)); + *s = (stack) { stacks, (ULONG) thread[i].ClientId.UniqueThread, + (char *) (teb.DeallocationStack ?: teb.Tib.StackLimit), + (char *) teb.Tib.StackBase }; + stacks = s; + } + free (buf); + } + + char *fill_if_match (char *base, ULONG type, char *dest) + { + for (stack *s = stacks; s; s = s->next) + if (base >= s->start && base < s->end) + { + char *p = dest + __small_sprintf (dest, "[stack (tid %ld)", + s->thread_id); + if (type & MEM_MAPPED) + p = stpcpy (p, " shared"); + stpcpy (p, "]"); + return dest; + } + return 0; + } + + ~stack_info () + { + stack *n = 0; + for (stack *m = stacks; m; m = n) + { + n = m->next; + cfree (m); + } + } +}; + static _off64_t format_process_maps (void *data, char *&destbuf) { @@ -720,6 +819,7 @@ format_process_maps (void *data, char *&destbuf) MEMORY_BASIC_INFORMATION mb; dos_drive_mappings drive_maps; heap_info heaps (p->dwProcessId); + stack_info stacks (p->dwProcessId, proc); struct __stat64 st; long last_pass = 0; @@ -811,7 +911,10 @@ format_process_maps (void *data, char *&destbuf) sys_wcstombs (posix_modname, NT_MAX_PATH, dosname); stat64 (posix_modname, &st); } - else if (!heaps.fill_if_match (cur.abase, mb.Type, posix_modname)) + else if (!stacks.fill_if_match (cur.abase, mb.Type, + posix_modname) + && !heaps.fill_if_match (cur.abase, mb.Type, + posix_modname)) { if (mb.Type & MEM_MAPPED) strcpy (posix_modname, "[shareable]"); -- 2.43.5