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