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 (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /*
26 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
27 */
28
29 /*
30 * Libkvm Kernel Target
31 *
32 * The libkvm kernel target provides access to both crash dumps and live
33 * kernels through /dev/ksyms and /dev/kmem, using the facilities provided by
34 * the libkvm.so library. The target-specific data structures are shared
35 * between this file (common code) and the ISA-dependent parts of the target,
36 * and so they are defined in the mdb_kvm.h header. The target processes an
37 * "executable" (/dev/ksyms or the unix.X file) which contains a primary
38 * .symtab and .dynsym, and then also iterates over the krtld module chain in
39 * the kernel in order to obtain a list of loaded modules and per-module symbol
40 * tables. To improve startup performance, the per-module symbol tables are
41 * instantiated on-the-fly whenever an address lookup falls within the text
42 * section of a given module. The target also relies on services from the
43 * mdb_ks (kernel support) module, which contains pieces of the implementation
44 * that must be compiled against the kernel implementation.
45 */
46
47 #include <sys/modctl.h>
48 #include <sys/kobj.h>
49 #include <sys/kobj_impl.h>
50 #include <sys/utsname.h>
51 #include <sys/panic.h>
52 #include <sys/dumphdr.h>
53 #include <sys/dumpadm.h>
54
55 #include <dlfcn.h>
56 #include <libctf.h>
57 #include <string.h>
58 #include <fcntl.h>
59 #include <errno.h>
60
61 #include <mdb/mdb_target_impl.h>
62 #include <mdb/mdb_err.h>
63 #include <mdb/mdb_debug.h>
64 #include <mdb/mdb_string.h>
65 #include <mdb/mdb_modapi.h>
66 #include <mdb/mdb_io_impl.h>
67 #include <mdb/mdb_ctf.h>
68 #include <mdb/mdb_kvm.h>
69 #include <mdb/mdb_module.h>
70 #include <mdb/mdb_kb.h>
71 #include <mdb/mdb.h>
72
73 #define KT_RELOC_BUF(buf, obase, nbase) \
74 ((uintptr_t)(buf) - (uintptr_t)(obase) + (uintptr_t)(nbase))
75
76 #define KT_BAD_BUF(buf, base, size) \
77 ((uintptr_t)(buf) < (uintptr_t)(base) || \
78 ((uintptr_t)(buf) >= (uintptr_t)(base) + (uintptr_t)(size)))
79
80 typedef struct kt_symarg {
81 mdb_tgt_sym_f *sym_cb; /* Caller's callback function */
82 void *sym_data; /* Callback function argument */
83 uint_t sym_type; /* Symbol type/binding filter */
84 mdb_syminfo_t sym_info; /* Symbol id and table id */
85 const char *sym_obj; /* Containing object */
86 } kt_symarg_t;
87
88 typedef struct kt_maparg {
89 mdb_tgt_t *map_target; /* Target used for mapping iter */
90 mdb_tgt_map_f *map_cb; /* Caller's callback function */
91 void *map_data; /* Callback function argument */
92 } kt_maparg_t;
93
94 static const char KT_MODULE[] = "mdb_ks";
95 static const char KT_CTFPARENT[] = "genunix";
96
97 static void
98 kt_load_module(kt_data_t *kt, mdb_tgt_t *t, kt_module_t *km)
99 {
100 km->km_data = mdb_alloc(km->km_datasz, UM_SLEEP);
101
102 (void) mdb_tgt_vread(t, km->km_data, km->km_datasz, km->km_symspace_va);
103
104 km->km_symbuf = (void *)
105 KT_RELOC_BUF(km->km_symtab_va, km->km_symspace_va, km->km_data);
106
107 km->km_strtab = (char *)
108 KT_RELOC_BUF(km->km_strtab_va, km->km_symspace_va, km->km_data);
109
110 km->km_symtab = mdb_gelf_symtab_create_raw(&kt->k_file->gf_ehdr,
111 &km->km_symtab_hdr, km->km_symbuf,
112 &km->km_strtab_hdr, km->km_strtab, MDB_TGT_SYMTAB);
113 }
114
115 static void
116 kt_load_modules(kt_data_t *kt, mdb_tgt_t *t)
468 {
469 kt_data_t *kt = mdb.m_target->t_data;
470 struct utsname uts;
471
472 bzero(&uts, sizeof (uts));
473 (void) strcpy(uts.nodename, "unknown machine");
474 (void) kt_uname(mdb.m_target, &uts);
475
476 if (mdb_prop_postmortem) {
477 mdb_printf("debugging %scrash dump %s (%d-bit) from %s\n",
478 kt->k_xpv_domu ? "domain " : "", kt->k_kvmfile,
479 (int)(sizeof (void *) * NBBY), uts.nodename);
480 } else {
481 mdb_printf("debugging live kernel (%d-bit) on %s\n",
482 (int)(sizeof (void *) * NBBY), uts.nodename);
483 }
484
485 mdb_printf("operating system: %s %s (%s)\n",
486 uts.release, uts.version, uts.machine);
487
488 if (kt->k_dumphdr) {
489 dumphdr_t *dh = kt->k_dumphdr;
490
491 mdb_printf("image uuid: %s\n", dh->dump_uuid[0] != '\0' ?
492 dh->dump_uuid : "(not set)");
493 mdb_printf("panic message: %s\n", dh->dump_panicstring);
494
495 kt->k_dump_print_content(dh, kt->k_dumpcontent);
496 } else {
497 char uuid[37];
498
499 if (mdb_readsym(uuid, 37, "dump_osimage_uuid") == 37 &&
500 uuid[36] == '\0') {
501 mdb_printf("image uuid: %s\n", uuid);
502 }
503 }
504
505 return (DCMD_OK);
506 }
507
508 static const mdb_dcmd_t kt_dcmds[] = {
509 { "$c", "?[cnt]", "print stack backtrace", kt_stack },
510 { "$C", "?[cnt]", "print stack backtrace", kt_stackv },
511 { "$r", NULL, "print general-purpose registers", kt_regs },
512 { "$?", NULL, "print status and registers", kt_regs },
513 { "regs", NULL, "print general-purpose registers", kt_regs },
514 { "stack", "?[cnt]", "print stack backtrace", kt_stack },
515 { "stackregs", "?", "print stack backtrace and registers", kt_stackr },
516 #ifdef __x86
517 { "cpustack", "?[-v] [-c cpuid] [cnt]", "print stack backtrace for a "
518 "specific CPU", kt_cpustack },
519 { "cpuregs", "?[-c cpuid]", "print general-purpose registers for a "
520 "specific CPU", kt_cpuregs },
521 #endif
565 /*
566 * If we're examining a crash dump, root is /, and uname(2)
567 * does not match the utsname in the dump, issue a warning.
568 * Note that we are assuming that the modules and macros in
569 * /usr/lib are compiled against the kernel from uname -rv.
570 */
571 if (mdb_prop_postmortem && strcmp(mdb.m_root, "/") == 0 &&
572 uname(&u1) >= 0 && kt_uname(t, &u2) >= 0 &&
573 (strcmp(u1.release, u2.release) ||
574 strcmp(u1.version, u2.version))) {
575 mdb_warn("warning: dump is from %s %s %s; dcmds and "
576 "macros may not match kernel implementation\n",
577 u2.sysname, u2.release, u2.version);
578 }
579
580 if (mdb_module_load(KT_MODULE, MDB_MOD_GLOBAL) < 0) {
581 warn("failed to load kernel support module -- "
582 "some modules may not load\n");
583 }
584
585 if (mdb_prop_postmortem && kt->k_dumphdr != NULL) {
586 sym = dlsym(RTLD_NEXT, "mdb_dump_print_content");
587 if (sym != NULL)
588 kt->k_dump_print_content = (void (*)())sym;
589
590 sym = dlsym(RTLD_NEXT, "mdb_dump_find_curproc");
591 if (sym != NULL)
592 kt->k_dump_find_curproc = (int (*)())sym;
593
594 kt->k_dumpcontent = kt_find_dump_contents(kt);
595 }
596
597 if (t->t_flags & MDB_TGT_F_PRELOAD) {
598 oflag = mdb_iob_getflags(mdb.m_out) & MDB_IOB_PGENABLE;
599
600 mdb_iob_clrflags(mdb.m_out, oflag);
601 mdb_iob_puts(mdb.m_out, "Preloading module symbols: [");
602 mdb_iob_flush(mdb.m_out);
603 }
604
|
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 (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /*
26 * Copyright 2019 Joyent, Inc.
27 */
28
29 /*
30 * Libkvm Kernel Target
31 *
32 * The libkvm kernel target provides access to both crash dumps and live
33 * kernels through /dev/ksyms and /dev/kmem, using the facilities provided by
34 * the libkvm.so library. The target-specific data structures are shared
35 * between this file (common code) and the ISA-dependent parts of the target,
36 * and so they are defined in the mdb_kvm.h header. The target processes an
37 * "executable" (/dev/ksyms or the unix.X file) which contains a primary
38 * .symtab and .dynsym, and then also iterates over the krtld module chain in
39 * the kernel in order to obtain a list of loaded modules and per-module symbol
40 * tables. To improve startup performance, the per-module symbol tables are
41 * instantiated on-the-fly whenever an address lookup falls within the text
42 * section of a given module. The target also relies on services from the
43 * mdb_ks (kernel support) module, which contains pieces of the implementation
44 * that must be compiled against the kernel implementation.
45 */
46
47 #include <sys/modctl.h>
48 #include <sys/kobj.h>
49 #include <sys/kobj_impl.h>
50 #include <sys/utsname.h>
51 #include <sys/panic.h>
52 #include <sys/dumphdr.h>
53 #include <sys/dumpadm.h>
54 #include <sys/uuid.h>
55
56 #include <dlfcn.h>
57 #include <libctf.h>
58 #include <string.h>
59 #include <fcntl.h>
60 #include <errno.h>
61
62 #include <mdb/mdb_target_impl.h>
63 #include <mdb/mdb_err.h>
64 #include <mdb/mdb_debug.h>
65 #include <mdb/mdb_string.h>
66 #include <mdb/mdb_modapi.h>
67 #include <mdb/mdb_io_impl.h>
68 #include <mdb/mdb_ctf.h>
69 #include <mdb/mdb_kvm.h>
70 #include <mdb/mdb_module.h>
71 #include <mdb/mdb_kb.h>
72 #include <mdb/mdb_ks.h>
73 #include <mdb/mdb.h>
74
75 #define KT_RELOC_BUF(buf, obase, nbase) \
76 ((uintptr_t)(buf) - (uintptr_t)(obase) + (uintptr_t)(nbase))
77
78 #define KT_BAD_BUF(buf, base, size) \
79 ((uintptr_t)(buf) < (uintptr_t)(base) || \
80 ((uintptr_t)(buf) >= (uintptr_t)(base) + (uintptr_t)(size)))
81
82 typedef struct kt_symarg {
83 mdb_tgt_sym_f *sym_cb; /* Caller's callback function */
84 void *sym_data; /* Callback function argument */
85 uint_t sym_type; /* Symbol type/binding filter */
86 mdb_syminfo_t sym_info; /* Symbol id and table id */
87 const char *sym_obj; /* Containing object */
88 } kt_symarg_t;
89
90 typedef struct kt_maparg {
91 mdb_tgt_t *map_target; /* Target used for mapping iter */
92 mdb_tgt_map_f *map_cb; /* Caller's callback function */
93 void *map_data; /* Callback function argument */
94 } kt_maparg_t;
95
96 static const char KT_MODULE[] = "mdb_ks";
97 static const char KT_CTFPARENT[] = "genunix";
98
99 static void (*print_buildversion)(void);
100
101 static void
102 kt_load_module(kt_data_t *kt, mdb_tgt_t *t, kt_module_t *km)
103 {
104 km->km_data = mdb_alloc(km->km_datasz, UM_SLEEP);
105
106 (void) mdb_tgt_vread(t, km->km_data, km->km_datasz, km->km_symspace_va);
107
108 km->km_symbuf = (void *)
109 KT_RELOC_BUF(km->km_symtab_va, km->km_symspace_va, km->km_data);
110
111 km->km_strtab = (char *)
112 KT_RELOC_BUF(km->km_strtab_va, km->km_symspace_va, km->km_data);
113
114 km->km_symtab = mdb_gelf_symtab_create_raw(&kt->k_file->gf_ehdr,
115 &km->km_symtab_hdr, km->km_symbuf,
116 &km->km_strtab_hdr, km->km_strtab, MDB_TGT_SYMTAB);
117 }
118
119 static void
120 kt_load_modules(kt_data_t *kt, mdb_tgt_t *t)
472 {
473 kt_data_t *kt = mdb.m_target->t_data;
474 struct utsname uts;
475
476 bzero(&uts, sizeof (uts));
477 (void) strcpy(uts.nodename, "unknown machine");
478 (void) kt_uname(mdb.m_target, &uts);
479
480 if (mdb_prop_postmortem) {
481 mdb_printf("debugging %scrash dump %s (%d-bit) from %s\n",
482 kt->k_xpv_domu ? "domain " : "", kt->k_kvmfile,
483 (int)(sizeof (void *) * NBBY), uts.nodename);
484 } else {
485 mdb_printf("debugging live kernel (%d-bit) on %s\n",
486 (int)(sizeof (void *) * NBBY), uts.nodename);
487 }
488
489 mdb_printf("operating system: %s %s (%s)\n",
490 uts.release, uts.version, uts.machine);
491
492 if (print_buildversion != NULL)
493 print_buildversion();
494
495 if (kt->k_dumphdr) {
496 dumphdr_t *dh = kt->k_dumphdr;
497
498 mdb_printf("image uuid: %s\n", dh->dump_uuid[0] != '\0' ?
499 dh->dump_uuid : "(not set)");
500 mdb_printf("panic message: %s\n", dh->dump_panicstring);
501
502 kt->k_dump_print_content(dh, kt->k_dumpcontent);
503 } else {
504 char uuid[UUID_PRINTABLE_STRING_LENGTH];
505
506 if (mdb_readsym(uuid, sizeof (uuid),
507 "dump_osimage_uuid") == sizeof (uuid) &&
508 uuid[sizeof (uuid) - 1] == '\0') {
509 mdb_printf("image uuid: %s\n", uuid[0] != '\0' ?
510 uuid : "(not set)");
511 }
512 }
513
514 return (DCMD_OK);
515 }
516
517 static const mdb_dcmd_t kt_dcmds[] = {
518 { "$c", "?[cnt]", "print stack backtrace", kt_stack },
519 { "$C", "?[cnt]", "print stack backtrace", kt_stackv },
520 { "$r", NULL, "print general-purpose registers", kt_regs },
521 { "$?", NULL, "print status and registers", kt_regs },
522 { "regs", NULL, "print general-purpose registers", kt_regs },
523 { "stack", "?[cnt]", "print stack backtrace", kt_stack },
524 { "stackregs", "?", "print stack backtrace and registers", kt_stackr },
525 #ifdef __x86
526 { "cpustack", "?[-v] [-c cpuid] [cnt]", "print stack backtrace for a "
527 "specific CPU", kt_cpustack },
528 { "cpuregs", "?[-c cpuid]", "print general-purpose registers for a "
529 "specific CPU", kt_cpuregs },
530 #endif
574 /*
575 * If we're examining a crash dump, root is /, and uname(2)
576 * does not match the utsname in the dump, issue a warning.
577 * Note that we are assuming that the modules and macros in
578 * /usr/lib are compiled against the kernel from uname -rv.
579 */
580 if (mdb_prop_postmortem && strcmp(mdb.m_root, "/") == 0 &&
581 uname(&u1) >= 0 && kt_uname(t, &u2) >= 0 &&
582 (strcmp(u1.release, u2.release) ||
583 strcmp(u1.version, u2.version))) {
584 mdb_warn("warning: dump is from %s %s %s; dcmds and "
585 "macros may not match kernel implementation\n",
586 u2.sysname, u2.release, u2.version);
587 }
588
589 if (mdb_module_load(KT_MODULE, MDB_MOD_GLOBAL) < 0) {
590 warn("failed to load kernel support module -- "
591 "some modules may not load\n");
592 }
593
594 print_buildversion = (void (*)(void))dlsym(RTLD_NEXT,
595 "mdb_print_buildversion");
596
597 if (mdb_prop_postmortem && kt->k_dumphdr != NULL) {
598 sym = dlsym(RTLD_NEXT, "mdb_dump_print_content");
599 if (sym != NULL)
600 kt->k_dump_print_content = (void (*)())sym;
601
602 sym = dlsym(RTLD_NEXT, "mdb_dump_find_curproc");
603 if (sym != NULL)
604 kt->k_dump_find_curproc = (int (*)())sym;
605
606 kt->k_dumpcontent = kt_find_dump_contents(kt);
607 }
608
609 if (t->t_flags & MDB_TGT_F_PRELOAD) {
610 oflag = mdb_iob_getflags(mdb.m_out) & MDB_IOB_PGENABLE;
611
612 mdb_iob_clrflags(mdb.m_out, oflag);
613 mdb_iob_puts(mdb.m_out, "Preloading module symbols: [");
614 mdb_iob_flush(mdb.m_out);
615 }
616
|