1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #ifndef _MDB_PROC_H 28*7c478bd9Sstevel@tonic-gate #define _MDB_PROC_H 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_target_impl.h> 33*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_io_impl.h> 34*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_addrvec.h> 35*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h> 36*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_gelf.h> 37*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_tdb.h> 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 40*7c478bd9Sstevel@tonic-gate #include <libproc.h> 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate #ifdef __cplusplus 43*7c478bd9Sstevel@tonic-gate extern "C" { 44*7c478bd9Sstevel@tonic-gate #endif 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate #ifdef _MDB 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate /* 49*7c478bd9Sstevel@tonic-gate * The proc target must provide support for examining multi-threaded processes 50*7c478bd9Sstevel@tonic-gate * that use the raw LWP interface, as well as those that use either of the 51*7c478bd9Sstevel@tonic-gate * existing libthread.so implementations. We must also support multiple active 52*7c478bd9Sstevel@tonic-gate * instances of the proc target, as well as the notion that a clean process 53*7c478bd9Sstevel@tonic-gate * can dlopen() libthread after startup, at which point we need to switch to 54*7c478bd9Sstevel@tonic-gate * using libthread_db interfaces to properly debug it. To satisfy these 55*7c478bd9Sstevel@tonic-gate * constraints, we declare an ops vector of functions for obtaining the 56*7c478bd9Sstevel@tonic-gate * register sets of each thread. The proc target will define two versions 57*7c478bd9Sstevel@tonic-gate * of this vector, one for the LWP mode and one for the libthread_db mode, 58*7c478bd9Sstevel@tonic-gate * and then switch the ops vector pointer as appropriate during debugging. 59*7c478bd9Sstevel@tonic-gate * The macros defined below expand to calls to the appropriate entry point. 60*7c478bd9Sstevel@tonic-gate */ 61*7c478bd9Sstevel@tonic-gate typedef struct pt_ptl_ops { 62*7c478bd9Sstevel@tonic-gate int (*ptl_ctor)(mdb_tgt_t *); 63*7c478bd9Sstevel@tonic-gate void (*ptl_dtor)(mdb_tgt_t *, void *); 64*7c478bd9Sstevel@tonic-gate mdb_tgt_tid_t (*ptl_tid)(mdb_tgt_t *, void *); 65*7c478bd9Sstevel@tonic-gate int (*ptl_iter)(mdb_tgt_t *, void *, mdb_addrvec_t *); 66*7c478bd9Sstevel@tonic-gate int (*ptl_getregs)(mdb_tgt_t *, void *, mdb_tgt_tid_t, prgregset_t); 67*7c478bd9Sstevel@tonic-gate int (*ptl_setregs)(mdb_tgt_t *, void *, mdb_tgt_tid_t, prgregset_t); 68*7c478bd9Sstevel@tonic-gate #ifdef __sparc 69*7c478bd9Sstevel@tonic-gate int (*ptl_getxregs)(mdb_tgt_t *, void *, mdb_tgt_tid_t, 70*7c478bd9Sstevel@tonic-gate prxregset_t *); 71*7c478bd9Sstevel@tonic-gate int (*ptl_setxregs)(mdb_tgt_t *, void *, mdb_tgt_tid_t, 72*7c478bd9Sstevel@tonic-gate const prxregset_t *); 73*7c478bd9Sstevel@tonic-gate #endif 74*7c478bd9Sstevel@tonic-gate int (*ptl_getfpregs)(mdb_tgt_t *, void *, mdb_tgt_tid_t, 75*7c478bd9Sstevel@tonic-gate prfpregset_t *); 76*7c478bd9Sstevel@tonic-gate int (*ptl_setfpregs)(mdb_tgt_t *, void *, mdb_tgt_tid_t, 77*7c478bd9Sstevel@tonic-gate const prfpregset_t *); 78*7c478bd9Sstevel@tonic-gate } pt_ptl_ops_t; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate #define PTL_CTOR(t) \ 81*7c478bd9Sstevel@tonic-gate (((pt_data_t *)(t)->t_data)->p_ptl_ops->ptl_ctor(t)) 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate #define PTL_DTOR(t) \ 84*7c478bd9Sstevel@tonic-gate (((pt_data_t *)(t)->t_data)->p_ptl_ops->ptl_dtor((t), \ 85*7c478bd9Sstevel@tonic-gate ((pt_data_t *)((t)->t_data))->p_ptl_hdl)) 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate #define PTL_TID(t) \ 88*7c478bd9Sstevel@tonic-gate (((pt_data_t *)((t)->t_data))->p_ptl_ops->ptl_tid((t), \ 89*7c478bd9Sstevel@tonic-gate ((pt_data_t *)(t)->t_data)->p_ptl_hdl)) 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate #define PTL_ITER(t, ap) \ 92*7c478bd9Sstevel@tonic-gate (((pt_data_t *)(t)->t_data)->p_ptl_ops->ptl_iter((t), \ 93*7c478bd9Sstevel@tonic-gate ((pt_data_t *)((t)->t_data))->p_ptl_hdl, (ap))) 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate #define PTL_GETREGS(t, tid, gregs) \ 96*7c478bd9Sstevel@tonic-gate (((pt_data_t *)((t)->t_data))->p_ptl_ops->ptl_getregs((t), \ 97*7c478bd9Sstevel@tonic-gate ((pt_data_t *)((t)->t_data))->p_ptl_hdl, (tid), (gregs))) 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate #define PTL_SETREGS(t, tid, gregs) \ 100*7c478bd9Sstevel@tonic-gate (((pt_data_t *)((t)->t_data))->p_ptl_ops->ptl_setregs((t), \ 101*7c478bd9Sstevel@tonic-gate ((pt_data_t *)((t)->t_data))->p_ptl_hdl, (tid), (gregs))) 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate #ifdef __sparc 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate #define PTL_GETXREGS(t, tid, xregs) \ 106*7c478bd9Sstevel@tonic-gate (((pt_data_t *)((t)->t_data))->p_ptl_ops->ptl_getxregs((t), \ 107*7c478bd9Sstevel@tonic-gate ((pt_data_t *)((t)->t_data))->p_ptl_hdl, (tid), (xregs))) 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate #define PTL_SETXREGS(t, tid, xregs) \ 110*7c478bd9Sstevel@tonic-gate (((pt_data_t *)((t)->t_data))->p_ptl_ops->ptl_setxregs((t), \ 111*7c478bd9Sstevel@tonic-gate ((pt_data_t *)((t)->t_data))->p_ptl_hdl, (tid), (xregs))) 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate #endif /* __sparc */ 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate #define PTL_GETFPREGS(t, tid, fpregs) \ 116*7c478bd9Sstevel@tonic-gate (((pt_data_t *)((t)->t_data))->p_ptl_ops->ptl_getfpregs((t), \ 117*7c478bd9Sstevel@tonic-gate ((pt_data_t *)((t)->t_data))->p_ptl_hdl, (tid), (fpregs))) 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate #define PTL_SETFPREGS(t, tid, fpregs) \ 120*7c478bd9Sstevel@tonic-gate (((pt_data_t *)((t)->t_data))->p_ptl_ops->ptl_setfpregs((t), \ 121*7c478bd9Sstevel@tonic-gate ((pt_data_t *)((t)->t_data))->p_ptl_hdl, (tid), (fpregs))) 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate /* 124*7c478bd9Sstevel@tonic-gate * When we are following children and a vfork(2) occurs, we append the libproc 125*7c478bd9Sstevel@tonic-gate * handle for the parent to a list of vfork parents. We need to keep track of 126*7c478bd9Sstevel@tonic-gate * this handle so that when the child subsequently execs or dies, we clear out 127*7c478bd9Sstevel@tonic-gate * our breakpoints before releasing the parent. 128*7c478bd9Sstevel@tonic-gate */ 129*7c478bd9Sstevel@tonic-gate typedef struct pt_vforkp { 130*7c478bd9Sstevel@tonic-gate mdb_list_t p_list; /* List forward/back pointers */ 131*7c478bd9Sstevel@tonic-gate struct ps_prochandle *p_pshandle; /* libproc handle */ 132*7c478bd9Sstevel@tonic-gate } pt_vforkp_t; 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate /* 135*7c478bd9Sstevel@tonic-gate * Private data structure for the proc target. Among other things, we keep 136*7c478bd9Sstevel@tonic-gate * pointers to the various symbol tables and the ELF file for the executable 137*7c478bd9Sstevel@tonic-gate * here, along with handles for our ops vector defined above. 138*7c478bd9Sstevel@tonic-gate */ 139*7c478bd9Sstevel@tonic-gate typedef struct pt_data { 140*7c478bd9Sstevel@tonic-gate struct ps_prochandle *p_idlehandle; /* idle libproc handle */ 141*7c478bd9Sstevel@tonic-gate mdb_gelf_symtab_t *p_symtab; /* Standard symbol table */ 142*7c478bd9Sstevel@tonic-gate mdb_gelf_symtab_t *p_dynsym; /* Dynamic symbol table */ 143*7c478bd9Sstevel@tonic-gate mdb_gelf_file_t *p_file; /* ELF file object */ 144*7c478bd9Sstevel@tonic-gate mdb_io_t *p_fio; /* Current file i/o backend */ 145*7c478bd9Sstevel@tonic-gate mdb_io_t *p_aout_fio; /* Original file i/o backend */ 146*7c478bd9Sstevel@tonic-gate char p_platform[MAXNAMELEN]; /* Platform string */ 147*7c478bd9Sstevel@tonic-gate char p_symname[MDB_TGT_SYM_NAMLEN]; /* Temporary buffer for syms */ 148*7c478bd9Sstevel@tonic-gate char p_objname[MDB_TGT_MAPSZ]; /* Temporary buffer for objs */ 149*7c478bd9Sstevel@tonic-gate mdb_map_t p_map; /* Persistent map for callers */ 150*7c478bd9Sstevel@tonic-gate mdb_list_t p_vforkp; /* List of vfork parents */ 151*7c478bd9Sstevel@tonic-gate mdb_nv_t p_regs; /* Register descriptions */ 152*7c478bd9Sstevel@tonic-gate const mdb_tdb_ops_t *p_tdb_ops; /* libthread_db ops */ 153*7c478bd9Sstevel@tonic-gate const pt_ptl_ops_t *p_ptl_ops; /* Proc thread layer ops */ 154*7c478bd9Sstevel@tonic-gate void *p_ptl_hdl; /* Proc thread layer handle */ 155*7c478bd9Sstevel@tonic-gate rd_agent_t *p_rtld; /* librtld_db agent handle */ 156*7c478bd9Sstevel@tonic-gate const char *p_stdin; /* File for stdin redirect */ 157*7c478bd9Sstevel@tonic-gate const char *p_stdout; /* File for stdout redirect */ 158*7c478bd9Sstevel@tonic-gate int p_oflags; /* Flags for open(2) */ 159*7c478bd9Sstevel@tonic-gate int p_gflags; /* Flags for Pgrab() */ 160*7c478bd9Sstevel@tonic-gate int p_rflags; /* Flags for Prelease() */ 161*7c478bd9Sstevel@tonic-gate int p_signal; /* Signal to post at next run */ 162*7c478bd9Sstevel@tonic-gate int p_rtld_finished; /* Has rtld init completed? */ 163*7c478bd9Sstevel@tonic-gate int p_rdstate; /* Dlopen state (see below) */ 164*7c478bd9Sstevel@tonic-gate int p_maxsig; /* Maximum valid signal */ 165*7c478bd9Sstevel@tonic-gate mdb_nv_t p_env; /* Current environment */ 166*7c478bd9Sstevel@tonic-gate } pt_data_t; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate #define PT_RD_NONE 0 /* No update pending */ 169*7c478bd9Sstevel@tonic-gate #define PT_RD_ADD 1 /* Dlopen detected */ 170*7c478bd9Sstevel@tonic-gate #define PT_RD_CONSIST 2 /* Link maps consistent */ 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate /* 173*7c478bd9Sstevel@tonic-gate * The mdb_tgt_gregset type is opaque to callers of the target interface. 174*7c478bd9Sstevel@tonic-gate * Inside the target we define it explicitly to be a prgregset_t. 175*7c478bd9Sstevel@tonic-gate */ 176*7c478bd9Sstevel@tonic-gate struct mdb_tgt_gregset { 177*7c478bd9Sstevel@tonic-gate prgregset_t gregs; 178*7c478bd9Sstevel@tonic-gate }; 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate typedef struct pt_symarg { 181*7c478bd9Sstevel@tonic-gate mdb_tgt_t *psym_targ; /* Target pointer */ 182*7c478bd9Sstevel@tonic-gate uint_t psym_which; /* Type of symbol table */ 183*7c478bd9Sstevel@tonic-gate uint_t psym_type; /* Type of symbols to match */ 184*7c478bd9Sstevel@tonic-gate mdb_tgt_sym_f *psym_func; /* Callback function */ 185*7c478bd9Sstevel@tonic-gate void *psym_private; /* Callback data */ 186*7c478bd9Sstevel@tonic-gate mdb_syminfo_t psym_info; /* Symbol id and table id */ 187*7c478bd9Sstevel@tonic-gate const char *psym_obj; /* Containing object */ 188*7c478bd9Sstevel@tonic-gate } pt_symarg_t; 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate typedef struct pt_maparg { 191*7c478bd9Sstevel@tonic-gate mdb_tgt_t *pmap_targ; /* Target pointer */ 192*7c478bd9Sstevel@tonic-gate mdb_tgt_map_f *pmap_func; /* Callback function */ 193*7c478bd9Sstevel@tonic-gate void *pmap_private; /* Callback data */ 194*7c478bd9Sstevel@tonic-gate } pt_maparg_t; 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate typedef struct pt_stkarg { 197*7c478bd9Sstevel@tonic-gate mdb_tgt_stack_f *pstk_func; /* Callback function */ 198*7c478bd9Sstevel@tonic-gate void *pstk_private; /* Callback data */ 199*7c478bd9Sstevel@tonic-gate uint_t pstk_gotpc; /* Non-zero pc found */ 200*7c478bd9Sstevel@tonic-gate } pt_stkarg_t; 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate typedef struct pt_addarg_t { 203*7c478bd9Sstevel@tonic-gate pt_data_t *pa_pt; /* Proc target data */ 204*7c478bd9Sstevel@tonic-gate mdb_addrvec_t *pa_ap; /* Addrvec pointer */ 205*7c478bd9Sstevel@tonic-gate } pt_addarg_t; 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate typedef struct pt_brkpt { 208*7c478bd9Sstevel@tonic-gate uintptr_t ptb_addr; /* Breakpoint address */ 209*7c478bd9Sstevel@tonic-gate ulong_t ptb_instr; /* Saved instruction */ 210*7c478bd9Sstevel@tonic-gate } pt_brkpt_t; 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate typedef struct pt_bparg { 213*7c478bd9Sstevel@tonic-gate char *pta_symbol; /* Symbolic name */ 214*7c478bd9Sstevel@tonic-gate uintptr_t pta_addr; /* Explicit address */ 215*7c478bd9Sstevel@tonic-gate } pt_bparg_t; 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate /* 218*7c478bd9Sstevel@tonic-gate * The proc_isadep.c file is expected to define the following 219*7c478bd9Sstevel@tonic-gate * ISA-dependent pieces of the proc target: 220*7c478bd9Sstevel@tonic-gate */ 221*7c478bd9Sstevel@tonic-gate extern int pt_regs(uintptr_t, uint_t, int, const mdb_arg_t *); 222*7c478bd9Sstevel@tonic-gate extern int pt_fpregs(uintptr_t, uint_t, int, const mdb_arg_t *); 223*7c478bd9Sstevel@tonic-gate extern int pt_step_out(mdb_tgt_t *, uintptr_t *); 224*7c478bd9Sstevel@tonic-gate extern int pt_next(mdb_tgt_t *, uintptr_t *); 225*7c478bd9Sstevel@tonic-gate extern int pt_getfpreg(mdb_tgt_t *, mdb_tgt_tid_t, ushort_t, ushort_t, 226*7c478bd9Sstevel@tonic-gate mdb_tgt_reg_t *); 227*7c478bd9Sstevel@tonic-gate extern int pt_putfpreg(mdb_tgt_t *, mdb_tgt_tid_t, ushort_t, ushort_t, 228*7c478bd9Sstevel@tonic-gate mdb_tgt_reg_t); 229*7c478bd9Sstevel@tonic-gate extern void pt_addfpregs(mdb_tgt_t *); 230*7c478bd9Sstevel@tonic-gate extern const char *pt_disasm(const GElf_Ehdr *); 231*7c478bd9Sstevel@tonic-gate extern int pt_frameregs(void *, uintptr_t, uint_t, const long *, 232*7c478bd9Sstevel@tonic-gate const mdb_tgt_gregset_t *, boolean_t); 233*7c478bd9Sstevel@tonic-gate extern const mdb_tgt_regdesc_t pt_regdesc[]; 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate #endif /* _MDB */ 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate #ifdef __cplusplus 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate #endif 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate #endif /* _MDB_PROC_H */ 242