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