/* $NetBSD: db_proc.c,v 1.16 2024/04/15 06:48:06 skrll Exp $ */ /*- * Copyright (c) 2009, 2020 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Andrew Doran. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1982, 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: kern_proc.c 8.4 (Berkeley) 1/4/94 */ #include __KERNEL_RCSID(0, "$NetBSD: db_proc.c,v 1.16 2024/04/15 06:48:06 skrll Exp $"); #ifndef _KERNEL #include #endif #include #include #include #ifdef _KERNEL /* XXX */ #include #endif #include proc_t * db_proc_first(void) { return db_read_ptr("allproc"); } proc_t * db_proc_next(proc_t *p) { db_read_bytes((db_addr_t)&p->p_list.le_next, sizeof(p), (char *)&p); return p; } proc_t * db_proc_find(pid_t pid) { proc_t *p; pid_t tp; for (p = db_proc_first(); p != NULL; p = db_proc_next(p)) { db_read_bytes((db_addr_t)&p->p_pid, sizeof(tp), (char *)&tp); if (tp == pid) { return p; } } return NULL; } static void db_read_string(const char *src, size_t len, char *dst) { size_t i; for (i = 0; i < len; i++) { db_read_bytes((db_addr_t)&src[i], 1, &dst[i]); if (dst[i] == '\0') break; } } void db_show_all_procs(db_expr_t addr, bool haddr, db_expr_t count, const char *modif) { static struct pgrp pgrp; static proc_t p; static lwp_t l; const char *mode, *ename; proc_t *pp; lwp_t *lp; char db_nbuf[MAXCOMLEN + 1], wbuf[MAXCOMLEN + 1]; bool run; int cpuno; if (modif[0] == 0) mode = "l"; /* default == lwp mode */ else mode = strchr("mawln", modif[0]); if (mode == NULL || *mode == 'm') { db_printf("usage: show all procs [/a] [/l] [/n] [/w]\n"); db_printf("\t/a == show process address info\n"); db_printf("\t/l == show LWP info [default]\n"); db_printf("\t/n == show normal process info\n"); db_printf("\t/w == show process wait/emul info\n"); return; } switch (*mode) { case 'a': db_printf("PID %-16s %18s %18s %18s\n", "COMMAND", "STRUCT PROC *", "UAREA *", "VMSPACE/VM_MAP"); break; case 'l': db_printf("PID %5s S %3s %9s %18s %18s %-8s\n", "LID", "CPU", "FLAGS", "STRUCT LWP *", "NAME", "WAIT"); break; case 'n': db_printf("PID %8s %8s %10s S %7s %4s %16s %7s\n", "PPID", "PGRP", "UID", "FLAGS", "LWPS", "COMMAND", "WAIT"); break; case 'w': db_printf("PID %5s %16s %8s %4s %-16s %s\n", "LID", "COMMAND", "EMUL", "PRI", "WAIT-MSG", "WAIT-CHANNEL"); break; } for (pp = db_proc_first(); pp != NULL; pp = db_proc_next(pp)) { db_read_bytes((db_addr_t)pp, sizeof(p), (char *)&p); if (p.p_stat == 0) { continue; } lp = p.p_lwps.lh_first; if (lp != NULL) { db_read_bytes((db_addr_t)lp, sizeof(l), (char *)&l); } db_printf("%-5d", p.p_pid); switch (*mode) { case 'a': db_printf(" %-16.16s %18lx %18lx %18lx\n", p.p_comm, (long)pp, (long)(lp != NULL ? l.l_addr : 0), (long)p.p_vmspace); break; case 'l': while (lp != NULL) { if (l.l_name != NULL) { db_read_string(l.l_name, MAXCOMLEN, db_nbuf); db_nbuf[MAXCOMLEN] = '\0'; } else { strlcpy(db_nbuf, p.p_comm, sizeof(db_nbuf)); } run = (l.l_stat == LSONPROC || (l.l_pflag & LP_RUNNING) != 0); if (l.l_cpu != NULL) { db_read_bytes((db_addr_t) &l.l_cpu->ci_data.cpu_index, sizeof(cpuno), (char *)&cpuno); } else cpuno = -1; if (l.l_wchan && l.l_wmesg) { db_read_string(l.l_wmesg, sizeof(wbuf), wbuf); wbuf[MAXCOMLEN] = '\0'; } else { wbuf[0] = '\0'; } db_printf("%c%5d %d %3d %9x %18lx %18s %-8s\n", (run ? '>' : ' '), l.l_lid, l.l_stat, cpuno, l.l_flag, (long)lp, db_nbuf, wbuf); lp = LIST_NEXT((&l), l_sibling); if (lp != NULL) { db_printf("%-5d", p.p_pid); db_read_bytes((db_addr_t)lp, sizeof(l), (char *)&l); } } break; case 'n': db_read_bytes((db_addr_t)p.p_pgrp, sizeof(pgrp), (char *)&pgrp); if (lp != NULL && l.l_wchan && l.l_wmesg) { db_read_string(l.l_wmesg, sizeof(wbuf), wbuf); wbuf[MAXCOMLEN] = '\0'; } else { wbuf[0] = '\0'; } db_printf("%8d %8d %10d %d %#7x %4d %16s %7.7s\n", p.p_pptr != NULL ? p.p_pptr->p_pid : -1, pgrp.pg_id, #ifdef _KERNEL kauth_cred_getuid(p.p_cred), #else /* XXX CRASH(8) */ 666, #endif p.p_stat, p.p_flag, p.p_nlwps, p.p_comm, (p.p_nlwps != 1) ? "*" : wbuf); break; case 'w': while (lp != NULL) { if (l.l_wchan && l.l_wmesg) { db_read_string(l.l_wmesg, sizeof(wbuf), wbuf); wbuf[MAXCOMLEN] = '\0'; } else { wbuf[0] = '\0'; } run = (l.l_stat == LSONPROC || (l.l_pflag & LP_RUNNING) != 0); db_read_bytes((db_addr_t)&p.p_emul->e_name, sizeof(ename), (char *)&ename); db_read_string(ename, sizeof(db_nbuf), db_nbuf); db_nbuf[MAXCOMLEN] = '\0'; db_printf( "%c%5d %16s %8s %4d %-16s %-18lx\n", (run ? '>' : ' '), l.l_lid, p.p_comm, db_nbuf, l.l_priority, wbuf, (long)l.l_wchan); lp = LIST_NEXT((&l), l_sibling); if (lp != NULL) { db_printf("%-5d", p.p_pid); db_read_bytes((db_addr_t)lp, sizeof(l), (char *)&l); } } break; } } } void db_show_proc(db_expr_t addr, bool haddr, db_expr_t count, const char *modif) { static proc_t p; static lwp_t l; const char *mode; proc_t *pp; lwp_t *lp; char db_nbuf[MAXCOMLEN + 1], wbuf[MAXCOMLEN + 1]; bool run; int cpuno; if (modif[0] == 0) mode = "p"; /* default == by pid */ else mode = strchr("ap", modif[0]); if (mode == NULL || !haddr) { db_printf("usage: show proc [/a] [/p] address|pid\n"); db_printf("\t/a == argument is an address of any lwp\n"); db_printf("\t/p == argument is a pid [default]\n"); return; } switch (*mode) { case 'a': lp = (lwp_t *)(uintptr_t)addr; db_printf("lwp_t %lx\n", (long)lp); db_read_bytes((db_addr_t)lp, sizeof(l), (char *)&l); pp = l.l_proc; break; default: case 'p': pp = db_proc_find((pid_t)addr); lp = NULL; break; } if (pp == NULL) { db_printf("bad address\n"); return; } db_read_bytes((db_addr_t)pp, sizeof(p), (char *)&p); if (lp == NULL) lp = p.p_lwps.lh_first; db_printf("%s: pid %d proc %lx vmspace/map %lx flags %x\n", p.p_comm, p.p_pid, (long)pp, (long)p.p_vmspace, p.p_flag); while (lp != NULL) { db_read_bytes((db_addr_t)lp, sizeof(l), (char *)&l); run = (l.l_stat == LSONPROC || (l.l_pflag & LP_RUNNING) != 0); db_printf("%slwp %d", (run ? "> " : " "), l.l_lid); if (l.l_name != NULL) { db_read_string(l.l_name, MAXCOMLEN, db_nbuf); db_nbuf[MAXCOMLEN] = '\0'; db_printf(" [%s]", db_nbuf); } db_printf(" %lx pcb %lx\n", (long)lp, (long)l.l_addr); if (l.l_cpu != NULL) { db_read_bytes((db_addr_t) &l.l_cpu->ci_data.cpu_index, sizeof(cpuno), (char *)&cpuno); } else cpuno = -1; db_printf(" stat %d flags %x cpu %d pri %d ref %d\n", l.l_stat, l.l_flag, cpuno, l.l_priority, l.l_refcnt); if (l.l_wchan && l.l_wmesg) { db_read_string(l.l_wmesg, MAXCOMLEN, wbuf); wbuf[MAXCOMLEN] = '\0'; db_printf(" wmesg %s wchan %lx\n", wbuf, (long)l.l_wchan); } lp = LIST_NEXT(&l, l_sibling); } }