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