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