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 (c) 2018, 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 & FPSIG53) 254 p += mdb_snprintf(p, (size_t)(end - p), "|SIG53"); 255 if (cw & FPSIG64) 256 p += mdb_snprintf(p, (size_t)(end - p), "|SIG64"); 257 258 if ((cw & FPRC) == (FPRD|FPRU)) 259 p += mdb_snprintf(p, (size_t)(end - p), "|RTZ"); 260 else if (cw & FPRD) 261 p += mdb_snprintf(p, (size_t)(end - p), "|RD"); 262 else if (cw & FPRU) 263 p += mdb_snprintf(p, (size_t)(end - p), "|RU"); 264 else 265 p += mdb_snprintf(p, (size_t)(end - p), "|RTN"); 266 267 if (cw & FPA) 268 p += mdb_snprintf(p, (size_t)(end - p), "|A"); 269 else 270 p += mdb_snprintf(p, (size_t)(end - p), "|P"); 271 if (cw & WFPB17) 272 p += mdb_snprintf(p, (size_t)(end - p), "|WFPB17"); 273 if (cw & WFPB24) 274 p += mdb_snprintf(p, (size_t)(end - p), "|WFPB24"); 275 276 if (buf[0] == '|') 277 return (buf + 1); 278 279 return ("0"); 280 } 281 282 static const char * 283 fpsw2str(uint32_t cw, char *buf, size_t nbytes) 284 { 285 char *end = buf + nbytes; 286 char *p = buf; 287 288 buf[0] = '\0'; 289 290 /* 291 * Decode all masks in the 80387 status word. 292 */ 293 if (cw & FPS_IE) 294 p += mdb_snprintf(p, (size_t)(end - p), "|IE"); 295 if (cw & FPS_DE) 296 p += mdb_snprintf(p, (size_t)(end - p), "|DE"); 297 if (cw & FPS_ZE) 298 p += mdb_snprintf(p, (size_t)(end - p), "|ZE"); 299 if (cw & FPS_OE) 300 p += mdb_snprintf(p, (size_t)(end - p), "|OE"); 301 if (cw & FPS_UE) 302 p += mdb_snprintf(p, (size_t)(end - p), "|UE"); 303 if (cw & FPS_PE) 304 p += mdb_snprintf(p, (size_t)(end - p), "|PE"); 305 if (cw & FPS_SF) 306 p += mdb_snprintf(p, (size_t)(end - p), "|SF"); 307 if (cw & FPS_ES) 308 p += mdb_snprintf(p, (size_t)(end - p), "|ES"); 309 if (cw & FPS_C0) 310 p += mdb_snprintf(p, (size_t)(end - p), "|C0"); 311 if (cw & FPS_C1) 312 p += mdb_snprintf(p, (size_t)(end - p), "|C1"); 313 if (cw & FPS_C2) 314 p += mdb_snprintf(p, (size_t)(end - p), "|C2"); 315 if (cw & FPS_C3) 316 p += mdb_snprintf(p, (size_t)(end - p), "|C3"); 317 if (cw & FPS_B) 318 p += mdb_snprintf(p, (size_t)(end - p), "|B"); 319 320 if (buf[0] == '|') 321 return (buf + 1); 322 323 return ("0"); 324 } 325 326 static const char * 327 fpmxcsr2str(uint32_t mxcsr, char *buf, size_t nbytes) 328 { 329 char *end = buf + nbytes; 330 char *p = buf; 331 332 buf[0] = '\0'; 333 334 /* 335 * Decode the MXCSR word 336 */ 337 if (mxcsr & SSE_IE) 338 p += mdb_snprintf(p, (size_t)(end - p), "|IE"); 339 if (mxcsr & SSE_DE) 340 p += mdb_snprintf(p, (size_t)(end - p), "|DE"); 341 if (mxcsr & SSE_ZE) 342 p += mdb_snprintf(p, (size_t)(end - p), "|ZE"); 343 if (mxcsr & SSE_OE) 344 p += mdb_snprintf(p, (size_t)(end - p), "|OE"); 345 if (mxcsr & SSE_UE) 346 p += mdb_snprintf(p, (size_t)(end - p), "|UE"); 347 if (mxcsr & SSE_PE) 348 p += mdb_snprintf(p, (size_t)(end - p), "|PE"); 349 350 if (mxcsr & SSE_DAZ) 351 p += mdb_snprintf(p, (size_t)(end - p), "|DAZ"); 352 353 if (mxcsr & SSE_IM) 354 p += mdb_snprintf(p, (size_t)(end - p), "|IM"); 355 if (mxcsr & SSE_DM) 356 p += mdb_snprintf(p, (size_t)(end - p), "|DM"); 357 if (mxcsr & SSE_ZM) 358 p += mdb_snprintf(p, (size_t)(end - p), "|ZM"); 359 if (mxcsr & SSE_OM) 360 p += mdb_snprintf(p, (size_t)(end - p), "|OM"); 361 if (mxcsr & SSE_UM) 362 p += mdb_snprintf(p, (size_t)(end - p), "|UM"); 363 if (mxcsr & SSE_PM) 364 p += mdb_snprintf(p, (size_t)(end - p), "|PM"); 365 366 if ((mxcsr & SSE_RC) == (SSE_RD|SSE_RU)) 367 p += mdb_snprintf(p, (size_t)(end - p), "|RTZ"); 368 else if (mxcsr & SSE_RD) 369 p += mdb_snprintf(p, (size_t)(end - p), "|RD"); 370 else if (mxcsr & SSE_RU) 371 p += mdb_snprintf(p, (size_t)(end - p), "|RU"); 372 else 373 p += mdb_snprintf(p, (size_t)(end - p), "|RTN"); 374 375 if (mxcsr & SSE_FZ) 376 p += mdb_snprintf(p, (size_t)(end - p), "|FZ"); 377 378 if (buf[0] == '|') 379 return (buf + 1); 380 return ("0"); 381 } 382 383 /*ARGSUSED*/ 384 int 385 pt_fpregs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 386 { 387 mdb_tgt_t *t = mdb.m_target; 388 mdb_tgt_tid_t tid; 389 uint32_t hw = FP_NO; 390 uint_t sse = 0; 391 prfpregset_t fprs; 392 struct _fpstate fps; 393 char buf[256]; 394 uint_t top; 395 int i; 396 397 /* 398 * Union for overlaying _fpreg structure on to quad-precision 399 * floating-point value (long double). 400 */ 401 union { 402 struct _fpreg reg; 403 long double ld; 404 } fpru; 405 406 /* 407 * Array of strings corresponding to FPU tag word values (see 408 * section 7.3.6 of the Intel Programmer's Reference Manual). 409 */ 410 const char *tag_strings[] = { "valid", "zero", "special", "empty" }; 411 412 if (argc != 0) 413 return (DCMD_USAGE); 414 415 if (t->t_pshandle == NULL || Pstate(t->t_pshandle) == PS_UNDEAD) { 416 mdb_warn("no process active\n"); 417 return (DCMD_ERR); 418 } 419 420 if (Pstate(t->t_pshandle) == PS_LOST) { 421 mdb_warn("debugger has lost control of process\n"); 422 return (DCMD_ERR); 423 } 424 425 if (flags & DCMD_ADDRSPEC) 426 tid = (mdb_tgt_tid_t)addr; 427 else 428 tid = PTL_TID(t); 429 430 if (mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, &hw, 431 sizeof (hw), "libc.so", "_fp_hw") < 0 && 432 mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, &hw, 433 sizeof (hw), MDB_TGT_OBJ_EXEC, "_fp_hw") < 0) 434 mdb_warn("failed to read _fp_hw value"); 435 436 if (mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, &sse, 437 sizeof (sse), "libc.so", "_sse_hw") < 0 && 438 mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, &sse, 439 sizeof (sse), MDB_TGT_OBJ_EXEC, "_sse_hw") < 0) 440 mdb_warn("failed to read _sse_hw value"); 441 442 mdb_printf("_fp_hw 0x%02x (", hw); 443 switch (hw) { 444 case FP_SW: 445 mdb_printf("80387 software emulator"); 446 break; 447 case FP_287: 448 mdb_printf("80287 chip"); 449 break; 450 case FP_387: 451 mdb_printf("80387 chip"); 452 break; 453 case FP_486: 454 mdb_printf("80486 chip"); 455 break; 456 default: 457 mdb_printf("no floating point support"); 458 break; 459 } 460 if (sse) 461 mdb_printf(" with SSE"); 462 mdb_printf(")\n"); 463 464 if (!(hw & FP_HW)) 465 return (DCMD_OK); /* just abort if no hardware present */ 466 467 if (PTL_GETFPREGS(t, tid, &fprs) != 0) { 468 mdb_warn("failed to get floating point registers"); 469 return (DCMD_ERR); 470 } 471 472 bcopy(&fprs.fp_reg_set.fpchip_state, &fps, sizeof (fps)); 473 474 fps.cw &= 0xffff; /* control word is really 16 bits */ 475 fps.sw &= 0xffff; /* status word is really 16 bits */ 476 fps.status &= 0xffff; /* saved status word is really 16 bits */ 477 fps.cssel &= 0xffff; /* %cs is really 16-bits */ 478 fps.datasel &= 0xffff; /* %ds is really 16-bits too */ 479 480 mdb_printf("cw 0x%04x (%s)\n", fps.cw, 481 fpcw2str(fps.cw, buf, sizeof (buf))); 482 483 top = (fps.sw & FPS_TOP) >> 11; 484 mdb_printf("sw 0x%04x (TOP=0t%u) (%s)\n", fps.sw, 485 top, fpsw2str(fps.sw, buf, sizeof (buf))); 486 487 mdb_printf("xcp sw 0x%04x (%s)\n\n", fps.status, 488 fpsw2str(fps.status, buf, sizeof (buf))); 489 490 mdb_printf("ipoff %a\n", fps.ipoff); 491 mdb_printf("cssel 0x%x\n", fps.cssel); 492 mdb_printf("dtoff %a\n", fps.dataoff); 493 mdb_printf("dtsel 0x%x\n\n", fps.datasel); 494 495 for (i = 0; i < 8; i++) { 496 /* 497 * Recall that we need to use the current TOP-of-stack value to 498 * associate the _st[] index back to a physical register number, 499 * since tag word indices are physical register numbers. Then 500 * to get the tag value, we shift over two bits for each tag 501 * index, and then grab the bottom two bits. 502 */ 503 uint_t tag_index = (i + top) & 7; 504 uint_t tag_value = (fps.tag >> (tag_index * 2)) & 3; 505 506 fpru.reg = fps._st[i]; 507 mdb_printf("%%st%d 0x%04x.%04x%04x%04x%04x = %lg %s\n", 508 i, fpru.reg.exponent, 509 fpru.reg.significand[3], fpru.reg.significand[2], 510 fpru.reg.significand[1], fpru.reg.significand[0], 511 fpru.ld, tag_strings[tag_value]); 512 } 513 514 if (!sse) 515 return (DCMD_OK); 516 517 mdb_printf("\nmxcsr 0x%04x (%s)\n", fps.mxcsr, 518 fpmxcsr2str(fps.mxcsr, buf, sizeof (buf))); 519 mdb_printf("xcp 0x%04x (%s)\n\n", fps.xstatus, 520 fpmxcsr2str(fps.xstatus, buf, sizeof (buf))); 521 522 for (i = 0; i < 8; i++) 523 mdb_printf("%%xmm%d 0x%08x%08x%08x%08x\n", i, 524 fps.xmm[i][3], fps.xmm[i][2], 525 fps.xmm[i][1], fps.xmm[i][0]); 526 527 return (DCMD_OK); 528 } 529 530 /*ARGSUSED*/ 531 int 532 pt_getfpreg(mdb_tgt_t *t, mdb_tgt_tid_t tid, ushort_t rd_num, 533 ushort_t rd_flags, mdb_tgt_reg_t *rp) 534 { 535 return (set_errno(ENOTSUP)); 536 } 537 538 /*ARGSUSED*/ 539 int 540 pt_putfpreg(mdb_tgt_t *t, mdb_tgt_tid_t tid, ushort_t rd_num, 541 ushort_t rd_flags, mdb_tgt_reg_t rval) 542 { 543 return (set_errno(ENOTSUP)); 544 } 545 546 /*ARGSUSED*/ 547 void 548 pt_addfpregs(mdb_tgt_t *t) 549 { 550 /* not implemented */ 551 } 552 553 /*ARGSUSED*/ 554 int 555 pt_frameregs(void *arglim, uintptr_t pc, uint_t argc, const long *argv, 556 const mdb_tgt_gregset_t *gregs, boolean_t pc_faked) 557 { 558 return (set_errno(ENOTSUP)); 559 } 560 561 /*ARGSUSED*/ 562 const char * 563 pt_disasm(const GElf_Ehdr *ehp) 564 { 565 return ("ia32"); 566 } 567 568 /* 569 * Determine the return address for the current frame. 570 */ 571 int 572 pt_step_out(mdb_tgt_t *t, uintptr_t *p) 573 { 574 const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp; 575 576 if (Pstate(t->t_pshandle) != PS_STOP) 577 return (set_errno(EMDB_TGTBUSY)); 578 579 return (mdb_ia32_step_out(t, p, psp->pr_reg[EIP], psp->pr_reg[EBP], 580 psp->pr_reg[UESP], pt_read_instr(t))); 581 } 582 583 /* 584 * Return the address of the next instruction following a call, or return -1 585 * and set errno to EAGAIN if the target should just single-step. 586 */ 587 int 588 pt_next(mdb_tgt_t *t, uintptr_t *p) 589 { 590 const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp; 591 592 if (Pstate(t->t_pshandle) != PS_STOP) 593 return (set_errno(EMDB_TGTBUSY)); 594 595 return (mdb_ia32_next(t, p, psp->pr_reg[EIP], pt_read_instr(t))); 596 } 597