1*127563b6Sskrll /* $NetBSD: db_proc.c,v 1.16 2024/04/15 06:48:06 skrll Exp $ */
2cd6b1c8fSad
3cd6b1c8fSad /*-
482002773Sad * Copyright (c) 2009, 2020 The NetBSD Foundation, Inc.
5cd6b1c8fSad * All rights reserved.
6cd6b1c8fSad *
7cd6b1c8fSad * This code is derived from software contributed to The NetBSD Foundation
8cd6b1c8fSad * by Andrew Doran.
9cd6b1c8fSad *
10cd6b1c8fSad * Redistribution and use in source and binary forms, with or without
11cd6b1c8fSad * modification, are permitted provided that the following conditions
12cd6b1c8fSad * are met:
13cd6b1c8fSad * 1. Redistributions of source code must retain the above copyright
14cd6b1c8fSad * notice, this list of conditions and the following disclaimer.
15cd6b1c8fSad * 2. Redistributions in binary form must reproduce the above copyright
16cd6b1c8fSad * notice, this list of conditions and the following disclaimer in the
17cd6b1c8fSad * documentation and/or other materials provided with the distribution.
18cd6b1c8fSad *
19cd6b1c8fSad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20cd6b1c8fSad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21cd6b1c8fSad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22cd6b1c8fSad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23cd6b1c8fSad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24cd6b1c8fSad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25cd6b1c8fSad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26cd6b1c8fSad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27cd6b1c8fSad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28cd6b1c8fSad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29cd6b1c8fSad * POSSIBILITY OF SUCH DAMAGE.
30cd6b1c8fSad */
31cd6b1c8fSad
32cd6b1c8fSad /*
33cd6b1c8fSad * Copyright (c) 1982, 1986, 1989, 1991, 1993
34cd6b1c8fSad * The Regents of the University of California. All rights reserved.
35cd6b1c8fSad *
36cd6b1c8fSad * Redistribution and use in source and binary forms, with or without
37cd6b1c8fSad * modification, are permitted provided that the following conditions
38cd6b1c8fSad * are met:
39cd6b1c8fSad * 1. Redistributions of source code must retain the above copyright
40cd6b1c8fSad * notice, this list of conditions and the following disclaimer.
41cd6b1c8fSad * 2. Redistributions in binary form must reproduce the above copyright
42cd6b1c8fSad * notice, this list of conditions and the following disclaimer in the
43cd6b1c8fSad * documentation and/or other materials provided with the distribution.
44cd6b1c8fSad * 3. Neither the name of the University nor the names of its contributors
45cd6b1c8fSad * may be used to endorse or promote products derived from this software
46cd6b1c8fSad * without specific prior written permission.
47cd6b1c8fSad *
48cd6b1c8fSad * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49cd6b1c8fSad * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50cd6b1c8fSad * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51cd6b1c8fSad * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52cd6b1c8fSad * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53cd6b1c8fSad * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54cd6b1c8fSad * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55cd6b1c8fSad * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56cd6b1c8fSad * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57cd6b1c8fSad * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58cd6b1c8fSad * SUCH DAMAGE.
59cd6b1c8fSad *
60cd6b1c8fSad * from: kern_proc.c 8.4 (Berkeley) 1/4/94
61cd6b1c8fSad */
62cd6b1c8fSad
63cd6b1c8fSad #include <sys/cdefs.h>
64*127563b6Sskrll __KERNEL_RCSID(0, "$NetBSD: db_proc.c,v 1.16 2024/04/15 06:48:06 skrll Exp $");
65d2ea53a0Smrg
66d2ea53a0Smrg #ifndef _KERNEL
67d2ea53a0Smrg #include <stdbool.h>
68d2ea53a0Smrg #endif
69cd6b1c8fSad
70cd6b1c8fSad #include <sys/param.h>
71cd6b1c8fSad #include <sys/cpu.h>
72cd6b1c8fSad #include <sys/proc.h>
73d2ea53a0Smrg #ifdef _KERNEL /* XXX */
74cd6b1c8fSad #include <sys/kauth.h>
75d2ea53a0Smrg #endif
76cd6b1c8fSad
774540375fSmrg #include <ddb/ddb.h>
784540375fSmrg
79cd6b1c8fSad proc_t *
db_proc_first(void)80cd6b1c8fSad db_proc_first(void)
81cd6b1c8fSad {
82cd6b1c8fSad
83cd6b1c8fSad return db_read_ptr("allproc");
84cd6b1c8fSad }
85cd6b1c8fSad
86cd6b1c8fSad proc_t *
db_proc_next(proc_t * p)87cd6b1c8fSad db_proc_next(proc_t *p)
88cd6b1c8fSad {
89cd6b1c8fSad
90cd6b1c8fSad db_read_bytes((db_addr_t)&p->p_list.le_next, sizeof(p), (char *)&p);
91cd6b1c8fSad return p;
92cd6b1c8fSad }
93cd6b1c8fSad
94cd6b1c8fSad proc_t *
db_proc_find(pid_t pid)95cd6b1c8fSad db_proc_find(pid_t pid)
96cd6b1c8fSad {
97cd6b1c8fSad proc_t *p;
98cd6b1c8fSad pid_t tp;
99cd6b1c8fSad
100cd6b1c8fSad for (p = db_proc_first(); p != NULL; p = db_proc_next(p)) {
101cd6b1c8fSad db_read_bytes((db_addr_t)&p->p_pid, sizeof(tp),
102cd6b1c8fSad (char *)&tp);
103cd6b1c8fSad if (tp == pid) {
104cd6b1c8fSad return p;
105cd6b1c8fSad }
106cd6b1c8fSad }
107cd6b1c8fSad return NULL;
108cd6b1c8fSad }
109cd6b1c8fSad
1107c827ea2Smaxv static void
db_read_string(const char * src,size_t len,char * dst)1117c827ea2Smaxv db_read_string(const char *src, size_t len, char *dst)
1127c827ea2Smaxv {
1137c827ea2Smaxv size_t i;
1147c827ea2Smaxv
1157c827ea2Smaxv for (i = 0; i < len; i++) {
1167c827ea2Smaxv db_read_bytes((db_addr_t)&src[i], 1, &dst[i]);
117038a8e9aSmaxv if (dst[i] == '\0')
1187c827ea2Smaxv break;
1197c827ea2Smaxv }
1207c827ea2Smaxv }
1217c827ea2Smaxv
122cd6b1c8fSad void
db_show_all_procs(db_expr_t addr,bool haddr,db_expr_t count,const char * modif)123cd6b1c8fSad db_show_all_procs(db_expr_t addr, bool haddr, db_expr_t count,
124cd6b1c8fSad const char *modif)
125cd6b1c8fSad {
126cd6b1c8fSad static struct pgrp pgrp;
127cd6b1c8fSad static proc_t p;
128cd6b1c8fSad static lwp_t l;
129cd6b1c8fSad const char *mode, *ename;
130cd6b1c8fSad proc_t *pp;
131cd6b1c8fSad lwp_t *lp;
132cd6b1c8fSad char db_nbuf[MAXCOMLEN + 1], wbuf[MAXCOMLEN + 1];
133cd6b1c8fSad bool run;
134cd6b1c8fSad int cpuno;
135cd6b1c8fSad
136cd6b1c8fSad if (modif[0] == 0)
137cd6b1c8fSad mode = "l"; /* default == lwp mode */
138cd6b1c8fSad else
139cd6b1c8fSad mode = strchr("mawln", modif[0]);
140cd6b1c8fSad
141cd6b1c8fSad if (mode == NULL || *mode == 'm') {
142cd6b1c8fSad db_printf("usage: show all procs [/a] [/l] [/n] [/w]\n");
143cd6b1c8fSad db_printf("\t/a == show process address info\n");
1442a672d40Schristos db_printf("\t/l == show LWP info [default]\n");
1452a672d40Schristos db_printf("\t/n == show normal process info\n");
146cd6b1c8fSad db_printf("\t/w == show process wait/emul info\n");
147cd6b1c8fSad return;
148cd6b1c8fSad }
149cd6b1c8fSad
150cd6b1c8fSad switch (*mode) {
151cd6b1c8fSad case 'a':
1520df87276Ssimonb db_printf("PID %-16s %18s %18s %18s\n",
153cd6b1c8fSad "COMMAND", "STRUCT PROC *", "UAREA *", "VMSPACE/VM_MAP");
154cd6b1c8fSad break;
155cd6b1c8fSad case 'l':
156*127563b6Sskrll db_printf("PID %5s S %3s %9s %18s %18s %-8s\n",
157cd6b1c8fSad "LID", "CPU", "FLAGS", "STRUCT LWP *", "NAME", "WAIT");
158cd6b1c8fSad break;
159cd6b1c8fSad case 'n':
160cd6b1c8fSad db_printf("PID %8s %8s %10s S %7s %4s %16s %7s\n",
161cd6b1c8fSad "PPID", "PGRP", "UID", "FLAGS", "LWPS", "COMMAND", "WAIT");
162cd6b1c8fSad break;
163cd6b1c8fSad case 'w':
164*127563b6Sskrll db_printf("PID %5s %16s %8s %4s %-16s %s\n",
165cd6b1c8fSad "LID", "COMMAND", "EMUL", "PRI", "WAIT-MSG",
166cd6b1c8fSad "WAIT-CHANNEL");
167cd6b1c8fSad break;
168cd6b1c8fSad }
169cd6b1c8fSad
170cd6b1c8fSad for (pp = db_proc_first(); pp != NULL; pp = db_proc_next(pp)) {
171cd6b1c8fSad db_read_bytes((db_addr_t)pp, sizeof(p), (char *)&p);
172cd6b1c8fSad if (p.p_stat == 0) {
173cd6b1c8fSad continue;
174cd6b1c8fSad }
175cd6b1c8fSad lp = p.p_lwps.lh_first;
176cd6b1c8fSad if (lp != NULL) {
177cd6b1c8fSad db_read_bytes((db_addr_t)lp, sizeof(l), (char *)&l);
178cd6b1c8fSad }
179cd6b1c8fSad db_printf("%-5d", p.p_pid);
180cd6b1c8fSad
181cd6b1c8fSad switch (*mode) {
182cd6b1c8fSad case 'a':
1830df87276Ssimonb db_printf(" %-16.16s %18lx %18lx %18lx\n",
184cd6b1c8fSad p.p_comm, (long)pp,
185cd6b1c8fSad (long)(lp != NULL ? l.l_addr : 0),
186cd6b1c8fSad (long)p.p_vmspace);
187cd6b1c8fSad break;
188cd6b1c8fSad case 'l':
189cd6b1c8fSad while (lp != NULL) {
190cd6b1c8fSad if (l.l_name != NULL) {
1917c827ea2Smaxv db_read_string(l.l_name,
192cd6b1c8fSad MAXCOMLEN, db_nbuf);
1937c827ea2Smaxv db_nbuf[MAXCOMLEN] = '\0';
194cd6b1c8fSad } else {
195cd6b1c8fSad strlcpy(db_nbuf, p.p_comm,
196cd6b1c8fSad sizeof(db_nbuf));
197cd6b1c8fSad }
198cd6b1c8fSad run = (l.l_stat == LSONPROC ||
19982002773Sad (l.l_pflag & LP_RUNNING) != 0);
200cd6b1c8fSad if (l.l_cpu != NULL) {
201cd6b1c8fSad db_read_bytes((db_addr_t)
202cd6b1c8fSad &l.l_cpu->ci_data.cpu_index,
203cd6b1c8fSad sizeof(cpuno), (char *)&cpuno);
204cd6b1c8fSad } else
205cd6b1c8fSad cpuno = -1;
206cd6b1c8fSad if (l.l_wchan && l.l_wmesg) {
2077c827ea2Smaxv db_read_string(l.l_wmesg,
2087c827ea2Smaxv sizeof(wbuf), wbuf);
2097c827ea2Smaxv wbuf[MAXCOMLEN] = '\0';
210cd6b1c8fSad } else {
211cd6b1c8fSad wbuf[0] = '\0';
212cd6b1c8fSad }
213*127563b6Sskrll db_printf("%c%5d %d %3d %9x %18lx %18s %-8s\n",
214cd6b1c8fSad (run ? '>' : ' '), l.l_lid,
215cd6b1c8fSad l.l_stat, cpuno, l.l_flag, (long)lp,
216cd6b1c8fSad db_nbuf, wbuf);
217cd6b1c8fSad lp = LIST_NEXT((&l), l_sibling);
218cd6b1c8fSad if (lp != NULL) {
219cd6b1c8fSad db_printf("%-5d", p.p_pid);
220cd6b1c8fSad db_read_bytes((db_addr_t)lp, sizeof(l),
221cd6b1c8fSad (char *)&l);
222cd6b1c8fSad }
223cd6b1c8fSad }
224cd6b1c8fSad break;
225cd6b1c8fSad case 'n':
226cd6b1c8fSad db_read_bytes((db_addr_t)p.p_pgrp, sizeof(pgrp),
227cd6b1c8fSad (char *)&pgrp);
228cd6b1c8fSad if (lp != NULL && l.l_wchan && l.l_wmesg) {
2297c827ea2Smaxv db_read_string(l.l_wmesg,
2307c827ea2Smaxv sizeof(wbuf), wbuf);
2317c827ea2Smaxv wbuf[MAXCOMLEN] = '\0';
232cd6b1c8fSad } else {
233cd6b1c8fSad wbuf[0] = '\0';
234cd6b1c8fSad }
235cd6b1c8fSad db_printf("%8d %8d %10d %d %#7x %4d %16s %7.7s\n",
2365a05c3b8Shikaru p.p_pptr != NULL ? p.p_pptr->p_pid : -1, pgrp.pg_id,
237cd6b1c8fSad #ifdef _KERNEL
238cd6b1c8fSad kauth_cred_getuid(p.p_cred),
239cd6b1c8fSad #else
240cd6b1c8fSad /* XXX CRASH(8) */ 666,
241cd6b1c8fSad #endif
242cd6b1c8fSad p.p_stat, p.p_flag,
243cd6b1c8fSad p.p_nlwps, p.p_comm,
244cd6b1c8fSad (p.p_nlwps != 1) ? "*" : wbuf);
245cd6b1c8fSad break;
246cd6b1c8fSad
247cd6b1c8fSad case 'w':
248cd6b1c8fSad while (lp != NULL) {
249cd6b1c8fSad if (l.l_wchan && l.l_wmesg) {
2507c827ea2Smaxv db_read_string(l.l_wmesg,
2517c827ea2Smaxv sizeof(wbuf), wbuf);
2527c827ea2Smaxv wbuf[MAXCOMLEN] = '\0';
253cd6b1c8fSad } else {
254cd6b1c8fSad wbuf[0] = '\0';
255cd6b1c8fSad }
2560f329bf7Sjym run = (l.l_stat == LSONPROC ||
25782002773Sad (l.l_pflag & LP_RUNNING) != 0);
258cd6b1c8fSad db_read_bytes((db_addr_t)&p.p_emul->e_name,
259cd6b1c8fSad sizeof(ename), (char *)&ename);
2607c827ea2Smaxv
2617c827ea2Smaxv db_read_string(ename, sizeof(db_nbuf), db_nbuf);
2627c827ea2Smaxv db_nbuf[MAXCOMLEN] = '\0';
2637c827ea2Smaxv
264cd6b1c8fSad db_printf(
265*127563b6Sskrll "%c%5d %16s %8s %4d %-16s %-18lx\n",
2660f329bf7Sjym (run ? '>' : ' '), l.l_lid,
2670f329bf7Sjym p.p_comm, db_nbuf,
268cd6b1c8fSad l.l_priority, wbuf, (long)l.l_wchan);
269cd6b1c8fSad lp = LIST_NEXT((&l), l_sibling);
270cd6b1c8fSad if (lp != NULL) {
271cd6b1c8fSad db_printf("%-5d", p.p_pid);
272cd6b1c8fSad db_read_bytes((db_addr_t)lp, sizeof(l),
273cd6b1c8fSad (char *)&l);
274cd6b1c8fSad }
275cd6b1c8fSad }
276cd6b1c8fSad break;
277cd6b1c8fSad }
278cd6b1c8fSad }
279cd6b1c8fSad }
280cd6b1c8fSad
2812a672d40Schristos void
db_show_proc(db_expr_t addr,bool haddr,db_expr_t count,const char * modif)2822a672d40Schristos db_show_proc(db_expr_t addr, bool haddr, db_expr_t count, const char *modif)
2832a672d40Schristos {
2842a672d40Schristos static proc_t p;
2852a672d40Schristos static lwp_t l;
2862a672d40Schristos const char *mode;
2872a672d40Schristos proc_t *pp;
2882a672d40Schristos lwp_t *lp;
2892a672d40Schristos char db_nbuf[MAXCOMLEN + 1], wbuf[MAXCOMLEN + 1];
2902a672d40Schristos bool run;
2912a672d40Schristos int cpuno;
2922a672d40Schristos
2932a672d40Schristos if (modif[0] == 0)
2942a672d40Schristos mode = "p"; /* default == by pid */
2952a672d40Schristos else
2962a672d40Schristos mode = strchr("ap", modif[0]);
2972a672d40Schristos
2982a672d40Schristos if (mode == NULL || !haddr) {
2992a672d40Schristos db_printf("usage: show proc [/a] [/p] address|pid\n");
3002a672d40Schristos db_printf("\t/a == argument is an address of any lwp\n");
3012a672d40Schristos db_printf("\t/p == argument is a pid [default]\n");
3022a672d40Schristos return;
3032a672d40Schristos }
3042a672d40Schristos
3052a672d40Schristos switch (*mode) {
3062a672d40Schristos case 'a':
30720cb9e7fSnakayama lp = (lwp_t *)(uintptr_t)addr;
3082a672d40Schristos db_printf("lwp_t %lx\n", (long)lp);
3092a672d40Schristos db_read_bytes((db_addr_t)lp, sizeof(l), (char *)&l);
3102a672d40Schristos pp = l.l_proc;
3112a672d40Schristos break;
3122a672d40Schristos default:
3132a672d40Schristos case 'p':
3142a672d40Schristos pp = db_proc_find((pid_t)addr);
3152a672d40Schristos lp = NULL;
3162a672d40Schristos break;
3172a672d40Schristos }
3182a672d40Schristos
3192a672d40Schristos if (pp == NULL) {
3202a672d40Schristos db_printf("bad address\n");
3212a672d40Schristos return;
3222a672d40Schristos }
3232a672d40Schristos
3242a672d40Schristos db_read_bytes((db_addr_t)pp, sizeof(p), (char *)&p);
3252a672d40Schristos if (lp == NULL)
3262a672d40Schristos lp = p.p_lwps.lh_first;
3272a672d40Schristos
3282a672d40Schristos db_printf("%s: pid %d proc %lx vmspace/map %lx flags %x\n",
3292a672d40Schristos p.p_comm, p.p_pid, (long)pp, (long)p.p_vmspace, p.p_flag);
3302a672d40Schristos
3312a672d40Schristos while (lp != NULL) {
3322a672d40Schristos db_read_bytes((db_addr_t)lp, sizeof(l), (char *)&l);
3332a672d40Schristos
3342a672d40Schristos run = (l.l_stat == LSONPROC ||
33582002773Sad (l.l_pflag & LP_RUNNING) != 0);
3362a672d40Schristos
3372a672d40Schristos db_printf("%slwp %d", (run ? "> " : " "), l.l_lid);
3382a672d40Schristos if (l.l_name != NULL) {
3397c827ea2Smaxv db_read_string(l.l_name, MAXCOMLEN, db_nbuf);
3407c827ea2Smaxv db_nbuf[MAXCOMLEN] = '\0';
3412a672d40Schristos db_printf(" [%s]", db_nbuf);
3422a672d40Schristos }
3432a672d40Schristos db_printf(" %lx pcb %lx\n", (long)lp, (long)l.l_addr);
3442a672d40Schristos
3452a672d40Schristos if (l.l_cpu != NULL) {
3462a672d40Schristos db_read_bytes((db_addr_t)
3472a672d40Schristos &l.l_cpu->ci_data.cpu_index,
3482a672d40Schristos sizeof(cpuno), (char *)&cpuno);
3492a672d40Schristos } else
3502a672d40Schristos cpuno = -1;
35106d11bb0Smlelstv db_printf(" stat %d flags %x cpu %d pri %d ref %d\n",
35206d11bb0Smlelstv l.l_stat, l.l_flag, cpuno, l.l_priority, l.l_refcnt);
3532a672d40Schristos
3542a672d40Schristos if (l.l_wchan && l.l_wmesg) {
3557c827ea2Smaxv db_read_string(l.l_wmesg, MAXCOMLEN, wbuf);
3567c827ea2Smaxv wbuf[MAXCOMLEN] = '\0';
3572a672d40Schristos db_printf(" wmesg %s wchan %lx\n",
3582a672d40Schristos wbuf, (long)l.l_wchan);
3592a672d40Schristos }
3602a672d40Schristos
3612a672d40Schristos lp = LIST_NEXT(&l, l_sibling);
3622a672d40Schristos }
3632a672d40Schristos }
364