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