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