Print this page
15254 %ymm registers not restored after signal handler
15367 x86 getfpregs() summons corrupting %xmm ghosts
15333 want x86 /proc xregs support (libc_db, libproc, mdb, etc.)
15336 want libc functions for extended ucontext_t
15334 want ps_lwphandle-specific reg routines
15328 FPU_CW_INIT mistreats reserved bit
15335 i86pc fpu_subr.c isn't really platform-specific
15332 setcontext(2) isn't actually noreturn
15331 need <sys/stdalign.h>
Change-Id: I7060aa86042dfb989f77fc3323c065ea2eafa9ad
Conflicts:
    usr/src/uts/common/fs/proc/prcontrol.c
    usr/src/uts/intel/os/archdep.c
    usr/src/uts/intel/sys/ucontext.h
    usr/src/uts/intel/syscall/getcontext.c


   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 /*
  27  * Copyright 2018 Joyent, Inc.
  28  * Copyright (c) 2014 by Delphix. All rights reserved.
  29  * Copyright 2020 Oxide Computer Company
  30  */
  31 
  32 /*
  33  * User Process Target
  34  *
  35  * The user process target is invoked when the -u or -p command-line options
  36  * are used, or when an ELF executable file or ELF core file is specified on
  37  * the command-line.  This target is also selected by default when no target
  38  * options are present.  In this case, it defaults the executable name to
  39  * "a.out".  If no process or core file is currently attached, the target
  40  * functions as a kind of virtual /dev/zero (in accordance with adb(1)
  41  * semantics); reads from the virtual address space return zeroes and writes
  42  * fail silently.  The proc target itself is designed as a wrapper around the
  43  * services provided by libproc.so: t->t_pshandle is set to the struct
  44  * ps_prochandle pointer returned as a handle by libproc.  The target also
  45  * opens the executable file itself using the MDB GElf services, for
  46  * interpreting the .symtab and .dynsym if no libproc handle has been
  47  * initialized, and for handling i/o to and from the object file.  Currently,
  48  * the only ISA-dependent portions of the proc target are the $r and ::fpregs
  49  * dcmds, the callbacks for t_next() and t_step_out(), and the list of named


4622 
4623         if (t->t_pshandle == NULL)
4624                 return (set_errno(EMDB_NOPROC));
4625 
4626         if ((v = mdb_nv_lookup(&pt->p_regs, rname)) != NULL) {
4627                 uintmax_t rd_nval = mdb_nv_get_value(v);
4628                 ushort_t rd_num = MDB_TGT_R_NUM(rd_nval);
4629                 ushort_t rd_flags = MDB_TGT_R_FLAGS(rd_nval);
4630 
4631                 if (!MDB_TGT_R_IS_FP(rd_flags)) {
4632 
4633                         if (rd_flags & MDB_TGT_R_32)
4634                                 r &= 0xffffffffULL;
4635                         else if (rd_flags & MDB_TGT_R_16)
4636                                 r &= 0xffffULL;
4637                         else if (rd_flags & MDB_TGT_R_8H)
4638                                 r = (r & 0xffULL) << 8;
4639                         else if (rd_flags & MDB_TGT_R_8L)
4640                                 r &= 0xffULL;
4641 
4642 #if defined(__sparc) && defined(_ILP32)
4643                         /*
4644                          * If we are debugging on 32-bit SPARC, the globals and
4645                          * outs can have 32 upper bits stored in the xregs.
4646                          */
4647                         int is_g = (rd_num == R_G0 ||
4648                             rd_num >= R_G1 && rd_num <= R_G7);
4649                         int is_o = (rd_num >= R_O0 && rd_num <= R_O7);
4650                         prxregset_t xrs;
4651 
4652                         if ((is_g || is_o) && PTL_GETXREGS(t, tid, &xrs) == 0 &&
4653                             xrs.pr_type == XR_TYPE_V8P) {
4654                                 if (is_g) {
4655                                         xrs.pr_un.pr_v8p.pr_xg[rd_num -
4656                                             R_G0 + XR_G0] = (uint32_t)(r >> 32);
4657                                 } else if (is_o) {
4658                                         xrs.pr_un.pr_v8p.pr_xo[rd_num -
4659                                             R_O0 + XR_O0] = (uint32_t)(r >> 32);
4660                                 }
4661 
4662                                 if (PTL_SETXREGS(t, tid, &xrs) == -1)
4663                                         return (-1);
4664                         }
4665 #endif  /* __sparc && _ILP32 */
4666 
4667                         if (PTL_GETREGS(t, tid, grs) == 0) {
4668                                 grs[rd_num] = (prgreg_t)r;
4669                                 return (PTL_SETREGS(t, tid, grs));
4670                         }
4671                         return (-1);
4672                 } else
4673                         return (pt_putfpreg(t, tid, rd_num, rd_flags, r));
4674         }
4675 
4676         return (set_errno(EMDB_BADREG));
4677 }
4678 
4679 static int
4680 pt_stack_call(pt_stkarg_t *psp, const prgregset_t grs, uint_t argc, long *argv)
4681 {
4682         psp->pstk_gotpc |= (grs[R_PC] != 0);
4683 
4684         if (!psp->pstk_gotpc)
4685                 return (0); /* skip initial zeroed frames */
4686 


4820 pt_lwp_getregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid, prgregset_t gregs)
4821 {
4822         if (t->t_pshandle != NULL) {
4823                 return (ptl_err(Plwp_getregs(t->t_pshandle,
4824                     (lwpid_t)tid, gregs)));
4825         }
4826         return (set_errno(EMDB_NOPROC));
4827 }
4828 
4829 /*ARGSUSED*/
4830 static int
4831 pt_lwp_setregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid, prgregset_t gregs)
4832 {
4833         if (t->t_pshandle != NULL) {
4834                 return (ptl_err(Plwp_setregs(t->t_pshandle,
4835                     (lwpid_t)tid, gregs)));
4836         }
4837         return (set_errno(EMDB_NOPROC));
4838 }
4839 
4840 #ifdef  __sparc
4841 
4842 /*ARGSUSED*/
4843 static int
4844 pt_lwp_getxregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid, prxregset_t *xregs)

4845 {
4846         if (t->t_pshandle != NULL) {
4847                 return (ptl_err(Plwp_getxregs(t->t_pshandle,
4848                     (lwpid_t)tid, xregs)));
4849         }
4850         return (set_errno(EMDB_NOPROC));
4851 }
4852 
4853 /*ARGSUSED*/







4854 static int
4855 pt_lwp_setxregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid,
4856     const prxregset_t *xregs)
4857 {
4858         if (t->t_pshandle != NULL) {
4859                 return (ptl_err(Plwp_setxregs(t->t_pshandle,
4860                     (lwpid_t)tid, xregs)));
4861         }
4862         return (set_errno(EMDB_NOPROC));
4863 }
4864 
4865 #endif  /* __sparc */
4866 
4867 /*ARGSUSED*/
4868 static int
4869 pt_lwp_getfpregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid,
4870     prfpregset_t *fpregs)
4871 {
4872         if (t->t_pshandle != NULL) {
4873                 return (ptl_err(Plwp_getfpregs(t->t_pshandle,
4874                     (lwpid_t)tid, fpregs)));
4875         }
4876         return (set_errno(EMDB_NOPROC));
4877 }
4878 
4879 /*ARGSUSED*/
4880 static int
4881 pt_lwp_setfpregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid,
4882     const prfpregset_t *fpregs)
4883 {
4884         if (t->t_pshandle != NULL) {
4885                 return (ptl_err(Plwp_setfpregs(t->t_pshandle,
4886                     (lwpid_t)tid, fpregs)));
4887         }
4888         return (set_errno(EMDB_NOPROC));
4889 }
4890 
4891 static const pt_ptl_ops_t proc_lwp_ops = {
4892         (int (*)())(uintptr_t)mdb_tgt_nop,
4893         (void (*)())(uintptr_t)mdb_tgt_nop,
4894         pt_lwp_tid,
4895         pt_lwp_iter,
4896         pt_lwp_getregs,
4897         pt_lwp_setregs,
4898 #ifdef __sparc
4899         pt_lwp_getxregs,
4900         pt_lwp_setxregs,
4901 #endif
4902         pt_lwp_getfpregs,
4903         pt_lwp_setfpregs
4904 };
4905 
4906 static int
4907 pt_tdb_ctor(mdb_tgt_t *t)
4908 {
4909         pt_data_t *pt = t->t_data;
4910         td_thragent_t *tap;
4911         td_err_e err;
4912 
4913         if ((err = pt->p_tdb_ops->td_ta_new(t->t_pshandle, &tap)) != TD_OK)
4914                 return (set_errno(tdb_to_errno(err)));
4915 
4916         pt->p_ptl_hdl = tap;
4917         return (0);
4918 }
4919 
4920 static void
4921 pt_tdb_dtor(mdb_tgt_t *t, void *tap)
4922 {
4923         pt_data_t *pt = t->t_data;


5007 pt_tdb_setregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid, prgregset_t gregs)
5008 {
5009         pt_data_t *pt = t->t_data;
5010 
5011         td_thrhandle_t th;
5012         td_err_e err;
5013 
5014         if (t->t_pshandle == NULL)
5015                 return (set_errno(EMDB_NOPROC));
5016 
5017         if ((err = pt->p_tdb_ops->td_ta_map_id2thr(tap, tid, &th)) != TD_OK)
5018                 return (set_errno(tdb_to_errno(err)));
5019 
5020         err = pt->p_tdb_ops->td_thr_setgregs(&th, gregs);
5021         if (err != TD_OK && err != TD_PARTIALREG)
5022                 return (set_errno(tdb_to_errno(err)));
5023 
5024         return (0);
5025 }
5026 
5027 #ifdef __sparc
5028 
5029 static int
5030 pt_tdb_getxregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid, prxregset_t *xregs)

5031 {
5032         pt_data_t *pt = t->t_data;
5033 
5034         td_thrhandle_t th;
5035         td_err_e err;


5036 
5037         if (t->t_pshandle == NULL)
5038                 return (set_errno(EMDB_NOPROC));
5039 
5040         if ((err = pt->p_tdb_ops->td_ta_map_id2thr(tap, tid, &th)) != TD_OK)
5041                 return (set_errno(tdb_to_errno(err)));
5042 
5043         err = pt->p_tdb_ops->td_thr_getxregs(&th, xregs);
5044         if (err != TD_OK && err != TD_PARTIALREG)
5045                 return (set_errno(tdb_to_errno(err)));
5046 














5047         return (0);
5048 }
5049 







5050 static int
5051 pt_tdb_setxregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid,
5052     const prxregset_t *xregs)
5053 {
5054         pt_data_t *pt = t->t_data;
5055 
5056         td_thrhandle_t th;
5057         td_err_e err;
5058 
5059         if (t->t_pshandle == NULL)
5060                 return (set_errno(EMDB_NOPROC));
5061 
5062         if ((err = pt->p_tdb_ops->td_ta_map_id2thr(tap, tid, &th)) != TD_OK)
5063                 return (set_errno(tdb_to_errno(err)));
5064 
5065         err = pt->p_tdb_ops->td_thr_setxregs(&th, xregs);
5066         if (err != TD_OK && err != TD_PARTIALREG)
5067                 return (set_errno(tdb_to_errno(err)));
5068 
5069         return (0);
5070 }
5071 
5072 #endif  /* __sparc */
5073 
5074 static int
5075 pt_tdb_getfpregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid,
5076     prfpregset_t *fpregs)
5077 {
5078         pt_data_t *pt = t->t_data;
5079 
5080         td_thrhandle_t th;
5081         td_err_e err;
5082 
5083         if (t->t_pshandle == NULL)
5084                 return (set_errno(EMDB_NOPROC));
5085 
5086         if ((err = pt->p_tdb_ops->td_ta_map_id2thr(tap, tid, &th)) != TD_OK)
5087                 return (set_errno(tdb_to_errno(err)));
5088 
5089         err = pt->p_tdb_ops->td_thr_getfpregs(&th, fpregs);
5090         if (err != TD_OK && err != TD_PARTIALREG)
5091                 return (set_errno(tdb_to_errno(err)));
5092 
5093         return (0);


5099 {
5100         pt_data_t *pt = t->t_data;
5101 
5102         td_thrhandle_t th;
5103         td_err_e err;
5104 
5105         if (t->t_pshandle == NULL)
5106                 return (set_errno(EMDB_NOPROC));
5107 
5108         if ((err = pt->p_tdb_ops->td_ta_map_id2thr(tap, tid, &th)) != TD_OK)
5109                 return (set_errno(tdb_to_errno(err)));
5110 
5111         err = pt->p_tdb_ops->td_thr_setfpregs(&th, fpregs);
5112         if (err != TD_OK && err != TD_PARTIALREG)
5113                 return (set_errno(tdb_to_errno(err)));
5114 
5115         return (0);
5116 }
5117 
5118 static const pt_ptl_ops_t proc_tdb_ops = {
5119         pt_tdb_ctor,
5120         pt_tdb_dtor,
5121         pt_tdb_tid,
5122         pt_tdb_iter,
5123         pt_tdb_getregs,
5124         pt_tdb_setregs,
5125 #ifdef __sparc
5126         pt_tdb_getxregs,
5127         pt_tdb_setxregs,
5128 #endif
5129         pt_tdb_getfpregs,
5130         pt_tdb_setfpregs
5131 };
5132 
5133 static ssize_t
5134 pt_xd_auxv(mdb_tgt_t *t, void *buf, size_t nbytes)
5135 {
5136         struct ps_prochandle *P = t->t_pshandle;
5137         const auxv_t *auxp, *auxv = NULL;
5138         int auxn = 0;
5139 
5140         if (P != NULL && (auxv = Pgetauxvec(P)) != NULL &&
5141             auxv->a_type != AT_NULL) {
5142                 for (auxp = auxv, auxn = 1; auxp->a_type != 0; auxp++)
5143                         auxn++;
5144         }
5145 
5146         if (buf == NULL && nbytes == 0)
5147                 return (sizeof (auxv_t) * auxn);
5148 
5149         if (auxn == 0)
5150                 return (set_errno(ENODATA));




   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 /*
  27  * Copyright 2018 Joyent, Inc.
  28  * Copyright (c) 2014 by Delphix. All rights reserved.
  29  * Copyright 2023 Oxide Computer Company
  30  */
  31 
  32 /*
  33  * User Process Target
  34  *
  35  * The user process target is invoked when the -u or -p command-line options
  36  * are used, or when an ELF executable file or ELF core file is specified on
  37  * the command-line.  This target is also selected by default when no target
  38  * options are present.  In this case, it defaults the executable name to
  39  * "a.out".  If no process or core file is currently attached, the target
  40  * functions as a kind of virtual /dev/zero (in accordance with adb(1)
  41  * semantics); reads from the virtual address space return zeroes and writes
  42  * fail silently.  The proc target itself is designed as a wrapper around the
  43  * services provided by libproc.so: t->t_pshandle is set to the struct
  44  * ps_prochandle pointer returned as a handle by libproc.  The target also
  45  * opens the executable file itself using the MDB GElf services, for
  46  * interpreting the .symtab and .dynsym if no libproc handle has been
  47  * initialized, and for handling i/o to and from the object file.  Currently,
  48  * the only ISA-dependent portions of the proc target are the $r and ::fpregs
  49  * dcmds, the callbacks for t_next() and t_step_out(), and the list of named


4622 
4623         if (t->t_pshandle == NULL)
4624                 return (set_errno(EMDB_NOPROC));
4625 
4626         if ((v = mdb_nv_lookup(&pt->p_regs, rname)) != NULL) {
4627                 uintmax_t rd_nval = mdb_nv_get_value(v);
4628                 ushort_t rd_num = MDB_TGT_R_NUM(rd_nval);
4629                 ushort_t rd_flags = MDB_TGT_R_FLAGS(rd_nval);
4630 
4631                 if (!MDB_TGT_R_IS_FP(rd_flags)) {
4632 
4633                         if (rd_flags & MDB_TGT_R_32)
4634                                 r &= 0xffffffffULL;
4635                         else if (rd_flags & MDB_TGT_R_16)
4636                                 r &= 0xffffULL;
4637                         else if (rd_flags & MDB_TGT_R_8H)
4638                                 r = (r & 0xffULL) << 8;
4639                         else if (rd_flags & MDB_TGT_R_8L)
4640                                 r &= 0xffULL;
4641 

























4642                         if (PTL_GETREGS(t, tid, grs) == 0) {
4643                                 grs[rd_num] = (prgreg_t)r;
4644                                 return (PTL_SETREGS(t, tid, grs));
4645                         }
4646                         return (-1);
4647                 } else
4648                         return (pt_putfpreg(t, tid, rd_num, rd_flags, r));
4649         }
4650 
4651         return (set_errno(EMDB_BADREG));
4652 }
4653 
4654 static int
4655 pt_stack_call(pt_stkarg_t *psp, const prgregset_t grs, uint_t argc, long *argv)
4656 {
4657         psp->pstk_gotpc |= (grs[R_PC] != 0);
4658 
4659         if (!psp->pstk_gotpc)
4660                 return (0); /* skip initial zeroed frames */
4661 


4795 pt_lwp_getregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid, prgregset_t gregs)
4796 {
4797         if (t->t_pshandle != NULL) {
4798                 return (ptl_err(Plwp_getregs(t->t_pshandle,
4799                     (lwpid_t)tid, gregs)));
4800         }
4801         return (set_errno(EMDB_NOPROC));
4802 }
4803 
4804 /*ARGSUSED*/
4805 static int
4806 pt_lwp_setregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid, prgregset_t gregs)
4807 {
4808         if (t->t_pshandle != NULL) {
4809                 return (ptl_err(Plwp_setregs(t->t_pshandle,
4810                     (lwpid_t)tid, gregs)));
4811         }
4812         return (set_errno(EMDB_NOPROC));
4813 }
4814 

4815 
4816 /*ARGSUSED*/
4817 static int
4818 pt_lwp_getxregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid, prxregset_t **xregs,
4819     size_t *sizep)
4820 {
4821         if (t->t_pshandle != NULL) {
4822                 return (ptl_err(Plwp_getxregs(t->t_pshandle,
4823                     (lwpid_t)tid, xregs, sizep)));
4824         }
4825         return (set_errno(EMDB_NOPROC));
4826 }
4827 
4828 static void
4829 pt_lwp_freexregs(mdb_tgt_t *t, void *tap, prxregset_t *xregs, size_t size)
4830 {
4831         if (t->t_pshandle != NULL) {
4832                 Plwp_freexregs(t->t_pshandle, xregs, size);
4833         }
4834 }
4835 
4836 static int
4837 pt_lwp_setxregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid,
4838     const prxregset_t *xregs, size_t len)
4839 {
4840         if (t->t_pshandle != NULL) {
4841                 return (ptl_err(Plwp_setxregs(t->t_pshandle,
4842                     (lwpid_t)tid, xregs, len)));
4843         }
4844         return (set_errno(EMDB_NOPROC));
4845 }
4846 


4847 /*ARGSUSED*/
4848 static int
4849 pt_lwp_getfpregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid,
4850     prfpregset_t *fpregs)
4851 {
4852         if (t->t_pshandle != NULL) {
4853                 return (ptl_err(Plwp_getfpregs(t->t_pshandle,
4854                     (lwpid_t)tid, fpregs)));
4855         }
4856         return (set_errno(EMDB_NOPROC));
4857 }
4858 
4859 /*ARGSUSED*/
4860 static int
4861 pt_lwp_setfpregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid,
4862     const prfpregset_t *fpregs)
4863 {
4864         if (t->t_pshandle != NULL) {
4865                 return (ptl_err(Plwp_setfpregs(t->t_pshandle,
4866                     (lwpid_t)tid, fpregs)));
4867         }
4868         return (set_errno(EMDB_NOPROC));
4869 }
4870 
4871 static const pt_ptl_ops_t proc_lwp_ops = {
4872         .ptl_ctor = (int (*)())(uintptr_t)mdb_tgt_nop,
4873         .ptl_dtor = (void (*)())(uintptr_t)mdb_tgt_nop,
4874         .ptl_tid = pt_lwp_tid,
4875         .ptl_iter = pt_lwp_iter,
4876         .ptl_getregs = pt_lwp_getregs,
4877         .ptl_setregs = pt_lwp_setregs,
4878         .ptl_getxregs = pt_lwp_getxregs,
4879         .ptl_freexregs = pt_lwp_freexregs,
4880         .ptl_setxregs = pt_lwp_setxregs,
4881         .ptl_getfpregs = pt_lwp_getfpregs,
4882         .ptl_setfpregs = pt_lwp_setfpregs

4883 };
4884 
4885 static int
4886 pt_tdb_ctor(mdb_tgt_t *t)
4887 {
4888         pt_data_t *pt = t->t_data;
4889         td_thragent_t *tap;
4890         td_err_e err;
4891 
4892         if ((err = pt->p_tdb_ops->td_ta_new(t->t_pshandle, &tap)) != TD_OK)
4893                 return (set_errno(tdb_to_errno(err)));
4894 
4895         pt->p_ptl_hdl = tap;
4896         return (0);
4897 }
4898 
4899 static void
4900 pt_tdb_dtor(mdb_tgt_t *t, void *tap)
4901 {
4902         pt_data_t *pt = t->t_data;


4986 pt_tdb_setregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid, prgregset_t gregs)
4987 {
4988         pt_data_t *pt = t->t_data;
4989 
4990         td_thrhandle_t th;
4991         td_err_e err;
4992 
4993         if (t->t_pshandle == NULL)
4994                 return (set_errno(EMDB_NOPROC));
4995 
4996         if ((err = pt->p_tdb_ops->td_ta_map_id2thr(tap, tid, &th)) != TD_OK)
4997                 return (set_errno(tdb_to_errno(err)));
4998 
4999         err = pt->p_tdb_ops->td_thr_setgregs(&th, gregs);
5000         if (err != TD_OK && err != TD_PARTIALREG)
5001                 return (set_errno(tdb_to_errno(err)));
5002 
5003         return (0);
5004 }
5005 


5006 static int
5007 pt_tdb_getxregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid, prxregset_t **xregs,
5008     size_t *sizep)
5009 {
5010         pt_data_t *pt = t->t_data;
5011 
5012         td_thrhandle_t th;
5013         td_err_e err;
5014         int xregsize;
5015         prxregset_t *pxr;
5016 
5017         if (t->t_pshandle == NULL)
5018                 return (set_errno(EMDB_NOPROC));
5019 
5020         if ((err = pt->p_tdb_ops->td_ta_map_id2thr(tap, tid, &th)) != TD_OK)
5021                 return (set_errno(tdb_to_errno(err)));
5022 
5023         if ((err = pt->p_tdb_ops->td_thr_getxregsize(&th, &xregsize)) != TD_OK)

5024                 return (set_errno(tdb_to_errno(err)));
5025 
5026         if (xregsize == 0) {
5027                 return (set_errno(ENODATA));
5028         }
5029 
5030         pxr = mdb_alloc(xregsize, UM_SLEEP);
5031 
5032         err = pt->p_tdb_ops->td_thr_getxregs(&th, pxr);
5033         if (err != TD_OK && err != TD_PARTIALREG) {
5034                 mdb_free(pxr, xregsize);
5035                 return (set_errno(tdb_to_errno(err)));
5036         }
5037 
5038         *xregs = pxr;
5039         *sizep = xregsize;
5040         return (0);
5041 }
5042 
5043 static void
5044 pt_tdb_freexregs(mdb_tgt_t *t __unused, void *tap __unused, prxregset_t *pxr,
5045     size_t size)
5046 {
5047         mdb_free(pxr, size);
5048 }
5049 
5050 static int
5051 pt_tdb_setxregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid,
5052     const prxregset_t *xregs, size_t len __unused)
5053 {
5054         pt_data_t *pt = t->t_data;
5055 
5056         td_thrhandle_t th;
5057         td_err_e err;
5058 
5059         if (t->t_pshandle == NULL)
5060                 return (set_errno(EMDB_NOPROC));
5061 
5062         if ((err = pt->p_tdb_ops->td_ta_map_id2thr(tap, tid, &th)) != TD_OK)
5063                 return (set_errno(tdb_to_errno(err)));
5064 
5065         err = pt->p_tdb_ops->td_thr_setxregs(&th, xregs);
5066         if (err != TD_OK && err != TD_PARTIALREG)
5067                 return (set_errno(tdb_to_errno(err)));
5068 
5069         return (0);
5070 }
5071 


5072 static int
5073 pt_tdb_getfpregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid,
5074     prfpregset_t *fpregs)
5075 {
5076         pt_data_t *pt = t->t_data;
5077 
5078         td_thrhandle_t th;
5079         td_err_e err;
5080 
5081         if (t->t_pshandle == NULL)
5082                 return (set_errno(EMDB_NOPROC));
5083 
5084         if ((err = pt->p_tdb_ops->td_ta_map_id2thr(tap, tid, &th)) != TD_OK)
5085                 return (set_errno(tdb_to_errno(err)));
5086 
5087         err = pt->p_tdb_ops->td_thr_getfpregs(&th, fpregs);
5088         if (err != TD_OK && err != TD_PARTIALREG)
5089                 return (set_errno(tdb_to_errno(err)));
5090 
5091         return (0);


5097 {
5098         pt_data_t *pt = t->t_data;
5099 
5100         td_thrhandle_t th;
5101         td_err_e err;
5102 
5103         if (t->t_pshandle == NULL)
5104                 return (set_errno(EMDB_NOPROC));
5105 
5106         if ((err = pt->p_tdb_ops->td_ta_map_id2thr(tap, tid, &th)) != TD_OK)
5107                 return (set_errno(tdb_to_errno(err)));
5108 
5109         err = pt->p_tdb_ops->td_thr_setfpregs(&th, fpregs);
5110         if (err != TD_OK && err != TD_PARTIALREG)
5111                 return (set_errno(tdb_to_errno(err)));
5112 
5113         return (0);
5114 }
5115 
5116 static const pt_ptl_ops_t proc_tdb_ops = {
5117         .ptl_ctor = pt_tdb_ctor,
5118         .ptl_dtor = pt_tdb_dtor,
5119         .ptl_tid = pt_tdb_tid,
5120         .ptl_iter = pt_tdb_iter,
5121         .ptl_getregs = pt_tdb_getregs,
5122         .ptl_setregs = pt_tdb_setregs,
5123         .ptl_getxregs = pt_tdb_getxregs,
5124         .ptl_freexregs = pt_tdb_freexregs,
5125         .ptl_setxregs = pt_tdb_setxregs,
5126         .ptl_getfpregs = pt_tdb_getfpregs,
5127         .ptl_setfpregs = pt_tdb_setfpregs

5128 };
5129 
5130 static ssize_t
5131 pt_xd_auxv(mdb_tgt_t *t, void *buf, size_t nbytes)
5132 {
5133         struct ps_prochandle *P = t->t_pshandle;
5134         const auxv_t *auxp, *auxv = NULL;
5135         int auxn = 0;
5136 
5137         if (P != NULL && (auxv = Pgetauxvec(P)) != NULL &&
5138             auxv->a_type != AT_NULL) {
5139                 for (auxp = auxv, auxn = 1; auxp->a_type != 0; auxp++)
5140                         auxn++;
5141         }
5142 
5143         if (buf == NULL && nbytes == 0)
5144                 return (sizeof (auxv_t) * auxn);
5145 
5146         if (auxn == 0)
5147                 return (set_errno(ENODATA));