1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 6473 edp * Common Development and Distribution License (the "License"). 6 6473 edp * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 6473 edp * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel #pragma ident "%Z%%M% %I% %E% SMI" 27 0 stevel 28 0 stevel /* 29 0 stevel * Kernel Process View Target 30 0 stevel * 31 0 stevel * The kproc target is activated when the user is debugging a kernel using the 32 0 stevel * kvm target and executes a ::context dcmd to change the debugger view to one 33 0 stevel * of the running processes. The kvm target's t_setcontext operation will 34 0 stevel * create and activate a kproc target in response to this call. The kproc 35 0 stevel * target itself is built upon the kvm target's libkvm cookie and the ability 36 0 stevel * to read information from the kernel itself and the ability to read the 37 0 stevel * address space of a particular user process with kvm_aread(). It also relies 38 0 stevel * on a special set of functions provided by the kvm target's mdb_ks support 39 0 stevel * module in order to bootstrap: specifically, given the initial proc pointer, 40 0 stevel * mdb_ks provides functions to return the set of address space mappings, the 41 0 stevel * address space pointer itself, the aux vector vector saved in the u-area, 42 0 stevel * and the process data model. The kproc target maintains a list of address 43 0 stevel * space mappings (kp_map_t) and load objects (kp_file_t), and for each load 44 0 stevel * object will attempt to read the corresponding dynamic symbol table. In 45 0 stevel * order to bootstrap, the target uses the AT_BASE and AT_ENTRY aux vector 46 0 stevel * elements to locate the dynamic linker and executable mappings. With these 47 0 stevel * mappings in place, we initialize a librtld_db agent on the target (see 48 0 stevel * mdb_pservice.c for how this is done), and then process each load object 49 0 stevel * found in the link-map chain. In order to simplify the construction of 50 0 stevel * symbol tables for each load object, we would like make use of our existing 51 0 stevel * library of GElf processing code. Since the MDB GElf code uses mdb_io 52 0 stevel * objects to read in an ELF file, we simply define a new type of mdb_io object 53 0 stevel * where each read operation is translated into a call to kproc's t_vread 54 0 stevel * function to read from the range of the address space defined by the mapping 55 0 stevel * as if it were a file. 56 0 stevel */ 57 0 stevel 58 0 stevel #include <sys/types.h> 59 0 stevel #include <sys/proc.h> 60 0 stevel #include <sys/auxv.h> 61 0 stevel 62 0 stevel #include <strings.h> 63 0 stevel #include <limits.h> 64 0 stevel #include <rtld_db.h> 65 0 stevel #include <procfs.h> 66 0 stevel #include <dlfcn.h> 67 0 stevel #include <kvm.h> 68 0 stevel 69 0 stevel #include <mdb/mdb_target_impl.h> 70 0 stevel #include <mdb/mdb_debug.h> 71 0 stevel #include <mdb/mdb_string.h> 72 0 stevel #include <mdb/mdb_err.h> 73 0 stevel #include <mdb/mdb_ks.h> 74 0 stevel #include <mdb/mdb_gelf.h> 75 0 stevel #include <mdb/mdb_io_impl.h> 76 0 stevel #include <mdb/mdb.h> 77 0 stevel 78 0 stevel typedef struct kp_symarg { 79 0 stevel mdb_tgt_sym_f *sym_cb; /* Caller's callback function */ 80 0 stevel void *sym_data; /* Callback function argument */ 81 0 stevel uint_t sym_type; /* Symbol type/binding filter */ 82 0 stevel uintptr_t sym_adjust; /* Symbol value adjustment */ 83 0 stevel mdb_syminfo_t sym_info; /* Symbol id and table id */ 84 0 stevel const char *sym_obj; /* Containing object */ 85 0 stevel } kp_symarg_t; 86 0 stevel 87 0 stevel typedef struct kp_file { 88 0 stevel mdb_gelf_file_t *kpf_file; /* ELF file object */ 89 0 stevel mdb_io_t *kpf_fio; /* ELF file back-end */ 90 0 stevel mdb_gelf_symtab_t *kpf_dynsym; /* Dynamic symbol table */ 91 0 stevel struct kp_map *kpf_map; /* Primary (text) mapping */ 92 0 stevel const char *kpf_basename; /* Mapping basename */ 93 0 stevel uintptr_t kpf_dyn_base; /* Load address for ET_DYN files */ 94 0 stevel uintptr_t kpf_text_base; /* Base address of text mapping */ 95 0 stevel uintptr_t kpf_data_base; /* Base address of data mapping */ 96 0 stevel struct kp_file *kpf_next; /* Pointer to next file */ 97 0 stevel } kp_file_t; 98 0 stevel 99 0 stevel typedef struct kp_map { 100 0 stevel mdb_map_t kpm_map; /* Mapping information */ 101 0 stevel kp_file_t *kpm_file; /* Pointer to load object */ 102 0 stevel struct kp_map *kpm_next; /* Pointer to next mapping */ 103 0 stevel } kp_map_t; 104 0 stevel 105 0 stevel typedef struct kp_io { 106 0 stevel mdb_tgt_t *kpi_tgt; /* Backpointer to kproc target */ 107 0 stevel kp_map_t *kpi_map; /* Mapping for this i/o */ 108 0 stevel uintptr_t kpi_ptr; /* Virtual address pointer */ 109 0 stevel uintptr_t kpi_lim; /* Virtual address limit */ 110 0 stevel } kp_io_t; 111 0 stevel 112 0 stevel typedef struct kp_data { 113 0 stevel mdb_tgt_t *kp_parent; /* Parent kvm target */ 114 0 stevel kvm_t *kp_cookie; /* Cookie for libkvm routines */ 115 0 stevel rd_agent_t *kp_rap; /* Cookie for librtld_db routines */ 116 0 stevel proc_t *kp_proc; /* Proc address in dump */ 117 0 stevel struct as *kp_as; /* Proc as address in dump */ 118 0 stevel pid_t kp_pid; /* Process ID */ 119 0 stevel auxv_t *kp_auxv; /* Auxv array from u-area */ 120 0 stevel int kp_nauxv; /* Length of kp_auxv */ 121 0 stevel const char *kp_platform; /* Platform string from kvm target */ 122 0 stevel uint_t kp_model; /* Process data model */ 123 0 stevel kp_file_t *kp_file_head; /* Head of load object list */ 124 0 stevel kp_file_t *kp_file_tail; /* Tail of load object list */ 125 0 stevel kp_map_t *kp_map_head; /* Head of mapping list */ 126 0 stevel kp_map_t *kp_map_tail; /* Tail of mapping list */ 127 0 stevel int kp_num_files; /* Length of load object list */ 128 0 stevel int kp_num_maps; /* Length of mapping list */ 129 0 stevel kp_map_t *kp_map_exec; /* Executable mapping */ 130 0 stevel kp_map_t *kp_map_ldso; /* Interpreter mapping */ 131 0 stevel kp_file_t kp_prfile; /* Fake file for mdb.m_prsym */ 132 0 stevel } kp_data_t; 133 0 stevel 134 0 stevel static mdb_io_t *kp_io_create(mdb_tgt_t *, kp_map_t *); 135 0 stevel 136 0 stevel static kp_map_t * 137 0 stevel kp_addr_to_kpmap(kp_data_t *kp, uintptr_t addr) 138 0 stevel { 139 0 stevel kp_map_t *kpm; 140 0 stevel 141 0 stevel for (kpm = kp->kp_map_head; kpm != NULL; kpm = kpm->kpm_next) { 142 0 stevel if (addr >= kpm->kpm_map.map_base && 143 0 stevel addr < kpm->kpm_map.map_base + kpm->kpm_map.map_size) 144 0 stevel return (kpm); 145 0 stevel } 146 0 stevel 147 0 stevel return (NULL); 148 0 stevel } 149 0 stevel 150 0 stevel static long 151 0 stevel kp_getauxval(kp_data_t *kp, int type) 152 0 stevel { 153 0 stevel auxv_t *auxp; 154 0 stevel 155 0 stevel for (auxp = kp->kp_auxv; auxp->a_type != AT_NULL; auxp++) { 156 0 stevel if (auxp->a_type == type) 157 0 stevel return (auxp->a_un.a_val); 158 0 stevel } 159 0 stevel 160 0 stevel return (-1L); 161 0 stevel } 162 0 stevel 163 0 stevel static void 164 0 stevel kp_add_mapping(const mdb_map_t *pmp, void *data) 165 0 stevel { 166 0 stevel kp_map_t *kpm = mdb_zalloc(sizeof (kp_map_t), UM_SLEEP); 167 0 stevel kp_data_t *kp = data; 168 0 stevel 169 0 stevel bcopy(pmp, &kpm->kpm_map, sizeof (mdb_map_t)); 170 0 stevel 171 0 stevel if (kp->kp_map_tail != NULL) 172 0 stevel kp->kp_map_tail->kpm_next = kpm; 173 0 stevel else 174 0 stevel kp->kp_map_head = kpm; 175 0 stevel 176 0 stevel kp->kp_map_tail = kpm; 177 0 stevel kp->kp_num_maps++; 178 0 stevel } 179 0 stevel 180 0 stevel static kp_file_t * 181 0 stevel kp_file_create(mdb_tgt_t *t, kp_map_t *kpm, GElf_Half etype) 182 0 stevel { 183 0 stevel kp_file_t *kpf = mdb_zalloc(sizeof (kp_file_t), UM_SLEEP); 184 0 stevel kp_data_t *kp = t->t_data; 185 6830 edp size_t dyns_sz; 186 6830 edp void *dyns; 187 0 stevel 188 0 stevel kpf->kpf_fio = kp_io_create(t, kpm); 189 0 stevel kpf->kpf_map = kpm; 190 0 stevel kpf->kpf_basename = strbasename(kpm->kpm_map.map_name); 191 0 stevel kpf->kpf_file = mdb_gelf_create(kpf->kpf_fio, etype, GF_PROGRAM); 192 0 stevel kpf->kpf_text_base = kpm->kpm_map.map_base; 193 0 stevel 194 0 stevel if (kpm != kp->kp_map_exec) 195 0 stevel kpf->kpf_dyn_base = kpf->kpf_text_base; 196 0 stevel 197 0 stevel if (kpf->kpf_file == NULL) 198 0 stevel goto err; /* Failed to create ELF file */ 199 0 stevel 200 0 stevel mdb_dprintf(MDB_DBG_TGT, "loading symbols for %s\n", 201 0 stevel kpm->kpm_map.map_name); 202 6830 edp 203 6830 edp if ((kp->kp_rap != NULL) && (rd_get_dyns(kp->kp_rap, 204 6830 edp kpf->kpf_text_base, &dyns, &dyns_sz) == RD_OK)) 205 6830 edp mdb_gelf_dyns_set(kpf->kpf_file, dyns, dyns_sz); 206 0 stevel 207 0 stevel kpf->kpf_dynsym = mdb_gelf_symtab_create_dynamic(kpf->kpf_file, 208 0 stevel MDB_TGT_DYNSYM); 209 0 stevel 210 0 stevel if (kpf->kpf_dynsym == NULL) 211 0 stevel goto err; /* Failed to create symbol table */ 212 0 stevel 213 0 stevel kpm->kpm_file = kpf; 214 0 stevel 215 0 stevel if (kp->kp_file_tail != NULL) 216 0 stevel kp->kp_file_tail->kpf_next = kpf; 217 0 stevel else 218 0 stevel kp->kp_file_head = kpf; 219 0 stevel 220 0 stevel kp->kp_file_tail = kpf; 221 0 stevel kp->kp_num_files++; 222 0 stevel 223 0 stevel return (kpf); 224 0 stevel 225 0 stevel err: 226 0 stevel if (kpf->kpf_file != NULL) 227 0 stevel mdb_gelf_destroy(kpf->kpf_file); 228 0 stevel else 229 0 stevel mdb_io_destroy(kpf->kpf_fio); 230 0 stevel mdb_free(kpf, sizeof (kp_file_t)); 231 0 stevel return (NULL); 232 0 stevel } 233 0 stevel 234 0 stevel static void 235 0 stevel kp_file_destroy(kp_file_t *kpf) 236 0 stevel { 237 0 stevel if (kpf->kpf_dynsym != NULL) 238 0 stevel mdb_gelf_symtab_destroy(kpf->kpf_dynsym); 239 0 stevel 240 0 stevel mdb_gelf_destroy(kpf->kpf_file); 241 0 stevel mdb_free(kpf, sizeof (kp_file_t)); 242 0 stevel } 243 0 stevel 244 0 stevel static int 245 0 stevel kp_setcontext(mdb_tgt_t *t, void *context) 246 0 stevel { 247 0 stevel kp_data_t *kp = t->t_data; 248 0 stevel 249 0 stevel if (kp->kp_proc != context) { 250 0 stevel mdb_tgt_destroy(t); 251 0 stevel return (mdb_tgt_setcontext(mdb.m_target, context)); 252 0 stevel } 253 0 stevel 254 0 stevel mdb_warn("debugger context is already set to proc %p\n", context); 255 0 stevel return (0); 256 0 stevel } 257 0 stevel 258 0 stevel static kp_map_t * 259 0 stevel kp_find_data(kp_data_t *kp, kp_file_t *kpf, const rd_loadobj_t *rlp) 260 0 stevel { 261 0 stevel GElf_Phdr *gpp = kpf->kpf_file->gf_phdrs; 262 0 stevel size_t i, n = kpf->kpf_file->gf_npload; 263 0 stevel 264 0 stevel /* 265 0 stevel * Find the first loadable, writeable Phdr and compute kpf_data_base 266 0 stevel * as the virtual address at which is was loaded. 267 0 stevel */ 268 0 stevel for (i = 0; i < n; i++, gpp++) { 269 0 stevel if (gpp->p_type == PT_LOAD && (gpp->p_flags & PF_W)) { 270 0 stevel kpf->kpf_data_base = gpp->p_vaddr; 271 0 stevel if (kpf->kpf_map != kp->kp_map_exec) 272 0 stevel kpf->kpf_data_base += rlp->rl_base; 273 0 stevel break; 274 0 stevel } 275 0 stevel } 276 0 stevel 277 0 stevel /* 278 0 stevel * If we found a suitable Phdr and set kpf_data_base, return 279 0 stevel * the mapping information for this address; otherwise fail. 280 0 stevel */ 281 0 stevel if (kpf->kpf_data_base != 0) 282 0 stevel return (kp_addr_to_kpmap(kp, kpf->kpf_data_base)); 283 0 stevel 284 0 stevel return (NULL); 285 0 stevel } 286 0 stevel 287 0 stevel static int 288 0 stevel kp_iter_mapping(const rd_loadobj_t *rlp, mdb_tgt_t *t) 289 0 stevel { 290 0 stevel kp_data_t *kp = t->t_data; 291 0 stevel kp_file_t *kpf; 292 0 stevel kp_map_t *kpm; 293 0 stevel 294 0 stevel char name[MDB_TGT_MAPSZ]; 295 0 stevel 296 0 stevel if (mdb_tgt_readstr(t, MDB_TGT_AS_VIRT, name, 297 0 stevel sizeof (name), (mdb_tgt_addr_t)rlp->rl_nameaddr) <= 0) { 298 0 stevel mdb_dprintf(MDB_DBG_TGT, "failed to read name %p", 299 0 stevel (void *)rlp->rl_nameaddr); 300 0 stevel return (1); /* Keep going; forget this if we can't read name */ 301 0 stevel } 302 0 stevel 303 0 stevel mdb_dprintf(MDB_DBG_TGT, "rd_loadobj name = \"%s\" rl_base = %p\n", 304 0 stevel name, (void *)rlp->rl_base); 305 0 stevel 306 0 stevel if ((kpm = kp_addr_to_kpmap(kp, rlp->rl_base)) == NULL) 307 0 stevel return (1); /* Keep going; no mapping at this address */ 308 0 stevel 309 0 stevel (void) strncpy(kpm->kpm_map.map_name, name, MDB_TGT_MAPSZ); 310 0 stevel kpm->kpm_map.map_name[MDB_TGT_MAPSZ - 1] = '\0'; 311 0 stevel 312 0 stevel if ((kpf = kpm->kpm_file) == NULL) { 313 0 stevel if (kpm == kp->kp_map_exec) 314 0 stevel kpf = kp_file_create(t, kpm, ET_EXEC); 315 0 stevel else 316 0 stevel kpf = kp_file_create(t, kpm, ET_DYN); 317 0 stevel 318 0 stevel if (kpf == NULL) 319 0 stevel return (1); /* Keep going; failed to build ELF file */ 320 0 stevel } else 321 0 stevel kpf->kpf_basename = strbasename(kpm->kpm_map.map_name); 322 0 stevel 323 0 stevel if ((kpm = kp_find_data(kp, kpf, rlp)) != NULL) { 324 0 stevel mdb_dprintf(MDB_DBG_TGT, "found data for %s at %p\n", 325 0 stevel kpf->kpf_basename, (void *)kpm->kpm_map.map_base); 326 0 stevel kpm->kpm_file = kpf; 327 0 stevel } 328 0 stevel 329 0 stevel return (1); 330 0 stevel } 331 0 stevel 332 0 stevel /*ARGSUSED*/ 333 0 stevel static int 334 0 stevel kp_status_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 335 0 stevel { 336 0 stevel kp_data_t *kp = mdb.m_target->t_data; 337 0 stevel 338 0 stevel mdb_printf("debugging PID %d (%d-bit) in kernel crash dump\n", 339 0 stevel kp->kp_pid, kp->kp_model == PR_MODEL_ILP32 ? 32 : 64); 340 0 stevel 341 0 stevel if (kp->kp_map_exec != NULL) { 342 0 stevel mdb_printf("executable file: %s\n", 343 0 stevel kp->kp_map_exec->kpm_map.map_name); 344 0 stevel } 345 0 stevel 346 0 stevel return (DCMD_OK); 347 0 stevel } 348 0 stevel 349 0 stevel static const mdb_dcmd_t kp_dcmds[] = { 350 0 stevel { "status", NULL, "print summary of current target", kp_status_dcmd }, 351 0 stevel { NULL } 352 0 stevel }; 353 0 stevel 354 0 stevel static void 355 0 stevel kp_activate(mdb_tgt_t *t) 356 0 stevel { 357 0 stevel kp_data_t *kp = t->t_data; 358 0 stevel 359 0 stevel mdb_prop_postmortem = TRUE; 360 0 stevel mdb_prop_kernel = FALSE; 361 0 stevel 362 0 stevel if (kp->kp_model == PR_MODEL_ILP32) 363 0 stevel mdb_prop_datamodel = MDB_TGT_MODEL_ILP32; 364 0 stevel else 365 0 stevel mdb_prop_datamodel = MDB_TGT_MODEL_LP64; 366 0 stevel 367 0 stevel /* 368 0 stevel * Initialize our rtld_db agent and then iterate over the link map, 369 0 stevel * instantiating kp_file objects as we go. 370 0 stevel */ 371 0 stevel if ((kp->kp_rap = rd_new((struct ps_prochandle *)t)) != NULL) { 372 0 stevel (void) rd_loadobj_iter(kp->kp_rap, (rl_iter_f *) 373 0 stevel kp_iter_mapping, t); 374 0 stevel } else { 375 0 stevel mdb_warn("unable to initialize rtld_db agent for proc %p\n", 376 0 stevel (void *)kp->kp_proc); 377 0 stevel } 378 0 stevel 379 0 stevel (void) mdb_tgt_register_dcmds(t, &kp_dcmds[0], MDB_MOD_FORCE); 380 0 stevel 381 0 stevel if (kp->kp_map_exec != NULL && kp->kp_map_exec->kpm_file != NULL) 382 0 stevel mdb_tgt_elf_export(kp->kp_map_exec->kpm_file->kpf_file); 383 0 stevel else 384 0 stevel mdb_tgt_elf_export(NULL); 385 0 stevel } 386 0 stevel 387 0 stevel static void 388 0 stevel kp_deactivate(mdb_tgt_t *t) 389 0 stevel { 390 0 stevel const mdb_dcmd_t *dcp; 391 0 stevel 392 0 stevel for (dcp = &kp_dcmds[0]; dcp->dc_name != NULL; dcp++) { 393 0 stevel if (mdb_module_remove_dcmd(t->t_module, dcp->dc_name) == -1) 394 0 stevel warn("failed to remove dcmd %s", dcp->dc_name); 395 0 stevel } 396 0 stevel 397 0 stevel mdb_prop_postmortem = FALSE; 398 0 stevel mdb_prop_kernel = FALSE; 399 0 stevel mdb_prop_datamodel = MDB_TGT_MODEL_UNKNOWN; 400 0 stevel } 401 0 stevel 402 0 stevel static void 403 0 stevel kp_destroy(mdb_tgt_t *t) 404 0 stevel { 405 0 stevel kp_data_t *kp = t->t_data; 406 0 stevel kp_map_t *kpm, *nkpm; 407 0 stevel kp_file_t *kpf, *nkpf; 408 0 stevel 409 0 stevel if (kp->kp_rap != NULL) 410 0 stevel rd_delete(kp->kp_rap); 411 0 stevel 412 0 stevel for (kpm = kp->kp_map_head; kpm != NULL; kpm = nkpm) { 413 0 stevel nkpm = kpm->kpm_next; 414 0 stevel mdb_free(kpm, sizeof (kp_map_t)); 415 0 stevel } 416 0 stevel 417 0 stevel for (kpf = kp->kp_file_head; kpf != NULL; kpf = nkpf) { 418 0 stevel nkpf = kpf->kpf_next; 419 0 stevel kp_file_destroy(kpf); 420 0 stevel } 421 0 stevel 422 0 stevel mdb_free(kp->kp_auxv, kp->kp_nauxv * sizeof (auxv_t)); 423 0 stevel mdb_free(kp, sizeof (kp_data_t)); 424 0 stevel } 425 0 stevel 426 0 stevel /*ARGSUSED*/ 427 0 stevel static const char * 428 0 stevel kp_name(mdb_tgt_t *t) 429 0 stevel { 430 0 stevel return ("kproc"); 431 0 stevel } 432 0 stevel 433 0 stevel static const char * 434 0 stevel kp_isa(mdb_tgt_t *t) 435 0 stevel { 436 0 stevel kp_data_t *kp = t->t_data; 437 0 stevel #ifdef __sparc 438 0 stevel return (kp->kp_model == PR_MODEL_ILP32 ? "sparc" : "sparcv9"); 439 0 stevel #else 440 0 stevel return (kp->kp_model == PR_MODEL_ILP32 ? "i386" : "amd64"); 441 0 stevel #endif 442 0 stevel } 443 0 stevel 444 0 stevel static const char * 445 0 stevel kp_platform(mdb_tgt_t *t) 446 0 stevel { 447 0 stevel return (((kp_data_t *)t->t_data)->kp_platform); 448 0 stevel } 449 0 stevel 450 0 stevel static int 451 0 stevel kp_uname(mdb_tgt_t *t, struct utsname *utsp) 452 0 stevel { 453 0 stevel kp_data_t *kp = t->t_data; 454 0 stevel return (mdb_tgt_uname(kp->kp_parent, utsp)); 455 0 stevel } 456 0 stevel 457 0 stevel static int 458 0 stevel kp_dmodel(mdb_tgt_t *t) 459 0 stevel { 460 0 stevel kp_data_t *kp = t->t_data; 461 0 stevel 462 0 stevel switch (kp->kp_model) { 463 0 stevel case PR_MODEL_ILP32: 464 0 stevel return (MDB_TGT_MODEL_ILP32); 465 0 stevel case PR_MODEL_LP64: 466 0 stevel return (MDB_TGT_MODEL_LP64); 467 0 stevel } 468 0 stevel 469 0 stevel return (MDB_TGT_MODEL_UNKNOWN); 470 0 stevel } 471 0 stevel 472 0 stevel static kp_map_t * 473 0 stevel kp_name_to_kpmap(kp_data_t *kp, const char *name) 474 0 stevel { 475 0 stevel size_t namelen; 476 0 stevel kp_file_t *kpf; 477 0 stevel kp_map_t *kpm; 478 0 stevel 479 0 stevel /* 480 0 stevel * Handle special reserved names (except for MDB_TGT_OBJ_EVERY): 481 0 stevel */ 482 0 stevel if (name == MDB_TGT_OBJ_EXEC) 483 0 stevel return (kp->kp_map_exec); 484 0 stevel 485 0 stevel if (name == MDB_TGT_OBJ_RTLD) 486 0 stevel return (kp->kp_map_ldso); 487 0 stevel 488 0 stevel /* 489 0 stevel * First pass: look for exact matches on the entire pathname 490 0 stevel * associated with the mapping or its basename. 491 0 stevel */ 492 0 stevel for (kpm = kp->kp_map_head; kpm != NULL; kpm = kpm->kpm_next) { 493 0 stevel if ((kpf = kpm->kpm_file) != NULL) { 494 0 stevel if (strcmp(kpm->kpm_map.map_name, name) == 0 || 495 0 stevel strcmp(kpf->kpf_basename, name) == 0) 496 0 stevel return (kpf->kpf_map); 497 0 stevel } 498 0 stevel } 499 0 stevel 500 0 stevel namelen = strlen(name); 501 0 stevel 502 0 stevel /* 503 0 stevel * Second pass: look for partial matches (initial basename match 504 0 stevel * up to a '.' suffix); allows "libc.so" or "libc" to match "libc.so.1" 505 0 stevel */ 506 0 stevel for (kpm = kp->kp_map_head; kpm != NULL; kpm = kpm->kpm_next) { 507 0 stevel if ((kpf = kpm->kpm_file) != NULL) { 508 0 stevel if (strncmp(kpf->kpf_basename, name, namelen) == 0 && 509 0 stevel kpf->kpf_basename[namelen] == '.') 510 0 stevel return (kpf->kpf_map); 511 0 stevel } 512 0 stevel } 513 0 stevel 514 0 stevel /* 515 0 stevel * One last check: we allow "a.out" to always alias the executable, 516 0 stevel * assuming this name was not in use for something else. 517 0 stevel */ 518 0 stevel if (strcmp(name, "a.out") == 0) 519 0 stevel return (kp->kp_map_exec); 520 0 stevel 521 0 stevel return (NULL); 522 0 stevel } 523 0 stevel 524 0 stevel 525 0 stevel static ssize_t 526 0 stevel kp_vread(mdb_tgt_t *t, void *buf, size_t nbytes, uintptr_t addr) 527 0 stevel { 528 0 stevel kp_data_t *kp = t->t_data; 529 0 stevel ssize_t n = kvm_aread(kp->kp_cookie, addr, buf, nbytes, kp->kp_as); 530 0 stevel 531 0 stevel if (n == -1) 532 0 stevel return (set_errno(EMDB_NOMAP)); 533 0 stevel 534 0 stevel return (n); 535 0 stevel } 536 0 stevel 537 0 stevel static ssize_t 538 0 stevel kp_vwrite(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr) 539 0 stevel { 540 0 stevel kp_data_t *kp = t->t_data; 541 0 stevel ssize_t n = kvm_awrite(kp->kp_cookie, addr, buf, nbytes, kp->kp_as); 542 0 stevel 543 0 stevel if (n == -1) 544 0 stevel return (set_errno(EMDB_NOMAP)); 545 0 stevel 546 0 stevel return (n); 547 0 stevel } 548 0 stevel 549 0 stevel 550 0 stevel int 551 0 stevel kp_vtop(mdb_tgt_t *t, mdb_tgt_as_t as, uintptr_t va, physaddr_t *pap) 552 0 stevel { 553 0 stevel kp_data_t *kp = t->t_data; 554 0 stevel physaddr_t pa; 555 0 stevel 556 0 stevel if (as != MDB_TGT_AS_VIRT) 557 0 stevel return (set_errno(EINVAL)); 558 0 stevel 559 0 stevel if ((pa = kvm_physaddr(kp->kp_cookie, kp->kp_as, va)) != -1ULL) { 560 0 stevel *pap = pa; 561 0 stevel return (0); 562 0 stevel } 563 0 stevel 564 0 stevel return (set_errno(EMDB_NOMAP)); 565 0 stevel } 566 0 stevel 567 0 stevel static int 568 0 stevel kp_lookup_by_name(mdb_tgt_t *t, const char *object, 569 0 stevel const char *name, GElf_Sym *symp, mdb_syminfo_t *sip) 570 0 stevel { 571 0 stevel kp_data_t *kp = t->t_data; 572 0 stevel kp_file_t *kpf; 573 0 stevel int n; 574 0 stevel 575 0 stevel GElf_Sym sym; 576 0 stevel uint_t symid; 577 0 stevel int rv = -1; 578 0 stevel 579 0 stevel /* 580 0 stevel * Simplify our task: if object is EVERY, then we need to search 581 0 stevel * kp_num_files files beginning at kp_file_head; otherwise we are 582 0 stevel * searching 1 file whose file pointer is obtained via object_to_map. 583 0 stevel */ 584 0 stevel if (object != MDB_TGT_OBJ_EVERY) { 585 0 stevel kp_map_t *kpm = kp_name_to_kpmap(kp, object); 586 0 stevel if (kpm == NULL || kpm->kpm_file == NULL) 587 0 stevel return (set_errno(EMDB_NOOBJ)); 588 0 stevel kpf = kpm->kpm_file; 589 0 stevel n = 1; 590 0 stevel } else { 591 0 stevel kpf = kp->kp_file_head; 592 0 stevel n = kp->kp_num_files; 593 0 stevel } 594 0 stevel 595 0 stevel /* 596 0 stevel * Iterate through the load object files and look for the symbol name 597 0 stevel * in the .dynsym of each. If we encounter a match with SHN_UNDEF, 598 0 stevel * keep looking in hopes of finding a better match. This means that 599 0 stevel * a name such as "puts" will match the puts function in libc instead 600 0 stevel * of matching the puts PLT entry in the a.out file. 601 0 stevel */ 602 0 stevel for (; n > 0; n--, kpf = kpf->kpf_next) { 603 0 stevel if (kpf->kpf_dynsym == NULL) 604 0 stevel continue; /* No symbols for this file */ 605 0 stevel 606 0 stevel if (mdb_gelf_symtab_lookup_by_name(kpf->kpf_dynsym, 607 0 stevel name, symp, &sip->sym_id) != 0) 608 0 stevel continue; /* Symbol name not found */ 609 0 stevel 610 0 stevel symp->st_value += kpf->kpf_dyn_base; 611 0 stevel 612 0 stevel if (symp->st_shndx != SHN_UNDEF) { 613 0 stevel sip->sym_table = MDB_TGT_DYNSYM; 614 0 stevel return (0); 615 0 stevel } 616 0 stevel 617 0 stevel if (rv != 0) { 618 0 stevel sym = *symp; 619 0 stevel symid = sip->sym_id; 620 0 stevel rv = 0; 621 0 stevel } 622 0 stevel } 623 0 stevel 624 0 stevel if (rv != 0) 625 0 stevel return (set_errno(EMDB_NOSYM)); 626 0 stevel 627 0 stevel sip->sym_table = MDB_TGT_DYNSYM; 628 0 stevel sip->sym_id = symid; 629 0 stevel *symp = sym; 630 0 stevel 631 0 stevel return (0); 632 0 stevel } 633 0 stevel 634 0 stevel static int 635 0 stevel kp_lookup_by_addr(mdb_tgt_t *t, uintptr_t addr, uint_t flags, 636 0 stevel char *buf, size_t nbytes, GElf_Sym *symp, mdb_syminfo_t *sip) 637 0 stevel { 638 0 stevel kp_data_t *kp = t->t_data; 639 0 stevel kp_map_t *kpm = kp_addr_to_kpmap(kp, addr); 640 0 stevel 641 0 stevel kp_file_t *sym_kpf = NULL; 642 0 stevel GElf_Sym sym; 643 0 stevel uint_t symid; 644 0 stevel 645 0 stevel const char *name; 646 0 stevel kp_file_t *kpf; 647 0 stevel int n; 648 0 stevel 649 0 stevel /* 650 0 stevel * Check the user's private symbol table first; if a match is 651 0 stevel * found there, we're done or we have a first guess. 652 0 stevel */ 653 0 stevel if (mdb_gelf_symtab_lookup_by_addr(mdb.m_prsym, 654 0 stevel addr, flags, buf, nbytes, symp, &sip->sym_id) == 0) { 655 0 stevel sym_kpf = &kp->kp_prfile; 656 0 stevel if (flags & MDB_TGT_SYM_EXACT) 657 0 stevel goto found; 658 0 stevel sym = *symp; 659 0 stevel symid = sip->sym_id; 660 0 stevel } 661 0 stevel 662 0 stevel /* 663 0 stevel * If no mapping contains the address and EXACT mode is set, we're done. 664 0 stevel * Otherwise we need to search all the symbol tables in fuzzy mode. 665 0 stevel * If we find a mapping, then we only need to search that symtab. 666 0 stevel */ 667 0 stevel if (kpm == NULL || kpm->kpm_file == NULL) { 668 0 stevel if (flags & MDB_TGT_SYM_EXACT) 669 0 stevel return (set_errno(EMDB_NOSYMADDR)); 670 0 stevel kpf = kp->kp_file_head; 671 0 stevel n = kp->kp_num_files; 672 0 stevel } else { 673 0 stevel kpf = kpm->kpm_file; 674 0 stevel n = 1; 675 0 stevel } 676 0 stevel 677 0 stevel /* 678 0 stevel * Iterate through our list of load objects, scanning each one which 679 0 stevel * has a symbol table. In fuzzy mode, we continue looking and 680 0 stevel * improve our choice if we find a closer symbol. 681 0 stevel */ 682 0 stevel for (; n > 0; n--, kpf = kpf->kpf_next) { 683 0 stevel if (kpf->kpf_dynsym == NULL) 684 0 stevel continue; /* No symbols for this file */ 685 0 stevel 686 0 stevel if (mdb_gelf_symtab_lookup_by_addr(kpf->kpf_dynsym, 687 0 stevel addr - kpf->kpf_dyn_base, flags, buf, nbytes, 688 0 stevel symp, &sip->sym_id) != 0) 689 0 stevel continue; /* No symbol for this address */ 690 0 stevel 691 0 stevel symp->st_value += kpf->kpf_dyn_base; 692 0 stevel 693 0 stevel if (flags & MDB_TGT_SYM_EXACT) { 694 0 stevel sym_kpf = kpf; 695 0 stevel goto found; 696 0 stevel } 697 0 stevel 698 0 stevel if (sym_kpf == NULL || mdb_gelf_sym_closer(symp, &sym, addr)) { 699 0 stevel sym_kpf = kpf; 700 0 stevel sym = *symp; 701 0 stevel symid = sip->sym_id; 702 0 stevel } 703 0 stevel } 704 0 stevel 705 0 stevel if (sym_kpf == NULL) 706 0 stevel return (set_errno(EMDB_NOSYMADDR)); 707 0 stevel 708 0 stevel *symp = sym; /* Copy our best symbol into the caller's symbol */ 709 0 stevel sip->sym_id = symid; 710 0 stevel found: 711 0 stevel /* 712 0 stevel * Once we've found something, copy the final name into the caller's 713 0 stevel * buffer and prefix it with the load object name if appropriate. 714 0 stevel */ 715 0 stevel name = mdb_gelf_sym_name(sym_kpf->kpf_dynsym, symp); 716 0 stevel 717 0 stevel if (sym_kpf != kp->kp_map_exec->kpm_file && sym_kpf != &kp->kp_prfile) { 718 0 stevel (void) mdb_snprintf(buf, nbytes, "%s`%s", 719 0 stevel sym_kpf->kpf_basename, name); 720 0 stevel } else if (nbytes > 0) { 721 0 stevel (void) strncpy(buf, name, nbytes); 722 0 stevel buf[nbytes - 1] = '\0'; 723 0 stevel } 724 0 stevel 725 0 stevel if (sym_kpf == &kp->kp_prfile) 726 0 stevel sip->sym_table = MDB_TGT_PRVSYM; 727 0 stevel else 728 0 stevel sip->sym_table = MDB_TGT_DYNSYM; 729 0 stevel 730 0 stevel return (0); 731 0 stevel } 732 0 stevel 733 0 stevel static int 734 0 stevel kp_symtab_func(void *data, const GElf_Sym *symp, const char *name, uint_t id) 735 0 stevel { 736 0 stevel kp_symarg_t *argp = data; 737 0 stevel if (mdb_tgt_sym_match(symp, argp->sym_type)) { 738 0 stevel GElf_Sym sym = *symp; 739 0 stevel 740 0 stevel sym.st_value += argp->sym_adjust; 741 0 stevel 742 0 stevel argp->sym_info.sym_id = id; 743 0 stevel 744 0 stevel return (argp->sym_cb(argp->sym_data, &sym, name, 745 0 stevel &argp->sym_info, argp->sym_obj)); 746 0 stevel } 747 0 stevel 748 0 stevel return (0); 749 0 stevel } 750 0 stevel 751 0 stevel static void 752 0 stevel kp_symtab_iter(kp_file_t *kpf, uint_t type, const char *obj, 753 0 stevel mdb_tgt_sym_f *cb, void *data) 754 0 stevel { 755 0 stevel if (kpf->kpf_dynsym != NULL) { 756 0 stevel kp_symarg_t arg; 757 0 stevel 758 0 stevel arg.sym_cb = cb; 759 0 stevel arg.sym_data = data; 760 0 stevel arg.sym_type = type; 761 0 stevel arg.sym_adjust = kpf->kpf_dyn_base; 762 0 stevel arg.sym_info.sym_table = kpf->kpf_dynsym->gst_tabid; 763 0 stevel arg.sym_obj = obj; 764 0 stevel 765 0 stevel mdb_gelf_symtab_iter(kpf->kpf_dynsym, kp_symtab_func, &arg); 766 0 stevel } 767 0 stevel } 768 0 stevel 769 0 stevel /*ARGSUSED*/ 770 0 stevel static int 771 0 stevel kp_symbol_iter(mdb_tgt_t *t, const char *object, uint_t which, 772 0 stevel uint_t type, mdb_tgt_sym_f *func, void *private) 773 0 stevel { 774 0 stevel kp_data_t *kp = t->t_data; 775 0 stevel kp_file_t *kpf = NULL; 776 0 stevel kp_map_t *kpm; 777 0 stevel 778 0 stevel switch ((uintptr_t)object) { 779 0 stevel case (uintptr_t)MDB_TGT_OBJ_EVERY: 780 0 stevel if (kp->kp_map_exec && kp->kp_map_exec->kpm_file) { 781 0 stevel kpf = kp->kp_map_exec->kpm_file; 782 0 stevel kp_symtab_iter(kpf, type, MDB_TGT_OBJ_EXEC, func, 783 0 stevel private); 784 0 stevel } 785 0 stevel if (kp->kp_map_ldso && kp->kp_map_ldso->kpm_file) { 786 0 stevel kpf = kp->kp_map_ldso->kpm_file; 787 0 stevel kp_symtab_iter(kpf, type, MDB_TGT_OBJ_RTLD, func, 788 0 stevel private); 789 0 stevel } 790 0 stevel return (0); 791 0 stevel 792 0 stevel case (uintptr_t)MDB_TGT_OBJ_EXEC: 793 0 stevel if (kp->kp_map_exec && kp->kp_map_exec->kpm_file) 794 0 stevel kpf = kp->kp_map_exec->kpm_file; 795 0 stevel break; 796 0 stevel 797 0 stevel case (uintptr_t)MDB_TGT_OBJ_RTLD: 798 0 stevel if (kp->kp_map_ldso && kp->kp_map_ldso->kpm_file) 799 0 stevel kpf = kp->kp_map_ldso->kpm_file; 800 0 stevel break; 801 0 stevel 802 0 stevel default: 803 0 stevel if ((kpm = kp_name_to_kpmap(kp, object)) != NULL) { 804 0 stevel kpf = kpm->kpm_file; 805 0 stevel break; 806 0 stevel } else 807 0 stevel return (set_errno(EMDB_NOOBJ)); 808 0 stevel } 809 0 stevel 810 0 stevel if (kpf != NULL) 811 0 stevel kp_symtab_iter(kpf, type, object, func, private); 812 0 stevel 813 0 stevel return (0); 814 0 stevel } 815 0 stevel 816 0 stevel static int 817 0 stevel kp_mapping_iter(mdb_tgt_t *t, mdb_tgt_map_f *func, void *private) 818 0 stevel { 819 0 stevel kp_data_t *kp = t->t_data; 820 0 stevel kp_map_t *kpm; 821 0 stevel 822 0 stevel for (kpm = kp->kp_map_head; kpm != NULL; kpm = kpm->kpm_next) { 823 0 stevel if (func(private, &kpm->kpm_map, kpm->kpm_map.map_name) != 0) 824 0 stevel break; 825 0 stevel } 826 0 stevel 827 0 stevel return (0); 828 0 stevel } 829 0 stevel 830 0 stevel static int 831 0 stevel kp_object_iter(mdb_tgt_t *t, mdb_tgt_map_f *func, void *private) 832 0 stevel { 833 0 stevel kp_data_t *kp = t->t_data; 834 0 stevel kp_file_t *kpf; 835 0 stevel 836 0 stevel for (kpf = kp->kp_file_head; kpf != NULL; kpf = kpf->kpf_next) { 837 0 stevel if (func(private, &kpf->kpf_map->kpm_map, 838 0 stevel kpf->kpf_map->kpm_map.map_name) != 0) 839 0 stevel break; 840 0 stevel } 841 0 stevel 842 0 stevel return (0); 843 0 stevel } 844 0 stevel 845 0 stevel static const mdb_map_t * 846 0 stevel kp_addr_to_map(mdb_tgt_t *t, uintptr_t addr) 847 0 stevel { 848 0 stevel kp_map_t *kpm = kp_addr_to_kpmap(t->t_data, addr); 849 0 stevel 850 0 stevel if (kpm != NULL) 851 0 stevel return (&kpm->kpm_map); 852 0 stevel 853 0 stevel (void) set_errno(EMDB_NOMAP); 854 0 stevel return (NULL); 855 0 stevel } 856 0 stevel 857 0 stevel static const mdb_map_t * 858 0 stevel kp_name_to_map(mdb_tgt_t *t, const char *name) 859 0 stevel { 860 0 stevel kp_map_t *kpm = kp_name_to_kpmap(t->t_data, name); 861 0 stevel 862 0 stevel if (kpm != NULL) 863 0 stevel return (&kpm->kpm_map); 864 0 stevel 865 0 stevel (void) set_errno(EMDB_NOOBJ); 866 0 stevel return (NULL); 867 0 stevel } 868 0 stevel 869 0 stevel /*ARGSUSED*/ 870 0 stevel static int 871 0 stevel kp_status(mdb_tgt_t *t, mdb_tgt_status_t *tsp) 872 0 stevel { 873 0 stevel bzero(tsp, sizeof (mdb_tgt_status_t)); 874 0 stevel tsp->st_state = MDB_TGT_DEAD; 875 0 stevel return (0); 876 0 stevel } 877 0 stevel 878 6473 edp static int 879 6473 edp kp_auxv(mdb_tgt_t *t, const auxv_t **auxvp) 880 6473 edp { 881 6473 edp kp_data_t *kp = t->t_data; 882 6473 edp *auxvp = kp->kp_auxv; 883 6473 edp return (0); 884 6473 edp } 885 6473 edp 886 0 stevel static const mdb_tgt_ops_t kproc_ops = { 887 0 stevel (int (*)()) mdb_tgt_notsup, /* t_setflags */ 888 0 stevel kp_setcontext, /* t_setcontext */ 889 0 stevel kp_activate, /* t_activate */ 890 0 stevel kp_deactivate, /* t_deactivate */ 891 0 stevel (void (*)()) mdb_tgt_nop, /* t_periodic */ 892 0 stevel kp_destroy, /* t_destroy */ 893 0 stevel kp_name, /* t_name */ 894 0 stevel kp_isa, /* t_isa */ 895 0 stevel kp_platform, /* t_platform */ 896 0 stevel kp_uname, /* t_uname */ 897 0 stevel kp_dmodel, /* t_dmodel */ 898 0 stevel (ssize_t (*)()) mdb_tgt_notsup, /* t_aread */ 899 0 stevel (ssize_t (*)()) mdb_tgt_notsup, /* t_awrite */ 900 0 stevel kp_vread, /* t_vread */ 901 0 stevel kp_vwrite, /* t_vwrite */ 902 0 stevel (ssize_t (*)()) mdb_tgt_notsup, /* t_pread */ 903 0 stevel (ssize_t (*)()) mdb_tgt_notsup, /* t_pwrite */ 904 0 stevel (ssize_t (*)()) mdb_tgt_notsup, /* t_fread */ 905 0 stevel (ssize_t (*)()) mdb_tgt_notsup, /* t_fwrite */ 906 0 stevel (ssize_t (*)()) mdb_tgt_notsup, /* t_ioread */ 907 0 stevel (ssize_t (*)()) mdb_tgt_notsup, /* t_iowrite */ 908 0 stevel kp_vtop, /* t_vtop */ 909 0 stevel kp_lookup_by_name, /* t_lookup_by_name */ 910 0 stevel kp_lookup_by_addr, /* t_lookup_by_addr */ 911 0 stevel kp_symbol_iter, /* t_symbol_iter */ 912 0 stevel kp_mapping_iter, /* t_mapping_iter */ 913 0 stevel kp_object_iter, /* t_object_iter */ 914 0 stevel kp_addr_to_map, /* t_addr_to_map */ 915 0 stevel kp_name_to_map, /* t_name_to_map */ 916 0 stevel (struct ctf_file *(*)()) mdb_tgt_null, /* t_addr_to_ctf */ 917 0 stevel (struct ctf_file *(*)()) mdb_tgt_null, /* t_name_to_ctf */ 918 0 stevel kp_status, /* t_status */ 919 0 stevel (int (*)()) mdb_tgt_notsup, /* t_run */ 920 0 stevel (int (*)()) mdb_tgt_notsup, /* t_step */ 921 0 stevel (int (*)()) mdb_tgt_notsup, /* t_step_out */ 922 0 stevel (int (*)()) mdb_tgt_notsup, /* t_step_branch */ 923 0 stevel (int (*)()) mdb_tgt_notsup, /* t_next */ 924 0 stevel (int (*)()) mdb_tgt_notsup, /* t_cont */ 925 0 stevel (int (*)()) mdb_tgt_notsup, /* t_signal */ 926 0 stevel (int (*)()) mdb_tgt_null, /* t_add_sbrkpt */ 927 0 stevel (int (*)()) mdb_tgt_null, /* t_add_vbrkpt */ 928 0 stevel (int (*)()) mdb_tgt_null, /* t_add_pwapt */ 929 0 stevel (int (*)()) mdb_tgt_null, /* t_add_vwapt */ 930 0 stevel (int (*)()) mdb_tgt_null, /* t_add_iowapt */ 931 0 stevel (int (*)()) mdb_tgt_null, /* t_add_sysenter */ 932 0 stevel (int (*)()) mdb_tgt_null, /* t_add_sysexit */ 933 0 stevel (int (*)()) mdb_tgt_null, /* t_add_signal */ 934 0 stevel (int (*)()) mdb_tgt_null, /* t_add_fault */ 935 0 stevel (int (*)()) mdb_tgt_notsup, /* t_getareg XXX */ 936 0 stevel (int (*)()) mdb_tgt_notsup, /* t_putareg XXX */ 937 6473 edp (int (*)()) mdb_tgt_notsup, /* t_stack_iter XXX */ 938 6473 edp kp_auxv /* t_auxv */ 939 0 stevel }; 940 0 stevel 941 0 stevel int 942 0 stevel mdb_kproc_tgt_create(mdb_tgt_t *t, int argc, const char *argv[]) 943 0 stevel { 944 0 stevel kp_data_t *kp = mdb_zalloc(sizeof (kp_data_t), UM_SLEEP); 945 0 stevel void *proc = (void *)argv[0]; 946 0 stevel long at_entry, at_base; 947 0 stevel GElf_Sym sym; 948 0 stevel 949 0 stevel int (*f_asiter)(uintptr_t, void (*)(const mdb_map_t *, void *), void *); 950 0 stevel int (*f_auxv)(uintptr_t, auxv_t *); 951 0 stevel uintptr_t (*f_as)(uintptr_t); 952 0 stevel uint_t (*f_model)(uintptr_t); 953 0 stevel pid_t (*f_pid)(uintptr_t); 954 0 stevel 955 0 stevel if (argc != 1) 956 0 stevel return (set_errno(EINVAL)); 957 0 stevel 958 0 stevel t->t_flags &= ~MDB_TGT_F_RDWR; 959 0 stevel t->t_data = kp; 960 0 stevel t->t_ops = &kproc_ops; 961 0 stevel 962 0 stevel f_asiter = (int (*)()) dlsym(RTLD_NEXT, "mdb_kproc_asiter"); 963 0 stevel f_auxv = (int (*)()) dlsym(RTLD_NEXT, "mdb_kproc_auxv"); 964 0 stevel f_as = (uintptr_t (*)()) dlsym(RTLD_NEXT, "mdb_kproc_as"); 965 0 stevel f_model = (model_t (*)()) dlsym(RTLD_NEXT, "mdb_kproc_model"); 966 0 stevel f_pid = (pid_t (*)()) dlsym(RTLD_NEXT, "mdb_kproc_pid"); 967 0 stevel 968 0 stevel if (f_asiter == NULL || f_auxv == NULL || 969 0 stevel f_as == NULL || f_model == NULL || f_pid == NULL) { 970 0 stevel warn("required kernel support module is not loaded\n"); 971 0 stevel goto err; 972 0 stevel } 973 0 stevel 974 0 stevel /* 975 0 stevel * Here the kproc target relies on the fact that at the time of its 976 0 stevel * instantiation, mdb.m_target is pointing at a kvm target, and 977 0 stevel * that the kvm target has stored its libkvm handle in t_pshandle. 978 0 stevel */ 979 0 stevel kp->kp_parent = mdb.m_target; 980 0 stevel kp->kp_cookie = mdb.m_target->t_pshandle; 981 0 stevel kp->kp_platform = mdb_tgt_platform(mdb.m_target); 982 0 stevel kp->kp_proc = proc; 983 0 stevel kp->kp_as = (struct as *)f_as((uintptr_t)proc); 984 0 stevel kp->kp_pid = f_pid((uintptr_t)proc); 985 0 stevel 986 0 stevel if (kp->kp_as == NULL) { 987 0 stevel warn("failed to obtain address space for proc %p\n", proc); 988 0 stevel goto err; 989 0 stevel } 990 0 stevel 991 0 stevel if (kp->kp_pid == -1) { 992 0 stevel warn("failed to obtain PID for proc %p\n", proc); 993 0 stevel goto err; 994 0 stevel } 995 0 stevel 996 0 stevel if (mdb_tgt_lookup_by_name(kp->kp_parent, MDB_TGT_OBJ_EXEC, "kas", 997 0 stevel &sym, NULL) == 0 && kp->kp_as == 998 0 stevel (struct as *)(uintptr_t)sym.st_value) { 999 0 stevel warn("specified process is a system process (no context)\n"); 1000 0 stevel goto err; 1001 0 stevel } 1002 0 stevel 1003 0 stevel if ((kp->kp_model = f_model((uintptr_t)proc)) == PR_MODEL_UNKNOWN) { 1004 0 stevel warn("failed to obtain data model for proc %p\n", proc); 1005 0 stevel goto err; 1006 0 stevel } 1007 0 stevel 1008 0 stevel if (f_asiter((uintptr_t)kp->kp_as, kp_add_mapping, kp) == -1) { 1009 0 stevel warn("failed to load mappings for proc %p", proc); 1010 0 stevel goto err; 1011 0 stevel } 1012 0 stevel 1013 0 stevel kp->kp_nauxv = f_auxv((uintptr_t)proc, NULL) + 1; 1014 0 stevel kp->kp_auxv = mdb_alloc(sizeof (auxv_t) * kp->kp_nauxv, UM_SLEEP); 1015 0 stevel 1016 0 stevel if (f_auxv((uintptr_t)proc, kp->kp_auxv) == -1) { 1017 0 stevel warn("failed to load auxv for proc %p", proc); 1018 0 stevel goto err; 1019 0 stevel } 1020 0 stevel 1021 0 stevel kp->kp_auxv[kp->kp_nauxv - 1].a_type = AT_NULL; 1022 0 stevel kp->kp_auxv[kp->kp_nauxv - 1].a_un.a_val = 0; 1023 0 stevel 1024 0 stevel if ((at_entry = kp_getauxval(kp, AT_ENTRY)) == -1L) { 1025 0 stevel warn("auxv for proc %p is missing AT_ENTRY\n", proc); 1026 0 stevel goto err; 1027 0 stevel } 1028 0 stevel 1029 0 stevel if ((at_base = kp_getauxval(kp, AT_BASE)) == -1L) { 1030 0 stevel warn("auxv for proc %p is missing AT_BASE\n", proc); 1031 0 stevel goto err; 1032 0 stevel } 1033 0 stevel 1034 0 stevel /* 1035 0 stevel * If we're applying kproc to a live kernel, we need to force libkvm 1036 0 stevel * to set the current process to the process in question so we can 1037 0 stevel * read from its address space. If kvm_getproc returns NULL, the 1038 0 stevel * process may have gone away since our previous calls to mdb_ks. 1039 0 stevel */ 1040 0 stevel if (mdb_prop_postmortem == FALSE && 1041 0 stevel kvm_getproc(kp->kp_cookie, kp->kp_pid) == NULL) 1042 0 stevel warn("failed to attach to PID %d\n", (int)kp->kp_pid); 1043 0 stevel 1044 0 stevel kp->kp_map_exec = kp_addr_to_kpmap(kp, at_entry); 1045 0 stevel kp->kp_map_ldso = kp_addr_to_kpmap(kp, at_base); 1046 0 stevel 1047 0 stevel (void) kp_file_create(t, kp->kp_map_exec, ET_EXEC); 1048 0 stevel (void) kp_file_create(t, kp->kp_map_ldso, ET_DYN); 1049 0 stevel 1050 0 stevel kp->kp_prfile.kpf_dynsym = mdb.m_prsym; 1051 0 stevel 1052 0 stevel return (0); 1053 0 stevel 1054 0 stevel err: 1055 0 stevel kp_destroy(t); 1056 0 stevel return (-1); 1057 0 stevel } 1058 0 stevel 1059 0 stevel static ssize_t 1060 0 stevel kp_io_read(mdb_io_t *io, void *buf, size_t nbytes) 1061 0 stevel { 1062 0 stevel kp_io_t *kpi = io->io_data; 1063 0 stevel kp_data_t *kp = kpi->kpi_tgt->t_data; 1064 0 stevel 1065 0 stevel kp_map_t *kpm = kp_addr_to_kpmap(kp, kpi->kpi_ptr); 1066 0 stevel size_t left; 1067 0 stevel 1068 0 stevel if (kpm != NULL) { 1069 0 stevel const mdb_map_t *mp = &kpm->kpm_map; 1070 0 stevel left = mp->map_base + mp->map_size - kpi->kpi_ptr; 1071 0 stevel } else 1072 0 stevel left = 0; 1073 0 stevel 1074 0 stevel if (left != 0) { 1075 0 stevel ssize_t rbytes = kp_vread(kpi->kpi_tgt, 1076 0 stevel buf, MIN(nbytes, left), kpi->kpi_ptr); 1077 0 stevel 1078 0 stevel if (rbytes >= 0) 1079 0 stevel kpi->kpi_ptr += rbytes; 1080 0 stevel 1081 0 stevel return (rbytes); 1082 0 stevel } 1083 0 stevel 1084 0 stevel return (0); /* At end of segment or in hole; return EOF */ 1085 0 stevel } 1086 0 stevel 1087 0 stevel static off64_t 1088 0 stevel kp_io_seek(mdb_io_t *io, off64_t offset, int whence) 1089 0 stevel { 1090 0 stevel kp_io_t *kpi = io->io_data; 1091 0 stevel const mdb_map_t *mp = &kpi->kpi_map->kpm_map; 1092 0 stevel uintptr_t nptr; 1093 0 stevel 1094 0 stevel if (io->io_next != NULL) 1095 0 stevel return (IOP_SEEK(io->io_next, offset, whence)); 1096 0 stevel 1097 0 stevel switch (whence) { 1098 0 stevel case SEEK_SET: 1099 0 stevel nptr = mp->map_base + offset; 1100 0 stevel break; 1101 0 stevel case SEEK_CUR: 1102 0 stevel nptr = kpi->kpi_ptr + offset; 1103 0 stevel break; 1104 0 stevel case SEEK_END: 1105 0 stevel nptr = kpi->kpi_lim + offset; 1106 0 stevel break; 1107 0 stevel default: 1108 0 stevel return (set_errno(EINVAL)); 1109 0 stevel } 1110 0 stevel 1111 0 stevel if (nptr < mp->map_base || nptr >= kpi->kpi_lim) 1112 0 stevel return (set_errno(EINVAL)); 1113 0 stevel 1114 0 stevel kpi->kpi_ptr = nptr; 1115 0 stevel return ((off64_t)(nptr - mp->map_base)); 1116 0 stevel } 1117 0 stevel 1118 0 stevel static void 1119 0 stevel kp_io_close(mdb_io_t *io) 1120 0 stevel { 1121 0 stevel mdb_free(io->io_data, sizeof (kp_io_t)); 1122 0 stevel } 1123 0 stevel 1124 0 stevel static const char * 1125 0 stevel kp_io_name(mdb_io_t *io) 1126 0 stevel { 1127 0 stevel kp_io_t *kpi = io->io_data; 1128 0 stevel 1129 0 stevel if (io->io_next != NULL) 1130 0 stevel return (IOP_NAME(io->io_next)); 1131 0 stevel 1132 0 stevel return (kpi->kpi_map->kpm_map.map_name); 1133 0 stevel } 1134 0 stevel 1135 0 stevel static const mdb_io_ops_t kp_io_ops = { 1136 0 stevel kp_io_read, 1137 0 stevel no_io_write, 1138 0 stevel kp_io_seek, 1139 0 stevel no_io_ctl, 1140 0 stevel kp_io_close, 1141 0 stevel kp_io_name, 1142 0 stevel no_io_link, 1143 0 stevel no_io_unlink, 1144 0 stevel no_io_setattr, 1145 0 stevel no_io_suspend, 1146 0 stevel no_io_resume 1147 0 stevel }; 1148 0 stevel 1149 0 stevel static mdb_io_t * 1150 0 stevel kp_io_create(mdb_tgt_t *t, kp_map_t *kpm) 1151 0 stevel { 1152 0 stevel kp_data_t *kp = t->t_data; 1153 0 stevel mdb_map_t *mp = &kp->kp_map_tail->kpm_map; 1154 0 stevel 1155 0 stevel mdb_io_t *io = mdb_alloc(sizeof (mdb_io_t), UM_SLEEP); 1156 0 stevel kp_io_t *kpi = mdb_alloc(sizeof (kp_io_t), UM_SLEEP); 1157 0 stevel 1158 0 stevel kpi->kpi_tgt = t; 1159 0 stevel kpi->kpi_map = kpm; 1160 0 stevel kpi->kpi_ptr = kpm->kpm_map.map_base; 1161 0 stevel kpi->kpi_lim = mp->map_base + mp->map_size; 1162 0 stevel 1163 0 stevel io->io_ops = &kp_io_ops; 1164 0 stevel io->io_data = kpi; 1165 0 stevel io->io_next = NULL; 1166 0 stevel io->io_refcnt = 0; 1167 0 stevel 1168 0 stevel return (io); 1169 0 stevel } 1170