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