1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 /* 12 * Copyright (c) 2013 by Delphix. All rights reserved. 13 */ 14 15 /* 16 * This file implements the mdb ::gcore command. The command relies on the 17 * libproc Pgcore function to actually generate the core file but we provide 18 * our own ops vector to populate data required by Pgcore. The ops vector 19 * function implementations simulate the functionality implemented by procfs. 20 * The data provided by some of the ops vector functions is not complete 21 * (missing data is documented in function headers) but there is enough 22 * information to generate a core file that can be loaded into mdb. 23 * 24 * Currently only x86 is supported. ISA-dependent functions are implemented 25 * in gcore_isadep.c. 26 */ 27 28 #ifndef _KMDB 29 30 /* 31 * The kernel has its own definition of exit which has a different signature 32 * than the user space definition. This seems to be the standard way to deal 33 * with this. 34 */ 35 #define exit kern_exit 36 37 #include <mdb/mdb_modapi.h> 38 #include <mdb/mdb_param.h> 39 #include <mdb/mdb_ks.h> 40 #include <mdb/mdb_ctf.h> 41 #include <mdb/mdb_debug.h> 42 #include <mdb/mdb_gcore.h> 43 44 #include <sys/class.h> 45 #include <sys/cpuvar.h> 46 #include <sys/proc.h> 47 #include <sys/lgrp.h> 48 #include <sys/pool.h> 49 #include <sys/project.h> 50 #include <sys/regset.h> 51 #include <sys/schedctl.h> 52 #include <sys/session.h> 53 #include <sys/syscall.h> 54 #include <sys/task.h> 55 #include <sys/var.h> 56 #include <sys/privregs.h> 57 #include <sys/fault.h> 58 #include <sys/sysmacros.h> 59 #include <sys/wait.h> 60 #include <vm/seg.h> 61 #include <vm/vpage.h> 62 #include <fs/proc/prdata.h> 63 64 #undef exit 65 66 #include <stdio.h> 67 #include <stdbool.h> 68 #include <string.h> 69 #include <libproc.h> 70 71 #include "avl.h" 72 73 #ifdef _LP64 74 #define LSPAN(type) (P2ROUNDUP(sizeof (type), 16)) 75 #else 76 #define LSPAN(type) (P2ROUNDUP(sizeof (type), 8)) 77 #endif 78 79 #define vpgtob(n) ((n) * sizeof (struct vpage)) 80 81 /* Macros to invoke gcore seg operations */ 82 #define GSOP_INIT(_gs) (_gs)->gs_ops->gsop_init((_gs)) 83 #define GSOP_FINI(_gs) (_gs)->gs_ops->gsop_fini((_gs)) 84 #define GSOP_INCORE(_gs, _addr, _eaddr) \ 85 (_gs)->gs_ops->gsop_incore((_gs), (_addr), (_eaddr)) 86 #define GSOP_GETPROT(_gs, _addr) \ 87 (_gs)->gs_ops->gsop_getprot((_gs), (_addr)) 88 #define GSOP_GETOFFSET(_gs, _addr) \ 89 (_gs)->gs_ops->gsop_getoffset((_gs), (_addr)) 90 #define GSOP_GETTYPE(_gs, _addr) \ 91 (_gs)->gs_ops->gsop_gettype((_gs), (_addr)) 92 #define GSOP_NAME(_gs, _name, _size) \ 93 (_gs)->gs_ops->gsop_name((_gs), (_name), (_size)) 94 #define GSOP_NORESERVE(_gs) \ 95 (_gs)->gs_ops->gsop_noreserve((_gs)) 96 97 #ifdef GCORE_DEBUG 98 #define dprintf(...) mdb_printf(__VA_ARGS__) 99 #else 100 #define dprintf(...) 101 #endif 102 103 /* Callback function type for processing lwp entries */ 104 typedef int (*lwp_callback_t)(mdb_proc_t *, lwpent_t *, void *); 105 106 /* Private data */ 107 static uintptr_t gcore_segvn_ops; 108 static priv_impl_info_t prinfo; 109 static sclass_t *gcore_sclass; 110 static uintptr_t gcore_kas; 111 static boolean_t gcore_initialized = B_FALSE; 112 113 typedef int (*gsop_init_t)(gcore_seg_t *); 114 typedef void (*gsop_fini_t)(gcore_seg_t *); 115 typedef u_offset_t (*gsop_incore_t)(gcore_seg_t *, u_offset_t, u_offset_t); 116 typedef uint_t (*gsop_getprot_t)(gcore_seg_t *, u_offset_t); 117 typedef int (*gsop_getoffset_t)(gcore_seg_t *, u_offset_t); 118 typedef void (*gsop_name_t)(gcore_seg_t *, char *name, size_t size); 119 typedef int (*gsop_gettype_t)(gcore_seg_t *, u_offset_t); 120 typedef boolean_t (*gsop_noreserve_t)(gcore_seg_t *); 121 122 typedef struct gcore_segops { 123 gsop_init_t gsop_init; 124 gsop_fini_t gsop_fini; 125 gsop_incore_t gsop_incore; 126 gsop_getprot_t gsop_getprot; 127 gsop_getoffset_t gsop_getoffset; 128 gsop_name_t gsop_name; 129 gsop_gettype_t gsop_gettype; 130 gsop_noreserve_t gsop_noreserve; 131 } gcore_segops_t; 132 133 static void map_list_free(prmap_node_t *); 134 static uintptr_t gcore_prchoose(mdb_proc_t *); 135 136 /* 137 * Segvn ops 138 */ 139 static int gsvn_init(gcore_seg_t *); 140 static void gsvn_fini(gcore_seg_t *); 141 static u_offset_t gsvn_incore(gcore_seg_t *, u_offset_t, u_offset_t); 142 static uint_t gsvn_getprot(gcore_seg_t *, u_offset_t); 143 static int gsvn_getoffset(gcore_seg_t *, u_offset_t); 144 static void gsvn_name(gcore_seg_t *, char *, size_t); 145 static int gsvn_gettype(gcore_seg_t *, u_offset_t); 146 static boolean_t gsvn_noreserve(gcore_seg_t *); 147 148 static gcore_segops_t gsvn_ops = { 149 .gsop_init = gsvn_init, 150 .gsop_fini = gsvn_fini, 151 .gsop_incore = gsvn_incore, 152 .gsop_getprot = gsvn_getprot, 153 .gsop_getoffset = gsvn_getoffset, 154 .gsop_name = gsvn_name, 155 .gsop_gettype = gsvn_gettype, 156 .gsop_noreserve = gsvn_noreserve 157 }; 158 159 static int 160 gsvn_init(gcore_seg_t *gs) 161 { 162 mdb_seg_t *seg = gs->gs_seg; 163 mdb_segvn_data_t *svd = NULL; 164 struct vpage *vpage = NULL; 165 size_t nvpage = 0; 166 167 if (seg->s_data != NULL) { 168 svd = mdb_alloc(sizeof (*svd), UM_SLEEP); 169 if (mdb_ctf_vread(svd, "segvn_data_t", "mdb_segvn_data_t", 170 seg->s_data, 0) == -1) { 171 goto error; 172 } 173 174 if (svd->pageprot != 0) { 175 nvpage = seg_pages(seg); 176 dprintf("vpage count: %d\n", nvpage); 177 178 vpage = mdb_alloc(vpgtob(nvpage), UM_SLEEP); 179 if (mdb_vread(vpage, vpgtob(nvpage), 180 (uintptr_t)svd->vpage) != vpgtob(nvpage)) { 181 mdb_warn("Failed to read vpages from %p\n", 182 svd->vpage); 183 goto error; 184 } 185 186 svd->vpage = vpage; 187 } else { 188 svd->vpage = NULL; 189 } 190 gs->gs_data = svd; 191 } else { 192 gs->gs_data = NULL; 193 } 194 195 return (0); 196 197 error: 198 mdb_free(vpage, vpgtob(nvpage)); 199 mdb_free(svd, sizeof (*svd)); 200 return (-1); 201 } 202 203 /*ARGSUSED*/ 204 static int 205 gsvn_getoffset(gcore_seg_t *gs, u_offset_t addr) 206 { 207 mdb_segvn_data_t *svd = gs->gs_data; 208 mdb_seg_t *seg = gs->gs_seg; 209 210 return (svd->offset + (uintptr_t)(addr - seg->s_base)); 211 } 212 213 static void 214 gsvn_name(gcore_seg_t *gs, char *name, size_t size) 215 { 216 mdb_segvn_data_t *svd = gs->gs_data; 217 218 name[0] = '\0'; 219 if (svd->vp != 0) { 220 mdb_seg_t *seg = gs->gs_seg; 221 mdb_as_t as; 222 mdb_proc_t p; 223 mdb_vnode_t vn; 224 225 if (mdb_ctf_vread(&vn, "vnode_t", "mdb_vnode_t", svd->vp, 0) 226 == -1) { 227 return; 228 } 229 230 if (mdb_ctf_vread(&as, "struct as", "mdb_as_t", seg->s_as, 0) 231 == -1) { 232 return; 233 } 234 235 if (mdb_ctf_vread(&p, "proc_t", "mdb_proc_t", as.a_proc, 0) 236 == -1) { 237 return; 238 } 239 240 if (vn.v_type == VREG && svd->vp == p.p_exec) { 241 (void) strncpy(name, "a.out", size); 242 } 243 244 /* 245 * procfs has more logic here to construct a name using 246 * vfs/vnode identifiers but didn't seem worthwhile to add 247 * here. 248 */ 249 } 250 } 251 252 /*ARGSUSED*/ 253 static int 254 gsvn_gettype(gcore_seg_t *gs, u_offset_t addr) 255 { 256 return (0); 257 } 258 259 static void 260 gsvn_fini(gcore_seg_t *gs) 261 { 262 mdb_segvn_data_t *svd = gs->gs_data; 263 264 if (svd != NULL) { 265 if (svd->vpage != NULL) { 266 size_t nvpage = seg_pages(gs->gs_seg); 267 268 mdb_free(svd->vpage, vpgtob(nvpage)); 269 } 270 mdb_free(svd, sizeof (*svd)); 271 } 272 } 273 274 static boolean_t 275 gsvn_noreserve(gcore_seg_t *gs) 276 { 277 mdb_segvn_data_t *svd = gs->gs_data; 278 279 if (svd == NULL) { 280 return (B_FALSE); 281 } 282 283 if (svd->flags & MAP_NORESERVE) { 284 mdb_vnode_t vn; 285 286 if (svd->vp == 0) { 287 return (B_TRUE); 288 } 289 290 if (mdb_ctf_vread(&vn, "vnode_t", "mdb_vnode_t", 291 svd->vp, 0) == -1) { 292 return (B_FALSE); 293 } 294 295 if (vn.v_type != VREG) { 296 return (B_TRUE); 297 } 298 } 299 300 return (B_FALSE); 301 } 302 303 static uintptr_t 304 gcore_anon_get_ptr(uintptr_t ah_addr, ulong_t an_idx) 305 { 306 mdb_anon_hdr_t ah; 307 uintptr_t anon_addr; 308 uintptr_t anon_ptr; 309 310 if (mdb_ctf_vread(&ah, "struct anon_hdr", "mdb_anon_hdr_t", ah_addr, 311 0) == -1) { 312 return (0); 313 } 314 315 /* 316 * Single level case. 317 */ 318 if ((ah.size <= ANON_CHUNK_SIZE) || (ah.flags & ANON_ALLOC_FORCE)) { 319 anon_addr = ah.array_chunk + (sizeof (anon_ptr) * an_idx); 320 if (mdb_vread(&anon_ptr, sizeof (anon_ptr), anon_addr) != 321 sizeof (anon_ptr)) { 322 mdb_warn("Failed to read anon_ptr from %p (1 level)\n", 323 anon_addr); 324 return (0); 325 } 326 327 return (anon_ptr & ANON_PTRMASK); 328 } 329 330 /* 331 * 2 level case. 332 */ 333 anon_addr = ah.array_chunk + (sizeof (anon_ptr) * 334 (an_idx >> ANON_CHUNK_SHIFT)); 335 336 if (mdb_vread(&anon_ptr, sizeof (anon_ptr), anon_addr) != 337 sizeof (anon_ptr)) { 338 mdb_warn("Failed to read anon_ptr from %p (2a level)\n", 339 anon_addr); 340 return (0); 341 } 342 343 if (anon_ptr == 0) { 344 return (0); 345 } 346 347 anon_addr = anon_ptr + (sizeof (anon_ptr) * 348 (an_idx & ANON_CHUNK_OFF)); 349 if (mdb_vread(&anon_ptr, sizeof (anon_ptr), anon_addr) != 350 sizeof (anon_ptr)) { 351 mdb_warn("Failed to read anon_ptr from %p (2b level)\n", 352 anon_addr); 353 return (0); 354 } 355 356 return (anon_ptr & ANON_PTRMASK); 357 } 358 359 static void 360 gcore_anon_get(uintptr_t ahp, ulong_t an_index, uintptr_t *vp, u_offset_t *off) 361 { 362 mdb_anon_t anon; 363 uintptr_t ap; 364 365 ap = gcore_anon_get_ptr(ahp, an_index); 366 if (ap != 0) { 367 if (mdb_ctf_vread(&anon, "struct anon", "mdb_anon_t", ap, 0) == 368 -1) { 369 return; 370 } 371 372 *vp = anon.an_vp; 373 *off = anon.an_off; 374 } else { 375 *vp = 0; 376 *off = 0; 377 } 378 } 379 380 static u_offset_t 381 gsvn_incore(gcore_seg_t *gs, u_offset_t addr, u_offset_t eaddr) 382 { 383 mdb_segvn_data_t *svd = gs->gs_data; 384 mdb_seg_t *seg = gs->gs_seg; 385 mdb_amp_t amp; 386 u_offset_t offset; 387 uintptr_t vp; 388 size_t p, ep; 389 390 if (svd->amp != 0 && mdb_ctf_vread(&, "amp_t", "mdb_amp_t", svd->amp, 391 0) == -1) { 392 return (eaddr); 393 } 394 395 p = seg_page(seg, addr); 396 ep = seg_page(seg, eaddr); 397 for (; p < ep; p++, addr += PAGESIZE) { 398 /* First check the anon map */ 399 if (svd->amp != 0) { 400 gcore_anon_get(amp.ahp, svd->anon_index + p, &vp, 401 &offset); 402 if (vp != 0 && mdb_page_lookup(vp, offset) != 0) { 403 break; 404 } 405 } 406 407 /* Now check the segment's vnode */ 408 vp = svd->vp; 409 offset = svd->offset + (addr - gs->gs_seg->s_base); 410 if (mdb_page_lookup(vp, offset) != 0) { 411 break; 412 } 413 414 dprintf("amp: %p vp: %p addr: %p offset: %p not in core!\n", 415 svd->amp, svd->vp, addr, offset); 416 } 417 418 return (addr); 419 } 420 421 static uint_t 422 gsvn_getprot(gcore_seg_t *gs, u_offset_t addr) 423 { 424 mdb_segvn_data_t *svd = gs->gs_data; 425 mdb_seg_t *seg = gs->gs_seg; 426 427 if (svd->pageprot == 0) { 428 return (svd->prot); 429 } 430 431 dprintf("addr: %p pgno: %p\n", addr, seg_page(seg, addr)); 432 return (VPP_PROT(&svd->vpage[seg_page(seg, addr)])); 433 } 434 435 /* 436 * Helper functions for constructing the process address space maps. 437 */ 438 /*ARGSUSED*/ 439 static int 440 as_segat_cb(uintptr_t seg_addr, const void *aw_buff, void *arg) 441 { 442 as_segat_cbarg_t *as_segat_arg = arg; 443 mdb_seg_t seg; 444 445 if (mdb_ctf_vread(&seg, "struct seg", "mdb_seg_t", seg_addr, 0) == -1) { 446 return (WALK_ERR); 447 } 448 449 if (as_segat_arg->addr < seg.s_base) { 450 return (WALK_NEXT); 451 } 452 453 if (as_segat_arg->addr >= seg.s_base + seg.s_size) { 454 return (WALK_NEXT); 455 } 456 457 as_segat_arg->res = seg_addr; 458 return (WALK_DONE); 459 } 460 461 /* 462 * Find a segment containing addr. 463 */ 464 static uintptr_t 465 gcore_as_segat(uintptr_t as_addr, uintptr_t addr) 466 { 467 as_segat_cbarg_t as_segat_arg; 468 uintptr_t segtree_addr; 469 470 as_segat_arg.addr = addr; 471 as_segat_arg.res = 0; 472 473 segtree_addr = as_addr + mdb_ctf_offsetof_by_name("struct as", 474 "a_segtree"); 475 (void) avl_walk_mdb(segtree_addr, as_segat_cb, &as_segat_arg); 476 477 return (as_segat_arg.res); 478 } 479 480 static uintptr_t 481 gcore_break_seg(mdb_proc_t *p) 482 { 483 uintptr_t addr = p->p_brkbase; 484 485 if (p->p_brkbase != 0) 486 addr += p->p_brksize - 1; 487 488 return (gcore_as_segat(p->p_as, addr)); 489 } 490 491 static u_offset_t 492 gcore_vnode_size(uintptr_t vnode_addr) 493 { 494 mdb_vnode_t vnode; 495 mdb_vnodeops_t vnodeops; 496 char vops_name[128]; 497 498 if (mdb_ctf_vread(&vnode, "vnode_t", "mdb_vnode_t", vnode_addr, 0) == 499 -1) { 500 return (-1); 501 } 502 503 if (mdb_ctf_vread(&vnodeops, "vnodeops_t", "mdb_vnodeops_t", 504 vnode.v_op, 0) == -1) { 505 return (-1); 506 } 507 508 if (mdb_readstr(vops_name, sizeof (vops_name), vnodeops.vnop_name) == 509 -1) { 510 mdb_warn("Failed to read vnop_name from %p\n", 511 vnodeops.vnop_name); 512 return (-1); 513 } 514 515 if (strcmp(vops_name, "zfs") == 0) { 516 mdb_znode_t znode; 517 518 if (mdb_ctf_vread(&znode, "znode_t", "mdb_znode_t", 519 vnode.v_data, 0) == -1) { 520 return (-1); 521 } 522 return (znode.z_size); 523 } 524 525 if (strcmp(vops_name, "tmpfs") == 0) { 526 mdb_tmpnode_t tnode; 527 528 if (mdb_ctf_vread(&tnode, "struct tmpnode", "mdb_tmpnode_t", 529 vnode.v_data, 0) == -1) { 530 return (-1); 531 } 532 return (tnode.tn_attr.va_size); 533 } 534 535 /* Unknown file system type. */ 536 mdb_warn("Unknown fs type: %s\n", vops_name); 537 return (-1); 538 } 539 540 static uint64_t 541 gcore_pr_getsegsize(mdb_seg_t *seg) 542 { 543 uint64_t size = seg->s_size; 544 545 if (seg->s_ops == gcore_segvn_ops) { 546 mdb_segvn_data_t svd; 547 548 if (mdb_ctf_vread(&svd, "segvn_data_t", "mdb_segvn_data_t", 549 seg->s_data, 0) == -1) { 550 return (-1); 551 } 552 553 if (svd.vp != 0) { 554 u_offset_t fsize; 555 u_offset_t offset; 556 557 fsize = gcore_vnode_size(svd.vp); 558 if (fsize == -1) { 559 return (-1); 560 } 561 offset = svd.offset; 562 563 if (fsize < offset) { 564 fsize = 0; 565 } else { 566 fsize -= offset; 567 } 568 569 fsize = roundup(fsize, PAGESIZE); 570 } 571 572 return (size); 573 } 574 575 return (size); 576 } 577 578 /*ARGSUSED*/ 579 static int 580 gcore_getwatchprot_cb(uintptr_t node_addr, const void *aw_buff, void *arg) 581 { 582 getwatchprot_cbarg_t *cbarg = arg; 583 584 if (mdb_ctf_vread(&cbarg->wp, "struct watched_page", 585 "mdb_watched_page_t", node_addr, 0) == -1) { 586 return (WALK_ERR); 587 } 588 589 if (cbarg->wp.wp_vaddr == cbarg->wp_vaddr) { 590 cbarg->found = B_TRUE; 591 return (WALK_DONE); 592 } 593 594 return (WALK_NEXT); 595 } 596 597 static void 598 gcore_getwatchprot(uintptr_t as_addr, u_offset_t addr, uint_t *prot) 599 { 600 getwatchprot_cbarg_t cbarg; 601 uintptr_t wp_addr; 602 603 cbarg.wp_vaddr = (uintptr_t)addr & (uintptr_t)PAGEMASK; 604 cbarg.found = B_FALSE; 605 606 wp_addr = as_addr + mdb_ctf_offsetof_by_name("struct as", "a_wpage"); 607 (void) avl_walk_mdb(wp_addr, gcore_getwatchprot_cb, &cbarg); 608 609 if (cbarg.found) { 610 *prot = cbarg.wp.wp_oprot; 611 } 612 } 613 614 static u_offset_t 615 gcore_pr_nextprot(gcore_seg_t *gs, u_offset_t *saddrp, u_offset_t eaddr, 616 uint_t *protp) 617 { 618 uint_t prot, nprot; 619 u_offset_t addr = *saddrp; 620 uintptr_t as_addr = gs->gs_seg->s_as; 621 int noreserve = 0; 622 623 noreserve = GSOP_NORESERVE(gs); 624 dprintf("addr: %p noreserve: %d\n", addr, noreserve); 625 626 if (noreserve) { 627 addr = GSOP_INCORE(gs, addr, eaddr); 628 if (addr == eaddr) { 629 prot = 0; 630 *saddrp = addr; 631 goto out; 632 } 633 } 634 635 prot = GSOP_GETPROT(gs, addr); 636 gcore_getwatchprot(as_addr, addr, &prot); 637 *saddrp = addr; 638 639 for (addr += PAGESIZE; addr < eaddr; addr += PAGESIZE) { 640 /* Discontinuity */ 641 if (noreserve && GSOP_INCORE(gs, addr, eaddr) != addr) { 642 goto out; 643 } 644 645 nprot = GSOP_GETPROT(gs, addr); 646 gcore_getwatchprot(as_addr, addr, &nprot); 647 648 if (nprot != prot) { 649 break; 650 } 651 } 652 653 out: 654 *protp = prot; 655 return (addr); 656 } 657 658 /* 659 * Get the page protection for the given start address. 660 * - saddrp: in - start address 661 * out - contains address of first in core page 662 * - naddrp: out - address of next in core page that has different protection 663 * - eaddr: in - end address 664 */ 665 static uint_t 666 gcore_pr_getprot(gcore_seg_t *gs, u_offset_t *saddrp, u_offset_t *naddrp, 667 u_offset_t eaddr) 668 { 669 u_offset_t naddr; 670 uint_t prot; 671 672 dprintf("seg: %p saddr: %p eaddr: %p\n", 673 gs->gs_seg, *saddrp, eaddr); 674 675 naddr = gcore_pr_nextprot(gs, saddrp, eaddr, &prot); 676 677 dprintf("seg: %p saddr: %p naddr: %p eaddr: %p\n", 678 gs->gs_seg, *saddrp, naddr, eaddr); 679 680 *naddrp = naddr; 681 return (prot); 682 } 683 684 static gcore_seg_t * 685 gcore_seg_create(mdb_seg_t *seg) 686 { 687 gcore_seg_t *gs; 688 689 gs = mdb_alloc(sizeof (*gs), UM_SLEEP); 690 gs->gs_seg = seg; 691 if (seg->s_ops == gcore_segvn_ops) { 692 gs->gs_ops = &gsvn_ops; 693 } else { 694 mdb_warn("Unhandled segment type, ops: %p\n", seg->s_ops); 695 goto error; 696 } 697 698 if (GSOP_INIT(gs) != 0) { 699 goto error; 700 } 701 702 return (gs); 703 704 error: 705 mdb_free(gs, sizeof (*gs)); 706 return (NULL); 707 } 708 709 static void 710 gcore_seg_destroy(gcore_seg_t *gs) 711 { 712 GSOP_FINI(gs); 713 mdb_free(gs, sizeof (*gs)); 714 } 715 716 /*ARGSUSED*/ 717 static int 718 read_maps_cb(uintptr_t seg_addr, const void *aw_buff, void *arg) 719 { 720 read_maps_cbarg_t *cbarg = arg; 721 mdb_segvn_data_t svd; 722 mdb_seg_t s; 723 mdb_seg_t *seg; 724 uint_t prot; 725 gcore_seg_t *gs; 726 uintptr_t eaddr; 727 u_offset_t saddr, baddr; 728 prmap_node_t *mnode; 729 prmap_t *mp; 730 731 if (mdb_ctf_vread(&s, "struct seg", "mdb_seg_t", seg_addr, 0) == -1) { 732 return (WALK_ERR); 733 } 734 seg = &s; 735 eaddr = seg->s_base + gcore_pr_getsegsize(seg); 736 737 if ((gs = gcore_seg_create(seg)) == NULL) { 738 mdb_warn("gcore_seg_create failed!\n"); 739 return (WALK_ERR); 740 } 741 742 /* 743 * Iterate from the base of the segment to its end, allocating a new 744 * prmap_node at each address boundary (baddr) between ranges that 745 * have different virtual memory protections. 746 */ 747 for (saddr = seg->s_base; saddr < eaddr; saddr = baddr) { 748 prot = gcore_pr_getprot(gs, &saddr, &baddr, eaddr); 749 if (saddr == eaddr) { 750 break; 751 } 752 753 mnode = mdb_alloc(sizeof (*mnode), UM_SLEEP); 754 mnode->next = NULL; 755 mp = &mnode->m; 756 757 if (cbarg->map_head == NULL) { 758 cbarg->map_head = cbarg->map_tail = mnode; 759 } else { 760 cbarg->map_tail->next = mnode; 761 cbarg->map_tail = mnode; 762 } 763 cbarg->map_len++; 764 765 mp->pr_vaddr = (uintptr_t)saddr; 766 mp->pr_size = baddr - saddr; 767 mp->pr_offset = GSOP_GETOFFSET(gs, saddr); 768 mp->pr_mflags = 0; 769 if (prot & PROT_READ) 770 mp->pr_mflags |= MA_READ; 771 if (prot & PROT_WRITE) 772 mp->pr_mflags |= MA_WRITE; 773 if (prot & PROT_EXEC) 774 mp->pr_mflags |= MA_EXEC; 775 if (GSOP_GETTYPE(gs, saddr) & MAP_SHARED) 776 mp->pr_mflags |= MA_SHARED; 777 if (GSOP_GETTYPE(gs, saddr) & MAP_NORESERVE) 778 mp->pr_mflags |= MA_NORESERVE; 779 if (seg->s_ops == gcore_segvn_ops) { 780 if (mdb_ctf_vread(&svd, "segvn_data_t", 781 "mdb_segvn_data_t", seg->s_data, 0) == 0 && 782 svd.vp == NULL) { 783 mp->pr_mflags |= MA_ANON; 784 } 785 } 786 if (seg_addr == cbarg->brkseg) 787 mp->pr_mflags |= MA_BREAK; 788 else if (seg_addr == cbarg->stkseg) 789 mp->pr_mflags |= MA_STACK; 790 791 mp->pr_pagesize = PAGESIZE; 792 793 /* 794 * Manufacture a filename for the "object" dir. 795 */ 796 GSOP_NAME(gs, mp->pr_mapname, sizeof (mp->pr_mapname)); 797 } 798 799 gcore_seg_destroy(gs); 800 801 return (0); 802 } 803 804 /* 805 * Helper functions for retrieving process and lwp state. 806 */ 807 static int 808 pcommon_init(mdb_proc_t *p, pcommon_t *pc) 809 { 810 mdb_pid_t pid; 811 mdb_sess_t sess; 812 mdb_task_t task; 813 mdb_kproject_t proj; 814 mdb_zone_t zone; 815 816 pc->pc_nlwp = p->p_lwpcnt; 817 pc->pc_nzomb = p->p_zombcnt; 818 819 if (mdb_ctf_vread(&pid, "struct pid", "mdb_pid_t", p->p_pidp, 0) == 820 -1) { 821 return (-1); 822 } 823 pc->pc_pid = pid.pid_id; 824 pc->pc_ppid = p->p_ppid; 825 826 if (mdb_ctf_vread(&pid, "struct pid", "mdb_pid_t", p->p_pgidp, 0) == 827 -1) { 828 return (-1); 829 } 830 pc->pc_pgid = pid.pid_id; 831 832 if (mdb_ctf_vread(&sess, "sess_t", "mdb_sess_t", p->p_sessp, 0) == 833 -1) { 834 return (-1); 835 } 836 if (mdb_ctf_vread(&pid, "struct pid", "mdb_pid_t", sess.s_sidp, 0) == 837 -1) { 838 return (-1); 839 } 840 pc->pc_sid = pid.pid_id; 841 842 if (mdb_ctf_vread(&task, "task_t", "mdb_task_t", p->p_task, 0) == -1) { 843 return (-1); 844 } 845 pc->pc_taskid = task.tk_tkid; 846 847 if (mdb_ctf_vread(&proj, "kproject_t", "mdb_kproject_t", task.tk_proj, 848 0) == -1) { 849 return (-1); 850 } 851 pc->pc_projid = proj.kpj_id; 852 853 if (mdb_ctf_vread(&zone, "zone_t", "mdb_zone_t", p->p_zone, 0) == -1) { 854 return (-1); 855 } 856 pc->pc_zoneid = zone.zone_id; 857 858 switch (p->p_model) { 859 case DATAMODEL_ILP32: 860 pc->pc_dmodel = PR_MODEL_ILP32; 861 break; 862 case DATAMODEL_LP64: 863 pc->pc_dmodel = PR_MODEL_LP64; 864 break; 865 } 866 867 return (0); 868 } 869 870 static uintptr_t 871 gcore_prchoose(mdb_proc_t *p) 872 { 873 mdb_kthread_t kthr; 874 mdb_kthread_t *t = &kthr; 875 ushort_t t_istop_whystop = 0; 876 ushort_t t_istop_whatstop = 0; 877 uintptr_t t_addr = NULL; 878 uintptr_t t_onproc = NULL; // running on processor 879 uintptr_t t_run = NULL; // runnable, on disp queue 880 uintptr_t t_sleep = NULL; // sleeping 881 uintptr_t t_susp = NULL; // suspended stop 882 uintptr_t t_jstop = NULL; // jobcontrol stop, w/o directed stop 883 uintptr_t t_jdstop = NULL; // jobcontrol stop with directed stop 884 uintptr_t t_req = NULL; // requested stop 885 uintptr_t t_istop = NULL; // event-of-interest stop 886 uintptr_t t_dtrace = NULL; // DTrace stop 887 888 /* 889 * If the agent lwp exists, it takes precedence over all others. 890 */ 891 if ((t_addr = p->p_agenttp) != NULL) { 892 return (t_addr); 893 } 894 895 if ((t_addr = p->p_tlist) == NULL) /* start at the head of the list */ 896 return (t_addr); 897 do { /* for each lwp in the process */ 898 if (mdb_ctf_vread(&kthr, "kthread_t", "mdb_kthread_t", 899 t_addr, 0) == -1) { 900 return (0); 901 } 902 903 if (VSTOPPED(t)) { /* virtually stopped */ 904 if (t_req == NULL) 905 t_req = t_addr; 906 continue; 907 } 908 909 switch (t->t_state) { 910 default: 911 return (0); 912 case TS_SLEEP: 913 if (t_sleep == NULL) 914 t_sleep = t_addr; 915 break; 916 case TS_RUN: 917 case TS_WAIT: 918 if (t_run == NULL) 919 t_run = t_addr; 920 break; 921 case TS_ONPROC: 922 if (t_onproc == NULL) 923 t_onproc = t_addr; 924 break; 925 /* 926 * Threads in the zombie state have the lowest 927 * priority when selecting a representative lwp. 928 */ 929 case TS_ZOMB: 930 break; 931 case TS_STOPPED: 932 switch (t->t_whystop) { 933 case PR_SUSPENDED: 934 if (t_susp == NULL) 935 t_susp = t_addr; 936 break; 937 case PR_JOBCONTROL: 938 if (t->t_proc_flag & TP_PRSTOP) { 939 if (t_jdstop == NULL) 940 t_jdstop = t_addr; 941 } else { 942 if (t_jstop == NULL) 943 t_jstop = t_addr; 944 } 945 break; 946 case PR_REQUESTED: 947 if (t->t_dtrace_stop && t_dtrace == NULL) 948 t_dtrace = t_addr; 949 else if (t_req == NULL) 950 t_req = t_addr; 951 break; 952 case PR_SYSENTRY: 953 case PR_SYSEXIT: 954 case PR_SIGNALLED: 955 case PR_FAULTED: 956 /* 957 * Make an lwp calling exit() be the 958 * last lwp seen in the process. 959 */ 960 if (t_istop == NULL || 961 (t_istop_whystop == PR_SYSENTRY && 962 t_istop_whatstop == SYS_exit)) { 963 t_istop = t_addr; 964 t_istop_whystop = t->t_whystop; 965 t_istop_whatstop = t->t_whatstop; 966 } 967 break; 968 case PR_CHECKPOINT: /* can't happen? */ 969 break; 970 default: 971 return (0); 972 } 973 break; 974 } 975 } while ((t_addr = t->t_forw) != p->p_tlist); 976 977 if (t_onproc) 978 t_addr = t_onproc; 979 else if (t_run) 980 t_addr = t_run; 981 else if (t_sleep) 982 t_addr = t_sleep; 983 else if (t_jstop) 984 t_addr = t_jstop; 985 else if (t_jdstop) 986 t_addr = t_jdstop; 987 else if (t_istop) 988 t_addr = t_istop; 989 else if (t_dtrace) 990 t_addr = t_dtrace; 991 else if (t_req) 992 t_addr = t_req; 993 else if (t_susp) 994 t_addr = t_susp; 995 else /* TS_ZOMB */ 996 t_addr = p->p_tlist; 997 998 return (t_addr); 999 } 1000 1001 /* 1002 * Fields not populated: 1003 * - pr_stype 1004 * - pr_oldpri 1005 * - pr_nice 1006 * - pr_time 1007 * - pr_pctcpu 1008 * - pr_cpu 1009 */ 1010 static int 1011 gcore_prgetlwpsinfo(uintptr_t t_addr, mdb_kthread_t *t, lwpsinfo_t *psp) 1012 { 1013 char c, state; 1014 mdb_cpu_t cpu; 1015 mdb_lpl_t lgrp; 1016 uintptr_t str_addr; 1017 1018 bzero(psp, sizeof (*psp)); 1019 1020 psp->pr_flag = 0; /* lwpsinfo_t.pr_flag is deprecated */ 1021 psp->pr_lwpid = t->t_tid; 1022 psp->pr_addr = t_addr; 1023 psp->pr_wchan = (uintptr_t)t->t_wchan; 1024 1025 /* map the thread state enum into a process state enum */ 1026 state = VSTOPPED(t) ? TS_STOPPED : t->t_state; 1027 switch (state) { 1028 case TS_SLEEP: state = SSLEEP; c = 'S'; break; 1029 case TS_RUN: state = SRUN; c = 'R'; break; 1030 case TS_ONPROC: state = SONPROC; c = 'O'; break; 1031 case TS_ZOMB: state = SZOMB; c = 'Z'; break; 1032 case TS_STOPPED: state = SSTOP; c = 'T'; break; 1033 case TS_WAIT: state = SWAIT; c = 'W'; break; 1034 default: state = 0; c = '?'; break; 1035 } 1036 psp->pr_state = state; 1037 psp->pr_sname = c; 1038 psp->pr_syscall = t->t_sysnum; 1039 psp->pr_pri = t->t_pri; 1040 psp->pr_start.tv_sec = t->t_start; 1041 psp->pr_start.tv_nsec = 0L; 1042 1043 str_addr = (uintptr_t)gcore_sclass[t->t_cid].cl_name; 1044 if (mdb_readstr(psp->pr_clname, sizeof (psp->pr_clname) - 1, str_addr) 1045 == -1) { 1046 mdb_warn("Failed to read string from %p\n", str_addr); 1047 return (-1); 1048 } 1049 bzero(psp->pr_name, sizeof (psp->pr_name)); 1050 1051 if (mdb_ctf_vread(&cpu, "struct cpu", "mdb_cpu_t", t->t_cpu, 0) == -1) { 1052 return (-1); 1053 } 1054 psp->pr_onpro = cpu.cpu_id; 1055 psp->pr_bindpro = t->t_bind_cpu; 1056 psp->pr_bindpset = t->t_bind_pset; 1057 1058 if (mdb_ctf_vread(&lgrp, "lpl_t", "mdb_lpl_t", t->t_lpl, 0) == -1) { 1059 return (-1); 1060 } 1061 psp->pr_lgrp = lgrp.lpl_lgrpid; 1062 1063 return (0); 1064 } 1065 1066 /*ARGSUSED*/ 1067 static int 1068 gcore_lpsinfo_cb(mdb_proc_t *p, lwpent_t *lwent, void *data) 1069 { 1070 lwpsinfo_t *lpsinfo = data; 1071 uintptr_t t_addr = (uintptr_t)lwent->le_thread; 1072 mdb_kthread_t kthrd; 1073 1074 if (t_addr != 0) { 1075 if (mdb_ctf_vread(&kthrd, "kthread_t", "mdb_kthread_t", t_addr, 1076 0) == -1) { 1077 return (-1); 1078 } 1079 return (gcore_prgetlwpsinfo(t_addr, &kthrd, lpsinfo)); 1080 } 1081 1082 bzero(lpsinfo, sizeof (*lpsinfo)); 1083 lpsinfo->pr_lwpid = lwent->le_lwpid; 1084 lpsinfo->pr_state = SZOMB; 1085 lpsinfo->pr_sname = 'Z'; 1086 lpsinfo->pr_start.tv_sec = lwent->le_start; 1087 lpsinfo->pr_bindpro = PBIND_NONE; 1088 lpsinfo->pr_bindpset = PS_NONE; 1089 return (0); 1090 } 1091 1092 static void 1093 gcore_schedctl_finish_sigblock(mdb_kthread_t *t) 1094 { 1095 mdb_sc_shared_t td; 1096 mdb_sc_shared_t *tdp; 1097 1098 if (t->t_schedctl == NULL) { 1099 return; 1100 } 1101 1102 if (mdb_ctf_vread(&td, "sc_shared_t", "mdb_sc_shared_t", t->t_schedctl, 1103 0) == -1) { 1104 return; 1105 } 1106 tdp = &td; 1107 1108 if (tdp->sc_sigblock) { 1109 t->t_hold.__sigbits[0] = FILLSET0 & ~CANTMASK0; 1110 t->t_hold.__sigbits[1] = FILLSET1 & ~CANTMASK1; 1111 t->t_hold.__sigbits[2] = FILLSET2 & ~CANTMASK2; 1112 tdp->sc_sigblock = 0; 1113 } 1114 } 1115 1116 static void 1117 gcore_prgetaction(mdb_proc_t *p, user_t *up, uint_t sig, struct sigaction *sp) 1118 { 1119 int nsig = NSIG; 1120 1121 bzero(sp, sizeof (*sp)); 1122 1123 if (sig != 0 && (unsigned)sig < nsig) { 1124 sp->sa_handler = up->u_signal[sig-1]; 1125 prassignset(&sp->sa_mask, &up->u_sigmask[sig-1]); 1126 if (sigismember(&up->u_sigonstack, sig)) 1127 sp->sa_flags |= SA_ONSTACK; 1128 if (sigismember(&up->u_sigresethand, sig)) 1129 sp->sa_flags |= SA_RESETHAND; 1130 if (sigismember(&up->u_sigrestart, sig)) 1131 sp->sa_flags |= SA_RESTART; 1132 if (sigismember(&p->p_siginfo, sig)) 1133 sp->sa_flags |= SA_SIGINFO; 1134 if (sigismember(&up->u_signodefer, sig)) 1135 sp->sa_flags |= SA_NODEFER; 1136 if (sig == SIGCLD) { 1137 if (p->p_flag & SNOWAIT) 1138 sp->sa_flags |= SA_NOCLDWAIT; 1139 if ((p->p_flag & SJCTL) == 0) 1140 sp->sa_flags |= SA_NOCLDSTOP; 1141 } 1142 } 1143 } 1144 1145 static void 1146 gcore_prgetprregs(mdb_klwp_t *lwp, prgregset_t prp) 1147 { 1148 gcore_getgregs(lwp, prp); 1149 } 1150 1151 /* 1152 * Field not populated: 1153 * - pr_tstamp 1154 * - pr_utime 1155 * - pr_stime 1156 * - pr_syscall 1157 * - pr_syarg 1158 * - pr_nsysarg 1159 * - pr_fpreg 1160 */ 1161 /*ARGSUSED*/ 1162 static int 1163 gcore_prgetlwpstatus(mdb_proc_t *p, uintptr_t t_addr, mdb_kthread_t *t, 1164 lwpstatus_t *sp, zone_t *zp) 1165 { 1166 uintptr_t lwp_addr = ttolwp(t); 1167 mdb_klwp_t lw; 1168 mdb_klwp_t *lwp; 1169 ulong_t instr; 1170 int flags; 1171 uintptr_t str_addr; 1172 struct pid pid; 1173 1174 if (mdb_ctf_vread(&lw, "klwp_t", "mdb_klwp_t", lwp_addr, 0) == -1) { 1175 return (-1); 1176 } 1177 lwp = &lw; 1178 1179 bzero(sp, sizeof (*sp)); 1180 flags = 0L; 1181 if (t->t_state == TS_STOPPED) { 1182 flags |= PR_STOPPED; 1183 if ((t->t_schedflag & TS_PSTART) == 0) 1184 flags |= PR_ISTOP; 1185 } else if (VSTOPPED(t)) { 1186 flags |= PR_STOPPED|PR_ISTOP; 1187 } 1188 if (!(flags & PR_ISTOP) && (t->t_proc_flag & TP_PRSTOP)) 1189 flags |= PR_DSTOP; 1190 if (lwp->lwp_asleep) 1191 flags |= PR_ASLEEP; 1192 if (t_addr == p->p_agenttp) 1193 flags |= PR_AGENT; 1194 if (!(t->t_proc_flag & TP_TWAIT)) 1195 flags |= PR_DETACH; 1196 if (t->t_proc_flag & TP_DAEMON) 1197 flags |= PR_DAEMON; 1198 if (p->p_proc_flag & P_PR_FORK) 1199 flags |= PR_FORK; 1200 if (p->p_proc_flag & P_PR_RUNLCL) 1201 flags |= PR_RLC; 1202 if (p->p_proc_flag & P_PR_KILLCL) 1203 flags |= PR_KLC; 1204 if (p->p_proc_flag & P_PR_ASYNC) 1205 flags |= PR_ASYNC; 1206 if (p->p_proc_flag & P_PR_BPTADJ) 1207 flags |= PR_BPTADJ; 1208 if (p->p_proc_flag & P_PR_PTRACE) 1209 flags |= PR_PTRACE; 1210 if (p->p_flag & SMSACCT) 1211 flags |= PR_MSACCT; 1212 if (p->p_flag & SMSFORK) 1213 flags |= PR_MSFORK; 1214 if (p->p_flag & SVFWAIT) 1215 flags |= PR_VFORKP; 1216 1217 if (mdb_vread(&pid, sizeof (struct pid), p->p_pgidp) != sizeof (pid)) { 1218 mdb_warn("Failed to read pid from %p\n", p->p_pgidp); 1219 return (-1); 1220 } 1221 if (pid.pid_pgorphaned) 1222 flags |= PR_ORPHAN; 1223 if (p->p_pidflag & CLDNOSIGCHLD) 1224 flags |= PR_NOSIGCHLD; 1225 if (p->p_pidflag & CLDWAITPID) 1226 flags |= PR_WAITPID; 1227 sp->pr_flags = flags; 1228 if (VSTOPPED(t)) { 1229 sp->pr_why = PR_REQUESTED; 1230 sp->pr_what = 0; 1231 } else { 1232 sp->pr_why = t->t_whystop; 1233 sp->pr_what = t->t_whatstop; 1234 } 1235 sp->pr_lwpid = t->t_tid; 1236 sp->pr_cursig = lwp->lwp_cursig; 1237 prassignset(&sp->pr_lwppend, &t->t_sig); 1238 gcore_schedctl_finish_sigblock(t); 1239 prassignset(&sp->pr_lwphold, &t->t_hold); 1240 if (t->t_whystop == PR_FAULTED) { 1241 bcopy(&lwp->lwp_siginfo, 1242 &sp->pr_info, sizeof (k_siginfo_t)); 1243 } else if (lwp->lwp_curinfo) { 1244 mdb_sigqueue_t sigq; 1245 1246 if (mdb_ctf_vread(&sigq, "sigqueue_t", "mdb_sigqueue_t", 1247 lwp->lwp_curinfo, 0) == -1) { 1248 return (-1); 1249 } 1250 bcopy(&sigq.sq_info, &sp->pr_info, sizeof (k_siginfo_t)); 1251 } 1252 1253 sp->pr_altstack = lwp->lwp_sigaltstack; 1254 gcore_prgetaction(p, PTOU(p), lwp->lwp_cursig, &sp->pr_action); 1255 sp->pr_oldcontext = lwp->lwp_oldcontext; 1256 sp->pr_ustack = lwp->lwp_ustack; 1257 1258 str_addr = (uintptr_t)gcore_sclass[t->t_cid].cl_name; 1259 if (mdb_readstr(sp->pr_clname, sizeof (sp->pr_clname) - 1, str_addr) == 1260 -1) { 1261 mdb_warn("Failed to read string from %p\n", str_addr); 1262 return (-1); 1263 } 1264 1265 /* 1266 * Fetch the current instruction, if not a system process. 1267 * We don't attempt this unless the lwp is stopped. 1268 */ 1269 if ((p->p_flag & SSYS) || p->p_as == gcore_kas) 1270 sp->pr_flags |= (PR_ISSYS|PR_PCINVAL); 1271 else if (!(flags & PR_STOPPED)) 1272 sp->pr_flags |= PR_PCINVAL; 1273 else if (!gcore_prfetchinstr(lwp, &instr)) 1274 sp->pr_flags |= PR_PCINVAL; 1275 else 1276 sp->pr_instr = instr; 1277 1278 if (gcore_prisstep(lwp)) 1279 sp->pr_flags |= PR_STEP; 1280 gcore_prgetprregs(lwp, sp->pr_reg); 1281 if ((t->t_state == TS_STOPPED && t->t_whystop == PR_SYSEXIT) || 1282 (flags & PR_VFORKP)) { 1283 user_t *up; 1284 auxv_t *auxp; 1285 int i; 1286 1287 sp->pr_errno = gcore_prgetrvals(lwp, &sp->pr_rval1, 1288 &sp->pr_rval2); 1289 if (sp->pr_errno == 0) 1290 sp->pr_errpriv = PRIV_NONE; 1291 else 1292 sp->pr_errpriv = lwp->lwp_badpriv; 1293 1294 if (t->t_sysnum == SYS_execve) { 1295 up = PTOU(p); 1296 sp->pr_sysarg[0] = 0; 1297 sp->pr_sysarg[1] = (uintptr_t)up->u_argv; 1298 sp->pr_sysarg[2] = (uintptr_t)up->u_envp; 1299 for (i = 0, auxp = up->u_auxv; 1300 i < sizeof (up->u_auxv) / sizeof (up->u_auxv[0]); 1301 i++, auxp++) { 1302 if (auxp->a_type == AT_SUN_EXECNAME) { 1303 sp->pr_sysarg[0] = 1304 (uintptr_t)auxp->a_un.a_ptr; 1305 break; 1306 } 1307 } 1308 } 1309 } 1310 return (0); 1311 } 1312 1313 static int 1314 gcore_lstatus_cb(mdb_proc_t *p, lwpent_t *lwent, void *data) 1315 { 1316 lwpstatus_t *lstatus = data; 1317 uintptr_t t_addr = (uintptr_t)lwent->le_thread; 1318 mdb_kthread_t kthrd; 1319 1320 if (t_addr == NULL) { 1321 return (1); 1322 } 1323 1324 if (mdb_ctf_vread(&kthrd, "kthread_t", "mdb_kthread_t", t_addr, 0) 1325 == -1) { 1326 return (-1); 1327 } 1328 1329 return (gcore_prgetlwpstatus(p, t_addr, &kthrd, lstatus, NULL)); 1330 } 1331 1332 static prheader_t * 1333 gcore_walk_lwps(mdb_proc_t *p, lwp_callback_t callback, int nlwp, 1334 size_t ent_size) 1335 { 1336 void *ent; 1337 prheader_t *php; 1338 lwpdir_t *ldp; 1339 lwpdir_t ld; 1340 lwpent_t lwent; 1341 int status; 1342 int i; 1343 1344 php = calloc(1, sizeof (prheader_t) + nlwp * ent_size); 1345 if (php == NULL) { 1346 return (NULL); 1347 } 1348 php->pr_nent = nlwp; 1349 php->pr_entsize = ent_size; 1350 1351 ent = php + 1; 1352 for (ldp = (lwpdir_t *)p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, 1353 ldp++) { 1354 if (mdb_vread(&ld, sizeof (ld), (uintptr_t)ldp) != 1355 sizeof (ld)) { 1356 mdb_warn("Failed to read lwpdir_t from %p\n", ldp); 1357 goto error; 1358 } 1359 1360 if (ld.ld_entry == NULL) { 1361 continue; 1362 } 1363 1364 if (mdb_vread(&lwent, sizeof (lwent), (uintptr_t)ld.ld_entry) != 1365 sizeof (lwent)) { 1366 mdb_warn("Failed to read lwpent_t from %p\n", 1367 ld.ld_entry); 1368 goto error; 1369 } 1370 1371 status = callback(p, &lwent, ent); 1372 if (status == -1) { 1373 dprintf("lwp callback %p returned -1\n", callback); 1374 goto error; 1375 } 1376 if (status == 1) { 1377 dprintf("lwp callback %p returned 1\n", callback); 1378 continue; 1379 } 1380 1381 ent = (caddr_t)ent + ent_size; 1382 } 1383 1384 return (php); 1385 1386 error: 1387 free(php); 1388 return (NULL); 1389 } 1390 1391 /* 1392 * Misc helper functions. 1393 */ 1394 /* 1395 * convert code/data pair into old style wait status 1396 */ 1397 static int 1398 gcore_wstat(int code, int data) 1399 { 1400 int stat = (data & 0377); 1401 1402 switch (code) { 1403 case CLD_EXITED: 1404 stat <<= 8; 1405 break; 1406 case CLD_DUMPED: 1407 stat |= WCOREFLG; 1408 break; 1409 case CLD_KILLED: 1410 break; 1411 case CLD_TRAPPED: 1412 case CLD_STOPPED: 1413 stat <<= 8; 1414 stat |= WSTOPFLG; 1415 break; 1416 case CLD_CONTINUED: 1417 stat = WCONTFLG; 1418 break; 1419 default: 1420 mdb_warn("wstat: bad code %d\n", code); 1421 } 1422 return (stat); 1423 } 1424 1425 #if defined(__i386) || defined(__amd64) 1426 static void 1427 gcore_usd_to_ssd(user_desc_t *usd, struct ssd *ssd, selector_t sel) 1428 { 1429 ssd->bo = USEGD_GETBASE(usd); 1430 ssd->ls = USEGD_GETLIMIT(usd); 1431 ssd->sel = sel; 1432 1433 /* 1434 * set type, dpl and present bits. 1435 */ 1436 ssd->acc1 = usd->usd_type; 1437 ssd->acc1 |= usd->usd_dpl << 5; 1438 ssd->acc1 |= usd->usd_p << (5 + 2); 1439 1440 /* 1441 * set avl, DB and granularity bits. 1442 */ 1443 ssd->acc2 = usd->usd_avl; 1444 1445 #if defined(__amd64) 1446 ssd->acc2 |= usd->usd_long << 1; 1447 #else 1448 ssd->acc2 |= usd->usd_reserved << 1; 1449 #endif 1450 1451 ssd->acc2 |= usd->usd_def32 << (1 + 1); 1452 ssd->acc2 |= usd->usd_gran << (1 + 1 + 1); 1453 } 1454 #endif 1455 1456 static priv_set_t * 1457 gcore_priv_getset(cred_t *cr, int set) 1458 { 1459 if ((CR_FLAGS(cr) & PRIV_AWARE) == 0) { 1460 switch (set) { 1461 case PRIV_EFFECTIVE: 1462 return (&CR_OEPRIV(cr)); 1463 case PRIV_PERMITTED: 1464 return (&CR_OPPRIV(cr)); 1465 } 1466 } 1467 return (&CR_PRIVS(cr)->crprivs[set]); 1468 } 1469 1470 static void 1471 gcore_priv_getinfo(const cred_t *cr, void *buf) 1472 { 1473 struct priv_info_uint *ii; 1474 1475 ii = buf; 1476 ii->val = CR_FLAGS(cr); 1477 ii->info.priv_info_size = (uint32_t)sizeof (*ii); 1478 ii->info.priv_info_type = PRIV_INFO_FLAGS; 1479 } 1480 1481 static void 1482 map_list_free(prmap_node_t *n) 1483 { 1484 prmap_node_t *next; 1485 1486 while (n != NULL) { 1487 next = n->next; 1488 mdb_free(n, sizeof (*n)); 1489 n = next; 1490 } 1491 } 1492 1493 /* 1494 * Ops vector functions for ::gcore. 1495 */ 1496 /*ARGSUSED*/ 1497 static ssize_t 1498 Pread_gcore(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr, 1499 void *data) 1500 { 1501 mdb_proc_t *p = data; 1502 ssize_t ret; 1503 1504 ret = mdb_aread(buf, n, addr, (void *)p->p_as); 1505 if (ret != n) { 1506 dprintf("%s: addr: %p len: %llx\n", __func__, addr, n); 1507 (void) memset(buf, 0, n); 1508 return (n); 1509 } 1510 1511 return (ret); 1512 } 1513 1514 /*ARGSUSED*/ 1515 static ssize_t 1516 Pwrite_gcore(struct ps_prochandle *P, const void *buf, size_t n, uintptr_t addr, 1517 void *data) 1518 { 1519 dprintf("%s: addr: %p len: %llx\n", __func__, addr, n); 1520 1521 return (-1); 1522 } 1523 1524 /*ARGSUSED*/ 1525 static int 1526 Pread_maps_gcore(struct ps_prochandle *P, prmap_t **Pmapp, ssize_t *nmapp, 1527 void *data) 1528 { 1529 mdb_proc_t *p = data; 1530 read_maps_cbarg_t cbarg; 1531 prmap_node_t *n; 1532 prmap_t *pmap; 1533 uintptr_t segtree_addr; 1534 int error; 1535 int i; 1536 1537 cbarg.p = p; 1538 cbarg.brkseg = gcore_break_seg(p); 1539 cbarg.stkseg = gcore_as_segat(p->p_as, gcore_prgetstackbase(p)); 1540 1541 (void) memset(&cbarg, 0, sizeof (cbarg)); 1542 segtree_addr = p->p_as + mdb_ctf_offsetof_by_name("struct as", 1543 "a_segtree"); 1544 error = avl_walk_mdb(segtree_addr, read_maps_cb, &cbarg); 1545 if (error != WALK_DONE) { 1546 return (-1); 1547 } 1548 1549 /* Conver the linked list into an array */ 1550 pmap = malloc(cbarg.map_len * sizeof (*pmap)); 1551 if (pmap == NULL) { 1552 map_list_free(cbarg.map_head); 1553 return (-1); 1554 } 1555 1556 for (i = 0, n = cbarg.map_head; i < cbarg.map_len; i++, n = n->next) { 1557 (void) memcpy(&pmap[i], &n->m, sizeof (prmap_t)); 1558 } 1559 map_list_free(cbarg.map_head); 1560 1561 for (i = 0; i < cbarg.map_len; i++) { 1562 dprintf("pr_vaddr: %p pr_size: %llx, pr_name: %s " 1563 "pr_offset: %p pr_mflags: 0x%x\n", 1564 pmap[i].pr_vaddr, pmap[i].pr_size, 1565 pmap[i].pr_mapname, pmap[i].pr_offset, 1566 pmap[i].pr_mflags); 1567 } 1568 1569 *Pmapp = pmap; 1570 *nmapp = cbarg.map_len; 1571 1572 return (0); 1573 } 1574 1575 /*ARGSUSED*/ 1576 static void 1577 Pread_aux_gcore(struct ps_prochandle *P, auxv_t **auxvp, int *nauxp, void *data) 1578 { 1579 mdb_proc_t *p = data; 1580 auxv_t *auxv; 1581 int naux; 1582 1583 naux = __KERN_NAUXV_IMPL; 1584 auxv = calloc(naux + 1, sizeof (*auxv)); 1585 if (auxv == NULL) { 1586 *auxvp = NULL; 1587 *nauxp = 0; 1588 return; 1589 } 1590 1591 (void) memcpy(auxv, p->p_user.u_auxv, naux * sizeof (*auxv)); 1592 1593 *auxvp = auxv; 1594 *nauxp = naux; 1595 } 1596 1597 /*ARGSUSED*/ 1598 static int 1599 Pcred_gcore(struct ps_prochandle *P, prcred_t *prcp, int ngroups, void *data) 1600 { 1601 mdb_proc_t *p = data; 1602 cred_t cr; 1603 credgrp_t crgrp; 1604 int i; 1605 1606 if (mdb_vread(&cr, sizeof (cr), p->p_cred) != sizeof (cr)) { 1607 mdb_warn("Failed to read cred_t from %p\n", p->p_cred); 1608 return (-1); 1609 } 1610 1611 prcp->pr_euid = cr.cr_uid; 1612 prcp->pr_ruid = cr.cr_ruid; 1613 prcp->pr_suid = cr.cr_suid; 1614 prcp->pr_egid = cr.cr_gid; 1615 prcp->pr_rgid = cr.cr_rgid; 1616 prcp->pr_sgid = cr.cr_sgid; 1617 1618 if (cr.cr_grps == 0) { 1619 prcp->pr_ngroups = 0; 1620 return (0); 1621 } 1622 1623 if (mdb_vread(&crgrp, sizeof (crgrp), (uintptr_t)cr.cr_grps) != 1624 sizeof (crgrp)) { 1625 mdb_warn("Failed to read credgrp_t from %p\n", cr.cr_grps); 1626 return (-1); 1627 } 1628 1629 prcp->pr_ngroups = MIN(ngroups, crgrp.crg_ngroups); 1630 for (i = 0; i < prcp->pr_ngroups; i++) { 1631 prcp->pr_groups[i] = crgrp.crg_groups[i]; 1632 } 1633 1634 return (0); 1635 } 1636 1637 /*ARGSUSED*/ 1638 static int 1639 Ppriv_gcore(struct ps_prochandle *P, prpriv_t **pprv, void *data) 1640 { 1641 mdb_proc_t *p = data; 1642 prpriv_t *pp; 1643 cred_t cr; 1644 priv_set_t *psa; 1645 size_t pprv_size; 1646 int i; 1647 1648 pprv_size = sizeof (prpriv_t) + PRIV_SETBYTES - sizeof (priv_chunk_t) + 1649 prinfo.priv_infosize; 1650 1651 pp = malloc(pprv_size); 1652 if (pp == NULL) { 1653 return (-1); 1654 } 1655 1656 if (mdb_vread(&cr, sizeof (cr), p->p_cred) != sizeof (cr)) { 1657 mdb_warn("Failed to read cred_t from %p\n", p->p_cred); 1658 free(pp); 1659 return (-1); 1660 } 1661 1662 pp->pr_nsets = PRIV_NSET; 1663 pp->pr_setsize = PRIV_SETSIZE; 1664 pp->pr_infosize = prinfo.priv_infosize; 1665 1666 psa = (priv_set_t *)pp->pr_sets; 1667 for (i = 0; i < PRIV_NSET; i++) { 1668 psa[i] = *gcore_priv_getset(&cr, i); 1669 } 1670 1671 gcore_priv_getinfo(&cr, (char *)pp + PRIV_PRPRIV_INFO_OFFSET(pp)); 1672 1673 *pprv = pp; 1674 return (0); 1675 } 1676 1677 /* 1678 * Fields not filled populated: 1679 * - pr_utime 1680 * - pr_stkbase 1681 * - pr_cutime 1682 * - pr_cstime 1683 * - pr_agentid 1684 */ 1685 /*ARGSUSED*/ 1686 static void 1687 Pstatus_gcore(struct ps_prochandle *P, pstatus_t *sp, void *data) 1688 { 1689 mdb_proc_t *p = data; 1690 uintptr_t t_addr; 1691 mdb_kthread_t kthr; 1692 mdb_kthread_t *t; 1693 pcommon_t pc; 1694 1695 t_addr = gcore_prchoose(p); 1696 if (t_addr != NULL) { 1697 if (mdb_ctf_vread(&kthr, "kthread_t", "mdb_kthread_t", t_addr, 1698 0) == -1) { 1699 return; 1700 } 1701 t = &kthr; 1702 } 1703 1704 /* just bzero the process part, prgetlwpstatus() does the rest */ 1705 bzero(sp, sizeof (pstatus_t) - sizeof (lwpstatus_t)); 1706 1707 if (pcommon_init(p, &pc) == -1) { 1708 return; 1709 } 1710 sp->pr_nlwp = pc.pc_nlwp; 1711 sp->pr_nzomb = pc.pc_nzomb; 1712 sp->pr_pid = pc.pc_pid; 1713 sp->pr_ppid = pc.pc_ppid; 1714 sp->pr_pgid = pc.pc_pgid; 1715 sp->pr_sid = pc.pc_sid; 1716 sp->pr_taskid = pc.pc_taskid; 1717 sp->pr_projid = pc.pc_projid; 1718 sp->pr_zoneid = pc.pc_zoneid; 1719 sp->pr_dmodel = pc.pc_dmodel; 1720 1721 prassignset(&sp->pr_sigpend, &p->p_sig); 1722 sp->pr_brkbase = p->p_brkbase; 1723 sp->pr_brksize = p->p_brksize; 1724 sp->pr_stkbase = gcore_prgetstackbase(p); 1725 sp->pr_stksize = p->p_stksize; 1726 1727 prassignset(&sp->pr_sigtrace, &p->p_sigmask); 1728 prassignset(&sp->pr_flttrace, &p->p_fltmask); 1729 prassignset(&sp->pr_sysentry, &PTOU(p)->u_entrymask); 1730 prassignset(&sp->pr_sysexit, &PTOU(p)->u_exitmask); 1731 1732 /* get the chosen lwp's status */ 1733 gcore_prgetlwpstatus(p, t_addr, t, &sp->pr_lwp, NULL); 1734 1735 /* replicate the flags */ 1736 sp->pr_flags = sp->pr_lwp.pr_flags; 1737 } 1738 1739 /* 1740 * Fields not populated: 1741 * - pr_contract 1742 * - pr_addr 1743 * - pr_rtime 1744 * - pr_ctime 1745 * - pr_ttydev 1746 * - pr_pctcpu 1747 * - pr_size 1748 * - pr_rsize 1749 * - pr_pctmem 1750 */ 1751 /*ARGSUSED*/ 1752 static const psinfo_t * 1753 Ppsinfo_gcore(struct ps_prochandle *P, psinfo_t *psp, void *data) 1754 { 1755 mdb_proc_t *p = data; 1756 mdb_kthread_t *t; 1757 mdb_pool_t pool; 1758 cred_t cr; 1759 uintptr_t t_addr; 1760 pcommon_t pc; 1761 1762 if ((t_addr = gcore_prchoose(p)) == NULL) { 1763 bzero(psp, sizeof (*psp)); 1764 } else { 1765 bzero(psp, sizeof (*psp) - sizeof (psp->pr_lwp)); 1766 } 1767 1768 if (pcommon_init(p, &pc) == -1) { 1769 return (NULL); 1770 } 1771 psp->pr_nlwp = pc.pc_nlwp; 1772 psp->pr_nzomb = pc.pc_nzomb; 1773 psp->pr_pid = pc.pc_pid; 1774 psp->pr_ppid = pc.pc_ppid; 1775 psp->pr_pgid = pc.pc_pgid; 1776 psp->pr_sid = pc.pc_sid; 1777 psp->pr_taskid = pc.pc_taskid; 1778 psp->pr_projid = pc.pc_projid; 1779 psp->pr_dmodel = pc.pc_dmodel; 1780 1781 /* 1782 * only export SSYS and SMSACCT; everything else is off-limits to 1783 * userland apps. 1784 */ 1785 psp->pr_flag = p->p_flag & (SSYS | SMSACCT); 1786 1787 if (mdb_vread(&cr, sizeof (cr), p->p_cred) != sizeof (cr)) { 1788 mdb_warn("Failed to read cred_t from %p\n", p->p_cred); 1789 return (NULL); 1790 } 1791 1792 psp->pr_uid = cr.cr_ruid; 1793 psp->pr_euid = cr.cr_uid; 1794 psp->pr_gid = cr.cr_rgid; 1795 psp->pr_egid = cr.cr_gid; 1796 1797 if (mdb_ctf_vread(&pool, "pool_t", "mdb_pool_t", p->p_pool, 0) == -1) { 1798 return (NULL); 1799 } 1800 psp->pr_poolid = pool.pool_id; 1801 1802 if (t_addr == 0) { 1803 int wcode = p->p_wcode; 1804 1805 if (wcode) 1806 psp->pr_wstat = gcore_wstat(wcode, p->p_wdata); 1807 psp->pr_ttydev = PRNODEV; 1808 psp->pr_lwp.pr_state = SZOMB; 1809 psp->pr_lwp.pr_sname = 'Z'; 1810 psp->pr_lwp.pr_bindpro = PBIND_NONE; 1811 psp->pr_lwp.pr_bindpset = PS_NONE; 1812 } else { 1813 mdb_kthread_t kthr; 1814 user_t *up = PTOU(p); 1815 1816 psp->pr_start = up->u_start; 1817 bcopy(up->u_comm, psp->pr_fname, 1818 MIN(sizeof (up->u_comm), sizeof (psp->pr_fname)-1)); 1819 bcopy(up->u_psargs, psp->pr_psargs, 1820 MIN(PRARGSZ-1, PSARGSZ)); 1821 1822 psp->pr_argc = up->u_argc; 1823 psp->pr_argv = up->u_argv; 1824 psp->pr_envp = up->u_envp; 1825 1826 /* get the chosen lwp's lwpsinfo */ 1827 if (mdb_ctf_vread(&kthr, "kthread_t", "mdb_kthread_t", t_addr, 1828 0) == -1) { 1829 return (NULL); 1830 } 1831 t = &kthr; 1832 1833 gcore_prgetlwpsinfo(t_addr, t, &psp->pr_lwp); 1834 } 1835 1836 return (NULL); 1837 } 1838 1839 /*ARGSUSED*/ 1840 static prheader_t * 1841 Plstatus_gcore(struct ps_prochandle *P, void *data) 1842 { 1843 mdb_proc_t *p = data; 1844 int nlwp = p->p_lwpcnt; 1845 size_t ent_size = LSPAN(lwpstatus_t); 1846 1847 return (gcore_walk_lwps(p, gcore_lstatus_cb, nlwp, ent_size)); 1848 } 1849 1850 /*ARGSUSED*/ 1851 static prheader_t * 1852 Plpsinfo_gcore(struct ps_prochandle *P, void *data) 1853 { 1854 mdb_proc_t *p = data; 1855 int nlwp = p->p_lwpcnt + p->p_zombcnt; 1856 size_t ent_size = LSPAN(lwpsinfo_t); 1857 1858 return (gcore_walk_lwps(p, gcore_lpsinfo_cb, nlwp, ent_size)); 1859 } 1860 1861 /*ARGSUSED*/ 1862 static char * 1863 Pplatform_gcore(struct ps_prochandle *P, char *s, size_t n, void *data) 1864 { 1865 char platform[SYS_NMLN]; 1866 1867 if (mdb_readvar(platform, "platform") == -1) { 1868 mdb_warn("failed to read platform!\n"); 1869 return (NULL); 1870 } 1871 dprintf("platform: %s\n", platform); 1872 1873 (void) strncpy(s, platform, n); 1874 return (s); 1875 } 1876 1877 /*ARGSUSED*/ 1878 static int 1879 Puname_gcore(struct ps_prochandle *P, struct utsname *u, void *data) 1880 { 1881 if (mdb_readvar(u, "utsname") != sizeof (*u)) { 1882 return (-1); 1883 } 1884 1885 return (0); 1886 } 1887 1888 /*ARGSUSED*/ 1889 static char * 1890 Pzonename_gcore(struct ps_prochandle *P, char *s, size_t n, void *data) 1891 { 1892 mdb_proc_t *p = data; 1893 mdb_zone_t zone; 1894 1895 if (mdb_ctf_vread(&zone, "zone_t", "mdb_zone_t", p->p_zone, 0) == -1) { 1896 return (NULL); 1897 } 1898 1899 if (mdb_readstr(s, n, zone.zone_name) == -1) { 1900 mdb_warn("Failed to read zone name from %p\n", zone.zone_name); 1901 return (NULL); 1902 } 1903 1904 return (s); 1905 } 1906 1907 /*ARGSUSED*/ 1908 static char * 1909 Pexecname_gcore(struct ps_prochandle *P, char *buf, size_t buflen, void *data) 1910 { 1911 mdb_proc_t *p = data; 1912 mdb_vnode_t vn; 1913 1914 if (mdb_ctf_vread(&vn, "vnode_t", "mdb_vnode_t", p->p_exec, 0) == -1) { 1915 return (NULL); 1916 } 1917 1918 if (mdb_readstr(buf, buflen, vn.v_path) == -1) { 1919 mdb_warn("Failed to read vnode path from %p\n", vn.v_path); 1920 return (NULL); 1921 } 1922 1923 dprintf("execname: %s\n", buf); 1924 1925 return (buf); 1926 } 1927 1928 #if defined(__i386) || defined(__amd64) 1929 /*ARGSUSED*/ 1930 static int 1931 Pldt_gcore(struct ps_prochandle *P, struct ssd *pldt, int nldt, void *data) 1932 { 1933 mdb_proc_t *p = data; 1934 user_desc_t *udp; 1935 user_desc_t *ldts; 1936 size_t ldt_size; 1937 int i, limit; 1938 1939 if (p->p_ldt == NULL) { 1940 return (0); 1941 } 1942 1943 limit = p->p_ldtlimit; 1944 1945 /* Is this call just to query the size ? */ 1946 if (pldt == NULL || nldt == 0) { 1947 return (limit); 1948 } 1949 1950 ldt_size = limit * sizeof (*ldts); 1951 ldts = malloc(ldt_size); 1952 if (ldts == NULL) { 1953 mdb_warn("Failed to malloc ldts (size %lld)n", ldt_size); 1954 return (-1); 1955 } 1956 1957 if (mdb_vread(ldts, ldt_size, p->p_ldt) != ldt_size) { 1958 mdb_warn("Failed to read ldts from %p\n", p->p_ldt); 1959 free(ldts); 1960 return (-1); 1961 } 1962 1963 for (i = LDT_UDBASE, udp = &ldts[i]; i <= limit; i++, udp++) { 1964 if (udp->usd_type != 0 || udp->usd_dpl != 0 || 1965 udp->usd_p != 0) { 1966 gcore_usd_to_ssd(udp, pldt++, SEL_LDT(i)); 1967 } 1968 } 1969 1970 free(ldts); 1971 return (limit); 1972 } 1973 #endif 1974 1975 static const ps_ops_t Pgcore_ops = { 1976 .pop_pread = Pread_gcore, 1977 .pop_pwrite = Pwrite_gcore, 1978 .pop_read_maps = Pread_maps_gcore, 1979 .pop_read_aux = Pread_aux_gcore, 1980 .pop_cred = Pcred_gcore, 1981 .pop_priv = Ppriv_gcore, 1982 .pop_psinfo = Ppsinfo_gcore, 1983 .pop_status = Pstatus_gcore, 1984 .pop_lstatus = Plstatus_gcore, 1985 .pop_lpsinfo = Plpsinfo_gcore, 1986 .pop_platform = Pplatform_gcore, 1987 .pop_uname = Puname_gcore, 1988 .pop_zonename = Pzonename_gcore, 1989 .pop_execname = Pexecname_gcore, 1990 #if defined(__i386) || defined(__amd64) 1991 .pop_ldt = Pldt_gcore 1992 #endif 1993 }; 1994 1995 /*ARGSUSED*/ 1996 int 1997 gcore_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1998 { 1999 struct ps_prochandle *P; 2000 char core_name[MAXNAMELEN]; 2001 mdb_proc_t p; 2002 mdb_pid_t pid; 2003 int error; 2004 2005 if (!gcore_initialized) { 2006 mdb_warn("gcore unavailable\n"); 2007 return (DCMD_ERR); 2008 } 2009 2010 if (mdb_ctf_vread(&p, "proc_t", "mdb_proc_t", addr, 0) == -1) { 2011 return (DCMD_ERR); 2012 } 2013 2014 if (p.p_flag & SSYS) { 2015 mdb_warn("'%s' is a system process\n", p.p_user.u_comm); 2016 return (DCMD_ERR); 2017 } 2018 2019 if (mdb_ctf_vread(&pid, "struct pid", "mdb_pid_t", p.p_pidp, 0) 2020 == -1) { 2021 return (DCMD_ERR); 2022 } 2023 2024 if ((P = Pgrab_ops(pid.pid_id, &p, &Pgcore_ops, PGRAB_INCORE)) == 2025 NULL) { 2026 mdb_warn("Failed to initialize proc handle"); 2027 return (DCMD_ERR); 2028 } 2029 2030 (void) snprintf(core_name, sizeof (core_name), "core.%s.%d", 2031 p.p_user.u_comm, pid.pid_id); 2032 2033 if ((error = Pgcore(P, core_name, CC_CONTENT_DEFAULT)) != 0) { 2034 mdb_warn("Failed to generate core file: %d", error); 2035 Pfree(P); 2036 return (DCMD_ERR); 2037 } 2038 2039 Pfree(P); 2040 mdb_printf("Created core file: %s\n", core_name); 2041 2042 return (0); 2043 } 2044 2045 void 2046 gcore_init(void) 2047 { 2048 GElf_Sym sym; 2049 uintptr_t priv_info_addr; 2050 2051 if (mdb_lookup_by_name("segvn_ops", &sym) == -1) { 2052 mdb_warn("Failed to lookup symbol 'segvn_ops'\n"); 2053 return; 2054 } 2055 gcore_segvn_ops = sym.st_value; 2056 2057 if (mdb_readvar(&priv_info_addr, "priv_info") == -1) { 2058 mdb_warn("Failed to read variable 'priv_info'\n"); 2059 return; 2060 } 2061 2062 if (mdb_vread(&prinfo, sizeof (prinfo), priv_info_addr) == -1) { 2063 mdb_warn("Failed to read prinfo from %p\n", priv_info_addr); 2064 return; 2065 } 2066 2067 if (mdb_lookup_by_name("sclass", &sym) == -1) { 2068 mdb_warn("Failed to lookup symbol 'segvn_ops'\n"); 2069 return; 2070 } 2071 2072 gcore_sclass = mdb_zalloc(sym.st_size, UM_SLEEP); 2073 if (mdb_vread(gcore_sclass, sym.st_size, sym.st_value) != sym.st_size) { 2074 mdb_warn("Failed to read sclass' from %p\n", sym.st_value); 2075 return; 2076 } 2077 2078 if (mdb_lookup_by_name("kas", &sym) == -1) { 2079 mdb_warn("Failed to lookup symbol 'kas'\n"); 2080 return; 2081 } 2082 gcore_kas = sym.st_value; 2083 2084 gcore_initialized = B_TRUE; 2085 } 2086 2087 #endif /* _KMDB */ 2088