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