1 1.80 martin /* $NetBSD: db_xxx.c,v 1.80 2023/11/02 10:31:55 martin Exp $ */ 2 1.1 gwr 3 1.1 gwr /* 4 1.1 gwr * Copyright (c) 1982, 1986, 1989, 1991, 1993 5 1.1 gwr * The Regents of the University of California. All rights reserved. 6 1.1 gwr * 7 1.1 gwr * Redistribution and use in source and binary forms, with or without 8 1.1 gwr * modification, are permitted provided that the following conditions 9 1.1 gwr * are met: 10 1.1 gwr * 1. Redistributions of source code must retain the above copyright 11 1.1 gwr * notice, this list of conditions and the following disclaimer. 12 1.1 gwr * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 gwr * notice, this list of conditions and the following disclaimer in the 14 1.1 gwr * documentation and/or other materials provided with the distribution. 15 1.26 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 gwr * may be used to endorse or promote products derived from this software 17 1.1 gwr * without specific prior written permission. 18 1.1 gwr * 19 1.1 gwr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 gwr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 gwr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 gwr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 gwr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 gwr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 gwr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 gwr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 gwr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 gwr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 gwr * SUCH DAMAGE. 30 1.1 gwr * 31 1.1 gwr * from: kern_proc.c 8.4 (Berkeley) 1/4/94 32 1.1 gwr */ 33 1.1 gwr 34 1.1 gwr /* 35 1.1 gwr * Miscellaneous DDB functions that are intimate (xxx) with various 36 1.1 gwr * data structures and functions used by the kernel (proc, callout). 37 1.1 gwr */ 38 1.15 lukem 39 1.46 dsl #include <sys/cdefs.h> 40 1.80 martin __KERNEL_RCSID(0, "$NetBSD: db_xxx.c,v 1.80 2023/11/02 10:31:55 martin Exp $"); 41 1.46 dsl 42 1.57 ad #ifdef _KERNEL_OPT 43 1.21 briggs #include "opt_kgdb.h" 44 1.53 ad #include "opt_aio.h" 45 1.62 rmind #include "opt_mqueue.h" 46 1.57 ad #endif 47 1.57 ad 48 1.59 mrg #ifndef _KERNEL 49 1.59 mrg #include <stdbool.h> 50 1.59 mrg #endif 51 1.59 mrg 52 1.1 gwr #include <sys/param.h> 53 1.72 riastrad #include <sys/atomic.h> 54 1.1 gwr #include <sys/systm.h> 55 1.1 gwr #include <sys/kernel.h> 56 1.1 gwr #include <sys/proc.h> 57 1.12 atatat #include <sys/msgbuf.h> 58 1.1 gwr #include <sys/callout.h> 59 1.49 blymn #include <sys/file.h> 60 1.49 blymn #include <sys/filedesc.h> 61 1.49 blymn #include <sys/lockdebug.h> 62 1.1 gwr #include <sys/signalvar.h> 63 1.3 ross #include <sys/resourcevar.h> 64 1.34 he #include <sys/pool.h> 65 1.57 ad #include <sys/uio.h> 66 1.38 elad #include <sys/kauth.h> 67 1.47 rmind #include <sys/mqueue.h> 68 1.49 blymn #include <sys/vnode.h> 69 1.54 ad #include <sys/module.h> 70 1.55 ad #include <sys/cpu.h> 71 1.56 yamt #include <sys/vmem.h> 72 1.76 ad #include <sys/condvar.h> 73 1.76 ad #include <sys/sleepq.h> 74 1.76 ad #include <sys/selinfo.h> 75 1.1 gwr 76 1.57 ad #include <ddb/ddb.h> 77 1.58 mrg #include <ddb/db_user.h> 78 1.1 gwr 79 1.21 briggs #ifdef KGDB 80 1.21 briggs #include <sys/kgdb.h> 81 1.21 briggs #endif 82 1.1 gwr 83 1.1 gwr void 84 1.42 matt db_kill_proc(db_expr_t addr, bool haddr, 85 1.40 christos db_expr_t count, const char *modif) 86 1.1 gwr { 87 1.63 christos #ifdef _KERNEL /* XXX CRASH(8) */ 88 1.63 christos struct proc *p; 89 1.63 christos ksiginfo_t ksi; 90 1.63 christos db_expr_t pid, sig; 91 1.63 christos int t; 92 1.63 christos 93 1.63 christos /* What pid? */ 94 1.63 christos if (!db_expression(&pid)) { 95 1.63 christos db_error("pid?\n"); 96 1.63 christos /*NOTREACHED*/ 97 1.63 christos } 98 1.63 christos /* What sig? */ 99 1.63 christos t = db_read_token(); 100 1.63 christos if (t == tCOMMA) { 101 1.63 christos if (!db_expression(&sig)) { 102 1.63 christos db_error("sig?\n"); 103 1.63 christos /*NOTREACHED*/ 104 1.63 christos } 105 1.63 christos } else { 106 1.63 christos db_unread_token(t); 107 1.63 christos sig = 15; 108 1.63 christos } 109 1.63 christos if (db_read_token() != tEOL) { 110 1.63 christos db_error("?\n"); 111 1.63 christos /*NOTREACHED*/ 112 1.63 christos } 113 1.65 christos /* We might stop when the mutex is held or when not */ 114 1.75 ad t = mutex_tryenter(&proc_lock); 115 1.66 christos #ifdef DIAGNOSTIC 116 1.66 christos if (!t) { 117 1.66 christos db_error("could not acquire proc_lock mutex\n"); 118 1.66 christos /*NOTREACHED*/ 119 1.66 christos } 120 1.66 christos #endif 121 1.63 christos p = proc_find((pid_t)pid); 122 1.63 christos if (p == NULL) { 123 1.66 christos if (t) 124 1.75 ad mutex_exit(&proc_lock); 125 1.66 christos db_error("no such proc\n"); 126 1.66 christos /*NOTREACHED*/ 127 1.63 christos } 128 1.63 christos KSI_INIT(&ksi); 129 1.63 christos ksi.ksi_signo = sig; 130 1.63 christos ksi.ksi_code = SI_USER; 131 1.63 christos ksi.ksi_pid = 0; 132 1.63 christos ksi.ksi_uid = 0; 133 1.66 christos mutex_enter(p->p_lock); 134 1.63 christos kpsignal2(p, &ksi); 135 1.66 christos mutex_exit(p->p_lock); 136 1.66 christos if (t) 137 1.75 ad mutex_exit(&proc_lock); 138 1.63 christos #else 139 1.74 christos db_kernelonly(); 140 1.63 christos #endif 141 1.1 gwr } 142 1.21 briggs 143 1.21 briggs #ifdef KGDB 144 1.21 briggs void 145 1.42 matt db_kgdb_cmd(db_expr_t addr, bool haddr, 146 1.40 christos db_expr_t count, const char *modif) 147 1.21 briggs { 148 1.21 briggs kgdb_active++; 149 1.21 briggs kgdb_trap(db_trap_type, DDB_REGS); 150 1.21 briggs kgdb_active--; 151 1.21 briggs } 152 1.21 briggs #endif 153 1.1 gwr 154 1.1 gwr void 155 1.49 blymn db_show_files_cmd(db_expr_t addr, bool haddr, 156 1.49 blymn db_expr_t count, const char *modif) 157 1.49 blymn { 158 1.57 ad #ifdef _KERNEL /* XXX CRASH(8) */ 159 1.49 blymn struct proc *p; 160 1.49 blymn int i; 161 1.50 blymn filedesc_t *fdp; 162 1.50 blymn fdfile_t *ff; 163 1.50 blymn file_t *fp; 164 1.70 matt struct vnode *vp; 165 1.49 blymn bool full = false; 166 1.61 ad fdtab_t *dt; 167 1.49 blymn 168 1.71 ozaki if (!haddr) { 169 1.71 ozaki db_printf("usage: show files address\n"); 170 1.71 ozaki db_printf("\taddress == an address of a proc structure\n"); 171 1.71 ozaki return; 172 1.71 ozaki } 173 1.71 ozaki 174 1.49 blymn if (modif[0] == 'f') 175 1.49 blymn full = true; 176 1.49 blymn 177 1.52 rmind p = (struct proc *) (uintptr_t) addr; 178 1.49 blymn 179 1.50 blymn fdp = p->p_fd; 180 1.72 riastrad dt = atomic_load_consume(&fdp->fd_dt); 181 1.61 ad for (i = 0; i < dt->dt_nfiles; i++) { 182 1.61 ad if ((ff = dt->dt_ff[i]) == NULL) 183 1.49 blymn continue; 184 1.49 blymn 185 1.73 riastrad fp = atomic_load_consume(&ff->ff_file); 186 1.49 blymn 187 1.49 blymn /* Only look at vnodes... */ 188 1.70 matt if (fp != NULL && fp->f_type == DTYPE_VNODE 189 1.70 matt && fp->f_vnode != NULL) { 190 1.70 matt vp = fp->f_vnode; 191 1.70 matt vfs_vnode_print(vp, full, db_printf); 192 1.49 blymn 193 1.49 blymn #ifdef LOCKDEBUG 194 1.70 matt db_printf("\nv_uobj.vmobjlock lock details:\n"); 195 1.70 matt lockdebug_lock_print(vp->v_uobj.vmobjlock, db_printf); 196 1.70 matt db_printf("\n"); 197 1.49 blymn #endif 198 1.49 blymn } 199 1.49 blymn } 200 1.57 ad #endif 201 1.49 blymn } 202 1.49 blymn 203 1.53 ad #ifdef AIO 204 1.49 blymn void 205 1.43 rmind db_show_aio_jobs(db_expr_t addr, bool haddr, 206 1.43 rmind db_expr_t count, const char *modif) 207 1.43 rmind { 208 1.57 ad 209 1.43 rmind aio_print_jobs(db_printf); 210 1.43 rmind } 211 1.53 ad #endif 212 1.43 rmind 213 1.62 rmind #ifdef MQUEUE 214 1.43 rmind void 215 1.47 rmind db_show_mqueue_cmd(db_expr_t addr, bool haddr, 216 1.47 rmind db_expr_t count, const char *modif) 217 1.47 rmind { 218 1.57 ad 219 1.57 ad #ifdef _KERNEL /* XXX CRASH(8) */ 220 1.47 rmind mqueue_print_list(db_printf); 221 1.57 ad #endif 222 1.47 rmind } 223 1.62 rmind #endif 224 1.47 rmind 225 1.47 rmind void 226 1.54 ad db_show_module_cmd(db_expr_t addr, bool haddr, 227 1.54 ad db_expr_t count, const char *modif) 228 1.54 ad { 229 1.57 ad 230 1.57 ad #ifdef _KERNEL /* XXX CRASH(8) */ 231 1.54 ad module_print_list(db_printf); 232 1.57 ad #endif 233 1.12 atatat } 234 1.12 atatat 235 1.12 atatat void 236 1.42 matt db_show_all_pools(db_expr_t addr, bool haddr, 237 1.40 christos db_expr_t count, const char *modif) 238 1.33 yamt { 239 1.33 yamt 240 1.57 ad #ifdef _KERNEL /* XXX CRASH(8) */ 241 1.33 yamt pool_printall(modif, db_printf); 242 1.57 ad #endif 243 1.33 yamt } 244 1.33 yamt 245 1.33 yamt void 246 1.56 yamt db_show_all_vmems(db_expr_t addr, bool have_addr, 247 1.56 yamt db_expr_t count, const char *modif) 248 1.56 yamt { 249 1.56 yamt 250 1.57 ad #ifdef _KERNEL /* XXX CRASH(8) */ 251 1.56 yamt vmem_printall(modif, db_printf); 252 1.57 ad #endif 253 1.56 yamt } 254 1.56 yamt 255 1.56 yamt void 256 1.60 ad db_dmesg(db_expr_t addr, bool haddr, db_expr_t count, const char *modif) 257 1.12 atatat { 258 1.60 ad struct kern_msgbuf mb, *mbp; 259 1.25 simonb db_expr_t print; 260 1.60 ad int newl, skip, i; 261 1.60 ad char *p, *bufdata, ch; 262 1.22 atatat 263 1.60 ad if (!db_read_int("msgbufenabled")) { 264 1.60 ad db_printf("message buffer not available\n"); 265 1.60 ad return; 266 1.60 ad } 267 1.60 ad mbp = (struct kern_msgbuf *)db_read_ptr("msgbufp"); 268 1.60 ad db_read_bytes((db_addr_t)mbp, sizeof(mb), (char *)&mb); 269 1.60 ad if (mb.msg_magic != MSG_MAGIC) { 270 1.22 atatat db_printf("message buffer not available\n"); 271 1.22 atatat return; 272 1.22 atatat } 273 1.12 atatat 274 1.12 atatat bufdata = &mbp->msg_bufc[0]; 275 1.12 atatat 276 1.60 ad if (haddr && addr < mb.msg_bufs) 277 1.25 simonb print = addr; 278 1.25 simonb else 279 1.60 ad print = mb.msg_bufs; 280 1.25 simonb 281 1.60 ad for (newl = skip = i = 0, p = bufdata + mb.msg_bufx; 282 1.60 ad i < mb.msg_bufs; i++, p++) { 283 1.60 ad if (p == bufdata + mb.msg_bufs) 284 1.12 atatat p = bufdata; 285 1.60 ad if (i < mb.msg_bufs - print) { 286 1.25 simonb continue; 287 1.60 ad } 288 1.60 ad db_read_bytes((db_addr_t)p, sizeof(ch), &ch); 289 1.12 atatat /* Skip "\n<.*>" syslog sequences. */ 290 1.12 atatat if (skip) { 291 1.12 atatat if (ch == '>') 292 1.12 atatat newl = skip = 0; 293 1.12 atatat continue; 294 1.12 atatat } 295 1.12 atatat if (newl && ch == '<') { 296 1.12 atatat skip = 1; 297 1.12 atatat continue; 298 1.12 atatat } 299 1.12 atatat if (ch == '\0') 300 1.12 atatat continue; 301 1.12 atatat newl = ch == '\n'; 302 1.12 atatat db_printf("%c", ch); 303 1.12 atatat } 304 1.12 atatat if (!newl) 305 1.12 atatat db_printf("\n"); 306 1.28 thorpej } 307 1.28 thorpej 308 1.28 thorpej void 309 1.42 matt db_show_sched_qs(db_expr_t addr, bool haddr, 310 1.40 christos db_expr_t count, const char *modif) 311 1.28 thorpej { 312 1.44 yamt 313 1.57 ad #ifdef _KERNEL /* XXX CRASH(8) */ 314 1.44 yamt sched_print_runqueue(db_printf); 315 1.57 ad #endif 316 1.1 gwr } 317 1.67 christos 318 1.67 christos void 319 1.67 christos db_show_panic(db_expr_t addr, bool haddr, db_expr_t count, const char *modif) 320 1.67 christos { 321 1.67 christos #ifdef _KERNEL /* XXX CRASH(8) */ 322 1.67 christos int s; 323 1.67 christos 324 1.67 christos s = splhigh(); 325 1.67 christos 326 1.67 christos db_printf("Panic string: %s\n", panicstr); 327 1.67 christos 328 1.67 christos (void)splx(s); 329 1.67 christos #endif 330 1.67 christos } 331 1.76 ad 332 1.76 ad void 333 1.76 ad db_show_condvar(db_expr_t addr, bool haddr, db_expr_t count, const char *modif) 334 1.76 ad { 335 1.77 martin kcondvar_t *cv = (kcondvar_t *)(uintptr_t)addr; 336 1.76 ad char buf[9], *wmesg; 337 1.76 ad 338 1.76 ad /* XXX messing with kcondvar_t guts without defs */ 339 1.76 ad db_read_bytes((db_addr_t)&cv->cv_opaque[1], sizeof(wmesg), 340 1.76 ad (char *)&wmesg); 341 1.76 ad db_read_bytes((db_addr_t)wmesg, sizeof(buf) - 1, buf); 342 1.76 ad buf[sizeof(buf) - 1] = '\0'; 343 1.76 ad db_printf("wmesg=%s ", buf); 344 1.76 ad db_show_sleepq((db_addr_t)&cv->cv_opaque[0], false, 0, modif); 345 1.76 ad } 346 1.76 ad 347 1.76 ad void 348 1.76 ad db_show_sleepq(db_expr_t addr, bool haddr, db_expr_t count, const char *modif) 349 1.76 ad { 350 1.76 ad sleepq_t sq; 351 1.76 ad lwp_t *lp; 352 1.76 ad 353 1.76 ad db_read_bytes(addr, sizeof(lp), (char *)&sq); 354 1.76 ad db_printf("sleepq="); 355 1.76 ad if ((lp = LIST_FIRST(&sq)) == NULL) { 356 1.76 ad db_printf("<empty>"); 357 1.76 ad } 358 1.76 ad while (lp != NULL) { 359 1.76 ad db_printf("%p", lp); 360 1.76 ad db_read_bytes((db_addr_t)&lp->l_sleepchain.le_next, sizeof(lp), 361 1.76 ad (char *)&lp); 362 1.76 ad if (lp != NULL) 363 1.76 ad db_printf(","); 364 1.76 ad } 365 1.76 ad db_printf("\n"); 366 1.76 ad } 367 1.76 ad 368 1.76 ad void 369 1.76 ad db_show_selinfo(db_expr_t addr, bool haddr, db_expr_t count, const char *modif) 370 1.76 ad { 371 1.76 ad struct selinfo sel; 372 1.76 ad 373 1.76 ad db_read_bytes(addr, sizeof(sel), (char *)&sel); 374 1.76 ad 375 1.76 ad db_printf("collision=%llx klist=%p cluster=%p lwp=%p fdinfo=%lx " 376 1.76 ad "sel_chain=%p\n", (long long)sel.sel_collision, 377 1.76 ad SLIST_FIRST(&sel.sel_klist), sel.sel_cluster, sel.sel_lwp, 378 1.76 ad (long)sel.sel_fdinfo, sel.sel_chain.sle_next); 379 1.76 ad } 380