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