Home | History | Annotate | Download | only in mdb
      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 */
    242