12364 mdb trips assertion related to autowrap
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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Copyright 2017 Joyent, Inc. 28 */ 29 30 /* 31 * Support for ::set dcmd. The +/-o option processing code is provided in a 32 * stand-alone function so it can be used by the command-line option processing 33 * code in mdb_main.c. This facility provides an easy way for us to add more 34 * configurable options without having to add a new dcmd each time. 35 */ 36 37 #include <mdb/mdb_target.h> 38 #include <mdb/mdb_modapi.h> 39 #include <mdb/mdb_string.h> 40 #include <mdb/mdb_debug.h> 41 #include <mdb/mdb.h> 42 43 /*ARGSUSED*/ 44 static int 45 opt_set_mflags(int enable, uint_t bits, const char *arg) 46 { 47 mdb.m_flags = (mdb.m_flags & ~bits) | (bits & -enable); 48 return (1); 49 } 50 51 /*ARGSUSED*/ 52 static int 53 opt_set_tflags(int enable, uint_t bits, const char *arg) 54 { 55 mdb.m_tgtflags = (mdb.m_tgtflags & ~bits) | (bits & -enable); 56 return (1); 57 } 58 59 static int 60 opt_pager(int enable, uint_t bits, const char *arg) 61 { 62 if (enable) 63 mdb_iob_setflags(mdb.m_out, MDB_IOB_PGENABLE); 64 else 65 mdb_iob_clrflags(mdb.m_out, MDB_IOB_PGENABLE); 66 67 return (opt_set_mflags(enable, bits, arg)); 68 } 69 70 static int 71 opt_adb(int enable, uint_t bits, const char *arg) 72 { 73 if (enable) 74 (void) mdb_set_prompt(""); 75 else if (mdb.m_promptlen == 0) 76 (void) mdb_set_prompt("> "); 77 78 (void) opt_pager(1 - enable, MDB_FL_PAGER, arg); 79 return (opt_set_mflags(enable, bits, arg)); 80 } 81 82 /*ARGSUSED*/ 83 static int 84 opt_armemlim(int enable, uint_t bits, const char *arg) 85 { 86 if (strisnum(arg)) { 87 mdb.m_armemlim = strtoi(arg); 88 return (1); 89 } 90 if (strcmp(arg, "none") == 0) { 91 mdb.m_armemlim = MDB_ARR_NOLIMIT; 92 return (1); 93 } 94 return (0); 95 } 96 97 /*ARGSUSED*/ 98 static int 99 opt_arstrlim(int enable, uint_t bits, const char *arg) 100 { 101 if (strisnum(arg)) { 102 mdb.m_arstrlim = strtoi(arg); 103 return (1); 104 } 105 if (strcmp(arg, "none") == 0) { 106 mdb.m_arstrlim = MDB_ARR_NOLIMIT; 107 return (1); 108 } 109 return (0); 110 } 111 112 /*ARGSUSED*/ 113 static int 114 opt_exec_mode(int enable, uint_t bits, const char *arg) 115 { 116 if (strcmp(arg, "ask") == 0) { 117 mdb.m_execmode = MDB_EM_ASK; 118 return (1); 119 } else if (strcmp(arg, "stop") == 0) { 120 mdb.m_execmode = MDB_EM_STOP; 121 return (1); 122 } else if (strcmp(arg, "follow") == 0) { 123 mdb.m_execmode = MDB_EM_FOLLOW; 124 return (1); 125 } 126 return (0); 127 } 128 129 /*ARGSUSED*/ 130 static int 131 opt_fork_mode(int enable, uint_t bits, const char *arg) 132 { 133 if (strcmp(arg, "ask") == 0) { 134 mdb.m_forkmode = MDB_FM_ASK; 135 return (1); 136 } else if (strcmp(arg, "parent") == 0) { 137 mdb.m_forkmode = MDB_FM_PARENT; 138 return (1); 139 } else if (strcmp(arg, "child") == 0) { 140 mdb.m_forkmode = MDB_FM_CHILD; 141 return (1); 142 } 143 return (0); 144 } 145 146 /*ARGSUSED*/ 147 static int 148 opt_set_term(int enable, uint_t bits, const char *arg) 149 { 150 mdb.m_termtype = strdup(arg); 151 mdb.m_flags &= ~MDB_FL_TERMGUESS; 152 153 return (1); 154 } 155 156 int 157 mdb_set_options(const char *s, int enable) 158 { 159 static const struct opdesc { 160 const char *opt_name; 161 int (*opt_func)(int, uint_t, const char *); 162 uint_t opt_bits; 163 } opdtab[] = { 164 { "adb", opt_adb, MDB_FL_REPLAST | MDB_FL_NOMODS | MDB_FL_ADB }, 165 { "array_mem_limit", opt_armemlim, 0 }, 166 { "array_str_limit", opt_arstrlim, 0 }, 167 { "follow_exec_mode", opt_exec_mode, 0 }, 168 { "follow_fork_mode", opt_fork_mode, 0 }, 169 { "pager", opt_pager, MDB_FL_PAGER }, 170 { "term", opt_set_term, 0 }, 171 172 { "autowrap", opt_set_mflags, MDB_FL_AUTOWRAP }, 173 { "ignoreeof", opt_set_mflags, MDB_FL_IGNEOF }, 174 { "repeatlast", opt_set_mflags, MDB_FL_REPLAST }, 175 { "latest", opt_set_mflags, MDB_FL_LATEST }, 176 { "noctf", opt_set_mflags, MDB_FL_NOCTF }, 177 { "nomods", opt_set_mflags, MDB_FL_NOMODS }, 178 { "showlmid", opt_set_mflags, MDB_FL_SHOWLMID }, 179 { "lmraw", opt_set_mflags, MDB_FL_LMRAW }, 180 { "stop_on_bpt_nosym", opt_set_mflags, MDB_FL_BPTNOSYMSTOP }, 181 { "write_readback", opt_set_mflags, MDB_FL_READBACK }, 182 183 { "allow_io_access", opt_set_tflags, MDB_TGT_F_ALLOWIO }, 184 { "nostop", opt_set_tflags, MDB_TGT_F_NOSTOP }, 185 { NULL, NULL, 0 } 186 }; 187 188 const struct opdesc *opp; 189 char *buf = strdup(s); 190 char *opt, *arg; 191 int status = 1; 192 193 for (opt = strtok(buf, ","); opt != NULL; opt = strtok(NULL, ",")) { 194 if ((arg = strchr(opt, '=')) != NULL) 195 *arg++ = '\0'; 196 197 for (opp = opdtab; opp->opt_name != NULL; opp++) { 198 if (strcmp(opt, opp->opt_name) == 0) { 199 if (opp->opt_bits != 0 && arg != NULL) { 200 mdb_warn("option does not accept an " 201 "argument -- %s\n", opt); 202 status = 0; 203 } else if (opp->opt_bits == 0 && arg == NULL) { 204 mdb_warn("option requires an argument " 205 "-- %s\n", opt); 206 status = 0; 207 } else if (opp->opt_func(enable != 0, 208 opp->opt_bits, arg) == 0) { 209 mdb_warn("invalid argument for option " 210 "%s -- %s\n", opt, arg); 211 status = 0; 212 } 213 break; 214 } 215 } 216 217 if (opp->opt_name == NULL) { 218 mdb_warn("invalid debugger option -- %s\n", opt); 219 status = 0; 220 } 221 } 222 223 mdb_free(buf, strlen(s) + 1); 224 return (status); 225 } 226 227 static void 228 print_path(const char **path, int indent) 229 { 230 if (path != NULL && *path != NULL) { 231 for (mdb_printf("%s\n", *path++); *path != NULL; path++) 232 mdb_printf("%*s%s\n", indent, " ", *path); 233 } 234 mdb_printf("\n"); 235 } 236 237 #define LABEL_INDENT 26 238 239 static void 240 print_properties(void) 241 { 242 int tflags = mdb_tgt_getflags(mdb.m_target); 243 uint_t oflags = mdb_iob_getflags(mdb.m_out) & MDB_IOB_AUTOWRAP; 244 245 mdb_iob_clrflags(mdb.m_out, MDB_IOB_AUTOWRAP); 246 mdb_printf("\n macro path: "); 247 print_path(mdb.m_ipath, 14); 248 mdb_printf(" module path: "); 249 print_path(mdb.m_lpath, 14); 250 mdb_iob_setflags(mdb.m_out, oflags); 251 252 mdb_printf("%*s %lr (%s)\n", LABEL_INDENT, "symbol matching distance:", 253 mdb.m_symdist, mdb.m_symdist ? "absolute mode" : "smart mode"); 254 255 mdb_printf("%*s ", LABEL_INDENT, "array member print limit:"); 256 if (mdb.m_armemlim != MDB_ARR_NOLIMIT) 257 mdb_printf("%u\n", mdb.m_armemlim); 258 else 259 mdb_printf("none\n"); 260 261 mdb_printf(" array string print limit: "); 262 if (mdb.m_arstrlim != MDB_ARR_NOLIMIT) 263 mdb_printf("%u\n", mdb.m_arstrlim); 264 else 265 mdb_printf("none\n"); 266 267 mdb_printf("%*s \"%s\"\n", LABEL_INDENT, "command prompt:", 268 mdb.m_prompt); 269 270 mdb_printf("%*s ", LABEL_INDENT, "debugger options:"); 271 (void) mdb_inc_indent(LABEL_INDENT + 1); 272 273 /* 274 * The ::set output implicitly relies on "autowrap" being enabled, so 275 * we enable it for the duration of the command. 276 */ 277 oflags = mdb.m_flags; 278 mdb.m_flags |= MDB_FL_AUTOWRAP; 279 280 mdb_printf("follow_exec_mode="); 281 switch (mdb.m_execmode) { 282 case MDB_EM_ASK: 283 mdb_printf("ask"); 284 break; 285 case MDB_EM_STOP: 286 mdb_printf("stop"); 287 break; 288 case MDB_EM_FOLLOW: 289 mdb_printf("follow"); 290 break; 291 } 292 293 #define COMMAFLAG(name) { mdb_printf(", "); mdb_printf(name); } 294 295 COMMAFLAG("follow_fork_mode"); 296 switch (mdb.m_forkmode) { 297 case MDB_FM_ASK: 298 mdb_printf("ask"); 299 break; 300 case MDB_FM_PARENT: 301 mdb_printf("parent"); 302 break; 303 case MDB_FM_CHILD: 304 mdb_printf("child"); 305 break; 306 } 307 308 if (mdb.m_flags & MDB_FL_ADB) 309 COMMAFLAG("adb"); 310 if (oflags & MDB_FL_AUTOWRAP) 311 COMMAFLAG("autowrap"); 312 if (mdb.m_flags & MDB_FL_IGNEOF) 313 COMMAFLAG("ignoreeof"); 314 if (mdb.m_flags & MDB_FL_LMRAW) 315 COMMAFLAG("lmraw"); 316 if (mdb.m_flags & MDB_FL_PAGER) 317 COMMAFLAG("pager"); 318 if (mdb.m_flags & MDB_FL_REPLAST) 319 COMMAFLAG("repeatlast"); 320 if (mdb.m_flags & MDB_FL_SHOWLMID) 321 COMMAFLAG("showlmid"); 322 if (mdb.m_flags & MDB_FL_BPTNOSYMSTOP) 323 COMMAFLAG("stop_on_bpt_nosym"); 324 if (mdb.m_flags & MDB_FL_READBACK) 325 COMMAFLAG("write_readback"); 326 mdb_printf("\n"); 327 (void) mdb_dec_indent(LABEL_INDENT + 1); 328 329 mdb_printf("%*s ", LABEL_INDENT, "target options:"); 330 (void) mdb_inc_indent(LABEL_INDENT + 1); 331 332 if (tflags & MDB_TGT_F_RDWR) 333 mdb_printf("read-write"); 334 else 335 mdb_printf("read-only"); 336 if (tflags & MDB_TGT_F_ALLOWIO) 337 COMMAFLAG("allow-io-access"); 338 if (tflags & MDB_TGT_F_FORCE) 339 COMMAFLAG("force-attach"); 340 if (tflags & MDB_TGT_F_PRELOAD) 341 COMMAFLAG("preload-syms"); 342 if (tflags & MDB_TGT_F_NOLOAD) 343 COMMAFLAG("no-load-objs"); 344 if (tflags & MDB_TGT_F_NOSTOP) 345 COMMAFLAG("no-stop"); 346 mdb_printf("\n"); 347 (void) mdb_dec_indent(LABEL_INDENT + 1); 348 349 mdb.m_flags = oflags; 350 } 351 352 /*ARGSUSED*/ 353 int 354 cmd_set(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 355 { 356 const char *opt_I = NULL, *opt_L = NULL, *opt_P = NULL, *opt_o = NULL; 357 const char *opt_plus_o = NULL, *opt_D = NULL; 358 uint_t opt_w = FALSE, opt_plus_w = FALSE, opt_W = FALSE; 359 uint_t opt_plus_W = FALSE, opt_F = FALSE; 360 uintptr_t opt_s = (uintptr_t)(long)-1; 361 362 int tflags = 0; 363 int i; 364 365 if (flags & DCMD_ADDRSPEC) 366 return (DCMD_USAGE); 367 368 /* 369 * If no options are specified, print out the current set of target 370 * and debugger properties that can be modified with ::set. 371 */ 372 if (argc == 0) { 373 print_properties(); 374 return (DCMD_OK); 375 } 376 377 while ((i = mdb_getopts(argc, argv, 378 'F', MDB_OPT_SETBITS, TRUE, &opt_F, 379 'I', MDB_OPT_STR, &opt_I, 380 'L', MDB_OPT_STR, &opt_L, 381 'P', MDB_OPT_STR, &opt_P, 382 'o', MDB_OPT_STR, &opt_o, 383 's', MDB_OPT_UINTPTR, &opt_s, 384 'w', MDB_OPT_SETBITS, TRUE, &opt_w, 385 'W', MDB_OPT_SETBITS, TRUE, &opt_W, 386 'D', MDB_OPT_STR, &opt_D, NULL)) != argc) { 387 uint_t n = 1; 388 389 argv += i; /* skip past args we processed */ 390 argc -= i; /* adjust argc */ 391 392 if (argv[0].a_type != MDB_TYPE_STRING) 393 return (DCMD_USAGE); 394 395 if (strcmp(argv->a_un.a_str, "+W") == 0) 396 opt_plus_W = TRUE; 397 else if (strcmp(argv->a_un.a_str, "+w") == 0) 398 opt_plus_w = TRUE; 399 else if (strcmp(argv->a_un.a_str, "+o") == 0 && 400 argc >= 2 && argv[1].a_type == MDB_TYPE_STRING) { 401 opt_plus_o = argv[1].a_un.a_str; 402 n = 2; 403 } else 404 return (DCMD_USAGE); 405 406 /* remove the flag and possible argument */ 407 argv += n; 408 argc -= n; 409 } 410 411 if ((opt_w && opt_plus_w) || (opt_W && opt_plus_W)) 412 return (DCMD_USAGE); 413 414 /* 415 * Handle -w, -/+W and -F first: as these options modify the target, 416 * they are the only ::set changes that can potentially fail. We'll 417 * use these flags to modify a copy of the target's t_flags, which we'll 418 * then pass to the target's setflags op. This allows the target to 419 * detect newly-set and newly-cleared flags by comparing the passed 420 * value to the current t_flags. 421 */ 422 tflags = mdb_tgt_getflags(mdb.m_target); 423 424 if (opt_w) 425 tflags |= MDB_TGT_F_RDWR; 426 if (opt_plus_w) 427 tflags &= ~MDB_TGT_F_RDWR; 428 if (opt_W) 429 tflags |= MDB_TGT_F_ALLOWIO; 430 if (opt_plus_W) 431 tflags &= ~MDB_TGT_F_ALLOWIO; 432 if (opt_F) 433 tflags |= MDB_TGT_F_FORCE; 434 435 if (tflags != mdb_tgt_getflags(mdb.m_target) && 436 mdb_tgt_setflags(mdb.m_target, tflags) == -1) 437 return (DCMD_ERR); 438 439 /* 440 * Now handle everything that either can't fail or we don't care if 441 * it does. Note that we handle +/-o first in case another option 442 * overrides a change made implicity by a +/-o argument (e.g. -P). 443 */ 444 if (opt_o != NULL) 445 (void) mdb_set_options(opt_o, TRUE); 446 if (opt_plus_o != NULL) 447 (void) mdb_set_options(opt_plus_o, FALSE); 448 if (opt_I != NULL) { 449 #ifdef _KMDB 450 mdb_warn("macro path cannot be set under kmdb\n"); 451 #else 452 mdb_set_ipath(opt_I); 453 #endif 454 } 455 if (opt_L != NULL) 456 mdb_set_lpath(opt_L); 457 if (opt_P != NULL) 458 (void) mdb_set_prompt(opt_P); 459 if (opt_s != (uintptr_t)-1) 460 mdb.m_symdist = (size_t)opt_s; 461 if (opt_D != NULL && (i = mdb_dstr2mode(opt_D)) != MDB_DBG_HELP) 462 mdb_dmode((uint_t)i); 463 464 return (DCMD_OK); 465 } --- EOF ---