1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate * CDDL HEADER START
3*0Sstevel@tonic-gate *
4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*0Sstevel@tonic-gate * with the License.
8*0Sstevel@tonic-gate *
9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate * and limitations under the License.
13*0Sstevel@tonic-gate *
14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate *
20*0Sstevel@tonic-gate * CDDL HEADER END
21*0Sstevel@tonic-gate */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24*0Sstevel@tonic-gate * Use is subject to license terms.
25*0Sstevel@tonic-gate */
26*0Sstevel@tonic-gate
27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
28*0Sstevel@tonic-gate
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate * User Process Target Intel 32-bit component
31*0Sstevel@tonic-gate *
32*0Sstevel@tonic-gate * This file provides the ISA-dependent portion of the user process target.
33*0Sstevel@tonic-gate * For more details on the implementation refer to mdb_proc.c.
34*0Sstevel@tonic-gate */
35*0Sstevel@tonic-gate
36*0Sstevel@tonic-gate #include <mdb/mdb_proc.h>
37*0Sstevel@tonic-gate #include <mdb/mdb_kreg.h>
38*0Sstevel@tonic-gate #include <mdb/mdb_err.h>
39*0Sstevel@tonic-gate #include <mdb/mdb_ia32util.h>
40*0Sstevel@tonic-gate #include <mdb/mdb.h>
41*0Sstevel@tonic-gate
42*0Sstevel@tonic-gate #include <sys/frame.h>
43*0Sstevel@tonic-gate #include <libproc.h>
44*0Sstevel@tonic-gate #include <sys/fp.h>
45*0Sstevel@tonic-gate #include <ieeefp.h>
46*0Sstevel@tonic-gate
47*0Sstevel@tonic-gate const mdb_tgt_regdesc_t pt_regdesc[] = {
48*0Sstevel@tonic-gate { "gs", GS, MDB_TGT_R_EXPORT },
49*0Sstevel@tonic-gate { "fs", FS, MDB_TGT_R_EXPORT },
50*0Sstevel@tonic-gate { "es", ES, MDB_TGT_R_EXPORT },
51*0Sstevel@tonic-gate { "ds", DS, MDB_TGT_R_EXPORT },
52*0Sstevel@tonic-gate { "edi", EDI, MDB_TGT_R_EXPORT },
53*0Sstevel@tonic-gate { "esi", ESI, MDB_TGT_R_EXPORT },
54*0Sstevel@tonic-gate { "ebp", EBP, MDB_TGT_R_EXPORT },
55*0Sstevel@tonic-gate { "kesp", ESP, MDB_TGT_R_EXPORT },
56*0Sstevel@tonic-gate { "ebx", EBX, MDB_TGT_R_EXPORT },
57*0Sstevel@tonic-gate { "edx", EDX, MDB_TGT_R_EXPORT },
58*0Sstevel@tonic-gate { "ecx", ECX, MDB_TGT_R_EXPORT },
59*0Sstevel@tonic-gate { "eax", EAX, MDB_TGT_R_EXPORT },
60*0Sstevel@tonic-gate { "trapno", TRAPNO, MDB_TGT_R_EXPORT },
61*0Sstevel@tonic-gate { "err", ERR, MDB_TGT_R_EXPORT },
62*0Sstevel@tonic-gate { "eip", EIP, MDB_TGT_R_EXPORT },
63*0Sstevel@tonic-gate { "cs", CS, MDB_TGT_R_EXPORT },
64*0Sstevel@tonic-gate { "eflags", EFL, MDB_TGT_R_EXPORT },
65*0Sstevel@tonic-gate { "esp", UESP, MDB_TGT_R_EXPORT },
66*0Sstevel@tonic-gate { "ss", SS, MDB_TGT_R_EXPORT },
67*0Sstevel@tonic-gate { NULL, 0, 0 }
68*0Sstevel@tonic-gate };
69*0Sstevel@tonic-gate
70*0Sstevel@tonic-gate /*
71*0Sstevel@tonic-gate * We cannot rely on pr_instr, because if we hit a breakpoint or the user has
72*0Sstevel@tonic-gate * artifically modified memory, it will no longer be correct.
73*0Sstevel@tonic-gate */
74*0Sstevel@tonic-gate static uint8_t
pt_read_instr(mdb_tgt_t * t)75*0Sstevel@tonic-gate pt_read_instr(mdb_tgt_t *t)
76*0Sstevel@tonic-gate {
77*0Sstevel@tonic-gate const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp;
78*0Sstevel@tonic-gate uint8_t ret = 0;
79*0Sstevel@tonic-gate
80*0Sstevel@tonic-gate (void) mdb_tgt_vread(t, &ret, sizeof (ret), psp->pr_reg[EIP]);
81*0Sstevel@tonic-gate
82*0Sstevel@tonic-gate return (ret);
83*0Sstevel@tonic-gate }
84*0Sstevel@tonic-gate
85*0Sstevel@tonic-gate /*ARGSUSED*/
86*0Sstevel@tonic-gate int
pt_regs(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)87*0Sstevel@tonic-gate pt_regs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
88*0Sstevel@tonic-gate {
89*0Sstevel@tonic-gate mdb_tgt_t *t = mdb.m_target;
90*0Sstevel@tonic-gate mdb_tgt_tid_t tid;
91*0Sstevel@tonic-gate prgregset_t grs;
92*0Sstevel@tonic-gate prgreg_t eflags;
93*0Sstevel@tonic-gate
94*0Sstevel@tonic-gate if (argc != 0)
95*0Sstevel@tonic-gate return (DCMD_USAGE);
96*0Sstevel@tonic-gate
97*0Sstevel@tonic-gate if (t->t_pshandle == NULL || Pstate(t->t_pshandle) == PS_UNDEAD) {
98*0Sstevel@tonic-gate mdb_warn("no process active\n");
99*0Sstevel@tonic-gate return (DCMD_ERR);
100*0Sstevel@tonic-gate }
101*0Sstevel@tonic-gate
102*0Sstevel@tonic-gate if (Pstate(t->t_pshandle) == PS_LOST) {
103*0Sstevel@tonic-gate mdb_warn("debugger has lost control of process\n");
104*0Sstevel@tonic-gate return (DCMD_ERR);
105*0Sstevel@tonic-gate }
106*0Sstevel@tonic-gate
107*0Sstevel@tonic-gate if (flags & DCMD_ADDRSPEC)
108*0Sstevel@tonic-gate tid = (mdb_tgt_tid_t)addr;
109*0Sstevel@tonic-gate else
110*0Sstevel@tonic-gate tid = PTL_TID(t);
111*0Sstevel@tonic-gate
112*0Sstevel@tonic-gate if (PTL_GETREGS(t, tid, grs) != 0) {
113*0Sstevel@tonic-gate mdb_warn("failed to get current register set");
114*0Sstevel@tonic-gate return (DCMD_ERR);
115*0Sstevel@tonic-gate }
116*0Sstevel@tonic-gate
117*0Sstevel@tonic-gate eflags = grs[EFL];
118*0Sstevel@tonic-gate
119*0Sstevel@tonic-gate mdb_printf("%%cs = 0x%04x\t\t%%eax = 0x%0?p %A\n",
120*0Sstevel@tonic-gate grs[CS], grs[EAX], grs[EAX]);
121*0Sstevel@tonic-gate
122*0Sstevel@tonic-gate mdb_printf("%%ds = 0x%04x\t\t%%ebx = 0x%0?p %A\n",
123*0Sstevel@tonic-gate grs[DS], grs[EBX], grs[EBX]);
124*0Sstevel@tonic-gate
125*0Sstevel@tonic-gate mdb_printf("%%ss = 0x%04x\t\t%%ecx = 0x%0?p %A\n",
126*0Sstevel@tonic-gate grs[SS], grs[ECX], grs[ECX]);
127*0Sstevel@tonic-gate
128*0Sstevel@tonic-gate mdb_printf("%%es = 0x%04x\t\t%%edx = 0x%0?p %A\n",
129*0Sstevel@tonic-gate grs[ES], grs[EDX], grs[EDX]);
130*0Sstevel@tonic-gate
131*0Sstevel@tonic-gate mdb_printf("%%fs = 0x%04x\t\t%%esi = 0x%0?p %A\n",
132*0Sstevel@tonic-gate grs[FS], grs[ESI], grs[ESI]);
133*0Sstevel@tonic-gate
134*0Sstevel@tonic-gate mdb_printf("%%gs = 0x%04x\t\t%%edi = 0x%0?p %A\n\n",
135*0Sstevel@tonic-gate grs[GS], grs[EDI], grs[EDI]);
136*0Sstevel@tonic-gate
137*0Sstevel@tonic-gate mdb_printf(" %%eip = 0x%0?p %A\n", grs[EIP], grs[EIP]);
138*0Sstevel@tonic-gate mdb_printf(" %%ebp = 0x%0?p\n", grs[EBP]);
139*0Sstevel@tonic-gate mdb_printf("%%kesp = 0x%0?p\n\n", grs[ESP]);
140*0Sstevel@tonic-gate mdb_printf("%%eflags = 0x%08x\n", eflags);
141*0Sstevel@tonic-gate
142*0Sstevel@tonic-gate mdb_printf(" id=%u vip=%u vif=%u ac=%u vm=%u rf=%u nt=%u iopl=0x%x\n",
143*0Sstevel@tonic-gate (eflags & KREG_EFLAGS_ID_MASK) >> KREG_EFLAGS_ID_SHIFT,
144*0Sstevel@tonic-gate (eflags & KREG_EFLAGS_VIP_MASK) >> KREG_EFLAGS_VIP_SHIFT,
145*0Sstevel@tonic-gate (eflags & KREG_EFLAGS_VIF_MASK) >> KREG_EFLAGS_VIF_SHIFT,
146*0Sstevel@tonic-gate (eflags & KREG_EFLAGS_AC_MASK) >> KREG_EFLAGS_AC_SHIFT,
147*0Sstevel@tonic-gate (eflags & KREG_EFLAGS_VM_MASK) >> KREG_EFLAGS_VM_SHIFT,
148*0Sstevel@tonic-gate (eflags & KREG_EFLAGS_RF_MASK) >> KREG_EFLAGS_RF_SHIFT,
149*0Sstevel@tonic-gate (eflags & KREG_EFLAGS_NT_MASK) >> KREG_EFLAGS_NT_SHIFT,
150*0Sstevel@tonic-gate (eflags & KREG_EFLAGS_IOPL_MASK) >> KREG_EFLAGS_IOPL_SHIFT);
151*0Sstevel@tonic-gate
152*0Sstevel@tonic-gate mdb_printf(" status=<%s,%s,%s,%s,%s,%s,%s,%s,%s>\n\n",
153*0Sstevel@tonic-gate (eflags & KREG_EFLAGS_OF_MASK) ? "OF" : "of",
154*0Sstevel@tonic-gate (eflags & KREG_EFLAGS_DF_MASK) ? "DF" : "df",
155*0Sstevel@tonic-gate (eflags & KREG_EFLAGS_IF_MASK) ? "IF" : "if",
156*0Sstevel@tonic-gate (eflags & KREG_EFLAGS_TF_MASK) ? "TF" : "tf",
157*0Sstevel@tonic-gate (eflags & KREG_EFLAGS_SF_MASK) ? "SF" : "sf",
158*0Sstevel@tonic-gate (eflags & KREG_EFLAGS_ZF_MASK) ? "ZF" : "zf",
159*0Sstevel@tonic-gate (eflags & KREG_EFLAGS_AF_MASK) ? "AF" : "af",
160*0Sstevel@tonic-gate (eflags & KREG_EFLAGS_PF_MASK) ? "PF" : "pf",
161*0Sstevel@tonic-gate (eflags & KREG_EFLAGS_CF_MASK) ? "CF" : "cf");
162*0Sstevel@tonic-gate
163*0Sstevel@tonic-gate mdb_printf(" %%esp = 0x%0?x\n", grs[UESP]);
164*0Sstevel@tonic-gate mdb_printf("%%trapno = 0x%x\n", grs[TRAPNO]);
165*0Sstevel@tonic-gate mdb_printf(" %%err = 0x%x\n", grs[ERR]);
166*0Sstevel@tonic-gate
167*0Sstevel@tonic-gate return (DCMD_OK);
168*0Sstevel@tonic-gate }
169*0Sstevel@tonic-gate
170*0Sstevel@tonic-gate static const char *
fpcw2str(uint32_t cw,char * buf,size_t nbytes)171*0Sstevel@tonic-gate fpcw2str(uint32_t cw, char *buf, size_t nbytes)
172*0Sstevel@tonic-gate {
173*0Sstevel@tonic-gate char *end = buf + nbytes;
174*0Sstevel@tonic-gate char *p = buf;
175*0Sstevel@tonic-gate
176*0Sstevel@tonic-gate buf[0] = '\0';
177*0Sstevel@tonic-gate
178*0Sstevel@tonic-gate /*
179*0Sstevel@tonic-gate * Decode all masks in the 80387 control word.
180*0Sstevel@tonic-gate */
181*0Sstevel@tonic-gate if (cw & FPIM)
182*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|IM");
183*0Sstevel@tonic-gate if (cw & FPDM)
184*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|DM");
185*0Sstevel@tonic-gate if (cw & FPZM)
186*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|ZM");
187*0Sstevel@tonic-gate if (cw & FPOM)
188*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|OM");
189*0Sstevel@tonic-gate if (cw & FPUM)
190*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|UM");
191*0Sstevel@tonic-gate if (cw & FPPM)
192*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|PM");
193*0Sstevel@tonic-gate if (cw & FPPC)
194*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|PC");
195*0Sstevel@tonic-gate if (cw & FPRC)
196*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|RC");
197*0Sstevel@tonic-gate if (cw & FPIC)
198*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|IC");
199*0Sstevel@tonic-gate
200*0Sstevel@tonic-gate /*
201*0Sstevel@tonic-gate * Decode precision, rounding, and infinity options in control word.
202*0Sstevel@tonic-gate */
203*0Sstevel@tonic-gate if (cw & FPSIG24)
204*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|SIG24");
205*0Sstevel@tonic-gate if (cw & FPSIG53)
206*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|SIG53");
207*0Sstevel@tonic-gate if (cw & FPSIG64)
208*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|SIG64");
209*0Sstevel@tonic-gate
210*0Sstevel@tonic-gate if ((cw & FPRC) == (FPRD|FPRU))
211*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|RTZ");
212*0Sstevel@tonic-gate else if (cw & FPRD)
213*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|RD");
214*0Sstevel@tonic-gate else if (cw & FPRU)
215*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|RU");
216*0Sstevel@tonic-gate else
217*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|RTN");
218*0Sstevel@tonic-gate
219*0Sstevel@tonic-gate if (cw & FPA)
220*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|A");
221*0Sstevel@tonic-gate else
222*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|P");
223*0Sstevel@tonic-gate if (cw & WFPB17)
224*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|WFPB17");
225*0Sstevel@tonic-gate if (cw & WFPB24)
226*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|WFPB24");
227*0Sstevel@tonic-gate
228*0Sstevel@tonic-gate if (buf[0] == '|')
229*0Sstevel@tonic-gate return (buf + 1);
230*0Sstevel@tonic-gate
231*0Sstevel@tonic-gate return ("0");
232*0Sstevel@tonic-gate }
233*0Sstevel@tonic-gate
234*0Sstevel@tonic-gate static const char *
fpsw2str(uint32_t cw,char * buf,size_t nbytes)235*0Sstevel@tonic-gate fpsw2str(uint32_t cw, char *buf, size_t nbytes)
236*0Sstevel@tonic-gate {
237*0Sstevel@tonic-gate char *end = buf + nbytes;
238*0Sstevel@tonic-gate char *p = buf;
239*0Sstevel@tonic-gate
240*0Sstevel@tonic-gate buf[0] = '\0';
241*0Sstevel@tonic-gate
242*0Sstevel@tonic-gate /*
243*0Sstevel@tonic-gate * Decode all masks in the 80387 status word.
244*0Sstevel@tonic-gate */
245*0Sstevel@tonic-gate if (cw & FPS_IE)
246*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|IE");
247*0Sstevel@tonic-gate if (cw & FPS_DE)
248*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|DE");
249*0Sstevel@tonic-gate if (cw & FPS_ZE)
250*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|ZE");
251*0Sstevel@tonic-gate if (cw & FPS_OE)
252*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|OE");
253*0Sstevel@tonic-gate if (cw & FPS_UE)
254*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|UE");
255*0Sstevel@tonic-gate if (cw & FPS_PE)
256*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|PE");
257*0Sstevel@tonic-gate if (cw & FPS_SF)
258*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|SF");
259*0Sstevel@tonic-gate if (cw & FPS_ES)
260*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|ES");
261*0Sstevel@tonic-gate if (cw & FPS_C0)
262*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|C0");
263*0Sstevel@tonic-gate if (cw & FPS_C1)
264*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|C1");
265*0Sstevel@tonic-gate if (cw & FPS_C2)
266*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|C2");
267*0Sstevel@tonic-gate if (cw & FPS_C3)
268*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|C3");
269*0Sstevel@tonic-gate if (cw & FPS_B)
270*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|B");
271*0Sstevel@tonic-gate
272*0Sstevel@tonic-gate if (buf[0] == '|')
273*0Sstevel@tonic-gate return (buf + 1);
274*0Sstevel@tonic-gate
275*0Sstevel@tonic-gate return ("0");
276*0Sstevel@tonic-gate }
277*0Sstevel@tonic-gate
278*0Sstevel@tonic-gate static const char *
fpmxcsr2str(uint32_t mxcsr,char * buf,size_t nbytes)279*0Sstevel@tonic-gate fpmxcsr2str(uint32_t mxcsr, char *buf, size_t nbytes)
280*0Sstevel@tonic-gate {
281*0Sstevel@tonic-gate char *end = buf + nbytes;
282*0Sstevel@tonic-gate char *p = buf;
283*0Sstevel@tonic-gate
284*0Sstevel@tonic-gate buf[0] = '\0';
285*0Sstevel@tonic-gate
286*0Sstevel@tonic-gate /*
287*0Sstevel@tonic-gate * Decode the MXCSR word
288*0Sstevel@tonic-gate */
289*0Sstevel@tonic-gate if (mxcsr & SSE_IE)
290*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|IE");
291*0Sstevel@tonic-gate if (mxcsr & SSE_DE)
292*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|DE");
293*0Sstevel@tonic-gate if (mxcsr & SSE_ZE)
294*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|ZE");
295*0Sstevel@tonic-gate if (mxcsr & SSE_OE)
296*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|OE");
297*0Sstevel@tonic-gate if (mxcsr & SSE_UE)
298*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|UE");
299*0Sstevel@tonic-gate if (mxcsr & SSE_PE)
300*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|PE");
301*0Sstevel@tonic-gate
302*0Sstevel@tonic-gate if (mxcsr & SSE_DAZ)
303*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|DAZ");
304*0Sstevel@tonic-gate
305*0Sstevel@tonic-gate if (mxcsr & SSE_IM)
306*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|IM");
307*0Sstevel@tonic-gate if (mxcsr & SSE_DM)
308*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|DM");
309*0Sstevel@tonic-gate if (mxcsr & SSE_ZM)
310*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|ZM");
311*0Sstevel@tonic-gate if (mxcsr & SSE_OM)
312*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|OM");
313*0Sstevel@tonic-gate if (mxcsr & SSE_UM)
314*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|UM");
315*0Sstevel@tonic-gate if (mxcsr & SSE_PM)
316*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|PM");
317*0Sstevel@tonic-gate
318*0Sstevel@tonic-gate if ((mxcsr & SSE_RC) == (SSE_RD|SSE_RU))
319*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|RTZ");
320*0Sstevel@tonic-gate else if (mxcsr & SSE_RD)
321*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|RD");
322*0Sstevel@tonic-gate else if (mxcsr & SSE_RU)
323*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|RU");
324*0Sstevel@tonic-gate else
325*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|RTN");
326*0Sstevel@tonic-gate
327*0Sstevel@tonic-gate if (mxcsr & SSE_FZ)
328*0Sstevel@tonic-gate p += mdb_snprintf(p, (size_t)(end - p), "|FZ");
329*0Sstevel@tonic-gate
330*0Sstevel@tonic-gate if (buf[0] == '|')
331*0Sstevel@tonic-gate return (buf + 1);
332*0Sstevel@tonic-gate return ("0");
333*0Sstevel@tonic-gate }
334*0Sstevel@tonic-gate
335*0Sstevel@tonic-gate /*ARGSUSED*/
336*0Sstevel@tonic-gate int
pt_fpregs(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)337*0Sstevel@tonic-gate pt_fpregs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
338*0Sstevel@tonic-gate {
339*0Sstevel@tonic-gate mdb_tgt_t *t = mdb.m_target;
340*0Sstevel@tonic-gate mdb_tgt_tid_t tid;
341*0Sstevel@tonic-gate uint32_t hw = FP_NO;
342*0Sstevel@tonic-gate uint_t sse = 0;
343*0Sstevel@tonic-gate prfpregset_t fprs;
344*0Sstevel@tonic-gate struct _fpstate fps;
345*0Sstevel@tonic-gate char buf[256];
346*0Sstevel@tonic-gate uint_t top;
347*0Sstevel@tonic-gate int i;
348*0Sstevel@tonic-gate
349*0Sstevel@tonic-gate /*
350*0Sstevel@tonic-gate * Union for overlaying _fpreg structure on to quad-precision
351*0Sstevel@tonic-gate * floating-point value (long double).
352*0Sstevel@tonic-gate */
353*0Sstevel@tonic-gate union {
354*0Sstevel@tonic-gate struct _fpreg reg;
355*0Sstevel@tonic-gate long double ld;
356*0Sstevel@tonic-gate } fpru;
357*0Sstevel@tonic-gate
358*0Sstevel@tonic-gate /*
359*0Sstevel@tonic-gate * Array of strings corresponding to FPU tag word values (see
360*0Sstevel@tonic-gate * section 7.3.6 of the Intel Programmer's Reference Manual).
361*0Sstevel@tonic-gate */
362*0Sstevel@tonic-gate const char *tag_strings[] = { "valid", "zero", "special", "empty" };
363*0Sstevel@tonic-gate
364*0Sstevel@tonic-gate if (argc != 0)
365*0Sstevel@tonic-gate return (DCMD_USAGE);
366*0Sstevel@tonic-gate
367*0Sstevel@tonic-gate if (t->t_pshandle == NULL || Pstate(t->t_pshandle) == PS_UNDEAD) {
368*0Sstevel@tonic-gate mdb_warn("no process active\n");
369*0Sstevel@tonic-gate return (DCMD_ERR);
370*0Sstevel@tonic-gate }
371*0Sstevel@tonic-gate
372*0Sstevel@tonic-gate if (Pstate(t->t_pshandle) == PS_LOST) {
373*0Sstevel@tonic-gate mdb_warn("debugger has lost control of process\n");
374*0Sstevel@tonic-gate return (DCMD_ERR);
375*0Sstevel@tonic-gate }
376*0Sstevel@tonic-gate
377*0Sstevel@tonic-gate if (flags & DCMD_ADDRSPEC)
378*0Sstevel@tonic-gate tid = (mdb_tgt_tid_t)addr;
379*0Sstevel@tonic-gate else
380*0Sstevel@tonic-gate tid = PTL_TID(t);
381*0Sstevel@tonic-gate
382*0Sstevel@tonic-gate if (mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, &hw,
383*0Sstevel@tonic-gate sizeof (hw), "libc.so", "_fp_hw") < 0 &&
384*0Sstevel@tonic-gate mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, &hw,
385*0Sstevel@tonic-gate sizeof (hw), MDB_TGT_OBJ_EXEC, "_fp_hw") < 0)
386*0Sstevel@tonic-gate mdb_warn("failed to read _fp_hw value");
387*0Sstevel@tonic-gate
388*0Sstevel@tonic-gate if (mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, &sse,
389*0Sstevel@tonic-gate sizeof (sse), "libc.so", "_sse_hw") < 0 &&
390*0Sstevel@tonic-gate mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, &sse,
391*0Sstevel@tonic-gate sizeof (sse), MDB_TGT_OBJ_EXEC, "_sse_hw") < 0)
392*0Sstevel@tonic-gate mdb_warn("failed to read _sse_hw value");
393*0Sstevel@tonic-gate
394*0Sstevel@tonic-gate mdb_printf("_fp_hw 0x%02x (", hw);
395*0Sstevel@tonic-gate switch (hw) {
396*0Sstevel@tonic-gate case FP_SW:
397*0Sstevel@tonic-gate mdb_printf("80387 software emulator");
398*0Sstevel@tonic-gate break;
399*0Sstevel@tonic-gate case FP_287:
400*0Sstevel@tonic-gate mdb_printf("80287 chip");
401*0Sstevel@tonic-gate break;
402*0Sstevel@tonic-gate case FP_387:
403*0Sstevel@tonic-gate mdb_printf("80387 chip");
404*0Sstevel@tonic-gate break;
405*0Sstevel@tonic-gate case FP_486:
406*0Sstevel@tonic-gate mdb_printf("80486 chip");
407*0Sstevel@tonic-gate break;
408*0Sstevel@tonic-gate default:
409*0Sstevel@tonic-gate mdb_printf("no floating point support");
410*0Sstevel@tonic-gate break;
411*0Sstevel@tonic-gate }
412*0Sstevel@tonic-gate if (sse)
413*0Sstevel@tonic-gate mdb_printf(" with SSE");
414*0Sstevel@tonic-gate mdb_printf(")\n");
415*0Sstevel@tonic-gate
416*0Sstevel@tonic-gate if (!(hw & FP_HW))
417*0Sstevel@tonic-gate return (DCMD_OK); /* just abort if no hardware present */
418*0Sstevel@tonic-gate
419*0Sstevel@tonic-gate if (PTL_GETFPREGS(t, tid, &fprs) != 0) {
420*0Sstevel@tonic-gate mdb_warn("failed to get floating point registers");
421*0Sstevel@tonic-gate return (DCMD_ERR);
422*0Sstevel@tonic-gate }
423*0Sstevel@tonic-gate
424*0Sstevel@tonic-gate bcopy(&fprs.fp_reg_set.fpchip_state, &fps, sizeof (fps));
425*0Sstevel@tonic-gate
426*0Sstevel@tonic-gate fps.cw &= 0xffff; /* control word is really 16 bits */
427*0Sstevel@tonic-gate fps.sw &= 0xffff; /* status word is really 16 bits */
428*0Sstevel@tonic-gate fps.status &= 0xffff; /* saved status word is really 16 bits */
429*0Sstevel@tonic-gate fps.cssel &= 0xffff; /* %cs is really 16-bits */
430*0Sstevel@tonic-gate fps.datasel &= 0xffff; /* %ds is really 16-bits too */
431*0Sstevel@tonic-gate
432*0Sstevel@tonic-gate mdb_printf("cw 0x%04x (%s)\n", fps.cw,
433*0Sstevel@tonic-gate fpcw2str(fps.cw, buf, sizeof (buf)));
434*0Sstevel@tonic-gate
435*0Sstevel@tonic-gate top = (fps.sw & FPS_TOP) >> 11;
436*0Sstevel@tonic-gate mdb_printf("sw 0x%04x (TOP=0t%u) (%s)\n", fps.sw,
437*0Sstevel@tonic-gate top, fpsw2str(fps.sw, buf, sizeof (buf)));
438*0Sstevel@tonic-gate
439*0Sstevel@tonic-gate mdb_printf("xcp sw 0x%04x (%s)\n\n", fps.status,
440*0Sstevel@tonic-gate fpsw2str(fps.status, buf, sizeof (buf)));
441*0Sstevel@tonic-gate
442*0Sstevel@tonic-gate mdb_printf("ipoff %a\n", fps.ipoff);
443*0Sstevel@tonic-gate mdb_printf("cssel 0x%x\n", fps.cssel);
444*0Sstevel@tonic-gate mdb_printf("dtoff %a\n", fps.dataoff);
445*0Sstevel@tonic-gate mdb_printf("dtsel 0x%x\n\n", fps.datasel);
446*0Sstevel@tonic-gate
447*0Sstevel@tonic-gate for (i = 0; i < 8; i++) {
448*0Sstevel@tonic-gate /*
449*0Sstevel@tonic-gate * Recall that we need to use the current TOP-of-stack value to
450*0Sstevel@tonic-gate * associate the _st[] index back to a physical register number,
451*0Sstevel@tonic-gate * since tag word indices are physical register numbers. Then
452*0Sstevel@tonic-gate * to get the tag value, we shift over two bits for each tag
453*0Sstevel@tonic-gate * index, and then grab the bottom two bits.
454*0Sstevel@tonic-gate */
455*0Sstevel@tonic-gate uint_t tag_index = (i + top) & 7;
456*0Sstevel@tonic-gate uint_t tag_value = (fps.tag >> (tag_index * 2)) & 3;
457*0Sstevel@tonic-gate
458*0Sstevel@tonic-gate fpru.reg = fps._st[i];
459*0Sstevel@tonic-gate mdb_printf("%%st%d 0x%04x.%04x%04x%04x%04x = %lg %s\n",
460*0Sstevel@tonic-gate i, fpru.reg.exponent,
461*0Sstevel@tonic-gate fpru.reg.significand[3], fpru.reg.significand[2],
462*0Sstevel@tonic-gate fpru.reg.significand[1], fpru.reg.significand[0],
463*0Sstevel@tonic-gate fpru.ld, tag_strings[tag_value]);
464*0Sstevel@tonic-gate }
465*0Sstevel@tonic-gate
466*0Sstevel@tonic-gate if (!sse)
467*0Sstevel@tonic-gate return (DCMD_OK);
468*0Sstevel@tonic-gate
469*0Sstevel@tonic-gate mdb_printf("\nmxcsr 0x%04x (%s)\n", fps.mxcsr,
470*0Sstevel@tonic-gate fpmxcsr2str(fps.mxcsr, buf, sizeof (buf)));
471*0Sstevel@tonic-gate mdb_printf("xcp 0x%04x (%s)\n\n", fps.xstatus,
472*0Sstevel@tonic-gate fpmxcsr2str(fps.xstatus, buf, sizeof (buf)));
473*0Sstevel@tonic-gate
474*0Sstevel@tonic-gate for (i = 0; i < 8; i++)
475*0Sstevel@tonic-gate mdb_printf("%%xmm%d 0x%08x%08x%08x%08x\n", i,
476*0Sstevel@tonic-gate fps.xmm[i][3], fps.xmm[i][2],
477*0Sstevel@tonic-gate fps.xmm[i][1], fps.xmm[i][0]);
478*0Sstevel@tonic-gate
479*0Sstevel@tonic-gate return (DCMD_OK);
480*0Sstevel@tonic-gate }
481*0Sstevel@tonic-gate
482*0Sstevel@tonic-gate /*ARGSUSED*/
483*0Sstevel@tonic-gate int
pt_getfpreg(mdb_tgt_t * t,mdb_tgt_tid_t tid,ushort_t rd_num,ushort_t rd_flags,mdb_tgt_reg_t * rp)484*0Sstevel@tonic-gate pt_getfpreg(mdb_tgt_t *t, mdb_tgt_tid_t tid, ushort_t rd_num,
485*0Sstevel@tonic-gate ushort_t rd_flags, mdb_tgt_reg_t *rp)
486*0Sstevel@tonic-gate {
487*0Sstevel@tonic-gate return (set_errno(ENOTSUP));
488*0Sstevel@tonic-gate }
489*0Sstevel@tonic-gate
490*0Sstevel@tonic-gate /*ARGSUSED*/
491*0Sstevel@tonic-gate int
pt_putfpreg(mdb_tgt_t * t,mdb_tgt_tid_t tid,ushort_t rd_num,ushort_t rd_flags,mdb_tgt_reg_t rval)492*0Sstevel@tonic-gate pt_putfpreg(mdb_tgt_t *t, mdb_tgt_tid_t tid, ushort_t rd_num,
493*0Sstevel@tonic-gate ushort_t rd_flags, mdb_tgt_reg_t rval)
494*0Sstevel@tonic-gate {
495*0Sstevel@tonic-gate return (set_errno(ENOTSUP));
496*0Sstevel@tonic-gate }
497*0Sstevel@tonic-gate
498*0Sstevel@tonic-gate /*ARGSUSED*/
499*0Sstevel@tonic-gate void
pt_addfpregs(mdb_tgt_t * t)500*0Sstevel@tonic-gate pt_addfpregs(mdb_tgt_t *t)
501*0Sstevel@tonic-gate {
502*0Sstevel@tonic-gate /* not implemented */
503*0Sstevel@tonic-gate }
504*0Sstevel@tonic-gate
505*0Sstevel@tonic-gate /*ARGSUSED*/
506*0Sstevel@tonic-gate int
pt_frameregs(void * arglim,uintptr_t pc,uint_t argc,const long * argv,const mdb_tgt_gregset_t * gregs,boolean_t pc_faked)507*0Sstevel@tonic-gate pt_frameregs(void *arglim, uintptr_t pc, uint_t argc, const long *argv,
508*0Sstevel@tonic-gate const mdb_tgt_gregset_t *gregs, boolean_t pc_faked)
509*0Sstevel@tonic-gate {
510*0Sstevel@tonic-gate return (set_errno(ENOTSUP));
511*0Sstevel@tonic-gate }
512*0Sstevel@tonic-gate
513*0Sstevel@tonic-gate /*ARGSUSED*/
514*0Sstevel@tonic-gate const char *
pt_disasm(const GElf_Ehdr * ehp)515*0Sstevel@tonic-gate pt_disasm(const GElf_Ehdr *ehp)
516*0Sstevel@tonic-gate {
517*0Sstevel@tonic-gate return ("ia32");
518*0Sstevel@tonic-gate }
519*0Sstevel@tonic-gate
520*0Sstevel@tonic-gate /*
521*0Sstevel@tonic-gate * Determine the return address for the current frame.
522*0Sstevel@tonic-gate */
523*0Sstevel@tonic-gate int
pt_step_out(mdb_tgt_t * t,uintptr_t * p)524*0Sstevel@tonic-gate pt_step_out(mdb_tgt_t *t, uintptr_t *p)
525*0Sstevel@tonic-gate {
526*0Sstevel@tonic-gate const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp;
527*0Sstevel@tonic-gate
528*0Sstevel@tonic-gate if (Pstate(t->t_pshandle) != PS_STOP)
529*0Sstevel@tonic-gate return (set_errno(EMDB_TGTBUSY));
530*0Sstevel@tonic-gate
531*0Sstevel@tonic-gate return (mdb_ia32_step_out(t, p, psp->pr_reg[EIP], psp->pr_reg[EBP],
532*0Sstevel@tonic-gate psp->pr_reg[UESP], pt_read_instr(t)));
533*0Sstevel@tonic-gate }
534*0Sstevel@tonic-gate
535*0Sstevel@tonic-gate /*
536*0Sstevel@tonic-gate * Return the address of the next instruction following a call, or return -1
537*0Sstevel@tonic-gate * and set errno to EAGAIN if the target should just single-step.
538*0Sstevel@tonic-gate */
539*0Sstevel@tonic-gate int
pt_next(mdb_tgt_t * t,uintptr_t * p)540*0Sstevel@tonic-gate pt_next(mdb_tgt_t *t, uintptr_t *p)
541*0Sstevel@tonic-gate {
542*0Sstevel@tonic-gate const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp;
543*0Sstevel@tonic-gate
544*0Sstevel@tonic-gate if (Pstate(t->t_pshandle) != PS_STOP)
545*0Sstevel@tonic-gate return (set_errno(EMDB_TGTBUSY));
546*0Sstevel@tonic-gate
547*0Sstevel@tonic-gate return (mdb_ia32_next(t, p, psp->pr_reg[EIP], pt_read_instr(t)));
548*0Sstevel@tonic-gate }
549