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 */