Print this page
2676 'mdb -f vmdump.0' ignores the -f
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Reviewed by: Gary Mills <gary_mills@fastmail.fm>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/mdb/common/mdb/mdb_main.c
+++ new/usr/src/cmd/mdb/common/mdb/mdb_main.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 + * Copyright 2012, Josef 'Jeff' Sipek <jeffpc@31bits.net>. All rights reserved.
24 25 */
25 26
26 27 #include <sys/types.h>
27 28 #include <sys/mman.h>
28 29 #include <sys/priocntl.h>
29 30 #include <sys/rtpriocntl.h>
30 31 #include <sys/resource.h>
31 32 #include <sys/termios.h>
32 33 #include <sys/param.h>
33 34 #include <sys/regset.h>
34 35 #include <sys/frame.h>
35 36 #include <sys/stack.h>
36 37 #include <sys/reg.h>
37 38
38 39 #include <libproc.h>
39 40 #include <libscf.h>
40 41 #include <alloca.h>
41 42 #include <unistd.h>
42 43 #include <string.h>
43 44 #include <stdlib.h>
44 45 #include <fcntl.h>
45 46 #include <dlfcn.h>
46 47 #include <libctf.h>
47 48 #include <errno.h>
48 49 #include <kvm.h>
49 50
50 51 #include <mdb/mdb_lex.h>
51 52 #include <mdb/mdb_debug.h>
52 53 #include <mdb/mdb_signal.h>
53 54 #include <mdb/mdb_string.h>
54 55 #include <mdb/mdb_modapi.h>
55 56 #include <mdb/mdb_target.h>
56 57 #include <mdb/mdb_gelf.h>
57 58 #include <mdb/mdb_conf.h>
58 59 #include <mdb/mdb_err.h>
59 60 #include <mdb/mdb_io_impl.h>
60 61 #include <mdb/mdb_frame.h>
61 62 #include <mdb/mdb_set.h>
62 63 #include <kmdb/kmdb_kctl.h>
63 64 #include <mdb/mdb.h>
64 65
65 66 #ifndef STACK_BIAS
66 67 #define STACK_BIAS 0
67 68 #endif
68 69
69 70 #if defined(__sparc)
70 71 #define STACK_REGISTER SP
71 72 #else
72 73 #define STACK_REGISTER REG_FP
73 74 #endif
74 75
75 76 #ifdef _LP64
76 77 #define MDB_DEF_IPATH \
77 78 "%r/usr/platform/%p/lib/adb/%i:" \
78 79 "%r/usr/platform/%m/lib/adb/%i:" \
79 80 "%r/usr/lib/adb/%i"
80 81 #define MDB_DEF_LPATH \
81 82 "%r/usr/platform/%p/lib/mdb/%t/%i:" \
82 83 "%r/usr/platform/%m/lib/mdb/%t/%i:" \
83 84 "%r/usr/lib/mdb/%t/%i"
84 85 #else
85 86 #define MDB_DEF_IPATH \
86 87 "%r/usr/platform/%p/lib/adb:" \
87 88 "%r/usr/platform/%m/lib/adb:" \
88 89 "%r/usr/lib/adb"
89 90 #define MDB_DEF_LPATH \
90 91 "%r/usr/platform/%p/lib/mdb/%t:" \
91 92 "%r/usr/platform/%m/lib/mdb/%t:" \
92 93 "%r/usr/lib/mdb/%t"
93 94 #endif
94 95
95 96 #define MDB_DEF_PROMPT "> "
96 97
97 98 /*
98 99 * Similar to the panic_* variables in the kernel, we keep some relevant
99 100 * information stored in a set of global _mdb_abort_* variables; in the
100 101 * event that the debugger dumps core, these will aid core dump analysis.
101 102 */
102 103 const char *volatile _mdb_abort_str; /* reason for failure */
103 104 siginfo_t _mdb_abort_info; /* signal info for fatal signal */
104 105 ucontext_t _mdb_abort_ctx; /* context fatal signal interrupted */
105 106 int _mdb_abort_rcount; /* number of times resume requested */
106 107 int _mdb_self_fd = -1; /* fd for self as for valid_frame */
107 108
108 109 static void
109 110 terminate(int status)
110 111 {
111 112 (void) mdb_signal_blockall();
112 113 mdb_destroy();
113 114 exit(status);
114 115 }
115 116
116 117 static void
117 118 print_frame(uintptr_t pc, int fnum)
118 119 {
119 120 Dl_info dli;
120 121
121 122 if (dladdr((void *)pc, &dli)) {
122 123 mdb_iob_printf(mdb.m_err, " [%d] %s`%s+0x%lx()\n", fnum,
123 124 strbasename(dli.dli_fname), dli.dli_sname,
124 125 pc - (uintptr_t)dli.dli_saddr);
125 126 } else
126 127 mdb_iob_printf(mdb.m_err, " [%d] %p()\n", fnum, pc);
127 128 }
128 129
129 130 static int
130 131 valid_frame(struct frame *fr)
131 132 {
132 133 static struct frame fake;
133 134 uintptr_t addr = (uintptr_t)fr;
134 135
135 136 if (pread(_mdb_self_fd, &fake, sizeof (fake), addr) != sizeof (fake)) {
136 137 mdb_iob_printf(mdb.m_err, " invalid frame (%p)\n", fr);
137 138 return (0);
138 139 }
139 140
140 141 if (addr & (STACK_ALIGN - 1)) {
141 142 mdb_iob_printf(mdb.m_err, " mis-aligned frame (%p)\n", fr);
142 143 return (0);
143 144 }
144 145
145 146 return (1);
146 147 }
147 148
148 149 /*ARGSUSED*/
149 150 static void
150 151 flt_handler(int sig, siginfo_t *sip, ucontext_t *ucp, void *data)
151 152 {
152 153 static const struct rlimit rl = {
153 154 (rlim_t)RLIM_INFINITY, (rlim_t)RLIM_INFINITY
154 155 };
155 156
156 157 const mdb_idcmd_t *idcp = NULL;
157 158
158 159 if (mdb.m_frame != NULL && mdb.m_frame->f_cp != NULL)
159 160 idcp = mdb.m_frame->f_cp->c_dcmd;
160 161
161 162 if (sip != NULL)
162 163 bcopy(sip, &_mdb_abort_info, sizeof (_mdb_abort_info));
163 164 if (ucp != NULL)
164 165 bcopy(ucp, &_mdb_abort_ctx, sizeof (_mdb_abort_ctx));
165 166
166 167 _mdb_abort_info.si_signo = sig;
167 168 (void) mdb_signal_sethandler(sig, SIG_DFL, NULL);
168 169
169 170 /*
170 171 * If there is no current dcmd, or the current dcmd comes from a
171 172 * builtin module, we don't allow resume and always core dump.
172 173 */
173 174 if (idcp == NULL || idcp->idc_modp == NULL ||
174 175 idcp->idc_modp == &mdb.m_rmod || idcp->idc_modp->mod_hdl == NULL)
175 176 goto dump;
176 177
177 178 if (mdb.m_term != NULL) {
178 179 struct frame *fr = (struct frame *)
179 180 (ucp->uc_mcontext.gregs[STACK_REGISTER] + STACK_BIAS);
180 181
181 182 char signame[SIG2STR_MAX];
182 183 int i = 1;
183 184 char c;
184 185
185 186 if (sig2str(sig, signame) == -1) {
186 187 mdb_iob_printf(mdb.m_err,
187 188 "\n*** %s: received signal %d at:\n",
188 189 mdb.m_pname, sig);
189 190 } else {
190 191 mdb_iob_printf(mdb.m_err,
191 192 "\n*** %s: received signal %s at:\n",
192 193 mdb.m_pname, signame);
193 194 }
194 195
195 196 if (ucp->uc_mcontext.gregs[REG_PC] != 0)
196 197 print_frame(ucp->uc_mcontext.gregs[REG_PC], i++);
197 198
198 199 while (fr != NULL && valid_frame(fr) && fr->fr_savpc != 0) {
199 200 print_frame(fr->fr_savpc, i++);
200 201 fr = (struct frame *)
201 202 ((uintptr_t)fr->fr_savfp + STACK_BIAS);
202 203 }
203 204
204 205 query:
205 206 mdb_iob_printf(mdb.m_err, "\n%s: (c)ore dump, (q)uit, "
206 207 "(r)ecover, or (s)top for debugger [cqrs]? ", mdb.m_pname);
207 208
208 209 mdb_iob_flush(mdb.m_err);
209 210
210 211 for (;;) {
211 212 if (IOP_READ(mdb.m_term, &c, sizeof (c)) != sizeof (c))
212 213 goto dump;
213 214
214 215 switch (c) {
215 216 case 'c':
216 217 case 'C':
217 218 (void) setrlimit(RLIMIT_CORE, &rl);
218 219 mdb_iob_printf(mdb.m_err, "\n%s: attempting "
219 220 "to dump core ...\n", mdb.m_pname);
220 221 goto dump;
221 222
222 223 case 'q':
223 224 case 'Q':
224 225 mdb_iob_discard(mdb.m_out);
225 226 mdb_iob_nl(mdb.m_err);
226 227 (void) mdb_signal_unblockall();
227 228 terminate(1);
228 229 /*NOTREACHED*/
229 230
230 231 case 'r':
231 232 case 'R':
232 233 mdb_iob_printf(mdb.m_err, "\n%s: unloading "
233 234 "module '%s' ...\n", mdb.m_pname,
234 235 idcp->idc_modp->mod_name);
235 236
236 237 (void) mdb_module_unload(
237 238 idcp->idc_modp->mod_name, 0);
238 239
239 240 (void) mdb_signal_sethandler(sig,
240 241 flt_handler, NULL);
241 242
242 243 _mdb_abort_rcount++;
243 244 mdb.m_intr = 0;
244 245 mdb.m_pend = 0;
245 246
246 247 (void) mdb_signal_unblockall();
247 248 longjmp(mdb.m_frame->f_pcb, MDB_ERR_ABORT);
248 249 /*NOTREACHED*/
249 250
250 251 case 's':
251 252 case 'S':
252 253 mdb_iob_printf(mdb.m_err, "\n%s: "
253 254 "attempting to stop pid %d ...\n",
254 255 mdb.m_pname, (int)getpid());
255 256
256 257 /*
257 258 * Stop ourself; if this fails or we are
258 259 * subsequently continued, ask again.
259 260 */
260 261 (void) mdb_signal_raise(SIGSTOP);
261 262 (void) mdb_signal_unblockall();
262 263 goto query;
263 264 }
264 265 }
265 266 }
266 267
267 268 dump:
268 269 if (SI_FROMUSER(sip)) {
269 270 (void) mdb_signal_block(sig);
270 271 (void) mdb_signal_raise(sig);
271 272 }
272 273
273 274 (void) sigfillset(&ucp->uc_sigmask);
274 275 (void) sigdelset(&ucp->uc_sigmask, sig);
275 276
276 277 if (_mdb_abort_str == NULL)
277 278 _mdb_abort_str = "fatal signal received";
278 279
279 280 ucp->uc_flags |= UC_SIGMASK;
280 281 (void) setcontext(ucp);
281 282 }
282 283
283 284 /*ARGSUSED*/
284 285 static void
285 286 int_handler(int sig, siginfo_t *sip, ucontext_t *ucp, void *data)
286 287 {
287 288 if (mdb.m_intr == 0)
288 289 longjmp(mdb.m_frame->f_pcb, MDB_ERR_SIGINT);
289 290 else
290 291 mdb.m_pend++;
291 292 }
292 293
293 294 static void
294 295 control_kmdb(int start)
295 296 {
296 297 int fd;
297 298
298 299 if ((fd = open("/dev/kmdb", O_RDONLY)) < 0)
299 300 die("failed to open /dev/kmdb");
300 301
301 302 if (start) {
302 303 char *state = mdb_get_config();
303 304
304 305 if (ioctl(fd, KMDB_IOC_START, state) < 0)
305 306 die("failed to start kmdb");
306 307
307 308 strfree(state);
308 309 } else {
309 310 if (ioctl(fd, KMDB_IOC_STOP) < 0)
310 311 die("failed to stop kmdb");
311 312 }
312 313
313 314 (void) close(fd);
314 315 }
315 316
316 317 static void
317 318 usage(int status)
318 319 {
319 320 mdb_iob_printf(mdb.m_err, "Usage: %s [-fkmuwyAFKMSUW] [+/-o option] "
320 321 "[-p pid] [-s dist] [-I path] [-L path]\n\t[-P prompt] "
321 322 "[-R root] [-V dis-version] [object [core] | core | suffix]\n\n",
322 323 mdb.m_pname);
323 324
324 325 mdb_iob_puts(mdb.m_err,
325 326 "\t-f force raw file debugging mode\n"
326 327 "\t-k force kernel debugging mode\n"
327 328 "\t-m disable demand-loading of module symbols\n"
328 329 "\t-o set specified debugger option (+o to unset)\n"
329 330 "\t-p attach to specified process-id\n"
330 331 "\t-s set symbol matching distance\n"
331 332 "\t-u force user program debugging mode\n"
332 333 "\t-w enable write mode\n"
333 334 "\t-y send terminal initialization sequences for tty mode\n"
334 335 "\t-A disable automatic loading of mdb modules\n"
335 336 "\t-F enable forcible takeover mode\n"
336 337 "\t-K stop operating system and enter live kernel debugger\n"
337 338 "\t-M preload all module symbols\n"
338 339 "\t-I set initial path for macro files\n"
339 340 "\t-L set initial path for module libs\n"
340 341 "\t-P set command-line prompt\n"
341 342 "\t-R set root directory for pathname expansion\n"
342 343 "\t-S suppress processing of ~/.mdbrc file\n"
343 344 "\t-U unload live kernel debugger\n"
344 345 "\t-W enable I/O-mapped memory access (kernel only)\n"
345 346 "\t-V set disassembler version\n");
346 347
347 348 terminate(status);
348 349 }
349 350
350 351 static char *
351 352 mdb_scf_console_term(void)
352 353 {
353 354 scf_simple_prop_t *prop;
354 355 char *term = NULL;
355 356
356 357 if ((prop = scf_simple_prop_get(NULL,
357 358 "svc:/system/console-login:default", "ttymon",
358 359 "terminal_type")) == NULL)
359 360 return (NULL);
360 361
361 362 if (scf_simple_prop_type(prop) == SCF_TYPE_ASTRING &&
362 363 (term = scf_simple_prop_next_astring(prop)) != NULL)
363 364 term = strdup(term);
364 365
365 366 scf_simple_prop_free(prop);
366 367 return (term);
367 368 }
368 369
369 370 /*
370 371 * Unpleasant hack: we might be debugging a hypervisor domain dump.
371 372 * Earlier versions use a non-ELF file. Later versions are ELF, but are
372 373 * /always/ ELF64, so our standard ehdr check isn't good enough. Since
373 374 * we don't want to know too much about the file format, we'll ask
374 375 * mdb_kb.
375 376 */
376 377 #ifdef __x86
377 378 static int
378 379 identify_xvm_file(const char *file, int *longmode)
379 380 {
380 381 int (*identify)(const char *, int *);
381 382
382 383 if (mdb_module_load("mdb_kb", MDB_MOD_GLOBAL | MDB_MOD_SILENT) != 0)
383 384 return (0);
384 385
385 386 identify = (int (*)())dlsym(RTLD_NEXT, "xkb_identify");
386 387
387 388 if (identify == NULL)
388 389 return (0);
389 390
390 391 return (identify(file, longmode));
391 392 }
392 393 #else
393 394 /*ARGSUSED*/
394 395 static int
395 396 identify_xvm_file(const char *file, int *longmode)
396 397 {
397 398 return (0);
398 399 }
399 400 #endif /* __x86 */
400 401
401 402 int
402 403 main(int argc, char *argv[], char *envp[])
403 404 {
404 405 extern int mdb_kvm_is_compressed_dump(mdb_io_t *);
405 406 mdb_tgt_ctor_f *tgt_ctor = NULL;
406 407 const char **tgt_argv = alloca(argc * sizeof (char *));
407 408 int tgt_argc = 0;
408 409 mdb_tgt_t *tgt;
409 410
410 411 char object[MAXPATHLEN], execname[MAXPATHLEN];
411 412 mdb_io_t *in_io, *out_io, *err_io, *null_io;
412 413 struct termios tios;
413 414 int status, c;
414 415 char *p;
415 416
416 417 const char *Iflag = NULL, *Lflag = NULL, *Vflag = NULL, *pidarg = NULL;
417 418 int fflag = 0, Kflag = 0, Rflag = 0, Sflag = 0, Oflag = 0, Uflag = 0;
418 419
419 420 int ttylike;
420 421 int longmode = 0;
421 422
422 423 stack_t sigstack;
423 424
424 425 if (realpath(getexecname(), execname) == NULL) {
425 426 (void) strncpy(execname, argv[0], MAXPATHLEN);
426 427 execname[MAXPATHLEN - 1] = '\0';
427 428 }
428 429
429 430 mdb_create(execname, argv[0]);
430 431 bzero(tgt_argv, argc * sizeof (char *));
431 432 argv[0] = (char *)mdb.m_pname;
432 433 _mdb_self_fd = open("/proc/self/as", O_RDONLY);
433 434
434 435 mdb.m_env = envp;
435 436
436 437 out_io = mdb_fdio_create(STDOUT_FILENO);
437 438 mdb.m_out = mdb_iob_create(out_io, MDB_IOB_WRONLY);
438 439
439 440 err_io = mdb_fdio_create(STDERR_FILENO);
440 441 mdb.m_err = mdb_iob_create(err_io, MDB_IOB_WRONLY);
441 442 mdb_iob_clrflags(mdb.m_err, MDB_IOB_AUTOWRAP);
442 443
443 444 null_io = mdb_nullio_create();
444 445 mdb.m_null = mdb_iob_create(null_io, MDB_IOB_WRONLY);
445 446
446 447 in_io = mdb_fdio_create(STDIN_FILENO);
447 448 if ((mdb.m_termtype = getenv("TERM")) != NULL) {
448 449 mdb.m_termtype = strdup(mdb.m_termtype);
449 450 mdb.m_flags |= MDB_FL_TERMGUESS;
450 451 }
451 452 mdb.m_term = NULL;
452 453
453 454 mdb_dmode(mdb_dstr2mode(getenv("MDB_DEBUG")));
454 455 mdb.m_pgid = getpgrp();
455 456
456 457 if (getenv("_MDB_EXEC") != NULL)
457 458 mdb.m_flags |= MDB_FL_EXEC;
458 459
459 460 /*
460 461 * Setup an alternate signal stack. When tearing down pipelines in
461 462 * terminate(), we may have to destroy the stack of the context in
462 463 * which we are currently executing the signal handler.
463 464 */
464 465 sigstack.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
465 466 MAP_PRIVATE | MAP_ANON, -1, 0);
466 467 if (sigstack.ss_sp == MAP_FAILED)
467 468 die("could not allocate signal stack");
468 469 sigstack.ss_size = SIGSTKSZ;
469 470 sigstack.ss_flags = 0;
470 471 if (sigaltstack(&sigstack, NULL) != 0)
471 472 die("could not set signal stack");
472 473
473 474 (void) mdb_signal_sethandler(SIGPIPE, SIG_IGN, NULL);
474 475 (void) mdb_signal_sethandler(SIGQUIT, SIG_IGN, NULL);
475 476
476 477 (void) mdb_signal_sethandler(SIGILL, flt_handler, NULL);
477 478 (void) mdb_signal_sethandler(SIGTRAP, flt_handler, NULL);
478 479 (void) mdb_signal_sethandler(SIGIOT, flt_handler, NULL);
479 480 (void) mdb_signal_sethandler(SIGEMT, flt_handler, NULL);
480 481 (void) mdb_signal_sethandler(SIGFPE, flt_handler, NULL);
481 482 (void) mdb_signal_sethandler(SIGBUS, flt_handler, NULL);
482 483 (void) mdb_signal_sethandler(SIGSEGV, flt_handler, NULL);
483 484
484 485 (void) mdb_signal_sethandler(SIGHUP, (mdb_signal_f *)terminate, NULL);
485 486 (void) mdb_signal_sethandler(SIGTERM, (mdb_signal_f *)terminate, NULL);
486 487
487 488 for (mdb.m_rdvers = RD_VERSION; mdb.m_rdvers > 0; mdb.m_rdvers--) {
488 489 if (rd_init(mdb.m_rdvers) == RD_OK)
489 490 break;
490 491 }
491 492
492 493 for (mdb.m_ctfvers = CTF_VERSION; mdb.m_ctfvers > 0; mdb.m_ctfvers--) {
493 494 if (ctf_version(mdb.m_ctfvers) != -1)
494 495 break;
495 496 }
496 497
497 498 if ((p = getenv("HISTSIZE")) != NULL && strisnum(p)) {
498 499 mdb.m_histlen = strtoi(p);
499 500 if (mdb.m_histlen < 1)
500 501 mdb.m_histlen = 1;
501 502 }
502 503
503 504 while (optind < argc) {
504 505 while ((c = getopt(argc, argv,
505 506 "fkmo:p:s:uwyACD:FI:KL:MOP:R:SUV:W")) != (int)EOF) {
506 507 switch (c) {
507 508 case 'f':
508 509 fflag++;
509 510 tgt_ctor = mdb_rawfile_tgt_create;
510 511 break;
511 512 case 'k':
512 513 tgt_ctor = mdb_kvm_tgt_create;
513 514 break;
514 515 case 'm':
515 516 mdb.m_tgtflags |= MDB_TGT_F_NOLOAD;
516 517 mdb.m_tgtflags &= ~MDB_TGT_F_PRELOAD;
517 518 break;
518 519 case 'o':
519 520 if (!mdb_set_options(optarg, TRUE))
520 521 terminate(2);
521 522 break;
522 523 case 'p':
523 524 tgt_ctor = mdb_proc_tgt_create;
524 525 pidarg = optarg;
525 526 break;
526 527 case 's':
527 528 if (!strisnum(optarg)) {
528 529 warn("expected integer following -s\n");
529 530 terminate(2);
530 531 }
531 532 mdb.m_symdist = (size_t)(uint_t)strtoi(optarg);
532 533 break;
533 534 case 'u':
534 535 tgt_ctor = mdb_proc_tgt_create;
535 536 break;
536 537 case 'w':
537 538 mdb.m_tgtflags |= MDB_TGT_F_RDWR;
538 539 break;
539 540 case 'y':
540 541 mdb.m_flags |= MDB_FL_USECUP;
541 542 break;
542 543 case 'A':
543 544 (void) mdb_set_options("nomods", TRUE);
544 545 break;
545 546 case 'C':
546 547 (void) mdb_set_options("noctf", TRUE);
547 548 break;
548 549 case 'D':
549 550 mdb_dmode(mdb_dstr2mode(optarg));
550 551 break;
551 552 case 'F':
552 553 mdb.m_tgtflags |= MDB_TGT_F_FORCE;
553 554 break;
554 555 case 'I':
555 556 Iflag = optarg;
556 557 break;
557 558 case 'L':
558 559 Lflag = optarg;
559 560 break;
560 561 case 'K':
561 562 Kflag++;
562 563 break;
563 564 case 'M':
564 565 mdb.m_tgtflags |= MDB_TGT_F_PRELOAD;
565 566 mdb.m_tgtflags &= ~MDB_TGT_F_NOLOAD;
566 567 break;
567 568 case 'O':
568 569 Oflag++;
569 570 break;
570 571 case 'P':
571 572 if (!mdb_set_prompt(optarg))
572 573 terminate(2);
573 574 break;
574 575 case 'R':
575 576 (void) strncpy(mdb.m_root, optarg, MAXPATHLEN);
576 577 mdb.m_root[MAXPATHLEN - 1] = '\0';
577 578 Rflag++;
578 579 break;
579 580 case 'S':
580 581 Sflag++;
581 582 break;
582 583 case 'U':
583 584 Uflag++;
584 585 break;
585 586 case 'V':
586 587 Vflag = optarg;
587 588 break;
588 589 case 'W':
589 590 mdb.m_tgtflags |= MDB_TGT_F_ALLOWIO;
590 591 break;
591 592 case '?':
592 593 if (optopt == '?')
593 594 usage(0);
594 595 /* FALLTHROUGH */
595 596 default:
596 597 usage(2);
597 598 }
598 599 }
599 600
600 601 if (optind < argc) {
601 602 const char *arg = argv[optind++];
602 603
603 604 if (arg[0] == '+' && strlen(arg) == 2) {
604 605 if (arg[1] != 'o') {
605 606 warn("illegal option -- %s\n", arg);
606 607 terminate(2);
607 608 }
608 609 if (optind >= argc) {
609 610 warn("option requires an argument -- "
610 611 "%s\n", arg);
611 612 terminate(2);
612 613 }
613 614 if (!mdb_set_options(argv[optind++], FALSE))
614 615 terminate(2);
615 616 } else
616 617 tgt_argv[tgt_argc++] = arg;
617 618 }
618 619 }
619 620
620 621 if (rd_ctl(RD_CTL_SET_HELPPATH, (void *)mdb.m_root) != RD_OK) {
621 622 warn("cannot set librtld_db helper path to %s\n", mdb.m_root);
622 623 terminate(2);
623 624 }
624 625
625 626 if (mdb.m_debug & MDB_DBG_HELP)
626 627 terminate(0); /* Quit here if we've printed out the tokens */
627 628
628 629
629 630 if (Iflag != NULL && strchr(Iflag, ';') != NULL) {
630 631 warn("macro path cannot contain semicolons\n");
631 632 terminate(2);
632 633 }
633 634
634 635 if (Lflag != NULL && strchr(Lflag, ';') != NULL) {
635 636 warn("module path cannot contain semicolons\n");
636 637 terminate(2);
637 638 }
638 639
639 640 if (Kflag || Uflag) {
640 641 char *nm;
641 642
642 643 if (tgt_ctor != NULL || Iflag != NULL) {
643 644 warn("neither -f, -k, -p, -u, nor -I "
644 645 "may be used with -K\n");
645 646 usage(2);
646 647 }
647 648
648 649 if (Lflag != NULL)
649 650 mdb_set_lpath(Lflag);
650 651
651 652 if ((nm = ttyname(STDIN_FILENO)) == NULL ||
652 653 strcmp(nm, "/dev/console") != 0) {
653 654 /*
654 655 * Due to the consequences of typing mdb -K instead of
655 656 * mdb -k on a tty other than /dev/console, we require
656 657 * -F when starting kmdb from a tty other than
657 658 * /dev/console.
658 659 */
659 660 if (!(mdb.m_tgtflags & MDB_TGT_F_FORCE)) {
660 661 die("-F must also be supplied to start kmdb "
661 662 "from non-console tty\n");
662 663 }
663 664
664 665 if (mdb.m_termtype == NULL || (mdb.m_flags &
665 666 MDB_FL_TERMGUESS)) {
666 667 if (mdb.m_termtype != NULL)
667 668 strfree(mdb.m_termtype);
668 669
669 670 if ((mdb.m_termtype = mdb_scf_console_term()) !=
670 671 NULL)
671 672 mdb.m_flags |= MDB_FL_TERMGUESS;
672 673 }
673 674 } else {
674 675 /*
675 676 * When on console, $TERM (if set) takes precedence over
676 677 * the SMF setting.
677 678 */
678 679 if (mdb.m_termtype == NULL && (mdb.m_termtype =
679 680 mdb_scf_console_term()) != NULL)
680 681 mdb.m_flags |= MDB_FL_TERMGUESS;
681 682 }
682 683
683 684 control_kmdb(Kflag);
684 685 terminate(0);
685 686 /*NOTREACHED*/
686 687 }
687 688
688 689 /*
689 690 * If standard input appears to have tty attributes, attempt to
690 691 * initialize a terminal i/o backend on top of stdin and stdout.
691 692 */
692 693 ttylike = (IOP_CTL(in_io, TCGETS, &tios) == 0);
693 694 if (ttylike) {
694 695 if ((mdb.m_term = mdb_termio_create(mdb.m_termtype,
695 696 in_io, out_io)) == NULL) {
696 697 if (!(mdb.m_flags & MDB_FL_EXEC)) {
697 698 warn("term init failed: command-line editing "
698 699 "and prompt will not be available\n");
699 700 }
700 701 } else {
701 702 in_io = mdb.m_term;
702 703 }
703 704 }
704 705
705 706 mdb.m_in = mdb_iob_create(in_io, MDB_IOB_RDONLY);
706 707 if (mdb.m_term != NULL) {
707 708 mdb_iob_setpager(mdb.m_out, mdb.m_term);
708 709 if (mdb.m_flags & MDB_FL_PAGER)
709 710 mdb_iob_setflags(mdb.m_out, MDB_IOB_PGENABLE);
710 711 else
711 712 mdb_iob_clrflags(mdb.m_out, MDB_IOB_PGENABLE);
712 713 } else if (ttylike)
713 714 mdb_iob_setflags(mdb.m_in, MDB_IOB_TTYLIKE);
714 715 else
715 716 mdb_iob_setbuf(mdb.m_in, mdb_alloc(1, UM_SLEEP), 1);
716 717
717 718 mdb_pservice_init();
718 719 mdb_lex_reset();
719 720
720 721 if ((mdb.m_shell = getenv("SHELL")) == NULL)
721 722 mdb.m_shell = "/bin/sh";
722 723
723 724 /*
724 725 * If the debugger state is to be inherited from a previous instance,
725 726 * restore it now prior to path evaluation so that %R is updated.
726 727 */
727 728 if ((p = getenv(MDB_CONFIG_ENV_VAR)) != NULL) {
728 729 mdb_set_config(p);
729 730 (void) unsetenv(MDB_CONFIG_ENV_VAR);
730 731 }
731 732
732 733 /*
733 734 * Path evaluation part 1: Create the initial module path to allow
734 735 * the target constructor to load a support module. Then expand
735 736 * any command-line arguments that modify the paths.
736 737 */
737 738 if (Iflag != NULL)
738 739 mdb_set_ipath(Iflag);
739 740 else
740 741 mdb_set_ipath(MDB_DEF_IPATH);
741 742
742 743 if (Lflag != NULL)
743 744 mdb_set_lpath(Lflag);
744 745 else
745 746 mdb_set_lpath(MDB_DEF_LPATH);
746 747
747 748 if (mdb_get_prompt() == NULL && !(mdb.m_flags & MDB_FL_ADB))
748 749 (void) mdb_set_prompt(MDB_DEF_PROMPT);
749 750
750 751 if (tgt_ctor == mdb_kvm_tgt_create) {
751 752 if (pidarg != NULL) {
752 753 warn("-p and -k options are mutually exclusive\n");
753 754 terminate(2);
754 755 }
755 756
756 757 if (tgt_argc == 0)
757 758 tgt_argv[tgt_argc++] = "/dev/ksyms";
758 759 if (tgt_argc == 1 && strisnum(tgt_argv[0]) == 0) {
759 760 if (mdb.m_tgtflags & MDB_TGT_F_ALLOWIO)
760 761 tgt_argv[tgt_argc++] = "/dev/allkmem";
761 762 else
762 763 tgt_argv[tgt_argc++] = "/dev/kmem";
763 764 }
764 765 }
765 766
766 767 if (pidarg != NULL) {
767 768 if (tgt_argc != 0) {
768 769 warn("-p may not be used with other arguments\n");
769 770 terminate(2);
770 771 }
771 772 if (proc_arg_psinfo(pidarg, PR_ARG_PIDS, NULL, &status) == -1) {
772 773 die("cannot attach to %s: %s\n",
773 774 pidarg, Pgrab_error(status));
774 775 }
775 776 if (strchr(pidarg, '/') != NULL)
776 777 (void) mdb_iob_snprintf(object, MAXPATHLEN,
777 778 "%s/object/a.out", pidarg);
778 779 else
779 780 (void) mdb_iob_snprintf(object, MAXPATHLEN,
780 781 "/proc/%s/object/a.out", pidarg);
781 782 tgt_argv[tgt_argc++] = object;
782 783 tgt_argv[tgt_argc++] = pidarg;
783 784 }
784 785
785 786 /*
786 787 * Find the first argument that is not a special "-" token. If one is
787 788 * found, we will examine this file and make some inferences below.
788 789 */
789 790 for (c = 0; c < tgt_argc && strcmp(tgt_argv[c], "-") == 0; c++)
790 791 continue;
791 792
792 793 if (c < tgt_argc) {
793 794 Elf32_Ehdr ehdr;
794 795 mdb_io_t *io;
795 796
↓ open down ↓ |
762 lines elided |
↑ open up ↑ |
796 797 /*
797 798 * If special "-" tokens preceded an argument, shift the entire
798 799 * argument list to the left to remove the leading "-" args.
799 800 */
800 801 if (c > 0) {
801 802 bcopy(&tgt_argv[c], tgt_argv,
802 803 sizeof (const char *) * (tgt_argc - c));
803 804 tgt_argc -= c;
804 805 }
805 806
807 + if (fflag)
808 + goto tcreate; /* skip re-exec and just create target */
809 +
806 810 /*
807 811 * If we just have an object file name, and that file doesn't
808 812 * exist, and it's a string of digits, infer it to be a
809 813 * sequence number referring to a pair of crash dump files.
810 814 */
811 815 if (tgt_argc == 1 && access(tgt_argv[0], F_OK) == -1 &&
812 816 strisnum(tgt_argv[0])) {
813 817
814 818 size_t len = strlen(tgt_argv[0]) + 8;
815 819 const char *object = tgt_argv[0];
816 820
817 821 tgt_argv[0] = mdb_alloc(len, UM_SLEEP);
818 822 tgt_argv[1] = mdb_alloc(len, UM_SLEEP);
819 823
820 824 (void) strcpy((char *)tgt_argv[0], "unix.");
821 825 (void) strcat((char *)tgt_argv[0], object);
822 826 (void) strcpy((char *)tgt_argv[1], "vmcore.");
823 827 (void) strcat((char *)tgt_argv[1], object);
824 828
825 829 if (access(tgt_argv[0], F_OK) == -1 &&
826 830 access(tgt_argv[1], F_OK) == -1) {
827 831 (void) strcpy((char *)tgt_argv[1], "vmdump.");
828 832 (void) strcat((char *)tgt_argv[1], object);
829 833 if (access(tgt_argv[1], F_OK) == 0) {
830 834 mdb_iob_printf(mdb.m_err,
831 835 "cannot open compressed dump; "
832 836 "decompress using savecore -f %s\n",
833 837 tgt_argv[1]);
834 838 terminate(0);
835 839 }
836 840 }
837 841
838 842 tgt_argc = 2;
839 843 }
840 844
841 845 /*
842 846 * We need to open the object file in order to determine its
843 847 * ELF class and potentially re-exec ourself.
844 848 */
845 849 if ((io = mdb_fdio_create_path(NULL, tgt_argv[0],
846 850 O_RDONLY, 0)) == NULL)
847 851 die("failed to open %s", tgt_argv[0]);
848 852
849 853 /*
850 854 * Check for a single vmdump.N compressed dump file,
851 855 * and give a helpful message.
852 856 */
853 857 if (tgt_argc == 1) {
854 858 if (mdb_kvm_is_compressed_dump(io)) {
855 859 mdb_iob_printf(mdb.m_err,
856 860 "cannot open compressed dump; "
857 861 "decompress using savecore -f %s\n",
858 862 tgt_argv[0]);
↓ open down ↓ |
43 lines elided |
↑ open up ↑ |
859 863 terminate(0);
860 864 }
861 865 }
862 866
863 867 /*
864 868 * If the target is unknown or is not the rawfile target, do
865 869 * a gelf_check to determine if the file is an ELF file. If
866 870 * it is not and the target is unknown, use the rawfile tgt.
867 871 * Otherwise an ELF-based target is needed, so we must abort.
868 872 */
869 - if (tgt_ctor != mdb_rawfile_tgt_create &&
870 - mdb_gelf_check(io, &ehdr, ET_NONE) == -1) {
873 + if (mdb_gelf_check(io, &ehdr, ET_NONE) == -1) {
871 874 if (tgt_ctor != NULL) {
872 875 (void) mdb_gelf_check(io, &ehdr, ET_EXEC);
873 876 mdb_io_destroy(io);
874 877 terminate(1);
875 878 } else
876 879 tgt_ctor = mdb_rawfile_tgt_create;
877 880 }
878 881
879 882 mdb_io_destroy(io);
880 883
881 - if (identify_xvm_file(tgt_argv[0], &longmode) == 1 &&
882 - !fflag) {
884 + if (identify_xvm_file(tgt_argv[0], &longmode) == 1) {
883 885 #ifdef _LP64
884 886 if (!longmode)
885 887 goto reexec;
886 888 #else
887 889 if (longmode)
888 890 goto reexec;
889 891 #endif
890 892 tgt_ctor = mdb_kvm_tgt_create;
891 893 goto tcreate;
892 894 }
893 895
894 - if (tgt_ctor == mdb_rawfile_tgt_create)
895 - goto tcreate; /* skip re-exec and just create target */
896 -
897 896 /*
898 897 * The object file turned out to be a user core file (ET_CORE),
899 898 * and no other arguments were specified, swap 0 and 1. The
900 899 * proc target will infer the executable for us.
901 900 */
902 901 if (ehdr.e_type == ET_CORE) {
903 902 tgt_argv[tgt_argc++] = tgt_argv[0];
904 903 tgt_argv[0] = NULL;
905 904 tgt_ctor = mdb_proc_tgt_create;
906 905 }
907 906
908 907 /*
909 908 * If tgt_argv[1] is filled in, open it up and determine if it
910 909 * is a vmcore file. If it is, gelf_check will fail and we
911 910 * set tgt_ctor to 'kvm'; otherwise we use the default.
912 911 */
913 912 if (tgt_argc > 1 && strcmp(tgt_argv[1], "-") != 0 &&
914 913 tgt_argv[0] != NULL && pidarg == NULL) {
915 914 Elf32_Ehdr chdr;
916 915
917 916 if (access(tgt_argv[1], F_OK) == -1)
918 917 die("failed to access %s", tgt_argv[1]);
919 918
920 919 /* *.N case: drop vmdump.N from the list */
921 920 if (tgt_argc == 3) {
922 921 if ((io = mdb_fdio_create_path(NULL,
923 922 tgt_argv[2], O_RDONLY, 0)) == NULL)
924 923 die("failed to open %s", tgt_argv[2]);
925 924 if (mdb_kvm_is_compressed_dump(io))
926 925 tgt_argv[--tgt_argc] = NULL;
927 926 mdb_io_destroy(io);
928 927 }
929 928
930 929 if ((io = mdb_fdio_create_path(NULL, tgt_argv[1],
931 930 O_RDONLY, 0)) == NULL)
932 931 die("failed to open %s", tgt_argv[1]);
933 932
934 933 if (mdb_gelf_check(io, &chdr, ET_NONE) == -1)
935 934 tgt_ctor = mdb_kvm_tgt_create;
936 935
937 936 mdb_io_destroy(io);
938 937 }
939 938
940 939 /*
941 940 * At this point, we've read the ELF header for either an
942 941 * object file or core into ehdr. If the class does not match
943 942 * ours, attempt to exec the mdb of the appropriate class.
944 943 */
945 944 #ifdef _LP64
946 945 if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
947 946 goto reexec;
948 947 #else
949 948 if (ehdr.e_ident[EI_CLASS] == ELFCLASS64)
950 949 goto reexec;
951 950 #endif
952 951 }
953 952
954 953 tcreate:
955 954 if (tgt_ctor == NULL)
956 955 tgt_ctor = mdb_proc_tgt_create;
957 956
958 957 tgt = mdb_tgt_create(tgt_ctor, mdb.m_tgtflags, tgt_argc, tgt_argv);
959 958
960 959 if (tgt == NULL) {
961 960 if (errno == EINVAL)
962 961 usage(2); /* target can return EINVAL to get usage */
963 962 if (errno == EMDB_TGT)
964 963 terminate(1); /* target already printed error msg */
965 964 die("failed to initialize target");
966 965 }
967 966
968 967 mdb_tgt_activate(tgt);
969 968
970 969 mdb_create_loadable_disasms();
971 970
972 971 if (Vflag != NULL && mdb_dis_select(Vflag) == -1)
973 972 warn("invalid disassembler mode -- %s\n", Vflag);
974 973
975 974
976 975 if (Rflag && mdb.m_term != NULL)
977 976 warn("Using proto area %s\n", mdb.m_root);
978 977
979 978 /*
980 979 * If the target was successfully constructed and -O was specified,
981 980 * we now attempt to enter piggy-mode for debugging jurassic problems.
982 981 */
983 982 if (Oflag) {
984 983 pcinfo_t pci;
985 984
986 985 (void) strcpy(pci.pc_clname, "RT");
987 986
988 987 if (priocntl(P_LWPID, P_MYID, PC_GETCID, (caddr_t)&pci) != -1) {
989 988 pcparms_t pcp;
990 989 rtparms_t *rtp = (rtparms_t *)pcp.pc_clparms;
991 990
992 991 rtp->rt_pri = 35;
993 992 rtp->rt_tqsecs = 0;
994 993 rtp->rt_tqnsecs = RT_TQDEF;
995 994
996 995 pcp.pc_cid = pci.pc_cid;
997 996
998 997 if (priocntl(P_LWPID, P_MYID, PC_SETPARMS,
999 998 (caddr_t)&pcp) == -1) {
1000 999 warn("failed to set RT parameters");
1001 1000 Oflag = 0;
1002 1001 }
1003 1002 } else {
1004 1003 warn("failed to get RT class id");
1005 1004 Oflag = 0;
1006 1005 }
1007 1006
1008 1007 if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
1009 1008 warn("failed to lock address space");
1010 1009 Oflag = 0;
1011 1010 }
1012 1011
1013 1012 if (Oflag)
1014 1013 mdb_printf("%s: oink, oink!\n", mdb.m_pname);
1015 1014 }
1016 1015
1017 1016 /*
1018 1017 * Path evaluation part 2: Re-evaluate the path now that the target
1019 1018 * is ready (and thus we have access to the real platform string).
1020 1019 * Do this before reading ~/.mdbrc to allow path modifications prior
1021 1020 * to performing module auto-loading.
1022 1021 */
1023 1022 mdb_set_ipath(mdb.m_ipathstr);
1024 1023 mdb_set_lpath(mdb.m_lpathstr);
1025 1024
1026 1025 if (!Sflag && (p = getenv("HOME")) != NULL) {
1027 1026 char rcpath[MAXPATHLEN];
1028 1027 mdb_io_t *rc_io;
1029 1028 int fd;
1030 1029
1031 1030 (void) mdb_iob_snprintf(rcpath, MAXPATHLEN, "%s/.mdbrc", p);
1032 1031 fd = open64(rcpath, O_RDONLY);
1033 1032
1034 1033 if (fd >= 0 && (rc_io = mdb_fdio_create_named(fd, rcpath))) {
1035 1034 mdb_iob_t *iob = mdb_iob_create(rc_io, MDB_IOB_RDONLY);
1036 1035 mdb_iob_t *old = mdb.m_in;
1037 1036
1038 1037 mdb.m_in = iob;
1039 1038 (void) mdb_run();
1040 1039 mdb.m_in = old;
1041 1040 }
1042 1041 }
1043 1042
1044 1043 if (!(mdb.m_flags & MDB_FL_NOMODS))
1045 1044 mdb_module_load_all(0);
1046 1045
1047 1046 (void) mdb_signal_sethandler(SIGINT, int_handler, NULL);
1048 1047 while ((status = mdb_run()) == MDB_ERR_ABORT ||
1049 1048 status == MDB_ERR_OUTPUT) {
1050 1049 /*
1051 1050 * If a write failed on stdout, give up. A more informative
1052 1051 * error message will already have been printed by mdb_run().
1053 1052 */
1054 1053 if (status == MDB_ERR_OUTPUT &&
1055 1054 mdb_iob_getflags(mdb.m_out) & MDB_IOB_ERR) {
1056 1055 mdb_warn("write to stdout failed, exiting\n");
1057 1056 break;
1058 1057 }
1059 1058 continue;
1060 1059 }
1061 1060
1062 1061 terminate((status == MDB_ERR_QUIT || status == 0) ? 0 : 1);
1063 1062 /*NOTREACHED*/
1064 1063 return (0);
1065 1064
1066 1065 reexec:
1067 1066 if ((p = strrchr(execname, '/')) == NULL)
1068 1067 die("cannot determine absolute pathname\n");
1069 1068 #ifdef _LP64
1070 1069 #ifdef __sparc
1071 1070 (void) strcpy(p, "/../sparcv7/");
1072 1071 #else
1073 1072 (void) strcpy(p, "/../i86/");
1074 1073 #endif
1075 1074 #else
1076 1075 #ifdef __sparc
1077 1076 (void) strcpy(p, "/../sparcv9/");
1078 1077 #else
1079 1078 (void) strcpy(p, "/../amd64/");
1080 1079 #endif
1081 1080 #endif
1082 1081 (void) strcat(p, mdb.m_pname);
1083 1082
1084 1083 if (mdb.m_term != NULL)
1085 1084 (void) IOP_CTL(in_io, TCSETSW, &tios);
1086 1085
1087 1086 (void) putenv("_MDB_EXEC=1");
1088 1087 (void) execv(execname, argv);
1089 1088
1090 1089 /*
1091 1090 * If execv fails, suppress ENOEXEC. Experience shows the most common
1092 1091 * reason is that the machine is booted under a 32-bit kernel, in which
1093 1092 * case it is clearer to only print the message below.
1094 1093 */
1095 1094 if (errno != ENOEXEC)
1096 1095 warn("failed to exec %s", execname);
1097 1096 #ifdef _LP64
1098 1097 die("64-bit %s cannot debug 32-bit program %s\n",
1099 1098 mdb.m_pname, tgt_argv[0] ?
1100 1099 tgt_argv[0] : tgt_argv[1]);
1101 1100 #else
1102 1101 die("32-bit %s cannot debug 64-bit program %s\n",
1103 1102 mdb.m_pname, tgt_argv[0] ?
1104 1103 tgt_argv[0] : tgt_argv[1]);
1105 1104 #endif
1106 1105
1107 1106 goto tcreate;
1108 1107 }
↓ open down ↓ |
202 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX