1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <mdb/mdb_target.h> 30 #include <mdb/mdb_modapi.h> 31 #include <mdb/mdb_string.h> 32 #include <mdb/mdb.h> 33 34 #include <libproc.h> 35 #include <string.h> 36 37 /*ARGSUSED*/ 38 void 39 cmd_event(mdb_tgt_t *t, int vid, void *s) 40 { 41 if (s != NULL && mdb_eval(s) == -1) 42 mdb_warn("failed to eval [ %d ] command \"%s\"", vid, s); 43 } 44 45 int 46 cmd_evset(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 47 { 48 uint_t setb = 0, clrb = 0; 49 const char *opt_c = NULL; 50 uint_t opt_F = FALSE; 51 uintptr_t opt_n = 0; 52 53 int *idv = mdb_zalloc(sizeof (int) * (argc + 1), UM_SLEEP | UM_GC); 54 int idc = 0; 55 56 int status = DCMD_OK; 57 const char *p; 58 void *data; 59 int argi; 60 61 if (flags & DCMD_ADDRSPEC) 62 idv[idc++] = (int)(intptr_t)addr; 63 64 /* 65 * Perform an initial pass through argv: we accumulate integer ids into 66 * idv, and compute a group of bits to set and a group to clear. 67 */ 68 while (argc != 0 && (argi = mdb_getopts(argc, argv, 69 'c', MDB_OPT_STR, &opt_c, 70 'd', MDB_OPT_SETBITS, MDB_TGT_SPEC_AUTODIS, &setb, 71 'D', MDB_OPT_SETBITS, MDB_TGT_SPEC_AUTODEL, &setb, 72 'e', MDB_OPT_SETBITS, MDB_TGT_SPEC_DISABLED, &clrb, 73 'F', MDB_OPT_SETBITS, TRUE, &opt_F, 74 'n', MDB_OPT_UINTPTR, &opt_n, 75 's', MDB_OPT_SETBITS, MDB_TGT_SPEC_AUTOSTOP, &setb, 76 't', MDB_OPT_SETBITS, MDB_TGT_SPEC_TEMPORARY, &setb, 77 'T', MDB_OPT_SETBITS, MDB_TGT_SPEC_STICKY, &setb, 78 NULL)) != argc) { 79 80 argv += argi; /* advance past elements processed by getopts */ 81 argc -= argi; /* decrement argc by number of args processed */ 82 83 if (argv->a_type == MDB_TYPE_STRING) { 84 if (argv->a_un.a_str[0] == '+') { 85 for (p = argv->a_un.a_str + 1; *p != '\0'; ) { 86 switch (*p++) { 87 case 'd': 88 clrb |= MDB_TGT_SPEC_AUTODIS; 89 break; 90 case 'D': 91 clrb |= MDB_TGT_SPEC_AUTODEL; 92 break; 93 case 'e': 94 setb |= MDB_TGT_SPEC_DISABLED; 95 break; 96 case 's': 97 clrb |= MDB_TGT_SPEC_AUTOSTOP; 98 break; 99 case 't': 100 clrb |= MDB_TGT_SPEC_TEMPORARY; 101 break; 102 case 'T': 103 clrb |= MDB_TGT_SPEC_STICKY; 104 break; 105 default: 106 mdb_warn("illegal option -- " 107 "+%c\n", p[-1]); 108 return (DCMD_USAGE); 109 } 110 } 111 } else if (argv->a_un.a_str[0] != '-') { 112 idv[idc++] = (int)(intmax_t) 113 strtonum(argv->a_un.a_str, 10); 114 } else 115 return (DCMD_USAGE); 116 } else 117 idv[idc++] = (int)(intmax_t)argv->a_un.a_val; 118 119 argc--; 120 argv++; 121 } 122 123 if (idc == 0) { 124 mdb_warn("expected one or more event IDs to be specified\n"); 125 return (DCMD_USAGE); 126 } 127 128 /* 129 * If -n was not specified, then -d means "disable now" instead of 130 * meaning "set auto-disable after n hits". 131 */ 132 if (opt_n == 0 && (setb & MDB_TGT_SPEC_AUTODIS)) 133 setb = (setb & ~MDB_TGT_SPEC_AUTODIS) | MDB_TGT_SPEC_DISABLED; 134 135 while (idc-- != 0) { 136 mdb_tgt_spec_desc_t sp; 137 int id = *idv++; 138 139 bzero(&sp, sizeof (mdb_tgt_spec_desc_t)); 140 (void) mdb_tgt_vespec_info(mdb.m_target, id, &sp, NULL, 0); 141 data = sp.spec_data; 142 143 if (opt_F == FALSE && (sp.spec_flags & MDB_TGT_SPEC_HIDDEN)) { 144 mdb_warn("cannot modify event %d: internal " 145 "debugger event\n", id); 146 status = DCMD_ERR; 147 continue; 148 } 149 150 sp.spec_flags |= setb; 151 sp.spec_flags &= ~clrb; 152 153 if (opt_c && !(sp.spec_flags & MDB_TGT_SPEC_HIDDEN)) { 154 if (opt_c[0] != '\0') 155 sp.spec_data = strdup(opt_c); 156 else 157 sp.spec_data = NULL; 158 } 159 160 if (opt_n) 161 sp.spec_limit = opt_n; 162 163 if (mdb_tgt_vespec_modify(mdb.m_target, id, sp.spec_flags, 164 sp.spec_limit, sp.spec_data) == -1) { 165 mdb_warn("failed to modify event %d", id); 166 data = sp.spec_data; 167 status = DCMD_ERR; 168 } 169 170 if (opt_c && data && !(sp.spec_flags & MDB_TGT_SPEC_HIDDEN)) 171 strfree(data); 172 } 173 174 return (status); 175 } 176 177 /* 178 * Utility routine for performing the stock argument processing that is common 179 * among the dcmds that create event specifiers. We parse out the standard set 180 * of event property options from the command-line, and return a copy of the 181 * argument list to the caller that consists solely of the remaining non-option 182 * arguments. If a parsing error occurs, NULL is returned. 183 */ 184 static const mdb_arg_t * 185 ev_getopts(uintmax_t addr, uint_t flags, int argc, const mdb_arg_t *argv, 186 uint_t *evflags, char **opt_c, uint_t *opt_i, uint_t *opt_l, 187 uint64_t *opt_L, uintptr_t *opt_n, uint_t *opt_o, uint_t *opt_p, 188 uint_t *rwx) 189 { 190 uint_t setb = 0, clrb = 0; 191 const char *p; 192 int argi; 193 194 mdb_arg_t *av; 195 int ac = 0; 196 197 /* keep lint happy */ 198 *opt_p = FALSE; 199 200 av = mdb_alloc(sizeof (mdb_arg_t) * (argc + 2), UM_SLEEP | UM_GC); 201 202 /* 203 * If an address was specified, take it as an additional immediate 204 * value argument by adding it to the argument list. 205 */ 206 if (flags & DCMD_ADDRSPEC) { 207 av[ac].a_type = MDB_TYPE_IMMEDIATE; 208 av[ac++].a_un.a_val = addr; 209 } 210 211 /* 212 * Now call mdb_getopts repeatedly to parse the argument list. We need 213 * to handle '+[a-z]' processing manually, and we also manually copy 214 * each non-option argument into the av[] array as we encounter them. 215 */ 216 while (argc != 0 && (argi = mdb_getopts(argc, argv, 217 'c', MDB_OPT_STR, opt_c, 218 'd', MDB_OPT_SETBITS, MDB_TGT_SPEC_AUTODIS, &setb, 219 'D', MDB_OPT_SETBITS, MDB_TGT_SPEC_AUTODEL, &setb, 220 'e', MDB_OPT_SETBITS, MDB_TGT_SPEC_DISABLED, &clrb, 221 'i', MDB_OPT_SETBITS, TRUE, opt_i, 222 'n', MDB_OPT_UINTPTR, opt_n, 223 'o', MDB_OPT_SETBITS, TRUE, opt_o, 224 #ifdef _KMDB 225 'p', MDB_OPT_SETBITS, TRUE, opt_p, 226 #endif 227 'r', MDB_OPT_SETBITS, MDB_TGT_WA_R, rwx, 228 's', MDB_OPT_SETBITS, MDB_TGT_SPEC_AUTOSTOP, &setb, 229 'l', MDB_OPT_SETBITS, TRUE, opt_l, 230 'L', MDB_OPT_UINT64, opt_L, 231 't', MDB_OPT_SETBITS, MDB_TGT_SPEC_TEMPORARY, &setb, 232 'T', MDB_OPT_SETBITS, MDB_TGT_SPEC_STICKY, &setb, 233 'w', MDB_OPT_SETBITS, MDB_TGT_WA_W, rwx, 234 'x', MDB_OPT_SETBITS, MDB_TGT_WA_X, rwx, NULL)) != argc) { 235 236 argv += argi; /* advance past elements processed by getopts */ 237 argc -= argi; /* decrement argc by number of args processed */ 238 239 if (argv->a_type == MDB_TYPE_STRING) { 240 if (argv->a_un.a_str[0] == '+') { 241 for (p = argv->a_un.a_str + 1; *p != '\0'; ) { 242 switch (*p++) { 243 case 'd': 244 clrb |= MDB_TGT_SPEC_AUTODIS; 245 break; 246 case 'D': 247 clrb |= MDB_TGT_SPEC_AUTODEL; 248 break; 249 case 'e': 250 setb |= MDB_TGT_SPEC_DISABLED; 251 break; 252 case 's': 253 clrb |= MDB_TGT_SPEC_AUTOSTOP; 254 break; 255 case 't': 256 clrb |= MDB_TGT_SPEC_TEMPORARY; 257 break; 258 case 'T': 259 clrb |= MDB_TGT_SPEC_STICKY; 260 break; 261 default: 262 mdb_warn("illegal option -- " 263 "+%c\n", p[-1]); 264 return (NULL); 265 } 266 } 267 } else if (argv->a_un.a_str[0] != '-') { 268 av[ac++] = *argv; 269 } else 270 return (NULL); 271 } else 272 av[ac++] = *argv; 273 274 argc--; 275 argv++; 276 } 277 278 /* 279 * If no arguments were found on the command-line, return NULL to 280 * indicate that the caller should return DCMD_USAGE. 281 */ 282 if (ac == 0) 283 return (NULL); 284 285 /* 286 * If -n was not specified, then -d means "disable now" instead of 287 * meaning "set auto-disable after n hits". 288 */ 289 if (opt_n == 0 && (setb & MDB_TGT_SPEC_AUTODIS)) 290 setb = (setb & ~MDB_TGT_SPEC_AUTODIS) | MDB_TGT_SPEC_DISABLED; 291 292 /* 293 * Return the final set of flags, and terminate the argument array 294 * with a NULL string argument. 295 */ 296 *evflags = setb & ~clrb; 297 298 av[ac].a_type = MDB_TYPE_STRING; 299 av[ac].a_un.a_str = NULL; 300 301 return (av); 302 } 303 304 /* 305 * Utility function for modifying the spec_data and spec_limit properties of an 306 * event specifier. We use this for handling the -c and -n options below. 307 */ 308 static void 309 ev_setopts(mdb_tgt_t *t, int id, const char *opt_c, uintptr_t opt_n) 310 { 311 mdb_tgt_spec_desc_t sp; 312 313 (void) mdb_tgt_vespec_info(t, id, &sp, NULL, 0); 314 315 if (opt_c != NULL) 316 sp.spec_data = strdup(opt_c); 317 if (opt_n != 0) 318 sp.spec_limit = opt_n; 319 320 if (mdb_tgt_vespec_modify(t, id, sp.spec_flags, 321 sp.spec_limit, sp.spec_data) == -1) { 322 mdb_warn("failed to modify event %d", id); 323 if (opt_c != NULL) 324 strfree(sp.spec_data); 325 } 326 } 327 328 int 329 cmd_bp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 330 { 331 char *opt_c = NULL; 332 uint_t opt_i = FALSE; 333 uint_t opt_l = FALSE; 334 uint64_t opt_L = 0; 335 uintptr_t opt_n = 0; 336 uint_t opt_o = FALSE; 337 uint_t opt_p = FALSE; 338 uint_t opt_rwx = 0; 339 int status = DCMD_OK; 340 int id; 341 342 if ((argv = ev_getopts(addr, flags, argc, argv, &flags, &opt_c, &opt_i, 343 &opt_l, &opt_L, &opt_n, &opt_o, &opt_p, &opt_rwx)) == NULL || 344 opt_i || opt_o || opt_rwx != 0 || opt_l || opt_L != 0 || opt_p) 345 return (DCMD_USAGE); 346 347 while (argv->a_type != MDB_TYPE_STRING || argv->a_un.a_str != NULL) { 348 if (argv->a_type == MDB_TYPE_STRING) { 349 id = mdb_tgt_add_sbrkpt(mdb.m_target, argv->a_un.a_str, 350 flags, cmd_event, NULL); 351 } else { 352 id = mdb_tgt_add_vbrkpt(mdb.m_target, argv->a_un.a_val, 353 flags, cmd_event, NULL); 354 } 355 356 if (id == 0) { 357 mdb_warn("failed to add breakpoint at %s", 358 argv->a_type == MDB_TYPE_STRING ? argv->a_un.a_str : 359 numtostr(argv->a_un.a_val, mdb.m_radix, 360 NTOS_UNSIGNED | NTOS_SHOWBASE)); 361 status = DCMD_ERR; 362 363 } else if (opt_c || opt_n) 364 ev_setopts(mdb.m_target, id, opt_c, opt_n); 365 366 argv++; 367 } 368 369 return (status); 370 } 371 372 373 int 374 cmd_sigbp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 375 { 376 char *opt_c = NULL; 377 uint_t opt_i = FALSE; 378 uint_t opt_l = FALSE; 379 uint64_t opt_L = 0; 380 uintptr_t opt_n = 0; 381 uint_t opt_o = FALSE; 382 uint_t opt_p = FALSE; 383 uint_t opt_rwx = 0; 384 int status = DCMD_OK; 385 int id, sig; 386 387 if ((argv = ev_getopts(addr, flags, argc, argv, &flags, &opt_c, &opt_i, 388 &opt_l, &opt_L, &opt_n, &opt_o, &opt_p, &opt_rwx)) == NULL || 389 opt_i || opt_l || opt_L != 0 || opt_o || opt_p || opt_rwx != 0) 390 return (DCMD_USAGE); 391 392 while (argv->a_type != MDB_TYPE_STRING || argv->a_un.a_str != NULL) { 393 if (argv->a_type == MDB_TYPE_STRING) { 394 if (proc_str2sig(argv->a_un.a_str, &sig) == -1) { 395 mdb_warn("invalid signal name -- %s\n", 396 argv->a_un.a_str); 397 status = DCMD_ERR; 398 argv++; 399 continue; 400 } 401 } else 402 sig = (int)(intmax_t)argv->a_un.a_val; 403 404 if ((id = mdb_tgt_add_signal(mdb.m_target, sig, flags, 405 cmd_event, NULL)) == 0) { 406 mdb_warn("failed to trace signal %d", sig); 407 status = DCMD_ERR; 408 } else if (opt_c || opt_n) 409 ev_setopts(mdb.m_target, id, opt_c, opt_n); 410 411 argv++; 412 } 413 414 return (status); 415 } 416 417 int 418 cmd_sysbp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 419 { 420 char *opt_c = NULL; 421 uint_t opt_i = FALSE; 422 uint_t opt_l = FALSE; 423 uint64_t opt_L = 0; 424 uintptr_t opt_n = 0; 425 uint_t opt_o = FALSE; 426 uint_t opt_p = FALSE; 427 uint_t opt_rwx = 0; 428 int status = DCMD_OK; 429 int id, sysnum; 430 431 if ((argv = ev_getopts(addr, flags, argc, argv, &flags, &opt_c, &opt_i, 432 &opt_l, &opt_L, &opt_n, &opt_o, &opt_p, &opt_rwx)) == NULL || 433 (opt_i && opt_o) || opt_l || opt_L != 0 || opt_p || opt_rwx != 0) 434 return (DCMD_USAGE); 435 436 while (argv->a_type != MDB_TYPE_STRING || argv->a_un.a_str != NULL) { 437 if (argv->a_type == MDB_TYPE_STRING) { 438 if (proc_str2sys(argv->a_un.a_str, &sysnum) == -1) { 439 mdb_warn("invalid system call name -- %s\n", 440 argv->a_un.a_str); 441 status = DCMD_ERR; 442 argv++; 443 continue; 444 } 445 } else 446 sysnum = (int)(intmax_t)argv->a_un.a_val; 447 448 if (opt_o) { 449 id = mdb_tgt_add_sysexit(mdb.m_target, sysnum, 450 flags, cmd_event, NULL); 451 } else { 452 id = mdb_tgt_add_sysenter(mdb.m_target, sysnum, 453 flags, cmd_event, NULL); 454 } 455 456 if (id == 0) { 457 mdb_warn("failed to trace system call %d", sysnum); 458 status = DCMD_ERR; 459 } else if (opt_c || opt_n) 460 ev_setopts(mdb.m_target, id, opt_c, opt_n); 461 462 argv++; 463 } 464 465 return (status); 466 } 467 468 int 469 cmd_fltbp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 470 { 471 char *opt_c = NULL; 472 uint_t opt_i = FALSE; 473 uint_t opt_l = FALSE; 474 uint64_t opt_L = 0; 475 uintptr_t opt_n = 0; 476 uint_t opt_o = FALSE; 477 uint_t opt_p = FALSE; 478 uint_t opt_rwx = 0; 479 int status = DCMD_OK; 480 int id, fltnum; 481 482 if ((argv = ev_getopts(addr, flags, argc, argv, &flags, &opt_c, 483 &opt_i, &opt_l, &opt_L, &opt_n, &opt_o, &opt_p, 484 &opt_rwx)) == NULL || opt_i || opt_l || opt_L != 0 || opt_o || 485 opt_p || opt_rwx != 0) 486 return (DCMD_USAGE); 487 488 while (argv->a_type != MDB_TYPE_STRING || argv->a_un.a_str != NULL) { 489 if (argv->a_type == MDB_TYPE_STRING) { 490 if (proc_str2flt(argv->a_un.a_str, &fltnum) == -1) { 491 mdb_warn("invalid fault name -- %s\n", 492 argv->a_un.a_str); 493 status = DCMD_ERR; 494 argv++; 495 continue; 496 } 497 } else 498 fltnum = (int)(intmax_t)argv->a_un.a_val; 499 500 id = mdb_tgt_add_fault(mdb.m_target, fltnum, 501 flags, cmd_event, NULL); 502 503 if (id == 0) { 504 mdb_warn("failed to trace fault %d", fltnum); 505 status = DCMD_ERR; 506 } else if (opt_c || opt_n) 507 ev_setopts(mdb.m_target, id, opt_c, opt_n); 508 509 argv++; 510 } 511 512 return (status); 513 } 514 515 /*ARGSUSED*/ 516 int 517 cmd_wp(uintptr_t x, uint_t flags, int argc, const mdb_arg_t *argv) 518 { 519 mdb_tgt_addr_t addr = mdb_get_dot(); 520 char *opt_c = NULL; 521 uint_t opt_i = FALSE; 522 uint_t opt_l = FALSE; 523 uint64_t opt_L = 0; 524 uintptr_t opt_n = 0; 525 uint_t opt_o = FALSE; 526 uint_t opt_p = FALSE; 527 uint_t opt_rwx = 0; 528 int id; 529 char buf[MDB_SYM_NAMLEN]; 530 GElf_Sym gsym; 531 int size; 532 533 if ((argv = ev_getopts(addr, flags, argc, argv, &flags, &opt_c, &opt_i, 534 &opt_l, &opt_L, &opt_n, &opt_o, &opt_p, &opt_rwx)) == NULL || 535 opt_o || (opt_p && opt_i)) 536 return (DCMD_USAGE); 537 538 #ifndef _KMDB 539 if (opt_i) 540 return (DCMD_USAGE); 541 #endif 542 543 if (argv->a_type != MDB_TYPE_IMMEDIATE) 544 return (DCMD_USAGE); 545 546 if (opt_rwx == 0) { 547 mdb_warn("at least one of -r, -w, or -x must be specified\n"); 548 return (DCMD_USAGE); 549 } 550 551 if ((opt_l) + (opt_L > 0) + (mdb.m_dcount != 1) > 1) { 552 mdb_warn("only one of -l, -L, or command count can be " 553 "specified\n"); 554 return (DCMD_ABORT); 555 } 556 557 if (opt_l) { 558 if (mdb_lookup_by_addr(addr, MDB_SYM_EXACT, buf, 559 sizeof (buf), &gsym) == -1) { 560 mdb_warn("failed to lookup symbol at %p", addr); 561 return (DCMD_ERR); 562 } 563 564 if (gsym.st_size == 0) { 565 mdb_warn("cannot set watchpoint: symbol '%s' has zero " 566 "size\n", buf); 567 return (DCMD_ERR); 568 } 569 size = gsym.st_size; 570 } else if (opt_L != 0) { 571 size = opt_L; 572 } else 573 size = mdb.m_dcount; 574 575 if (opt_p) { 576 id = mdb_tgt_add_pwapt(mdb.m_target, addr, size, opt_rwx, 577 flags, cmd_event, NULL); 578 } else if (opt_i) { 579 id = mdb_tgt_add_iowapt(mdb.m_target, addr, size, opt_rwx, 580 flags, cmd_event, NULL); 581 } else { 582 id = mdb_tgt_add_vwapt(mdb.m_target, addr, size, opt_rwx, 583 flags, cmd_event, NULL); 584 } 585 586 if (id == 0) { 587 mdb_warn("failed to set watchpoint at %p", addr); 588 return ((opt_l || opt_L) ? DCMD_ERR : DCMD_ABORT); 589 } 590 591 if (opt_c || opt_n) 592 ev_setopts(mdb.m_target, id, opt_c, opt_n); 593 594 /* 595 * We use m_dcount as an argument; don't loop. We ignore this 596 * restriction with the -l and -L options, since we read the size from 597 * the symbol and don't rely on the count. 598 */ 599 return ((opt_l || opt_L) ? DCMD_OK : DCMD_ABORT); 600 } 601 602 /*ARGSUSED*/ 603 int 604 cmd_oldbp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 605 { 606 char *s = mdb_argv_to_str(argc, argv); 607 608 if (mdb_tgt_add_vbrkpt(mdb.m_target, addr, 0, cmd_event, s) == 0) { 609 mdb_warn("failed to add breakpoint"); 610 if (s != NULL) 611 strfree(s); 612 return (DCMD_ERR); 613 } 614 615 return (DCMD_OK); 616 } 617 618 /*ARGSUSED*/ 619 static int 620 oldwp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv, uint_t rwx) 621 { 622 char *s = mdb_argv_to_str(argc, argv); 623 624 if (mdb_tgt_add_vwapt(mdb.m_target, addr, mdb.m_dcount, rwx, 0, 625 cmd_event, s) == 0) { 626 mdb_warn("failed to add watchpoint"); 627 if (s != NULL) 628 strfree(s); 629 return (DCMD_ABORT); 630 } 631 632 return (DCMD_ABORT); /* we use m_dcount as an argument; don't loop */ 633 } 634 635 int 636 cmd_oldwpr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 637 { 638 return (oldwp(addr, flags, argc, argv, MDB_TGT_WA_R)); 639 } 640 641 int 642 cmd_oldwpw(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 643 { 644 return (oldwp(addr, flags, argc, argv, MDB_TGT_WA_W)); 645 } 646 647 int 648 cmd_oldwpx(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 649 { 650 return (oldwp(addr, flags, argc, argv, MDB_TGT_WA_X)); 651 } 652 653 static const char _evset_help[] = 654 "+/-d disable specifier when hit count reaches limit (+d to unset);\n" 655 " if -n is not present with -d, specifier is disabled immediately\n\n" 656 "+/-D delete specifier when hit count reaches limit (+D to unset);\n" 657 "+/-e enable specifier (+e or -d to disable)\n" 658 "+/-s stop target when hit count reaches limit (+s to unset)\n" 659 "+/-t delete specifier the next time the target stops (+t to unset)\n" 660 "+/-T sticky bit: ::delete all will not remove specifier (+T to unset)\n\n" 661 "-c cmd execute \"cmd\" each time the corresponding event occurs\n" 662 "-n count set limit for -D, -d, or -s to \"count\" (default 1)\n\n"; 663 664 void 665 bp_help(void) 666 { 667 mdb_printf(_evset_help); 668 mdb_printf("addr set breakpoint at specified virtual address\n"); 669 mdb_printf("sym set deferred breakpoint at specified symbol\n"); 670 } 671 672 void 673 evset_help(void) 674 { 675 mdb_printf(_evset_help); 676 mdb_printf("addr/id set properties of specified event ids\n"); 677 } 678 679 void 680 fltbp_help(void) 681 { 682 mdb_printf(_evset_help); 683 mdb_printf("flt fault name (see <sys/fault.h>) or number\n"); 684 } 685 686 void 687 sigbp_help(void) 688 { 689 mdb_printf(_evset_help); 690 mdb_printf("SIG signal name (see signal(3HEAD)) or number\n"); 691 } 692 693 void 694 sysbp_help(void) 695 { 696 mdb_printf(_evset_help); 697 mdb_printf("-i trace system call on entry into kernel (default)\n" 698 "-o trace system call on exit from kernel\n\n" 699 "syscall system call name (see <sys/syscall.h>) or number\n"); 700 } 701 702 void 703 wp_help(void) 704 { 705 mdb_printf(_evset_help); 706 mdb_printf( 707 #ifdef _KMDB 708 "-p treat addr as a physical address\n" 709 "-i treat addr as an I/O port address\n" 710 #endif 711 "-l use size of addr's type for watched region\n" 712 "-L size set size of watched region (default 1)\n" 713 "-r trace read access to watched region\n" 714 "-w trace write access to watched region\n" 715 "-x trace execute access to watched region\n\n" 716 "addr address for base of watched region\n" 717 "repeat size of watched region (equivalent to -L)\n"); 718 } 719