Skip to content

Commit

Permalink
implement unix pid maps in winedbg
Browse files Browse the repository at this point in the history
fix dumb mistake
  • Loading branch information
marzent authored and Gcenx committed Feb 15, 2023
1 parent 93314ef commit a32eb43
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 1 deletion.
3 changes: 2 additions & 1 deletion programs/winedbg/dbg.y
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ static void parser(const char*);
%token tENABLE tDISABLE tBREAK tHBREAK tWATCH tRWATCH tDELETE tSET tPRINT tEXAM
%token tABORT tECHO
%token tCLASS tMAPS tSTACK tSEGMENTS tSYMBOL tREGS tALLREGS tWND tLOCAL tEXCEPTION
%token tPROCESS tTHREAD tEOL tEOF
%token tPROCESS tPROCESSMAP tTHREAD tEOL tEOF
%token tFRAME tSHARE tMODULE tCOND tDISPLAY tUNDISPLAY tDISASSEMBLE
%token tSTEPI tNEXTI tFINISH tSHOW tDIR tWHATIS tSOURCE
%token <string> tPATH tIDENTIFIER tSTRING tINTVAR
Expand Down Expand Up @@ -284,6 +284,7 @@ info_command:
| tINFO '*' tWND { info_win32_window(NULL, TRUE); }
| tINFO '*' tWND expr_rvalue { info_win32_window((HWND)(DWORD_PTR)$4, TRUE); }
| tINFO tPROCESS { info_win32_processes(); }
| tINFO tPROCESSMAP { info_win32_processes_map(); }
| tINFO tTHREAD { info_win32_threads(); }
| tINFO tFRAME { info_win32_frame_exceptions(dbg_curr_tid); }
| tINFO tFRAME expr_rvalue { info_win32_frame_exceptions($3); }
Expand Down
1 change: 1 addition & 0 deletions programs/winedbg/debug.l
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ STRING \"(\\[^\n]|[^\\"\n])*\"
<INFO_CMD>locals|local|loca|loc { return tLOCAL; }
<INFO_CMD>class|clas|cla { return tCLASS; }
<INFO_CMD>process|proces|proce|proc { return tPROCESS; }
<INFO_CMD>processmap|procesmap|procemap|procmap { return tPROCESSMAP; }
<INFO_CMD>threads|thread|threa|thre|thr|th { return tTHREAD; }
<INFO_CMD>exception|except|exc|ex { return tEXCEPTION; }
<INFO_CMD>registers|regs|reg|re { return tREGS; }
Expand Down
1 change: 1 addition & 0 deletions programs/winedbg/debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ extern void info_win32_module(DWORD64 mod);
extern void info_win32_class(HWND hWnd, const char* clsName);
extern void info_win32_window(HWND hWnd, BOOL detailed);
extern void info_win32_processes(void);
extern void info_win32_processes_map(void);
extern void info_win32_threads(void);
extern void info_win32_frame_exceptions(DWORD tid);
extern void info_win32_virtual(DWORD pid);
Expand Down
168 changes: 168 additions & 0 deletions programs/winedbg/info.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "winuser.h"
#include "tlhelp32.h"
#include "wine/debug.h"
#include "wine/server.h"

WINE_DEFAULT_DEBUG_CHANNEL(winedbg);

Expand Down Expand Up @@ -100,6 +101,7 @@ void info_help(void)
" info locals Displays values of all local vars for current frame",
" info maps <pid> Shows virtual mappings (in a given process)",
" info process Shows all running processes",
" info processmap Shows a windows to unix process map",
" info reg Displays values of the general registers at top of stack",
" info all-reg Displays the general and floating point registers",
" info segments <pid> Displays information about all known segments",
Expand Down Expand Up @@ -483,6 +485,81 @@ struct dump_proc
unsigned alloc;
};

struct pid_map
{
unsigned int pid;
unsigned int unix_pid;
};

static struct pid_map *get_pid_map( unsigned int *num_entries )
{
struct pid_map *map;
unsigned int i = 0, map_count = 16, buffer_len = 4096, process_count, pos = 0;
NTSTATUS ret;
char *buffer = NULL, *new_buffer;

if (!(buffer = HeapAlloc( GetProcessHeap(), 0, buffer_len ))) return NULL;

for (;;)
{
SERVER_START_REQ( list_processes )
{
wine_server_set_reply( req, buffer, buffer_len );
ret = wine_server_call( req );
buffer_len = reply->info_size;
process_count = reply->process_count;
}
SERVER_END_REQ;

if (ret != STATUS_INFO_LENGTH_MISMATCH) break;

if (!(new_buffer = HeapReAlloc( GetProcessHeap(), 0, buffer, buffer_len )))
{
HeapFree( GetProcessHeap(), 0, buffer );
return NULL;
}
buffer = new_buffer;
}

if (!(map = HeapAlloc( GetProcessHeap(), 0, map_count * sizeof(*map) )))
{
HeapFree( GetProcessHeap(), 0, buffer );
return NULL;
}

for (i = 0; i < process_count; ++i)
{
const struct process_info *process;

pos = (pos + 7) & ~7;
process = (const struct process_info *)(buffer + pos);

if (i >= map_count)
{
struct pid_map *new_map;
map_count *= 2;
if (!(new_map = HeapReAlloc( GetProcessHeap(), 0, map, map_count * sizeof(*map))))
{
HeapFree( GetProcessHeap(), 0, map );
HeapFree( GetProcessHeap(), 0, buffer );
return NULL;
}
map = new_map;
}

map[i].pid = process->pid;
map[i].unix_pid = process->unix_pid;

pos += sizeof(struct process_info) + process->name_len;
pos = (pos + 7) & ~7;
pos += process->thread_count * sizeof(struct thread_info);
}

HeapFree( GetProcessHeap(), 0, buffer );
*num_entries = process_count;
return map;
}

static unsigned get_parent(const struct dump_proc* dp, unsigned idx)
{
unsigned i;
Expand Down Expand Up @@ -517,6 +594,48 @@ static void dump_proc_info(const struct dump_proc* dp, unsigned idx, unsigned de
}
}

static unsigned int find_unix_pid( struct pid_map *map, unsigned int num_entries, unsigned int pid )
{
unsigned int i;

for (i = 0; i < num_entries; i++)
if (map[i].pid == pid)
return map[i].unix_pid;

return 0;
}

static void dump_proc_info_map(const struct dump_proc* dp, unsigned idx, unsigned depth)
{
struct pid_map *map = NULL;
struct dump_proc_entry* dpe;
unsigned int num_entries = 0;

map = get_pid_map( &num_entries );

for ( ; idx != -1; idx = dp->entries[idx].sibling)
{
assert(idx < dp->count);
dpe = &dp->entries[idx];
dbg_printf("%c%08lx %08x %-8ld ",
(dpe->proc.th32ProcessID == (dbg_curr_process ?
dbg_curr_process->pid : 0)) ? '>' : ' ',
dpe->proc.th32ProcessID,
find_unix_pid(map, num_entries, dpe->proc.th32ProcessID),
dpe->proc.cntThreads);
if (depth)
{
unsigned i;
for (i = 3 * (depth - 1); i > 0; i--) dbg_printf(" ");
dbg_printf("\\_ ");
}
dbg_printf("'%s'\n", dpe->proc.szExeFile);
dump_proc_info_map(dp, dpe->children, depth + 1);
}

HeapFree( GetProcessHeap(), 0, map );
}

void info_win32_processes(void)
{
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
Expand Down Expand Up @@ -565,6 +684,55 @@ void info_win32_processes(void)
}
}


void info_win32_processes_map(void)
{
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snap != INVALID_HANDLE_VALUE)
{
struct dump_proc dp;
unsigned i, first = -1;
BOOL ok;

dp.count = 0;
dp.alloc = 16;
dp.entries = HeapAlloc(GetProcessHeap(), 0, sizeof(*dp.entries) * dp.alloc);
if (!dp.entries)
{
CloseHandle(snap);
return;
}
dp.entries[dp.count].proc.dwSize = sizeof(dp.entries[dp.count].proc);
ok = Process32First(snap, &dp.entries[dp.count].proc);

/* fetch all process information into dp (skipping this debugger) */
while (ok)
{
if (dp.entries[dp.count].proc.th32ProcessID != GetCurrentProcessId())
dp.entries[dp.count++].children = -1;
if (dp.count >= dp.alloc)
{
dp.entries = HeapReAlloc(GetProcessHeap(), 0, dp.entries, sizeof(*dp.entries) * (dp.alloc *= 2));
if (!dp.entries) return;
}
dp.entries[dp.count].proc.dwSize = sizeof(dp.entries[dp.count].proc);
ok = Process32Next(snap, &dp.entries[dp.count].proc);
}
CloseHandle(snap);
/* chain the siblings wrt. their parent */
for (i = 0; i < dp.count; i++)
{
unsigned parent = get_parent(&dp, i);
unsigned *chain = parent == -1 ? &first : &dp.entries[parent].children;
dp.entries[i].sibling = *chain;
*chain = i;
}
dbg_printf(" %-8.8s %-8.8s %-8.8s %s (all id:s are in hex)\n", "pid", "unix_pid", "threads", "executable");
dump_proc_info_map(&dp, first, 0);
HeapFree(GetProcessHeap(), 0, dp.entries);
}
}

static BOOL get_process_name(DWORD pid, PROCESSENTRY32W* entry)
{
BOOL ret = FALSE;
Expand Down

0 comments on commit a32eb43

Please sign in to comment.