1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * Libkvm Kernel Target 31*7c478bd9Sstevel@tonic-gate * 32*7c478bd9Sstevel@tonic-gate * The libkvm kernel target provides access to both crash dumps and live 33*7c478bd9Sstevel@tonic-gate * kernels through /dev/ksyms and /dev/kmem, using the facilities provided by 34*7c478bd9Sstevel@tonic-gate * the libkvm.so library. The target-specific data structures are shared 35*7c478bd9Sstevel@tonic-gate * between this file (common code) and the ISA-dependent parts of the target, 36*7c478bd9Sstevel@tonic-gate * and so they are defined in the mdb_kvm.h header. The target processes an 37*7c478bd9Sstevel@tonic-gate * "executable" (/dev/ksyms or the unix.X file) which contains a primary 38*7c478bd9Sstevel@tonic-gate * .symtab and .dynsym, and then also iterates over the krtld module chain in 39*7c478bd9Sstevel@tonic-gate * the kernel in order to obtain a list of loaded modules and per-module symbol 40*7c478bd9Sstevel@tonic-gate * tables. To improve startup performance, the per-module symbol tables are 41*7c478bd9Sstevel@tonic-gate * instantiated on-the-fly whenever an address lookup falls within the text 42*7c478bd9Sstevel@tonic-gate * section of a given module. The target also relies on services from the 43*7c478bd9Sstevel@tonic-gate * mdb_ks (kernel support) module, which contains pieces of the implementation 44*7c478bd9Sstevel@tonic-gate * that must be compiled against the kernel implementation. 45*7c478bd9Sstevel@tonic-gate */ 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/kobj.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/kobj_impl.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/panic.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/dumphdr.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/dumpadm.h> 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate #include <dlfcn.h> 56*7c478bd9Sstevel@tonic-gate #include <libctf.h> 57*7c478bd9Sstevel@tonic-gate #include <string.h> 58*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 59*7c478bd9Sstevel@tonic-gate #include <errno.h> 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_target_impl.h> 62*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_err.h> 63*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_debug.h> 64*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_string.h> 65*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h> 66*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_io_impl.h> 67*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_ctf.h> 68*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_kvm.h> 69*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_module.h> 70*7c478bd9Sstevel@tonic-gate #include <mdb/mdb.h> 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate #define KT_RELOC_BUF(buf, obase, nbase) \ 73*7c478bd9Sstevel@tonic-gate ((uintptr_t)(buf) - (uintptr_t)(obase) + (uintptr_t)(nbase)) 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate #define KT_BAD_BUF(buf, base, size) \ 76*7c478bd9Sstevel@tonic-gate ((uintptr_t)(buf) < (uintptr_t)(base) || \ 77*7c478bd9Sstevel@tonic-gate ((uintptr_t)(buf) >= (uintptr_t)(base) + (uintptr_t)(size))) 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate typedef struct kt_symarg { 80*7c478bd9Sstevel@tonic-gate mdb_tgt_sym_f *sym_cb; /* Caller's callback function */ 81*7c478bd9Sstevel@tonic-gate void *sym_data; /* Callback function argument */ 82*7c478bd9Sstevel@tonic-gate uint_t sym_type; /* Symbol type/binding filter */ 83*7c478bd9Sstevel@tonic-gate mdb_syminfo_t sym_info; /* Symbol id and table id */ 84*7c478bd9Sstevel@tonic-gate const char *sym_obj; /* Containing object */ 85*7c478bd9Sstevel@tonic-gate } kt_symarg_t; 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate typedef struct kt_maparg { 88*7c478bd9Sstevel@tonic-gate mdb_tgt_t *map_target; /* Target used for mapping iter */ 89*7c478bd9Sstevel@tonic-gate mdb_tgt_map_f *map_cb; /* Caller's callback function */ 90*7c478bd9Sstevel@tonic-gate void *map_data; /* Callback function argument */ 91*7c478bd9Sstevel@tonic-gate } kt_maparg_t; 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate static const char KT_RTLD_NAME[] = "krtld"; 94*7c478bd9Sstevel@tonic-gate static const char KT_MODULE[] = "mdb_ks"; 95*7c478bd9Sstevel@tonic-gate static const char KT_CTFPARENT[] = "genunix"; 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate static void 98*7c478bd9Sstevel@tonic-gate kt_load_module(kt_data_t *kt, mdb_tgt_t *t, kt_module_t *km) 99*7c478bd9Sstevel@tonic-gate { 100*7c478bd9Sstevel@tonic-gate km->km_data = mdb_alloc(km->km_datasz, UM_SLEEP); 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate (void) mdb_tgt_vread(t, km->km_data, km->km_datasz, km->km_symspace_va); 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate km->km_symbuf = (void *) 105*7c478bd9Sstevel@tonic-gate KT_RELOC_BUF(km->km_symtab_va, km->km_symspace_va, km->km_data); 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate km->km_strtab = (char *) 108*7c478bd9Sstevel@tonic-gate KT_RELOC_BUF(km->km_strtab_va, km->km_symspace_va, km->km_data); 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate km->km_symtab = mdb_gelf_symtab_create_raw(&kt->k_file->gf_ehdr, 111*7c478bd9Sstevel@tonic-gate &km->km_symtab_hdr, km->km_symbuf, 112*7c478bd9Sstevel@tonic-gate &km->km_strtab_hdr, km->km_strtab, MDB_TGT_SYMTAB); 113*7c478bd9Sstevel@tonic-gate } 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate static void 116*7c478bd9Sstevel@tonic-gate kt_load_modules(kt_data_t *kt, mdb_tgt_t *t) 117*7c478bd9Sstevel@tonic-gate { 118*7c478bd9Sstevel@tonic-gate char name[MAXNAMELEN]; 119*7c478bd9Sstevel@tonic-gate uintptr_t addr, head; 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate struct module kmod; 122*7c478bd9Sstevel@tonic-gate struct modctl ctl; 123*7c478bd9Sstevel@tonic-gate Shdr symhdr, strhdr; 124*7c478bd9Sstevel@tonic-gate GElf_Sym sym; 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate kt_module_t *km; 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate if (mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC, 129*7c478bd9Sstevel@tonic-gate "modules", &sym, NULL) == -1) { 130*7c478bd9Sstevel@tonic-gate warn("failed to get 'modules' symbol"); 131*7c478bd9Sstevel@tonic-gate return; 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate if (mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, &ctl, sizeof (ctl), 135*7c478bd9Sstevel@tonic-gate MDB_TGT_OBJ_EXEC, "modules") != sizeof (ctl)) { 136*7c478bd9Sstevel@tonic-gate warn("failed to read 'modules' struct"); 137*7c478bd9Sstevel@tonic-gate return; 138*7c478bd9Sstevel@tonic-gate } 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate addr = head = (uintptr_t)sym.st_value; 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate do { 143*7c478bd9Sstevel@tonic-gate if (addr == NULL) 144*7c478bd9Sstevel@tonic-gate break; /* Avoid spurious NULL pointers in list */ 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate if (mdb_tgt_vread(t, &ctl, sizeof (ctl), addr) == -1) { 147*7c478bd9Sstevel@tonic-gate warn("failed to read modctl at %p", (void *)addr); 148*7c478bd9Sstevel@tonic-gate return; 149*7c478bd9Sstevel@tonic-gate } 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate if (ctl.mod_mp == NULL) 152*7c478bd9Sstevel@tonic-gate continue; /* No associated krtld structure */ 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate if (mdb_tgt_readstr(t, MDB_TGT_AS_VIRT, name, MAXNAMELEN, 155*7c478bd9Sstevel@tonic-gate (uintptr_t)ctl.mod_modname) <= 0) { 156*7c478bd9Sstevel@tonic-gate warn("failed to read module name at %p", 157*7c478bd9Sstevel@tonic-gate (void *)ctl.mod_modname); 158*7c478bd9Sstevel@tonic-gate continue; 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate mdb_dprintf(MDB_DBG_KMOD, "reading mod %s (%p)\n", 162*7c478bd9Sstevel@tonic-gate name, (void *)addr); 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate if (mdb_nv_lookup(&kt->k_modules, name) != NULL) { 165*7c478bd9Sstevel@tonic-gate warn("skipping duplicate module '%s', id=%d\n", 166*7c478bd9Sstevel@tonic-gate name, ctl.mod_id); 167*7c478bd9Sstevel@tonic-gate continue; 168*7c478bd9Sstevel@tonic-gate } 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate if (mdb_tgt_vread(t, &kmod, sizeof (kmod), 171*7c478bd9Sstevel@tonic-gate (uintptr_t)ctl.mod_mp) == -1) { 172*7c478bd9Sstevel@tonic-gate warn("failed to read module at %p\n", 173*7c478bd9Sstevel@tonic-gate (void *)ctl.mod_mp); 174*7c478bd9Sstevel@tonic-gate continue; 175*7c478bd9Sstevel@tonic-gate } 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate if (kmod.symspace == NULL || kmod.symhdr == NULL || 178*7c478bd9Sstevel@tonic-gate kmod.strhdr == NULL) { 179*7c478bd9Sstevel@tonic-gate /* 180*7c478bd9Sstevel@tonic-gate * If no buffer for the symbols has been allocated, 181*7c478bd9Sstevel@tonic-gate * or the shdrs for .symtab and .strtab are missing, 182*7c478bd9Sstevel@tonic-gate * then we're out of luck. 183*7c478bd9Sstevel@tonic-gate */ 184*7c478bd9Sstevel@tonic-gate continue; 185*7c478bd9Sstevel@tonic-gate } 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate if (mdb_tgt_vread(t, &symhdr, sizeof (Shdr), 188*7c478bd9Sstevel@tonic-gate (uintptr_t)kmod.symhdr) == -1) { 189*7c478bd9Sstevel@tonic-gate warn("failed to read .symtab header for '%s', id=%d", 190*7c478bd9Sstevel@tonic-gate name, ctl.mod_id); 191*7c478bd9Sstevel@tonic-gate continue; 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate if (mdb_tgt_vread(t, &strhdr, sizeof (Shdr), 195*7c478bd9Sstevel@tonic-gate (uintptr_t)kmod.strhdr) == -1) { 196*7c478bd9Sstevel@tonic-gate warn("failed to read .strtab header for '%s', id=%d", 197*7c478bd9Sstevel@tonic-gate name, ctl.mod_id); 198*7c478bd9Sstevel@tonic-gate continue; 199*7c478bd9Sstevel@tonic-gate } 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate /* 202*7c478bd9Sstevel@tonic-gate * Now get clever: f(*^ing krtld didn't used to bother updating 203*7c478bd9Sstevel@tonic-gate * its own kmod.symsize value. We know that prior to this bug 204*7c478bd9Sstevel@tonic-gate * being fixed, symspace was a contiguous buffer containing 205*7c478bd9Sstevel@tonic-gate * .symtab, .strtab, and the symbol hash table in that order. 206*7c478bd9Sstevel@tonic-gate * So if symsize is zero, recompute it as the size of .symtab 207*7c478bd9Sstevel@tonic-gate * plus the size of .strtab. We don't need to load the hash 208*7c478bd9Sstevel@tonic-gate * table anyway since we re-hash all the symbols internally. 209*7c478bd9Sstevel@tonic-gate */ 210*7c478bd9Sstevel@tonic-gate if (kmod.symsize == 0) 211*7c478bd9Sstevel@tonic-gate kmod.symsize = symhdr.sh_size + strhdr.sh_size; 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate /* 214*7c478bd9Sstevel@tonic-gate * Similar logic can be used to make educated guesses 215*7c478bd9Sstevel@tonic-gate * at the values of kmod.symtbl and kmod.strings. 216*7c478bd9Sstevel@tonic-gate */ 217*7c478bd9Sstevel@tonic-gate if (kmod.symtbl == NULL) 218*7c478bd9Sstevel@tonic-gate kmod.symtbl = kmod.symspace; 219*7c478bd9Sstevel@tonic-gate if (kmod.strings == NULL) 220*7c478bd9Sstevel@tonic-gate kmod.strings = kmod.symspace + symhdr.sh_size; 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate /* 223*7c478bd9Sstevel@tonic-gate * Make sure things seem reasonable before we proceed 224*7c478bd9Sstevel@tonic-gate * to actually read and decipher the symspace. 225*7c478bd9Sstevel@tonic-gate */ 226*7c478bd9Sstevel@tonic-gate if (KT_BAD_BUF(kmod.symtbl, kmod.symspace, kmod.symsize) || 227*7c478bd9Sstevel@tonic-gate KT_BAD_BUF(kmod.strings, kmod.symspace, kmod.symsize)) { 228*7c478bd9Sstevel@tonic-gate warn("skipping module '%s', id=%d (corrupt symspace)\n", 229*7c478bd9Sstevel@tonic-gate name, ctl.mod_id); 230*7c478bd9Sstevel@tonic-gate continue; 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate km = mdb_zalloc(sizeof (kt_module_t), UM_SLEEP); 234*7c478bd9Sstevel@tonic-gate km->km_name = strdup(name); 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate (void) mdb_nv_insert(&kt->k_modules, km->km_name, NULL, 237*7c478bd9Sstevel@tonic-gate (uintptr_t)km, MDB_NV_EXTNAME); 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate km->km_datasz = kmod.symsize; 240*7c478bd9Sstevel@tonic-gate km->km_symspace_va = (uintptr_t)kmod.symspace; 241*7c478bd9Sstevel@tonic-gate km->km_symtab_va = (uintptr_t)kmod.symtbl; 242*7c478bd9Sstevel@tonic-gate km->km_strtab_va = (uintptr_t)kmod.strings; 243*7c478bd9Sstevel@tonic-gate km->km_symtab_hdr = symhdr; 244*7c478bd9Sstevel@tonic-gate km->km_strtab_hdr = strhdr; 245*7c478bd9Sstevel@tonic-gate km->km_text_va = (uintptr_t)kmod.text; 246*7c478bd9Sstevel@tonic-gate km->km_text_size = kmod.text_size; 247*7c478bd9Sstevel@tonic-gate km->km_data_va = (uintptr_t)kmod.data; 248*7c478bd9Sstevel@tonic-gate km->km_data_size = kmod.data_size; 249*7c478bd9Sstevel@tonic-gate km->km_bss_va = (uintptr_t)kmod.bss; 250*7c478bd9Sstevel@tonic-gate km->km_bss_size = kmod.bss_size; 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate if (kt->k_ctfvalid) { 253*7c478bd9Sstevel@tonic-gate km->km_ctf_va = (uintptr_t)kmod.ctfdata; 254*7c478bd9Sstevel@tonic-gate km->km_ctf_size = kmod.ctfsize; 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate /* 258*7c478bd9Sstevel@tonic-gate * Add the module to the end of the list of modules in load- 259*7c478bd9Sstevel@tonic-gate * dependency order. This is needed to load the corresponding 260*7c478bd9Sstevel@tonic-gate * debugger modules in the same order for layering purposes. 261*7c478bd9Sstevel@tonic-gate */ 262*7c478bd9Sstevel@tonic-gate mdb_list_append(&kt->k_modlist, km); 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate if (t->t_flags & MDB_TGT_F_PRELOAD) { 265*7c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_out, " %s", name); 266*7c478bd9Sstevel@tonic-gate mdb_iob_flush(mdb.m_out); 267*7c478bd9Sstevel@tonic-gate kt_load_module(kt, t, km); 268*7c478bd9Sstevel@tonic-gate } 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate } while ((addr = (uintptr_t)ctl.mod_next) != head); 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate int 274*7c478bd9Sstevel@tonic-gate kt_setflags(mdb_tgt_t *t, int flags) 275*7c478bd9Sstevel@tonic-gate { 276*7c478bd9Sstevel@tonic-gate int iochg = ((flags ^ t->t_flags) & MDB_TGT_F_ALLOWIO) && 277*7c478bd9Sstevel@tonic-gate !mdb_prop_postmortem; 278*7c478bd9Sstevel@tonic-gate int rwchg = (flags ^ t->t_flags) & MDB_TGT_F_RDWR; 279*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 280*7c478bd9Sstevel@tonic-gate const char *kvmfile; 281*7c478bd9Sstevel@tonic-gate kvm_t *cookie; 282*7c478bd9Sstevel@tonic-gate int mode; 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate if (!iochg && !rwchg) 285*7c478bd9Sstevel@tonic-gate return (0); 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate if (iochg) { 288*7c478bd9Sstevel@tonic-gate kvmfile = (flags & MDB_TGT_F_ALLOWIO) ? "/dev/allkmem" : 289*7c478bd9Sstevel@tonic-gate "/dev/kmem"; 290*7c478bd9Sstevel@tonic-gate } else { 291*7c478bd9Sstevel@tonic-gate kvmfile = kt->k_kvmfile; 292*7c478bd9Sstevel@tonic-gate } 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate mode = (flags & MDB_TGT_F_RDWR) ? O_RDWR : O_RDONLY; 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate if ((cookie = kvm_open(kt->k_symfile, kvmfile, NULL, mode, 297*7c478bd9Sstevel@tonic-gate mdb.m_pname)) == NULL) { 298*7c478bd9Sstevel@tonic-gate /* We failed to re-open, so don't change t_flags */ 299*7c478bd9Sstevel@tonic-gate warn("failed to re-open target"); 300*7c478bd9Sstevel@tonic-gate return (-1); 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate /* 304*7c478bd9Sstevel@tonic-gate * We successfully reopened the target, so update k_kvmfile. Also set 305*7c478bd9Sstevel@tonic-gate * the RDWR and ALLOWIO bits in t_flags to match those in flags. 306*7c478bd9Sstevel@tonic-gate */ 307*7c478bd9Sstevel@tonic-gate (void) kvm_close(kt->k_cookie); 308*7c478bd9Sstevel@tonic-gate kt->k_cookie = cookie; 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate if (kvmfile != kt->k_kvmfile) { 311*7c478bd9Sstevel@tonic-gate strfree(kt->k_kvmfile); 312*7c478bd9Sstevel@tonic-gate kt->k_kvmfile = strdup(kvmfile); 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate t->t_flags = (t->t_flags & ~(MDB_TGT_F_RDWR | MDB_TGT_F_ALLOWIO)) | 316*7c478bd9Sstevel@tonic-gate (flags & (MDB_TGT_F_RDWR | MDB_TGT_F_ALLOWIO)); 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate return (0); 319*7c478bd9Sstevel@tonic-gate } 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate /* 322*7c478bd9Sstevel@tonic-gate * Determine which PIDs (if any) have their pages saved in the dump. We 323*7c478bd9Sstevel@tonic-gate * do this by looking for content flags in dump_flags in the header. These 324*7c478bd9Sstevel@tonic-gate * flags, which won't be set in older dumps, tell us whether a single process 325*7c478bd9Sstevel@tonic-gate * has had its pages included in the dump. If a single process has been 326*7c478bd9Sstevel@tonic-gate * included, we need to get the PID for that process from the dump_pids 327*7c478bd9Sstevel@tonic-gate * array in the dump. 328*7c478bd9Sstevel@tonic-gate */ 329*7c478bd9Sstevel@tonic-gate static int 330*7c478bd9Sstevel@tonic-gate kt_find_dump_contents(kt_data_t *kt) 331*7c478bd9Sstevel@tonic-gate { 332*7c478bd9Sstevel@tonic-gate dumphdr_t *dh = kt->k_dumphdr; 333*7c478bd9Sstevel@tonic-gate pid_t pid = -1; 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate if (dh->dump_flags & DF_ALL) 336*7c478bd9Sstevel@tonic-gate return (KT_DUMPCONTENT_ALL); 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate if (dh->dump_flags & DF_CURPROC) { 339*7c478bd9Sstevel@tonic-gate if ((pid = kt->k_dump_find_curproc()) == -1) 340*7c478bd9Sstevel@tonic-gate return (KT_DUMPCONTENT_INVALID); 341*7c478bd9Sstevel@tonic-gate else 342*7c478bd9Sstevel@tonic-gate return (pid); 343*7c478bd9Sstevel@tonic-gate } else { 344*7c478bd9Sstevel@tonic-gate return (KT_DUMPCONTENT_KERNEL); 345*7c478bd9Sstevel@tonic-gate } 346*7c478bd9Sstevel@tonic-gate } 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate static int 349*7c478bd9Sstevel@tonic-gate kt_dump_contains_proc(mdb_tgt_t *t, void *context) 350*7c478bd9Sstevel@tonic-gate { 351*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 352*7c478bd9Sstevel@tonic-gate pid_t (*f_pid)(uintptr_t); 353*7c478bd9Sstevel@tonic-gate pid_t reqpid; 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate switch (kt->k_dumpcontent) { 356*7c478bd9Sstevel@tonic-gate case KT_DUMPCONTENT_KERNEL: 357*7c478bd9Sstevel@tonic-gate return (0); 358*7c478bd9Sstevel@tonic-gate case KT_DUMPCONTENT_ALL: 359*7c478bd9Sstevel@tonic-gate return (1); 360*7c478bd9Sstevel@tonic-gate case KT_DUMPCONTENT_INVALID: 361*7c478bd9Sstevel@tonic-gate goto procnotfound; 362*7c478bd9Sstevel@tonic-gate default: 363*7c478bd9Sstevel@tonic-gate f_pid = (pid_t (*)()) dlsym(RTLD_NEXT, "mdb_kproc_pid"); 364*7c478bd9Sstevel@tonic-gate if (f_pid == NULL) 365*7c478bd9Sstevel@tonic-gate goto procnotfound; 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate reqpid = f_pid((uintptr_t)context); 368*7c478bd9Sstevel@tonic-gate if (reqpid == -1) 369*7c478bd9Sstevel@tonic-gate goto procnotfound; 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate return (kt->k_dumpcontent == reqpid); 372*7c478bd9Sstevel@tonic-gate } 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate procnotfound: 375*7c478bd9Sstevel@tonic-gate warn("unable to determine whether dump contains proc %p\n", context); 376*7c478bd9Sstevel@tonic-gate return (1); 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate int 380*7c478bd9Sstevel@tonic-gate kt_setcontext(mdb_tgt_t *t, void *context) 381*7c478bd9Sstevel@tonic-gate { 382*7c478bd9Sstevel@tonic-gate if (context != NULL) { 383*7c478bd9Sstevel@tonic-gate const char *argv[2]; 384*7c478bd9Sstevel@tonic-gate int argc = 0; 385*7c478bd9Sstevel@tonic-gate mdb_tgt_t *ct; 386*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate argv[argc++] = (const char *)context; 389*7c478bd9Sstevel@tonic-gate argv[argc] = NULL; 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate if (kt->k_dumphdr != NULL && 392*7c478bd9Sstevel@tonic-gate !kt_dump_contains_proc(t, context)) { 393*7c478bd9Sstevel@tonic-gate warn("dump does not contain pages for proc %p\n", 394*7c478bd9Sstevel@tonic-gate context); 395*7c478bd9Sstevel@tonic-gate return (-1); 396*7c478bd9Sstevel@tonic-gate } 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate if ((ct = mdb_tgt_create(mdb_kproc_tgt_create, 399*7c478bd9Sstevel@tonic-gate t->t_flags, argc, argv)) == NULL) 400*7c478bd9Sstevel@tonic-gate return (-1); 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate mdb_printf("debugger context set to proc %p\n", context); 403*7c478bd9Sstevel@tonic-gate mdb_tgt_activate(ct); 404*7c478bd9Sstevel@tonic-gate } else 405*7c478bd9Sstevel@tonic-gate mdb_printf("debugger context set to kernel\n"); 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate return (0); 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate static int 411*7c478bd9Sstevel@tonic-gate kt_stack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 412*7c478bd9Sstevel@tonic-gate { 413*7c478bd9Sstevel@tonic-gate kt_data_t *kt = mdb.m_target->t_data; 414*7c478bd9Sstevel@tonic-gate return (kt->k_dcmd_stack(addr, flags, argc, argv)); 415*7c478bd9Sstevel@tonic-gate } 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate static int 418*7c478bd9Sstevel@tonic-gate kt_stackv(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 419*7c478bd9Sstevel@tonic-gate { 420*7c478bd9Sstevel@tonic-gate kt_data_t *kt = mdb.m_target->t_data; 421*7c478bd9Sstevel@tonic-gate return (kt->k_dcmd_stackv(addr, flags, argc, argv)); 422*7c478bd9Sstevel@tonic-gate } 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate static int 425*7c478bd9Sstevel@tonic-gate kt_stackr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 426*7c478bd9Sstevel@tonic-gate { 427*7c478bd9Sstevel@tonic-gate kt_data_t *kt = mdb.m_target->t_data; 428*7c478bd9Sstevel@tonic-gate return (kt->k_dcmd_stackr(addr, flags, argc, argv)); 429*7c478bd9Sstevel@tonic-gate } 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate static int 432*7c478bd9Sstevel@tonic-gate kt_regs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 433*7c478bd9Sstevel@tonic-gate { 434*7c478bd9Sstevel@tonic-gate kt_data_t *kt = mdb.m_target->t_data; 435*7c478bd9Sstevel@tonic-gate return (kt->k_dcmd_regs(addr, flags, argc, argv)); 436*7c478bd9Sstevel@tonic-gate } 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 439*7c478bd9Sstevel@tonic-gate static int 440*7c478bd9Sstevel@tonic-gate kt_status_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 441*7c478bd9Sstevel@tonic-gate { 442*7c478bd9Sstevel@tonic-gate kt_data_t *kt = mdb.m_target->t_data; 443*7c478bd9Sstevel@tonic-gate struct utsname uts; 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate bzero(&uts, sizeof (uts)); 446*7c478bd9Sstevel@tonic-gate (void) strcpy(uts.nodename, "unknown machine"); 447*7c478bd9Sstevel@tonic-gate (void) kt_uname(mdb.m_target, &uts); 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate if (mdb_prop_postmortem) { 450*7c478bd9Sstevel@tonic-gate mdb_printf("debugging crash dump %s (%d-bit) from %s\n", 451*7c478bd9Sstevel@tonic-gate kt->k_kvmfile, (int)(sizeof (void *) * NBBY), uts.nodename); 452*7c478bd9Sstevel@tonic-gate } else { 453*7c478bd9Sstevel@tonic-gate mdb_printf("debugging live kernel (%d-bit) on %s\n", 454*7c478bd9Sstevel@tonic-gate (int)(sizeof (void *) * NBBY), uts.nodename); 455*7c478bd9Sstevel@tonic-gate } 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate mdb_printf("operating system: %s %s (%s)\n", 458*7c478bd9Sstevel@tonic-gate uts.release, uts.version, uts.machine); 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate if (kt->k_dumphdr) { 461*7c478bd9Sstevel@tonic-gate dumphdr_t *dh = kt->k_dumphdr; 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate mdb_printf("panic message: %s\n", dh->dump_panicstring); 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate kt->k_dump_print_content(dh, kt->k_dumpcontent); 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate static const mdb_dcmd_t kt_dcmds[] = { 472*7c478bd9Sstevel@tonic-gate { "$c", "?[cnt]", "print stack backtrace", kt_stack }, 473*7c478bd9Sstevel@tonic-gate { "$C", "?[cnt]", "print stack backtrace", kt_stackv }, 474*7c478bd9Sstevel@tonic-gate { "$r", NULL, "print general-purpose registers", kt_regs }, 475*7c478bd9Sstevel@tonic-gate { "$?", NULL, "print status and registers", kt_regs }, 476*7c478bd9Sstevel@tonic-gate { "regs", NULL, "print general-purpose registers", kt_regs }, 477*7c478bd9Sstevel@tonic-gate { "stack", "?[cnt]", "print stack backtrace", kt_stack }, 478*7c478bd9Sstevel@tonic-gate { "stackregs", "?", "print stack backtrace and registers", kt_stackr }, 479*7c478bd9Sstevel@tonic-gate { "status", NULL, "print summary of current target", kt_status_dcmd }, 480*7c478bd9Sstevel@tonic-gate { NULL } 481*7c478bd9Sstevel@tonic-gate }; 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate static uintmax_t 484*7c478bd9Sstevel@tonic-gate reg_disc_get(const mdb_var_t *v) 485*7c478bd9Sstevel@tonic-gate { 486*7c478bd9Sstevel@tonic-gate mdb_tgt_t *t = MDB_NV_COOKIE(v); 487*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 488*7c478bd9Sstevel@tonic-gate mdb_tgt_reg_t r = 0; 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate (void) mdb_tgt_getareg(t, kt->k_tid, mdb_nv_get_name(v), &r); 491*7c478bd9Sstevel@tonic-gate return (r); 492*7c478bd9Sstevel@tonic-gate } 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate void 495*7c478bd9Sstevel@tonic-gate kt_activate(mdb_tgt_t *t) 496*7c478bd9Sstevel@tonic-gate { 497*7c478bd9Sstevel@tonic-gate static const mdb_nv_disc_t reg_disc = { NULL, reg_disc_get }; 498*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 499*7c478bd9Sstevel@tonic-gate void *sym; 500*7c478bd9Sstevel@tonic-gate 501*7c478bd9Sstevel@tonic-gate int oflag; 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate mdb_prop_postmortem = (kt->k_dumphdr != NULL); 504*7c478bd9Sstevel@tonic-gate mdb_prop_kernel = TRUE; 505*7c478bd9Sstevel@tonic-gate mdb_prop_datamodel = MDB_TGT_MODEL_NATIVE; 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate if (kt->k_activated == FALSE) { 508*7c478bd9Sstevel@tonic-gate struct utsname u1, u2; 509*7c478bd9Sstevel@tonic-gate /* 510*7c478bd9Sstevel@tonic-gate * If we're examining a crash dump, root is /, and uname(2) 511*7c478bd9Sstevel@tonic-gate * does not match the utsname in the dump, issue a warning. 512*7c478bd9Sstevel@tonic-gate * Note that we are assuming that the modules and macros in 513*7c478bd9Sstevel@tonic-gate * /usr/lib are compiled against the kernel from uname -rv. 514*7c478bd9Sstevel@tonic-gate */ 515*7c478bd9Sstevel@tonic-gate if (mdb_prop_postmortem && strcmp(mdb.m_root, "/") == 0 && 516*7c478bd9Sstevel@tonic-gate uname(&u1) >= 0 && kt_uname(t, &u2) >= 0 && 517*7c478bd9Sstevel@tonic-gate (strcmp(u1.release, u2.release) || 518*7c478bd9Sstevel@tonic-gate strcmp(u1.version, u2.version))) { 519*7c478bd9Sstevel@tonic-gate mdb_warn("warning: dump is from %s %s %s; dcmds and " 520*7c478bd9Sstevel@tonic-gate "macros may not match kernel implementation\n", 521*7c478bd9Sstevel@tonic-gate u2.sysname, u2.release, u2.version); 522*7c478bd9Sstevel@tonic-gate } 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate if (mdb_module_load(KT_MODULE, MDB_MOD_GLOBAL) < 0) { 525*7c478bd9Sstevel@tonic-gate warn("failed to load kernel support module -- " 526*7c478bd9Sstevel@tonic-gate "some modules may not load\n"); 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate if (mdb_prop_postmortem) { 530*7c478bd9Sstevel@tonic-gate sym = dlsym(RTLD_NEXT, "mdb_dump_print_content"); 531*7c478bd9Sstevel@tonic-gate if (sym != NULL) 532*7c478bd9Sstevel@tonic-gate kt->k_dump_print_content = (void (*)())sym; 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate sym = dlsym(RTLD_NEXT, "mdb_dump_find_curproc"); 535*7c478bd9Sstevel@tonic-gate if (sym != NULL) 536*7c478bd9Sstevel@tonic-gate kt->k_dump_find_curproc = (int (*)())sym; 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate kt->k_dumpcontent = kt_find_dump_contents(kt); 539*7c478bd9Sstevel@tonic-gate } 540*7c478bd9Sstevel@tonic-gate 541*7c478bd9Sstevel@tonic-gate if (t->t_flags & MDB_TGT_F_PRELOAD) { 542*7c478bd9Sstevel@tonic-gate oflag = mdb_iob_getflags(mdb.m_out) & MDB_IOB_PGENABLE; 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate mdb_iob_clrflags(mdb.m_out, oflag); 545*7c478bd9Sstevel@tonic-gate mdb_iob_puts(mdb.m_out, "Preloading module symbols: ["); 546*7c478bd9Sstevel@tonic-gate mdb_iob_flush(mdb.m_out); 547*7c478bd9Sstevel@tonic-gate } 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate if (!(t->t_flags & MDB_TGT_F_NOLOAD)) 550*7c478bd9Sstevel@tonic-gate kt_load_modules(kt, t); 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate if (t->t_flags & MDB_TGT_F_PRELOAD) { 553*7c478bd9Sstevel@tonic-gate mdb_iob_puts(mdb.m_out, " ]\n"); 554*7c478bd9Sstevel@tonic-gate mdb_iob_setflags(mdb.m_out, oflag); 555*7c478bd9Sstevel@tonic-gate } 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate kt->k_activated = TRUE; 558*7c478bd9Sstevel@tonic-gate } 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate (void) mdb_tgt_register_dcmds(t, &kt_dcmds[0], MDB_MOD_FORCE); 561*7c478bd9Sstevel@tonic-gate 562*7c478bd9Sstevel@tonic-gate /* Export some of our registers as named variables */ 563*7c478bd9Sstevel@tonic-gate mdb_tgt_register_regvars(t, kt->k_rds, ®_disc, MDB_NV_RDONLY); 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate mdb_tgt_elf_export(kt->k_file); 566*7c478bd9Sstevel@tonic-gate } 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate void 569*7c478bd9Sstevel@tonic-gate kt_deactivate(mdb_tgt_t *t) 570*7c478bd9Sstevel@tonic-gate { 571*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 572*7c478bd9Sstevel@tonic-gate 573*7c478bd9Sstevel@tonic-gate const mdb_tgt_regdesc_t *rdp; 574*7c478bd9Sstevel@tonic-gate const mdb_dcmd_t *dcp; 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate for (rdp = kt->k_rds; rdp->rd_name != NULL; rdp++) { 577*7c478bd9Sstevel@tonic-gate mdb_var_t *v; 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate if (!(rdp->rd_flags & MDB_TGT_R_EXPORT)) 580*7c478bd9Sstevel@tonic-gate continue; /* Didn't export register as a variable */ 581*7c478bd9Sstevel@tonic-gate 582*7c478bd9Sstevel@tonic-gate if ((v = mdb_nv_lookup(&mdb.m_nv, rdp->rd_name)) != NULL) { 583*7c478bd9Sstevel@tonic-gate v->v_flags &= ~MDB_NV_PERSIST; 584*7c478bd9Sstevel@tonic-gate mdb_nv_remove(&mdb.m_nv, v); 585*7c478bd9Sstevel@tonic-gate } 586*7c478bd9Sstevel@tonic-gate } 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate for (dcp = &kt_dcmds[0]; dcp->dc_name != NULL; dcp++) { 589*7c478bd9Sstevel@tonic-gate if (mdb_module_remove_dcmd(t->t_module, dcp->dc_name) == -1) 590*7c478bd9Sstevel@tonic-gate warn("failed to remove dcmd %s", dcp->dc_name); 591*7c478bd9Sstevel@tonic-gate } 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate mdb_prop_postmortem = FALSE; 594*7c478bd9Sstevel@tonic-gate mdb_prop_kernel = FALSE; 595*7c478bd9Sstevel@tonic-gate mdb_prop_datamodel = MDB_TGT_MODEL_UNKNOWN; 596*7c478bd9Sstevel@tonic-gate } 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 599*7c478bd9Sstevel@tonic-gate const char * 600*7c478bd9Sstevel@tonic-gate kt_name(mdb_tgt_t *t) 601*7c478bd9Sstevel@tonic-gate { 602*7c478bd9Sstevel@tonic-gate return ("kvm"); 603*7c478bd9Sstevel@tonic-gate } 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate const char * 606*7c478bd9Sstevel@tonic-gate kt_platform(mdb_tgt_t *t) 607*7c478bd9Sstevel@tonic-gate { 608*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 609*7c478bd9Sstevel@tonic-gate return (kt->k_platform); 610*7c478bd9Sstevel@tonic-gate } 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate int 613*7c478bd9Sstevel@tonic-gate kt_uname(mdb_tgt_t *t, struct utsname *utsp) 614*7c478bd9Sstevel@tonic-gate { 615*7c478bd9Sstevel@tonic-gate return (mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, utsp, 616*7c478bd9Sstevel@tonic-gate sizeof (struct utsname), MDB_TGT_OBJ_EXEC, "utsname")); 617*7c478bd9Sstevel@tonic-gate } 618*7c478bd9Sstevel@tonic-gate 619*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 620*7c478bd9Sstevel@tonic-gate int 621*7c478bd9Sstevel@tonic-gate kt_dmodel(mdb_tgt_t *t) 622*7c478bd9Sstevel@tonic-gate { 623*7c478bd9Sstevel@tonic-gate return (MDB_TGT_MODEL_NATIVE); 624*7c478bd9Sstevel@tonic-gate } 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate ssize_t 627*7c478bd9Sstevel@tonic-gate kt_aread(mdb_tgt_t *t, mdb_tgt_as_t as, void *buf, 628*7c478bd9Sstevel@tonic-gate size_t nbytes, mdb_tgt_addr_t addr) 629*7c478bd9Sstevel@tonic-gate { 630*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 631*7c478bd9Sstevel@tonic-gate ssize_t rval; 632*7c478bd9Sstevel@tonic-gate 633*7c478bd9Sstevel@tonic-gate if ((rval = kt->k_aread(kt->k_cookie, addr, buf, nbytes, as)) == -1) 634*7c478bd9Sstevel@tonic-gate return (set_errno(EMDB_NOMAP)); 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate return (rval); 637*7c478bd9Sstevel@tonic-gate } 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate ssize_t 640*7c478bd9Sstevel@tonic-gate kt_awrite(mdb_tgt_t *t, mdb_tgt_as_t as, const void *buf, 641*7c478bd9Sstevel@tonic-gate size_t nbytes, mdb_tgt_addr_t addr) 642*7c478bd9Sstevel@tonic-gate { 643*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 644*7c478bd9Sstevel@tonic-gate ssize_t rval; 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate if ((rval = kt->k_awrite(kt->k_cookie, addr, buf, nbytes, as)) == -1) 647*7c478bd9Sstevel@tonic-gate return (set_errno(EMDB_NOMAP)); 648*7c478bd9Sstevel@tonic-gate 649*7c478bd9Sstevel@tonic-gate return (rval); 650*7c478bd9Sstevel@tonic-gate } 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate ssize_t 653*7c478bd9Sstevel@tonic-gate kt_vread(mdb_tgt_t *t, void *buf, size_t nbytes, uintptr_t addr) 654*7c478bd9Sstevel@tonic-gate { 655*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 656*7c478bd9Sstevel@tonic-gate ssize_t rval; 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate if ((rval = kvm_kread(kt->k_cookie, addr, buf, nbytes)) == -1) 659*7c478bd9Sstevel@tonic-gate return (set_errno(EMDB_NOMAP)); 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate return (rval); 662*7c478bd9Sstevel@tonic-gate } 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate ssize_t 665*7c478bd9Sstevel@tonic-gate kt_vwrite(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr) 666*7c478bd9Sstevel@tonic-gate { 667*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 668*7c478bd9Sstevel@tonic-gate ssize_t rval; 669*7c478bd9Sstevel@tonic-gate 670*7c478bd9Sstevel@tonic-gate if ((rval = kvm_kwrite(kt->k_cookie, addr, buf, nbytes)) == -1) 671*7c478bd9Sstevel@tonic-gate return (set_errno(EMDB_NOMAP)); 672*7c478bd9Sstevel@tonic-gate 673*7c478bd9Sstevel@tonic-gate return (rval); 674*7c478bd9Sstevel@tonic-gate } 675*7c478bd9Sstevel@tonic-gate 676*7c478bd9Sstevel@tonic-gate ssize_t 677*7c478bd9Sstevel@tonic-gate kt_fread(mdb_tgt_t *t, void *buf, size_t nbytes, uintptr_t addr) 678*7c478bd9Sstevel@tonic-gate { 679*7c478bd9Sstevel@tonic-gate return (kt_vread(t, buf, nbytes, addr)); 680*7c478bd9Sstevel@tonic-gate } 681*7c478bd9Sstevel@tonic-gate 682*7c478bd9Sstevel@tonic-gate ssize_t 683*7c478bd9Sstevel@tonic-gate kt_fwrite(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr) 684*7c478bd9Sstevel@tonic-gate { 685*7c478bd9Sstevel@tonic-gate return (kt_vwrite(t, buf, nbytes, addr)); 686*7c478bd9Sstevel@tonic-gate } 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate ssize_t 689*7c478bd9Sstevel@tonic-gate kt_pread(mdb_tgt_t *t, void *buf, size_t nbytes, physaddr_t addr) 690*7c478bd9Sstevel@tonic-gate { 691*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 692*7c478bd9Sstevel@tonic-gate ssize_t rval; 693*7c478bd9Sstevel@tonic-gate 694*7c478bd9Sstevel@tonic-gate if ((rval = kt->k_pread(kt->k_cookie, addr, buf, nbytes)) == -1) 695*7c478bd9Sstevel@tonic-gate return (set_errno(EMDB_NOMAP)); 696*7c478bd9Sstevel@tonic-gate 697*7c478bd9Sstevel@tonic-gate return (rval); 698*7c478bd9Sstevel@tonic-gate } 699*7c478bd9Sstevel@tonic-gate 700*7c478bd9Sstevel@tonic-gate ssize_t 701*7c478bd9Sstevel@tonic-gate kt_pwrite(mdb_tgt_t *t, const void *buf, size_t nbytes, physaddr_t addr) 702*7c478bd9Sstevel@tonic-gate { 703*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 704*7c478bd9Sstevel@tonic-gate ssize_t rval; 705*7c478bd9Sstevel@tonic-gate 706*7c478bd9Sstevel@tonic-gate if ((rval = kt->k_pwrite(kt->k_cookie, addr, buf, nbytes)) == -1) 707*7c478bd9Sstevel@tonic-gate return (set_errno(EMDB_NOMAP)); 708*7c478bd9Sstevel@tonic-gate 709*7c478bd9Sstevel@tonic-gate return (rval); 710*7c478bd9Sstevel@tonic-gate } 711*7c478bd9Sstevel@tonic-gate 712*7c478bd9Sstevel@tonic-gate int 713*7c478bd9Sstevel@tonic-gate kt_vtop(mdb_tgt_t *t, mdb_tgt_as_t as, uintptr_t va, physaddr_t *pap) 714*7c478bd9Sstevel@tonic-gate { 715*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 716*7c478bd9Sstevel@tonic-gate 717*7c478bd9Sstevel@tonic-gate struct as *asp; 718*7c478bd9Sstevel@tonic-gate physaddr_t pa; 719*7c478bd9Sstevel@tonic-gate mdb_module_t *mod; 720*7c478bd9Sstevel@tonic-gate mdb_var_t *v; 721*7c478bd9Sstevel@tonic-gate int (*fptr)(uintptr_t, struct as *, physaddr_t *); 722*7c478bd9Sstevel@tonic-gate 723*7c478bd9Sstevel@tonic-gate switch ((uintptr_t)as) { 724*7c478bd9Sstevel@tonic-gate case (uintptr_t)MDB_TGT_AS_PHYS: 725*7c478bd9Sstevel@tonic-gate case (uintptr_t)MDB_TGT_AS_FILE: 726*7c478bd9Sstevel@tonic-gate case (uintptr_t)MDB_TGT_AS_IO: 727*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 728*7c478bd9Sstevel@tonic-gate case (uintptr_t)MDB_TGT_AS_VIRT: 729*7c478bd9Sstevel@tonic-gate asp = kt->k_as; 730*7c478bd9Sstevel@tonic-gate break; 731*7c478bd9Sstevel@tonic-gate default: 732*7c478bd9Sstevel@tonic-gate asp = (struct as *)as; 733*7c478bd9Sstevel@tonic-gate } 734*7c478bd9Sstevel@tonic-gate 735*7c478bd9Sstevel@tonic-gate if ((pa = kvm_physaddr(kt->k_cookie, asp, va)) != -1ULL) { 736*7c478bd9Sstevel@tonic-gate *pap = pa; 737*7c478bd9Sstevel@tonic-gate return (0); 738*7c478bd9Sstevel@tonic-gate } 739*7c478bd9Sstevel@tonic-gate 740*7c478bd9Sstevel@tonic-gate if ((v = mdb_nv_lookup(&mdb.m_modules, "unix")) != NULL && 741*7c478bd9Sstevel@tonic-gate (mod = mdb_nv_get_cookie(v)) != NULL) { 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate fptr = (int (*)(uintptr_t, struct as *, physaddr_t *)) 744*7c478bd9Sstevel@tonic-gate dlsym(mod->mod_hdl, "platform_vtop"); 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate if ((fptr != NULL) && ((*fptr)(va, asp, pap) == 0)) 747*7c478bd9Sstevel@tonic-gate return (0); 748*7c478bd9Sstevel@tonic-gate } 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate return (set_errno(EMDB_NOMAP)); 751*7c478bd9Sstevel@tonic-gate } 752*7c478bd9Sstevel@tonic-gate 753*7c478bd9Sstevel@tonic-gate int 754*7c478bd9Sstevel@tonic-gate kt_lookup_by_name(mdb_tgt_t *t, const char *obj, const char *name, 755*7c478bd9Sstevel@tonic-gate GElf_Sym *symp, mdb_syminfo_t *sip) 756*7c478bd9Sstevel@tonic-gate { 757*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 758*7c478bd9Sstevel@tonic-gate kt_module_t *km, kmod; 759*7c478bd9Sstevel@tonic-gate mdb_var_t *v; 760*7c478bd9Sstevel@tonic-gate int n; 761*7c478bd9Sstevel@tonic-gate 762*7c478bd9Sstevel@tonic-gate /* 763*7c478bd9Sstevel@tonic-gate * To simplify the implementation, we create a fake module on the stack 764*7c478bd9Sstevel@tonic-gate * which is "prepended" to k_modlist and whose symtab is kt->k_symtab. 765*7c478bd9Sstevel@tonic-gate */ 766*7c478bd9Sstevel@tonic-gate kmod.km_symtab = kt->k_symtab; 767*7c478bd9Sstevel@tonic-gate kmod.km_list.ml_next = mdb_list_next(&kt->k_modlist); 768*7c478bd9Sstevel@tonic-gate 769*7c478bd9Sstevel@tonic-gate switch ((uintptr_t)obj) { 770*7c478bd9Sstevel@tonic-gate case (uintptr_t)MDB_TGT_OBJ_EXEC: 771*7c478bd9Sstevel@tonic-gate km = &kmod; 772*7c478bd9Sstevel@tonic-gate n = 1; 773*7c478bd9Sstevel@tonic-gate break; 774*7c478bd9Sstevel@tonic-gate 775*7c478bd9Sstevel@tonic-gate case (uintptr_t)MDB_TGT_OBJ_EVERY: 776*7c478bd9Sstevel@tonic-gate km = &kmod; 777*7c478bd9Sstevel@tonic-gate n = mdb_nv_size(&kt->k_modules) + 1; 778*7c478bd9Sstevel@tonic-gate break; 779*7c478bd9Sstevel@tonic-gate 780*7c478bd9Sstevel@tonic-gate case (uintptr_t)MDB_TGT_OBJ_RTLD: 781*7c478bd9Sstevel@tonic-gate obj = KT_RTLD_NAME; 782*7c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 783*7c478bd9Sstevel@tonic-gate 784*7c478bd9Sstevel@tonic-gate default: 785*7c478bd9Sstevel@tonic-gate if ((v = mdb_nv_lookup(&kt->k_modules, obj)) == NULL) 786*7c478bd9Sstevel@tonic-gate return (set_errno(EMDB_NOOBJ)); 787*7c478bd9Sstevel@tonic-gate 788*7c478bd9Sstevel@tonic-gate km = mdb_nv_get_cookie(v); 789*7c478bd9Sstevel@tonic-gate n = 1; 790*7c478bd9Sstevel@tonic-gate 791*7c478bd9Sstevel@tonic-gate if (km->km_symtab == NULL) 792*7c478bd9Sstevel@tonic-gate kt_load_module(kt, t, km); 793*7c478bd9Sstevel@tonic-gate } 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate for (; n > 0; n--, km = mdb_list_next(km)) { 796*7c478bd9Sstevel@tonic-gate if (mdb_gelf_symtab_lookup_by_name(km->km_symtab, name, 797*7c478bd9Sstevel@tonic-gate symp, &sip->sym_id) == 0) { 798*7c478bd9Sstevel@tonic-gate sip->sym_table = MDB_TGT_SYMTAB; 799*7c478bd9Sstevel@tonic-gate return (0); 800*7c478bd9Sstevel@tonic-gate } 801*7c478bd9Sstevel@tonic-gate } 802*7c478bd9Sstevel@tonic-gate 803*7c478bd9Sstevel@tonic-gate return (set_errno(EMDB_NOSYM)); 804*7c478bd9Sstevel@tonic-gate } 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate int 807*7c478bd9Sstevel@tonic-gate kt_lookup_by_addr(mdb_tgt_t *t, uintptr_t addr, uint_t flags, 808*7c478bd9Sstevel@tonic-gate char *buf, size_t nbytes, GElf_Sym *symp, mdb_syminfo_t *sip) 809*7c478bd9Sstevel@tonic-gate { 810*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 811*7c478bd9Sstevel@tonic-gate kt_module_t kmods[3], *kmods_begin = &kmods[0], *kmods_end; 812*7c478bd9Sstevel@tonic-gate const char *name; 813*7c478bd9Sstevel@tonic-gate 814*7c478bd9Sstevel@tonic-gate kt_module_t *km = &kmods[0]; /* Point km at first fake module */ 815*7c478bd9Sstevel@tonic-gate kt_module_t *sym_km = NULL; /* Module associated with best sym */ 816*7c478bd9Sstevel@tonic-gate GElf_Sym sym; /* Best symbol found so far if !exact */ 817*7c478bd9Sstevel@tonic-gate uint_t symid; /* ID of best symbol found so far */ 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate /* 820*7c478bd9Sstevel@tonic-gate * To simplify the implementation, we create fake modules on the stack 821*7c478bd9Sstevel@tonic-gate * that are "prepended" to k_modlist and whose symtab is set to 822*7c478bd9Sstevel@tonic-gate * each of three special symbol tables, in order of precedence. 823*7c478bd9Sstevel@tonic-gate */ 824*7c478bd9Sstevel@tonic-gate km->km_symtab = mdb.m_prsym; 825*7c478bd9Sstevel@tonic-gate 826*7c478bd9Sstevel@tonic-gate if (kt->k_symtab != NULL) { 827*7c478bd9Sstevel@tonic-gate km->km_list.ml_next = (mdb_list_t *)(km + 1); 828*7c478bd9Sstevel@tonic-gate km = mdb_list_next(km); 829*7c478bd9Sstevel@tonic-gate km->km_symtab = kt->k_symtab; 830*7c478bd9Sstevel@tonic-gate } 831*7c478bd9Sstevel@tonic-gate 832*7c478bd9Sstevel@tonic-gate if (kt->k_dynsym != NULL) { 833*7c478bd9Sstevel@tonic-gate km->km_list.ml_next = (mdb_list_t *)(km + 1); 834*7c478bd9Sstevel@tonic-gate km = mdb_list_next(km); 835*7c478bd9Sstevel@tonic-gate km->km_symtab = kt->k_dynsym; 836*7c478bd9Sstevel@tonic-gate } 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate km->km_list.ml_next = mdb_list_next(&kt->k_modlist); 839*7c478bd9Sstevel@tonic-gate kmods_end = km; 840*7c478bd9Sstevel@tonic-gate 841*7c478bd9Sstevel@tonic-gate /* 842*7c478bd9Sstevel@tonic-gate * Now iterate over the list of fake and real modules. If the module 843*7c478bd9Sstevel@tonic-gate * has no symbol table and the address is in the text section, 844*7c478bd9Sstevel@tonic-gate * instantiate the module's symbol table. In exact mode, we can 845*7c478bd9Sstevel@tonic-gate * jump to 'found' immediately if we match. Otherwise we continue 846*7c478bd9Sstevel@tonic-gate * looking and improve our choice if we find a closer symbol. 847*7c478bd9Sstevel@tonic-gate */ 848*7c478bd9Sstevel@tonic-gate for (km = &kmods[0]; km != NULL; km = mdb_list_next(km)) { 849*7c478bd9Sstevel@tonic-gate if (km->km_symtab == NULL && addr >= km->km_text_va && 850*7c478bd9Sstevel@tonic-gate addr < km->km_text_va + km->km_text_size) 851*7c478bd9Sstevel@tonic-gate kt_load_module(kt, t, km); 852*7c478bd9Sstevel@tonic-gate 853*7c478bd9Sstevel@tonic-gate if (mdb_gelf_symtab_lookup_by_addr(km->km_symtab, addr, 854*7c478bd9Sstevel@tonic-gate flags, buf, nbytes, symp, &sip->sym_id) != 0 || 855*7c478bd9Sstevel@tonic-gate symp->st_value == 0) 856*7c478bd9Sstevel@tonic-gate continue; 857*7c478bd9Sstevel@tonic-gate 858*7c478bd9Sstevel@tonic-gate if (flags & MDB_TGT_SYM_EXACT) { 859*7c478bd9Sstevel@tonic-gate sym_km = km; 860*7c478bd9Sstevel@tonic-gate goto found; 861*7c478bd9Sstevel@tonic-gate } 862*7c478bd9Sstevel@tonic-gate 863*7c478bd9Sstevel@tonic-gate if (sym_km == NULL || mdb_gelf_sym_closer(symp, &sym, addr)) { 864*7c478bd9Sstevel@tonic-gate sym_km = km; 865*7c478bd9Sstevel@tonic-gate sym = *symp; 866*7c478bd9Sstevel@tonic-gate symid = sip->sym_id; 867*7c478bd9Sstevel@tonic-gate } 868*7c478bd9Sstevel@tonic-gate } 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate if (sym_km == NULL) 871*7c478bd9Sstevel@tonic-gate return (set_errno(EMDB_NOSYMADDR)); 872*7c478bd9Sstevel@tonic-gate 873*7c478bd9Sstevel@tonic-gate *symp = sym; /* Copy our best symbol into the caller's symbol */ 874*7c478bd9Sstevel@tonic-gate sip->sym_id = symid; 875*7c478bd9Sstevel@tonic-gate found: 876*7c478bd9Sstevel@tonic-gate /* 877*7c478bd9Sstevel@tonic-gate * Once we've found something, copy the final name into the caller's 878*7c478bd9Sstevel@tonic-gate * buffer and prefix it with the load object name if appropriate. 879*7c478bd9Sstevel@tonic-gate */ 880*7c478bd9Sstevel@tonic-gate name = mdb_gelf_sym_name(sym_km->km_symtab, symp); 881*7c478bd9Sstevel@tonic-gate 882*7c478bd9Sstevel@tonic-gate if (sym_km < kmods_begin || sym_km > kmods_end) { 883*7c478bd9Sstevel@tonic-gate (void) mdb_snprintf(buf, nbytes, "%s`%s", 884*7c478bd9Sstevel@tonic-gate sym_km->km_name, name); 885*7c478bd9Sstevel@tonic-gate } else if (nbytes > 0) { 886*7c478bd9Sstevel@tonic-gate (void) strncpy(buf, name, nbytes); 887*7c478bd9Sstevel@tonic-gate buf[nbytes - 1] = '\0'; 888*7c478bd9Sstevel@tonic-gate } 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate if (sym_km->km_symtab == mdb.m_prsym) 891*7c478bd9Sstevel@tonic-gate sip->sym_table = MDB_TGT_PRVSYM; 892*7c478bd9Sstevel@tonic-gate else 893*7c478bd9Sstevel@tonic-gate sip->sym_table = MDB_TGT_SYMTAB; 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate return (0); 896*7c478bd9Sstevel@tonic-gate } 897*7c478bd9Sstevel@tonic-gate 898*7c478bd9Sstevel@tonic-gate static int 899*7c478bd9Sstevel@tonic-gate kt_symtab_func(void *data, const GElf_Sym *sym, const char *name, uint_t id) 900*7c478bd9Sstevel@tonic-gate { 901*7c478bd9Sstevel@tonic-gate kt_symarg_t *argp = data; 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate if (mdb_tgt_sym_match(sym, argp->sym_type)) { 904*7c478bd9Sstevel@tonic-gate argp->sym_info.sym_id = id; 905*7c478bd9Sstevel@tonic-gate 906*7c478bd9Sstevel@tonic-gate return (argp->sym_cb(argp->sym_data, sym, name, 907*7c478bd9Sstevel@tonic-gate &argp->sym_info, argp->sym_obj)); 908*7c478bd9Sstevel@tonic-gate } 909*7c478bd9Sstevel@tonic-gate 910*7c478bd9Sstevel@tonic-gate return (0); 911*7c478bd9Sstevel@tonic-gate } 912*7c478bd9Sstevel@tonic-gate 913*7c478bd9Sstevel@tonic-gate static void 914*7c478bd9Sstevel@tonic-gate kt_symtab_iter(mdb_gelf_symtab_t *gst, uint_t type, const char *obj, 915*7c478bd9Sstevel@tonic-gate mdb_tgt_sym_f *cb, void *p) 916*7c478bd9Sstevel@tonic-gate { 917*7c478bd9Sstevel@tonic-gate kt_symarg_t arg; 918*7c478bd9Sstevel@tonic-gate 919*7c478bd9Sstevel@tonic-gate arg.sym_cb = cb; 920*7c478bd9Sstevel@tonic-gate arg.sym_data = p; 921*7c478bd9Sstevel@tonic-gate arg.sym_type = type; 922*7c478bd9Sstevel@tonic-gate arg.sym_info.sym_table = gst->gst_tabid; 923*7c478bd9Sstevel@tonic-gate arg.sym_obj = obj; 924*7c478bd9Sstevel@tonic-gate 925*7c478bd9Sstevel@tonic-gate mdb_gelf_symtab_iter(gst, kt_symtab_func, &arg); 926*7c478bd9Sstevel@tonic-gate } 927*7c478bd9Sstevel@tonic-gate 928*7c478bd9Sstevel@tonic-gate int 929*7c478bd9Sstevel@tonic-gate kt_symbol_iter(mdb_tgt_t *t, const char *obj, uint_t which, uint_t type, 930*7c478bd9Sstevel@tonic-gate mdb_tgt_sym_f *cb, void *data) 931*7c478bd9Sstevel@tonic-gate { 932*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 933*7c478bd9Sstevel@tonic-gate kt_module_t *km; 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate mdb_gelf_symtab_t *symtab = NULL; 936*7c478bd9Sstevel@tonic-gate mdb_var_t *v; 937*7c478bd9Sstevel@tonic-gate 938*7c478bd9Sstevel@tonic-gate switch ((uintptr_t)obj) { 939*7c478bd9Sstevel@tonic-gate case (uintptr_t)MDB_TGT_OBJ_EXEC: 940*7c478bd9Sstevel@tonic-gate if (which == MDB_TGT_SYMTAB) 941*7c478bd9Sstevel@tonic-gate symtab = kt->k_symtab; 942*7c478bd9Sstevel@tonic-gate else 943*7c478bd9Sstevel@tonic-gate symtab = kt->k_dynsym; 944*7c478bd9Sstevel@tonic-gate break; 945*7c478bd9Sstevel@tonic-gate 946*7c478bd9Sstevel@tonic-gate case (uintptr_t)MDB_TGT_OBJ_EVERY: 947*7c478bd9Sstevel@tonic-gate if (which == MDB_TGT_DYNSYM) { 948*7c478bd9Sstevel@tonic-gate symtab = kt->k_dynsym; 949*7c478bd9Sstevel@tonic-gate obj = MDB_TGT_OBJ_EXEC; 950*7c478bd9Sstevel@tonic-gate break; 951*7c478bd9Sstevel@tonic-gate } 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate mdb_nv_rewind(&kt->k_modules); 954*7c478bd9Sstevel@tonic-gate while ((v = mdb_nv_advance(&kt->k_modules)) != NULL) { 955*7c478bd9Sstevel@tonic-gate km = mdb_nv_get_cookie(v); 956*7c478bd9Sstevel@tonic-gate 957*7c478bd9Sstevel@tonic-gate if (km->km_symtab == NULL) 958*7c478bd9Sstevel@tonic-gate kt_load_module(kt, t, km); 959*7c478bd9Sstevel@tonic-gate 960*7c478bd9Sstevel@tonic-gate if (km->km_symtab != NULL) 961*7c478bd9Sstevel@tonic-gate kt_symtab_iter(km->km_symtab, type, 962*7c478bd9Sstevel@tonic-gate km->km_name, cb, data); 963*7c478bd9Sstevel@tonic-gate } 964*7c478bd9Sstevel@tonic-gate break; 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate case (uintptr_t)MDB_TGT_OBJ_RTLD: 967*7c478bd9Sstevel@tonic-gate obj = KT_RTLD_NAME; 968*7c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate default: 971*7c478bd9Sstevel@tonic-gate v = mdb_nv_lookup(&kt->k_modules, obj); 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate if (v == NULL) 974*7c478bd9Sstevel@tonic-gate return (set_errno(EMDB_NOOBJ)); 975*7c478bd9Sstevel@tonic-gate 976*7c478bd9Sstevel@tonic-gate km = mdb_nv_get_cookie(v); 977*7c478bd9Sstevel@tonic-gate 978*7c478bd9Sstevel@tonic-gate if (km->km_symtab == NULL) 979*7c478bd9Sstevel@tonic-gate kt_load_module(kt, t, km); 980*7c478bd9Sstevel@tonic-gate 981*7c478bd9Sstevel@tonic-gate symtab = km->km_symtab; 982*7c478bd9Sstevel@tonic-gate } 983*7c478bd9Sstevel@tonic-gate 984*7c478bd9Sstevel@tonic-gate if (symtab) 985*7c478bd9Sstevel@tonic-gate kt_symtab_iter(symtab, type, obj, cb, data); 986*7c478bd9Sstevel@tonic-gate 987*7c478bd9Sstevel@tonic-gate return (0); 988*7c478bd9Sstevel@tonic-gate } 989*7c478bd9Sstevel@tonic-gate 990*7c478bd9Sstevel@tonic-gate static int 991*7c478bd9Sstevel@tonic-gate kt_mapping_walk(uintptr_t addr, const void *data, kt_maparg_t *marg) 992*7c478bd9Sstevel@tonic-gate { 993*7c478bd9Sstevel@tonic-gate /* 994*7c478bd9Sstevel@tonic-gate * This is a bit sketchy but avoids problematic compilation of this 995*7c478bd9Sstevel@tonic-gate * target against the current VM implementation. Now that we have 996*7c478bd9Sstevel@tonic-gate * vmem, we can make this less broken and more informative by changing 997*7c478bd9Sstevel@tonic-gate * this code to invoke the vmem walker in the near future. 998*7c478bd9Sstevel@tonic-gate */ 999*7c478bd9Sstevel@tonic-gate const struct kt_seg { 1000*7c478bd9Sstevel@tonic-gate caddr_t s_base; 1001*7c478bd9Sstevel@tonic-gate size_t s_size; 1002*7c478bd9Sstevel@tonic-gate } *segp = (const struct kt_seg *)data; 1003*7c478bd9Sstevel@tonic-gate 1004*7c478bd9Sstevel@tonic-gate mdb_map_t map; 1005*7c478bd9Sstevel@tonic-gate GElf_Sym sym; 1006*7c478bd9Sstevel@tonic-gate mdb_syminfo_t info; 1007*7c478bd9Sstevel@tonic-gate 1008*7c478bd9Sstevel@tonic-gate map.map_base = (uintptr_t)segp->s_base; 1009*7c478bd9Sstevel@tonic-gate map.map_size = segp->s_size; 1010*7c478bd9Sstevel@tonic-gate map.map_flags = MDB_TGT_MAP_R | MDB_TGT_MAP_W | MDB_TGT_MAP_X; 1011*7c478bd9Sstevel@tonic-gate 1012*7c478bd9Sstevel@tonic-gate if (kt_lookup_by_addr(marg->map_target, addr, MDB_TGT_SYM_EXACT, 1013*7c478bd9Sstevel@tonic-gate map.map_name, MDB_TGT_MAPSZ, &sym, &info) == -1) { 1014*7c478bd9Sstevel@tonic-gate 1015*7c478bd9Sstevel@tonic-gate (void) mdb_iob_snprintf(map.map_name, MDB_TGT_MAPSZ, 1016*7c478bd9Sstevel@tonic-gate "%lr", addr); 1017*7c478bd9Sstevel@tonic-gate } 1018*7c478bd9Sstevel@tonic-gate 1019*7c478bd9Sstevel@tonic-gate return (marg->map_cb(marg->map_data, &map, map.map_name)); 1020*7c478bd9Sstevel@tonic-gate } 1021*7c478bd9Sstevel@tonic-gate 1022*7c478bd9Sstevel@tonic-gate int 1023*7c478bd9Sstevel@tonic-gate kt_mapping_iter(mdb_tgt_t *t, mdb_tgt_map_f *func, void *private) 1024*7c478bd9Sstevel@tonic-gate { 1025*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 1026*7c478bd9Sstevel@tonic-gate kt_maparg_t m; 1027*7c478bd9Sstevel@tonic-gate 1028*7c478bd9Sstevel@tonic-gate m.map_target = t; 1029*7c478bd9Sstevel@tonic-gate m.map_cb = func; 1030*7c478bd9Sstevel@tonic-gate m.map_data = private; 1031*7c478bd9Sstevel@tonic-gate 1032*7c478bd9Sstevel@tonic-gate return (mdb_pwalk("seg", (mdb_walk_cb_t)kt_mapping_walk, &m, 1033*7c478bd9Sstevel@tonic-gate (uintptr_t)kt->k_as)); 1034*7c478bd9Sstevel@tonic-gate } 1035*7c478bd9Sstevel@tonic-gate 1036*7c478bd9Sstevel@tonic-gate static const mdb_map_t * 1037*7c478bd9Sstevel@tonic-gate kt_module_to_map(kt_module_t *km, mdb_map_t *map) 1038*7c478bd9Sstevel@tonic-gate { 1039*7c478bd9Sstevel@tonic-gate (void) strncpy(map->map_name, km->km_name, MDB_TGT_MAPSZ); 1040*7c478bd9Sstevel@tonic-gate map->map_name[MDB_TGT_MAPSZ - 1] = '\0'; 1041*7c478bd9Sstevel@tonic-gate map->map_base = km->km_text_va; 1042*7c478bd9Sstevel@tonic-gate map->map_size = km->km_text_size; 1043*7c478bd9Sstevel@tonic-gate map->map_flags = MDB_TGT_MAP_R | MDB_TGT_MAP_W | MDB_TGT_MAP_X; 1044*7c478bd9Sstevel@tonic-gate 1045*7c478bd9Sstevel@tonic-gate return (map); 1046*7c478bd9Sstevel@tonic-gate } 1047*7c478bd9Sstevel@tonic-gate 1048*7c478bd9Sstevel@tonic-gate int 1049*7c478bd9Sstevel@tonic-gate kt_object_iter(mdb_tgt_t *t, mdb_tgt_map_f *func, void *private) 1050*7c478bd9Sstevel@tonic-gate { 1051*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 1052*7c478bd9Sstevel@tonic-gate kt_module_t *km; 1053*7c478bd9Sstevel@tonic-gate mdb_map_t m; 1054*7c478bd9Sstevel@tonic-gate 1055*7c478bd9Sstevel@tonic-gate for (km = mdb_list_next(&kt->k_modlist); km; km = mdb_list_next(km)) { 1056*7c478bd9Sstevel@tonic-gate if (func(private, kt_module_to_map(km, &m), km->km_name) == -1) 1057*7c478bd9Sstevel@tonic-gate break; 1058*7c478bd9Sstevel@tonic-gate } 1059*7c478bd9Sstevel@tonic-gate 1060*7c478bd9Sstevel@tonic-gate return (0); 1061*7c478bd9Sstevel@tonic-gate } 1062*7c478bd9Sstevel@tonic-gate 1063*7c478bd9Sstevel@tonic-gate const mdb_map_t * 1064*7c478bd9Sstevel@tonic-gate kt_addr_to_map(mdb_tgt_t *t, uintptr_t addr) 1065*7c478bd9Sstevel@tonic-gate { 1066*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 1067*7c478bd9Sstevel@tonic-gate kt_module_t *km; 1068*7c478bd9Sstevel@tonic-gate 1069*7c478bd9Sstevel@tonic-gate for (km = mdb_list_next(&kt->k_modlist); km; km = mdb_list_next(km)) { 1070*7c478bd9Sstevel@tonic-gate if (addr - km->km_text_va < km->km_text_size || 1071*7c478bd9Sstevel@tonic-gate addr - km->km_data_va < km->km_data_size || 1072*7c478bd9Sstevel@tonic-gate addr - km->km_bss_va < km->km_bss_size) 1073*7c478bd9Sstevel@tonic-gate return (kt_module_to_map(km, &kt->k_map)); 1074*7c478bd9Sstevel@tonic-gate } 1075*7c478bd9Sstevel@tonic-gate 1076*7c478bd9Sstevel@tonic-gate (void) set_errno(EMDB_NOMAP); 1077*7c478bd9Sstevel@tonic-gate return (NULL); 1078*7c478bd9Sstevel@tonic-gate } 1079*7c478bd9Sstevel@tonic-gate 1080*7c478bd9Sstevel@tonic-gate const mdb_map_t * 1081*7c478bd9Sstevel@tonic-gate kt_name_to_map(mdb_tgt_t *t, const char *name) 1082*7c478bd9Sstevel@tonic-gate { 1083*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 1084*7c478bd9Sstevel@tonic-gate kt_module_t *km; 1085*7c478bd9Sstevel@tonic-gate mdb_map_t m; 1086*7c478bd9Sstevel@tonic-gate 1087*7c478bd9Sstevel@tonic-gate /* 1088*7c478bd9Sstevel@tonic-gate * If name is MDB_TGT_OBJ_EXEC, return the first module on the list, 1089*7c478bd9Sstevel@tonic-gate * which will be unix since we keep k_modlist in load order. 1090*7c478bd9Sstevel@tonic-gate */ 1091*7c478bd9Sstevel@tonic-gate if (name == MDB_TGT_OBJ_EXEC) 1092*7c478bd9Sstevel@tonic-gate return (kt_module_to_map(mdb_list_next(&kt->k_modlist), &m)); 1093*7c478bd9Sstevel@tonic-gate 1094*7c478bd9Sstevel@tonic-gate if (name == MDB_TGT_OBJ_RTLD) 1095*7c478bd9Sstevel@tonic-gate name = KT_RTLD_NAME; /* replace MDB_TGT_OBJ_RTLD with krtld */ 1096*7c478bd9Sstevel@tonic-gate 1097*7c478bd9Sstevel@tonic-gate for (km = mdb_list_next(&kt->k_modlist); km; km = mdb_list_next(km)) { 1098*7c478bd9Sstevel@tonic-gate if (strcmp(name, km->km_name) == 0) 1099*7c478bd9Sstevel@tonic-gate return (kt_module_to_map(km, &m)); 1100*7c478bd9Sstevel@tonic-gate } 1101*7c478bd9Sstevel@tonic-gate 1102*7c478bd9Sstevel@tonic-gate (void) set_errno(EMDB_NOOBJ); 1103*7c478bd9Sstevel@tonic-gate return (NULL); 1104*7c478bd9Sstevel@tonic-gate } 1105*7c478bd9Sstevel@tonic-gate 1106*7c478bd9Sstevel@tonic-gate static ctf_file_t * 1107*7c478bd9Sstevel@tonic-gate kt_load_ctfdata(mdb_tgt_t *t, kt_module_t *km) 1108*7c478bd9Sstevel@tonic-gate { 1109*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 1110*7c478bd9Sstevel@tonic-gate int err; 1111*7c478bd9Sstevel@tonic-gate 1112*7c478bd9Sstevel@tonic-gate if (km->km_ctfp != NULL) 1113*7c478bd9Sstevel@tonic-gate return (km->km_ctfp); 1114*7c478bd9Sstevel@tonic-gate 1115*7c478bd9Sstevel@tonic-gate if (km->km_ctf_va == NULL) { 1116*7c478bd9Sstevel@tonic-gate (void) set_errno(EMDB_NOCTF); 1117*7c478bd9Sstevel@tonic-gate return (NULL); 1118*7c478bd9Sstevel@tonic-gate } 1119*7c478bd9Sstevel@tonic-gate 1120*7c478bd9Sstevel@tonic-gate if (km->km_symtab == NULL) 1121*7c478bd9Sstevel@tonic-gate kt_load_module(t->t_data, t, km); 1122*7c478bd9Sstevel@tonic-gate 1123*7c478bd9Sstevel@tonic-gate if ((km->km_ctf_buf = mdb_alloc(km->km_ctf_size, UM_NOSLEEP)) == NULL) { 1124*7c478bd9Sstevel@tonic-gate warn("failed to allocate memory to load %s debugging " 1125*7c478bd9Sstevel@tonic-gate "information", km->km_name); 1126*7c478bd9Sstevel@tonic-gate return (NULL); 1127*7c478bd9Sstevel@tonic-gate } 1128*7c478bd9Sstevel@tonic-gate 1129*7c478bd9Sstevel@tonic-gate if (mdb_tgt_vread(t, km->km_ctf_buf, km->km_ctf_size, 1130*7c478bd9Sstevel@tonic-gate km->km_ctf_va) != km->km_ctf_size) { 1131*7c478bd9Sstevel@tonic-gate warn("failed to read %lu bytes of debug data for %s at %p", 1132*7c478bd9Sstevel@tonic-gate (ulong_t)km->km_ctf_size, km->km_name, 1133*7c478bd9Sstevel@tonic-gate (void *)km->km_ctf_va); 1134*7c478bd9Sstevel@tonic-gate mdb_free(km->km_ctf_buf, km->km_ctf_size); 1135*7c478bd9Sstevel@tonic-gate km->km_ctf_buf = NULL; 1136*7c478bd9Sstevel@tonic-gate return (NULL); 1137*7c478bd9Sstevel@tonic-gate } 1138*7c478bd9Sstevel@tonic-gate 1139*7c478bd9Sstevel@tonic-gate if ((km->km_ctfp = mdb_ctf_bufopen((const void *)km->km_ctf_buf, 1140*7c478bd9Sstevel@tonic-gate km->km_ctf_size, km->km_symbuf, &km->km_symtab_hdr, 1141*7c478bd9Sstevel@tonic-gate km->km_strtab, &km->km_strtab_hdr, &err)) == NULL) { 1142*7c478bd9Sstevel@tonic-gate mdb_free(km->km_ctf_buf, km->km_ctf_size); 1143*7c478bd9Sstevel@tonic-gate km->km_ctf_buf = NULL; 1144*7c478bd9Sstevel@tonic-gate (void) set_errno(ctf_to_errno(err)); 1145*7c478bd9Sstevel@tonic-gate return (NULL); 1146*7c478bd9Sstevel@tonic-gate } 1147*7c478bd9Sstevel@tonic-gate 1148*7c478bd9Sstevel@tonic-gate mdb_dprintf(MDB_DBG_KMOD, "loaded %lu bytes of CTF data for %s\n", 1149*7c478bd9Sstevel@tonic-gate (ulong_t)km->km_ctf_size, km->km_name); 1150*7c478bd9Sstevel@tonic-gate 1151*7c478bd9Sstevel@tonic-gate if (ctf_parent_name(km->km_ctfp) != NULL) { 1152*7c478bd9Sstevel@tonic-gate mdb_var_t *v; 1153*7c478bd9Sstevel@tonic-gate 1154*7c478bd9Sstevel@tonic-gate if ((v = mdb_nv_lookup(&kt->k_modules, 1155*7c478bd9Sstevel@tonic-gate ctf_parent_name(km->km_ctfp))) == NULL) { 1156*7c478bd9Sstevel@tonic-gate warn("failed to load CTF data for %s - parent %s not " 1157*7c478bd9Sstevel@tonic-gate "loaded\n", km->km_name, 1158*7c478bd9Sstevel@tonic-gate ctf_parent_name(km->km_ctfp)); 1159*7c478bd9Sstevel@tonic-gate } 1160*7c478bd9Sstevel@tonic-gate 1161*7c478bd9Sstevel@tonic-gate if (v != NULL) { 1162*7c478bd9Sstevel@tonic-gate kt_module_t *pm = mdb_nv_get_cookie(v); 1163*7c478bd9Sstevel@tonic-gate 1164*7c478bd9Sstevel@tonic-gate if (pm->km_ctfp == NULL) 1165*7c478bd9Sstevel@tonic-gate (void) kt_load_ctfdata(t, pm); 1166*7c478bd9Sstevel@tonic-gate 1167*7c478bd9Sstevel@tonic-gate if (pm->km_ctfp != NULL && ctf_import(km->km_ctfp, 1168*7c478bd9Sstevel@tonic-gate pm->km_ctfp) == CTF_ERR) { 1169*7c478bd9Sstevel@tonic-gate warn("failed to import parent types into " 1170*7c478bd9Sstevel@tonic-gate "%s: %s\n", km->km_name, 1171*7c478bd9Sstevel@tonic-gate ctf_errmsg(ctf_errno(km->km_ctfp))); 1172*7c478bd9Sstevel@tonic-gate } 1173*7c478bd9Sstevel@tonic-gate } 1174*7c478bd9Sstevel@tonic-gate } 1175*7c478bd9Sstevel@tonic-gate 1176*7c478bd9Sstevel@tonic-gate return (km->km_ctfp); 1177*7c478bd9Sstevel@tonic-gate } 1178*7c478bd9Sstevel@tonic-gate 1179*7c478bd9Sstevel@tonic-gate ctf_file_t * 1180*7c478bd9Sstevel@tonic-gate kt_addr_to_ctf(mdb_tgt_t *t, uintptr_t addr) 1181*7c478bd9Sstevel@tonic-gate { 1182*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 1183*7c478bd9Sstevel@tonic-gate kt_module_t *km; 1184*7c478bd9Sstevel@tonic-gate 1185*7c478bd9Sstevel@tonic-gate for (km = mdb_list_next(&kt->k_modlist); km; km = mdb_list_next(km)) { 1186*7c478bd9Sstevel@tonic-gate if (addr - km->km_text_va < km->km_text_size || 1187*7c478bd9Sstevel@tonic-gate addr - km->km_data_va < km->km_data_size || 1188*7c478bd9Sstevel@tonic-gate addr - km->km_bss_va < km->km_bss_size) 1189*7c478bd9Sstevel@tonic-gate return (kt_load_ctfdata(t, km)); 1190*7c478bd9Sstevel@tonic-gate } 1191*7c478bd9Sstevel@tonic-gate 1192*7c478bd9Sstevel@tonic-gate (void) set_errno(EMDB_NOMAP); 1193*7c478bd9Sstevel@tonic-gate return (NULL); 1194*7c478bd9Sstevel@tonic-gate } 1195*7c478bd9Sstevel@tonic-gate 1196*7c478bd9Sstevel@tonic-gate ctf_file_t * 1197*7c478bd9Sstevel@tonic-gate kt_name_to_ctf(mdb_tgt_t *t, const char *name) 1198*7c478bd9Sstevel@tonic-gate { 1199*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 1200*7c478bd9Sstevel@tonic-gate kt_module_t *km; 1201*7c478bd9Sstevel@tonic-gate 1202*7c478bd9Sstevel@tonic-gate if (name == MDB_TGT_OBJ_EXEC) 1203*7c478bd9Sstevel@tonic-gate name = KT_CTFPARENT; /* base CTF data is kept in genunix */ 1204*7c478bd9Sstevel@tonic-gate else if (name == MDB_TGT_OBJ_RTLD) 1205*7c478bd9Sstevel@tonic-gate name = KT_RTLD_NAME; /* replace MDB_TGT_OBJ_RTLD with krtld */ 1206*7c478bd9Sstevel@tonic-gate 1207*7c478bd9Sstevel@tonic-gate for (km = mdb_list_next(&kt->k_modlist); km; km = mdb_list_next(km)) { 1208*7c478bd9Sstevel@tonic-gate if (strcmp(name, km->km_name) == 0) 1209*7c478bd9Sstevel@tonic-gate return (kt_load_ctfdata(t, km)); 1210*7c478bd9Sstevel@tonic-gate } 1211*7c478bd9Sstevel@tonic-gate 1212*7c478bd9Sstevel@tonic-gate (void) set_errno(EMDB_NOOBJ); 1213*7c478bd9Sstevel@tonic-gate return (NULL); 1214*7c478bd9Sstevel@tonic-gate } 1215*7c478bd9Sstevel@tonic-gate 1216*7c478bd9Sstevel@tonic-gate int 1217*7c478bd9Sstevel@tonic-gate kt_status(mdb_tgt_t *t, mdb_tgt_status_t *tsp) 1218*7c478bd9Sstevel@tonic-gate { 1219*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 1220*7c478bd9Sstevel@tonic-gate 1221*7c478bd9Sstevel@tonic-gate bzero(tsp, sizeof (mdb_tgt_status_t)); 1222*7c478bd9Sstevel@tonic-gate tsp->st_state = kt->k_dumphdr ? MDB_TGT_DEAD : MDB_TGT_RUNNING; 1223*7c478bd9Sstevel@tonic-gate return (0); 1224*7c478bd9Sstevel@tonic-gate } 1225*7c478bd9Sstevel@tonic-gate 1226*7c478bd9Sstevel@tonic-gate static ssize_t 1227*7c478bd9Sstevel@tonic-gate kt_xd_dumphdr(mdb_tgt_t *t, void *buf, size_t nbytes) 1228*7c478bd9Sstevel@tonic-gate { 1229*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 1230*7c478bd9Sstevel@tonic-gate 1231*7c478bd9Sstevel@tonic-gate if (buf == NULL && nbytes == 0) 1232*7c478bd9Sstevel@tonic-gate return (sizeof (dumphdr_t)); 1233*7c478bd9Sstevel@tonic-gate 1234*7c478bd9Sstevel@tonic-gate if (kt->k_dumphdr == NULL) 1235*7c478bd9Sstevel@tonic-gate return (set_errno(ENODATA)); 1236*7c478bd9Sstevel@tonic-gate 1237*7c478bd9Sstevel@tonic-gate nbytes = MIN(nbytes, sizeof (dumphdr_t)); 1238*7c478bd9Sstevel@tonic-gate bcopy(kt->k_dumphdr, buf, nbytes); 1239*7c478bd9Sstevel@tonic-gate 1240*7c478bd9Sstevel@tonic-gate return (nbytes); 1241*7c478bd9Sstevel@tonic-gate } 1242*7c478bd9Sstevel@tonic-gate 1243*7c478bd9Sstevel@tonic-gate void 1244*7c478bd9Sstevel@tonic-gate kt_destroy(mdb_tgt_t *t) 1245*7c478bd9Sstevel@tonic-gate { 1246*7c478bd9Sstevel@tonic-gate kt_data_t *kt = t->t_data; 1247*7c478bd9Sstevel@tonic-gate kt_module_t *km, *nkm; 1248*7c478bd9Sstevel@tonic-gate 1249*7c478bd9Sstevel@tonic-gate (void) mdb_module_unload(KT_MODULE, 0); 1250*7c478bd9Sstevel@tonic-gate 1251*7c478bd9Sstevel@tonic-gate if (kt->k_regs != NULL) 1252*7c478bd9Sstevel@tonic-gate mdb_free(kt->k_regs, kt->k_regsize); 1253*7c478bd9Sstevel@tonic-gate 1254*7c478bd9Sstevel@tonic-gate if (kt->k_symtab != NULL) 1255*7c478bd9Sstevel@tonic-gate mdb_gelf_symtab_destroy(kt->k_symtab); 1256*7c478bd9Sstevel@tonic-gate 1257*7c478bd9Sstevel@tonic-gate if (kt->k_dynsym != NULL) 1258*7c478bd9Sstevel@tonic-gate mdb_gelf_symtab_destroy(kt->k_dynsym); 1259*7c478bd9Sstevel@tonic-gate 1260*7c478bd9Sstevel@tonic-gate if (kt->k_dumphdr != NULL) 1261*7c478bd9Sstevel@tonic-gate mdb_free(kt->k_dumphdr, sizeof (dumphdr_t)); 1262*7c478bd9Sstevel@tonic-gate 1263*7c478bd9Sstevel@tonic-gate mdb_gelf_destroy(kt->k_file); 1264*7c478bd9Sstevel@tonic-gate (void) kvm_close(kt->k_cookie); 1265*7c478bd9Sstevel@tonic-gate 1266*7c478bd9Sstevel@tonic-gate for (km = mdb_list_next(&kt->k_modlist); km; km = nkm) { 1267*7c478bd9Sstevel@tonic-gate if (km->km_symtab) 1268*7c478bd9Sstevel@tonic-gate mdb_gelf_symtab_destroy(km->km_symtab); 1269*7c478bd9Sstevel@tonic-gate 1270*7c478bd9Sstevel@tonic-gate if (km->km_data) 1271*7c478bd9Sstevel@tonic-gate mdb_free(km->km_data, km->km_datasz); 1272*7c478bd9Sstevel@tonic-gate 1273*7c478bd9Sstevel@tonic-gate if (km->km_ctfp) 1274*7c478bd9Sstevel@tonic-gate ctf_close(km->km_ctfp); 1275*7c478bd9Sstevel@tonic-gate 1276*7c478bd9Sstevel@tonic-gate if (km->km_ctf_buf != NULL) 1277*7c478bd9Sstevel@tonic-gate mdb_free(km->km_ctf_buf, km->km_ctf_size); 1278*7c478bd9Sstevel@tonic-gate 1279*7c478bd9Sstevel@tonic-gate nkm = mdb_list_next(km); 1280*7c478bd9Sstevel@tonic-gate strfree(km->km_name); 1281*7c478bd9Sstevel@tonic-gate mdb_free(km, sizeof (kt_module_t)); 1282*7c478bd9Sstevel@tonic-gate } 1283*7c478bd9Sstevel@tonic-gate 1284*7c478bd9Sstevel@tonic-gate mdb_nv_destroy(&kt->k_modules); 1285*7c478bd9Sstevel@tonic-gate 1286*7c478bd9Sstevel@tonic-gate strfree(kt->k_kvmfile); 1287*7c478bd9Sstevel@tonic-gate strfree(kt->k_symfile); 1288*7c478bd9Sstevel@tonic-gate 1289*7c478bd9Sstevel@tonic-gate mdb_free(kt, sizeof (kt_data_t)); 1290*7c478bd9Sstevel@tonic-gate } 1291*7c478bd9Sstevel@tonic-gate 1292*7c478bd9Sstevel@tonic-gate static int 1293*7c478bd9Sstevel@tonic-gate kt_data_stub(void) 1294*7c478bd9Sstevel@tonic-gate { 1295*7c478bd9Sstevel@tonic-gate return (-1); 1296*7c478bd9Sstevel@tonic-gate } 1297*7c478bd9Sstevel@tonic-gate 1298*7c478bd9Sstevel@tonic-gate int 1299*7c478bd9Sstevel@tonic-gate mdb_kvm_tgt_create(mdb_tgt_t *t, int argc, const char *argv[]) 1300*7c478bd9Sstevel@tonic-gate { 1301*7c478bd9Sstevel@tonic-gate kt_data_t *kt = mdb_zalloc(sizeof (kt_data_t), UM_SLEEP); 1302*7c478bd9Sstevel@tonic-gate int oflag = (t->t_flags & MDB_TGT_F_RDWR) ? O_RDWR : O_RDONLY; 1303*7c478bd9Sstevel@tonic-gate 1304*7c478bd9Sstevel@tonic-gate struct utsname uts; 1305*7c478bd9Sstevel@tonic-gate GElf_Sym sym; 1306*7c478bd9Sstevel@tonic-gate pgcnt_t pmem; 1307*7c478bd9Sstevel@tonic-gate 1308*7c478bd9Sstevel@tonic-gate if (argc != 2) 1309*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 1310*7c478bd9Sstevel@tonic-gate 1311*7c478bd9Sstevel@tonic-gate kt->k_symfile = strdup(argv[0]); 1312*7c478bd9Sstevel@tonic-gate kt->k_kvmfile = strdup(argv[1]); 1313*7c478bd9Sstevel@tonic-gate 1314*7c478bd9Sstevel@tonic-gate if ((kt->k_cookie = kvm_open(kt->k_symfile, kt->k_kvmfile, NULL, 1315*7c478bd9Sstevel@tonic-gate oflag, (char *)mdb.m_pname)) == NULL) 1316*7c478bd9Sstevel@tonic-gate goto err; 1317*7c478bd9Sstevel@tonic-gate 1318*7c478bd9Sstevel@tonic-gate if ((kt->k_fio = mdb_fdio_create_path(NULL, kt->k_symfile, 1319*7c478bd9Sstevel@tonic-gate O_RDONLY, 0)) == NULL) { 1320*7c478bd9Sstevel@tonic-gate mdb_warn("failed to open %s", kt->k_symfile); 1321*7c478bd9Sstevel@tonic-gate goto err; 1322*7c478bd9Sstevel@tonic-gate } 1323*7c478bd9Sstevel@tonic-gate 1324*7c478bd9Sstevel@tonic-gate if ((kt->k_file = mdb_gelf_create(kt->k_fio, 1325*7c478bd9Sstevel@tonic-gate ET_EXEC, GF_FILE)) == NULL) { 1326*7c478bd9Sstevel@tonic-gate mdb_io_destroy(kt->k_fio); 1327*7c478bd9Sstevel@tonic-gate goto err; 1328*7c478bd9Sstevel@tonic-gate } 1329*7c478bd9Sstevel@tonic-gate 1330*7c478bd9Sstevel@tonic-gate kt->k_symtab = 1331*7c478bd9Sstevel@tonic-gate mdb_gelf_symtab_create_file(kt->k_file, SHT_SYMTAB, MDB_TGT_SYMTAB); 1332*7c478bd9Sstevel@tonic-gate 1333*7c478bd9Sstevel@tonic-gate kt->k_dynsym = 1334*7c478bd9Sstevel@tonic-gate mdb_gelf_symtab_create_file(kt->k_file, SHT_DYNSYM, MDB_TGT_DYNSYM); 1335*7c478bd9Sstevel@tonic-gate 1336*7c478bd9Sstevel@tonic-gate if (mdb_gelf_symtab_lookup_by_name(kt->k_symtab, "kas", 1337*7c478bd9Sstevel@tonic-gate &sym, NULL) == -1) { 1338*7c478bd9Sstevel@tonic-gate warn("'kas' symbol is missing from kernel\n"); 1339*7c478bd9Sstevel@tonic-gate goto err; 1340*7c478bd9Sstevel@tonic-gate } 1341*7c478bd9Sstevel@tonic-gate 1342*7c478bd9Sstevel@tonic-gate kt->k_as = (struct as *)(uintptr_t)sym.st_value; 1343*7c478bd9Sstevel@tonic-gate 1344*7c478bd9Sstevel@tonic-gate if (mdb_gelf_symtab_lookup_by_name(kt->k_symtab, "platform", 1345*7c478bd9Sstevel@tonic-gate &sym, NULL) == -1) { 1346*7c478bd9Sstevel@tonic-gate warn("'platform' symbol is missing from kernel\n"); 1347*7c478bd9Sstevel@tonic-gate goto err; 1348*7c478bd9Sstevel@tonic-gate } 1349*7c478bd9Sstevel@tonic-gate 1350*7c478bd9Sstevel@tonic-gate if (kvm_kread(kt->k_cookie, sym.st_value, 1351*7c478bd9Sstevel@tonic-gate kt->k_platform, MAXNAMELEN) <= 0) { 1352*7c478bd9Sstevel@tonic-gate warn("failed to read 'platform' string from kernel"); 1353*7c478bd9Sstevel@tonic-gate goto err; 1354*7c478bd9Sstevel@tonic-gate } 1355*7c478bd9Sstevel@tonic-gate 1356*7c478bd9Sstevel@tonic-gate if (mdb_gelf_symtab_lookup_by_name(kt->k_symtab, "utsname", 1357*7c478bd9Sstevel@tonic-gate &sym, NULL) == -1) { 1358*7c478bd9Sstevel@tonic-gate warn("'utsname' symbol is missing from kernel\n"); 1359*7c478bd9Sstevel@tonic-gate goto err; 1360*7c478bd9Sstevel@tonic-gate } 1361*7c478bd9Sstevel@tonic-gate 1362*7c478bd9Sstevel@tonic-gate if (kvm_kread(kt->k_cookie, sym.st_value, &uts, sizeof (uts)) <= 0) { 1363*7c478bd9Sstevel@tonic-gate warn("failed to read 'utsname' struct from kernel"); 1364*7c478bd9Sstevel@tonic-gate goto err; 1365*7c478bd9Sstevel@tonic-gate } 1366*7c478bd9Sstevel@tonic-gate 1367*7c478bd9Sstevel@tonic-gate /* 1368*7c478bd9Sstevel@tonic-gate * These libkvm symbols were not present in Solaris 2.6; as such 1369*7c478bd9Sstevel@tonic-gate * we need to look them up manually using the run-time linker. 1370*7c478bd9Sstevel@tonic-gate */ 1371*7c478bd9Sstevel@tonic-gate kt->k_aread = (ssize_t (*)()) dlsym(RTLD_DEFAULT, "kvm_aread"); 1372*7c478bd9Sstevel@tonic-gate kt->k_awrite = (ssize_t (*)()) dlsym(RTLD_DEFAULT, "kvm_awrite"); 1373*7c478bd9Sstevel@tonic-gate kt->k_pread = (ssize_t (*)()) dlsym(RTLD_DEFAULT, "kvm_pread"); 1374*7c478bd9Sstevel@tonic-gate kt->k_pwrite = (ssize_t (*)()) dlsym(RTLD_DEFAULT, "kvm_pwrite"); 1375*7c478bd9Sstevel@tonic-gate 1376*7c478bd9Sstevel@tonic-gate /* 1377*7c478bd9Sstevel@tonic-gate * If any of these functions are unavailable with the current 1378*7c478bd9Sstevel@tonic-gate * bindings, replace them with calls to mdb_tgt_notsup(). 1379*7c478bd9Sstevel@tonic-gate */ 1380*7c478bd9Sstevel@tonic-gate if (kt->k_aread == NULL) 1381*7c478bd9Sstevel@tonic-gate kt->k_aread = (ssize_t (*)())mdb_tgt_notsup; 1382*7c478bd9Sstevel@tonic-gate if (kt->k_awrite == NULL) 1383*7c478bd9Sstevel@tonic-gate kt->k_awrite = (ssize_t (*)())mdb_tgt_notsup; 1384*7c478bd9Sstevel@tonic-gate if (kt->k_pread == NULL) 1385*7c478bd9Sstevel@tonic-gate kt->k_pread = (ssize_t (*)())mdb_tgt_notsup; 1386*7c478bd9Sstevel@tonic-gate if (kt->k_pwrite == NULL) 1387*7c478bd9Sstevel@tonic-gate kt->k_pwrite = (ssize_t (*)())mdb_tgt_notsup; 1388*7c478bd9Sstevel@tonic-gate 1389*7c478bd9Sstevel@tonic-gate kt->k_dump_print_content = (void (*)())kt_data_stub; 1390*7c478bd9Sstevel@tonic-gate kt->k_dump_find_curproc = kt_data_stub; 1391*7c478bd9Sstevel@tonic-gate 1392*7c478bd9Sstevel@tonic-gate /* 1393*7c478bd9Sstevel@tonic-gate * We set k_ctfvalid based on the presence of the CTF vmem arena 1394*7c478bd9Sstevel@tonic-gate * symbol. The CTF members were added to the end of struct module at 1395*7c478bd9Sstevel@tonic-gate * the same time, so this allows us to know whether we can use them. 1396*7c478bd9Sstevel@tonic-gate */ 1397*7c478bd9Sstevel@tonic-gate if (mdb_gelf_symtab_lookup_by_name(kt->k_symtab, "ctf_arena", &sym, 1398*7c478bd9Sstevel@tonic-gate NULL) == 0 && !(mdb.m_flags & MDB_FL_NOCTF)) 1399*7c478bd9Sstevel@tonic-gate kt->k_ctfvalid = 1; 1400*7c478bd9Sstevel@tonic-gate 1401*7c478bd9Sstevel@tonic-gate (void) mdb_nv_create(&kt->k_modules, UM_SLEEP); 1402*7c478bd9Sstevel@tonic-gate t->t_pshandle = kt->k_cookie; 1403*7c478bd9Sstevel@tonic-gate t->t_data = kt; 1404*7c478bd9Sstevel@tonic-gate 1405*7c478bd9Sstevel@tonic-gate #if defined(__sparc) 1406*7c478bd9Sstevel@tonic-gate #if defined(__sparcv9) 1407*7c478bd9Sstevel@tonic-gate kt_sparcv9_init(t); 1408*7c478bd9Sstevel@tonic-gate #else 1409*7c478bd9Sstevel@tonic-gate kt_sparcv7_init(t); 1410*7c478bd9Sstevel@tonic-gate #endif 1411*7c478bd9Sstevel@tonic-gate #elif defined(__amd64) 1412*7c478bd9Sstevel@tonic-gate kt_amd64_init(t); 1413*7c478bd9Sstevel@tonic-gate #elif defined(__i386) 1414*7c478bd9Sstevel@tonic-gate kt_ia32_init(t); 1415*7c478bd9Sstevel@tonic-gate #else 1416*7c478bd9Sstevel@tonic-gate #error "unknown ISA" 1417*7c478bd9Sstevel@tonic-gate #endif 1418*7c478bd9Sstevel@tonic-gate 1419*7c478bd9Sstevel@tonic-gate /* 1420*7c478bd9Sstevel@tonic-gate * We read our representative thread ID (address) from the kernel's 1421*7c478bd9Sstevel@tonic-gate * global panic_thread. It will remain 0 if this is a live kernel. 1422*7c478bd9Sstevel@tonic-gate */ 1423*7c478bd9Sstevel@tonic-gate (void) mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, &kt->k_tid, sizeof (void *), 1424*7c478bd9Sstevel@tonic-gate MDB_TGT_OBJ_EXEC, "panic_thread"); 1425*7c478bd9Sstevel@tonic-gate 1426*7c478bd9Sstevel@tonic-gate if ((mdb.m_flags & MDB_FL_ADB) && mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, 1427*7c478bd9Sstevel@tonic-gate &pmem, sizeof (pmem), MDB_TGT_OBJ_EXEC, "physmem") == sizeof (pmem)) 1428*7c478bd9Sstevel@tonic-gate mdb_printf("physmem %lx\n", (ulong_t)pmem); 1429*7c478bd9Sstevel@tonic-gate 1430*7c478bd9Sstevel@tonic-gate /* 1431*7c478bd9Sstevel@tonic-gate * If this is not a live kernel, read the dump header. We don't have to 1432*7c478bd9Sstevel@tonic-gate * sanity-check the header, as the kvm_open would not have succeeded 1433*7c478bd9Sstevel@tonic-gate * otherwise. 1434*7c478bd9Sstevel@tonic-gate */ 1435*7c478bd9Sstevel@tonic-gate if (strcmp(kt->k_symfile, "/dev/ksyms") != 0) { 1436*7c478bd9Sstevel@tonic-gate mdb_io_t *vmcore; 1437*7c478bd9Sstevel@tonic-gate 1438*7c478bd9Sstevel@tonic-gate kt->k_dumphdr = mdb_alloc(sizeof (dumphdr_t), UM_SLEEP); 1439*7c478bd9Sstevel@tonic-gate 1440*7c478bd9Sstevel@tonic-gate if ((vmcore = mdb_fdio_create_path(NULL, kt->k_kvmfile, 1441*7c478bd9Sstevel@tonic-gate O_RDONLY, 0)) == NULL) { 1442*7c478bd9Sstevel@tonic-gate mdb_warn("failed to open %s", kt->k_kvmfile); 1443*7c478bd9Sstevel@tonic-gate goto err; 1444*7c478bd9Sstevel@tonic-gate } 1445*7c478bd9Sstevel@tonic-gate 1446*7c478bd9Sstevel@tonic-gate if (IOP_READ(vmcore, kt->k_dumphdr, sizeof (dumphdr_t)) != 1447*7c478bd9Sstevel@tonic-gate sizeof (dumphdr_t)) { 1448*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read dump header"); 1449*7c478bd9Sstevel@tonic-gate mdb_io_destroy(vmcore); 1450*7c478bd9Sstevel@tonic-gate goto err; 1451*7c478bd9Sstevel@tonic-gate } 1452*7c478bd9Sstevel@tonic-gate 1453*7c478bd9Sstevel@tonic-gate mdb_io_destroy(vmcore); 1454*7c478bd9Sstevel@tonic-gate 1455*7c478bd9Sstevel@tonic-gate (void) mdb_tgt_xdata_insert(t, "dumphdr", 1456*7c478bd9Sstevel@tonic-gate "dump header structure", kt_xd_dumphdr); 1457*7c478bd9Sstevel@tonic-gate } 1458*7c478bd9Sstevel@tonic-gate 1459*7c478bd9Sstevel@tonic-gate return (0); 1460*7c478bd9Sstevel@tonic-gate 1461*7c478bd9Sstevel@tonic-gate err: 1462*7c478bd9Sstevel@tonic-gate if (kt->k_dumphdr != NULL) 1463*7c478bd9Sstevel@tonic-gate mdb_free(kt->k_dumphdr, sizeof (dumphdr_t)); 1464*7c478bd9Sstevel@tonic-gate 1465*7c478bd9Sstevel@tonic-gate if (kt->k_symtab != NULL) 1466*7c478bd9Sstevel@tonic-gate mdb_gelf_symtab_destroy(kt->k_symtab); 1467*7c478bd9Sstevel@tonic-gate 1468*7c478bd9Sstevel@tonic-gate if (kt->k_dynsym != NULL) 1469*7c478bd9Sstevel@tonic-gate mdb_gelf_symtab_destroy(kt->k_dynsym); 1470*7c478bd9Sstevel@tonic-gate 1471*7c478bd9Sstevel@tonic-gate if (kt->k_file != NULL) 1472*7c478bd9Sstevel@tonic-gate mdb_gelf_destroy(kt->k_file); 1473*7c478bd9Sstevel@tonic-gate 1474*7c478bd9Sstevel@tonic-gate if (kt->k_cookie != NULL) 1475*7c478bd9Sstevel@tonic-gate (void) kvm_close(kt->k_cookie); 1476*7c478bd9Sstevel@tonic-gate 1477*7c478bd9Sstevel@tonic-gate mdb_free(kt, sizeof (kt_data_t)); 1478*7c478bd9Sstevel@tonic-gate return (-1); 1479*7c478bd9Sstevel@tonic-gate } 1480