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 2005 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 SPARC v7 and v9 component 31 * 32 * This file provides the ISA-dependent portion of the user process target 33 * for both the sparcv7 and sparcv9 ISAs. For more details on the 34 * implementation refer to mdb_proc.c. 35 */ 36 37 #ifdef __sparcv9 38 #define __sparcv9cpu 39 #endif 40 41 #include <mdb/mdb_proc.h> 42 #include <mdb/mdb_kreg.h> 43 #include <mdb/mdb_err.h> 44 #include <mdb/mdb_stdlib.h> 45 #include <mdb/mdb.h> 46 47 #include <sys/elf_SPARC.h> 48 #include <sys/stack.h> 49 #include <libproc.h> 50 51 #ifndef STACK_BIAS 52 #define STACK_BIAS 0 53 #endif 54 55 const mdb_tgt_regdesc_t pt_regdesc[] = { 56 { "g0", R_G0, MDB_TGT_R_EXPORT }, 57 { "g1", R_G1, MDB_TGT_R_EXPORT }, 58 { "g2", R_G2, MDB_TGT_R_EXPORT }, 59 { "g3", R_G3, MDB_TGT_R_EXPORT }, 60 { "g4", R_G4, MDB_TGT_R_EXPORT }, 61 { "g5", R_G5, MDB_TGT_R_EXPORT }, 62 { "g6", R_G6, MDB_TGT_R_EXPORT }, 63 { "g7", R_G7, MDB_TGT_R_EXPORT }, 64 { "o0", R_O0, MDB_TGT_R_EXPORT }, 65 { "o1", R_O1, MDB_TGT_R_EXPORT }, 66 { "o2", R_O2, MDB_TGT_R_EXPORT }, 67 { "o3", R_O3, MDB_TGT_R_EXPORT }, 68 { "o4", R_O4, MDB_TGT_R_EXPORT }, 69 { "o5", R_O5, MDB_TGT_R_EXPORT }, 70 { "o6", R_O6, MDB_TGT_R_EXPORT }, 71 { "o7", R_O7, MDB_TGT_R_EXPORT }, 72 { "l0", R_L0, MDB_TGT_R_EXPORT }, 73 { "l1", R_L1, MDB_TGT_R_EXPORT }, 74 { "l2", R_L2, MDB_TGT_R_EXPORT }, 75 { "l3", R_L3, MDB_TGT_R_EXPORT }, 76 { "l4", R_L4, MDB_TGT_R_EXPORT }, 77 { "l5", R_L5, MDB_TGT_R_EXPORT }, 78 { "l6", R_L6, MDB_TGT_R_EXPORT }, 79 { "l7", R_L7, MDB_TGT_R_EXPORT }, 80 { "i0", R_I0, MDB_TGT_R_EXPORT }, 81 { "i1", R_I1, MDB_TGT_R_EXPORT }, 82 { "i2", R_I2, MDB_TGT_R_EXPORT }, 83 { "i3", R_I3, MDB_TGT_R_EXPORT }, 84 { "i4", R_I4, MDB_TGT_R_EXPORT }, 85 { "i5", R_I5, MDB_TGT_R_EXPORT }, 86 { "i6", R_I6, MDB_TGT_R_EXPORT }, 87 { "i7", R_I7, MDB_TGT_R_EXPORT }, 88 #ifdef __sparcv9 89 { "ccr", R_CCR, MDB_TGT_R_EXPORT }, 90 #else 91 { "psr", R_PSR, MDB_TGT_R_EXPORT }, 92 #endif 93 { "pc", R_PC, MDB_TGT_R_EXPORT }, 94 { "npc", R_nPC, MDB_TGT_R_EXPORT }, 95 { "y", R_Y, 0 }, 96 #ifdef __sparcv9 97 { "asi", R_ASI, MDB_TGT_R_EXPORT }, 98 { "fprs", R_FPRS, MDB_TGT_R_EXPORT }, 99 #else 100 { "wim", R_WIM, MDB_TGT_R_EXPORT | MDB_TGT_R_PRIV }, 101 { "tbr", R_TBR, MDB_TGT_R_EXPORT | MDB_TGT_R_PRIV }, 102 #endif 103 { "sp", R_SP, MDB_TGT_R_EXPORT | MDB_TGT_R_ALIAS }, 104 { "fp", R_FP, MDB_TGT_R_EXPORT | MDB_TGT_R_ALIAS }, 105 { NULL, 0, 0 } 106 }; 107 108 #define FPU_FSR 0 /* fake register number for %fsr */ 109 #define FPU_FPRS 1 /* fake register number for %fprs */ 110 111 /* 112 * We cannot rely on pr_instr, because if we hit a breakpoint or the user has 113 * artifically modified memory, it will no longer be correct. 114 */ 115 static uint32_t 116 pt_read_instr(mdb_tgt_t *t) 117 { 118 const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp; 119 uint32_t ret = 0; 120 121 (void) mdb_tgt_vread(t, &ret, sizeof (ret), psp->pr_reg[R_PC]); 122 123 return (ret); 124 } 125 126 /*ARGSUSED*/ 127 int 128 pt_regs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 129 { 130 mdb_tgt_t *t = mdb.m_target; 131 mdb_tgt_tid_t tid; 132 prgregset_t grs; 133 uint64_t xgregs[8]; 134 uint64_t xoregs[8]; 135 int rwidth, i; 136 137 #if defined(__sparc) && defined(_ILP32) 138 static const uint32_t zero[8] = { 0 }; 139 prxregset_t xrs; 140 #endif 141 142 #define GETREG2(x) ((uintptr_t)grs[(x)]), ((uintptr_t)grs[(x)]) 143 144 if (argc != 0) 145 return (DCMD_USAGE); 146 147 if (t->t_pshandle == NULL || Pstate(t->t_pshandle) == PS_UNDEAD) { 148 mdb_warn("no process active\n"); 149 return (DCMD_ERR); 150 } 151 152 if (Pstate(t->t_pshandle) == PS_LOST) { 153 mdb_warn("debugger has lost control of process\n"); 154 return (DCMD_ERR); 155 } 156 157 if (flags & DCMD_ADDRSPEC) 158 tid = (mdb_tgt_tid_t)addr; 159 else 160 tid = PTL_TID(t); 161 162 if (PTL_GETREGS(t, tid, grs) != 0) { 163 mdb_warn("failed to get current register set"); 164 return (DCMD_ERR); 165 } 166 167 for (i = 0; i < 8; i++) { 168 xgregs[i] = (ulong_t)grs[R_G0 + i]; 169 xoregs[i] = (ulong_t)grs[R_O0 + i]; 170 } 171 172 if (Pstatus(t->t_pshandle)->pr_dmodel == PR_MODEL_LP64) 173 rwidth = 16; 174 else 175 rwidth = 8; 176 177 #if defined(__sparc) && defined(_ILP32) 178 /* 179 * If we are debugging a 32-bit SPARC process on an UltraSPARC CPU, 180 * the globals and outs can have 32 upper bits hiding in the xregs. 181 */ 182 if (PTL_GETXREGS(t, tid, &xrs) == 0 && xrs.pr_type == XR_TYPE_V8P) { 183 for (i = 0; i < 8; i++) { 184 xgregs[i] |= (uint64_t) 185 xrs.pr_un.pr_v8p.pr_xg[XR_G0 + i] << 32; 186 xoregs[i] |= (uint64_t) 187 xrs.pr_un.pr_v8p.pr_xo[XR_O0 + i] << 32; 188 } 189 190 if (bcmp(xrs.pr_un.pr_v8p.pr_xg, zero, sizeof (zero)) || 191 bcmp(xrs.pr_un.pr_v8p.pr_xo, zero, sizeof (zero))) 192 rwidth = 16; /* one or more have upper bits set */ 193 } 194 #endif /* __sparc && _ILP32 */ 195 196 for (i = 0; i < 8; i++) { 197 mdb_printf("%%g%d = 0x%0*llx %15llA %%l%d = 0x%0?p %A\n", 198 i, rwidth, xgregs[i], xgregs[i], i, GETREG2(R_L0 + i)); 199 } 200 201 for (i = 0; i < 8; i++) { 202 mdb_printf("%%o%d = 0x%0*llx %15llA %%i%d = 0x%0?p %A\n", 203 i, rwidth, xoregs[i], xoregs[i], i, GETREG2(R_I0 + i)); 204 } 205 206 mdb_printf("\n"); 207 208 #ifdef __sparcv9 209 mdb_printf(" %%ccr = 0x%02x xcc=%c%c%c%c icc=%c%c%c%c\n", grs[R_CCR], 210 (grs[R_CCR] & KREG_CCR_XCC_N_MASK) ? 'N' : 'n', 211 (grs[R_CCR] & KREG_CCR_XCC_Z_MASK) ? 'Z' : 'z', 212 (grs[R_CCR] & KREG_CCR_XCC_V_MASK) ? 'V' : 'v', 213 (grs[R_CCR] & KREG_CCR_XCC_C_MASK) ? 'C' : 'c', 214 (grs[R_CCR] & KREG_CCR_ICC_N_MASK) ? 'N' : 'n', 215 (grs[R_CCR] & KREG_CCR_ICC_Z_MASK) ? 'Z' : 'z', 216 (grs[R_CCR] & KREG_CCR_ICC_V_MASK) ? 'V' : 'v', 217 (grs[R_CCR] & KREG_CCR_ICC_C_MASK) ? 'C' : 'c'); 218 #else /* __sparcv9 */ 219 mdb_printf(" %%psr = 0x%08x impl=0x%x ver=0x%x icc=%c%c%c%c\n" 220 " ec=%u ef=%u pil=%u s=%u ps=%u et=%u cwp=0x%x\n", 221 grs[R_PSR], 222 (grs[R_PSR] & KREG_PSR_IMPL_MASK) >> KREG_PSR_IMPL_SHIFT, 223 (grs[R_PSR] & KREG_PSR_VER_MASK) >> KREG_PSR_VER_SHIFT, 224 (grs[R_PSR] & KREG_PSR_ICC_N_MASK) ? 'N' : 'n', 225 (grs[R_PSR] & KREG_PSR_ICC_Z_MASK) ? 'Z' : 'z', 226 (grs[R_PSR] & KREG_PSR_ICC_V_MASK) ? 'V' : 'v', 227 (grs[R_PSR] & KREG_PSR_ICC_C_MASK) ? 'C' : 'c', 228 grs[R_PSR] & KREG_PSR_EC_MASK, grs[R_PSR] & KREG_PSR_EF_MASK, 229 (grs[R_PSR] & KREG_PSR_PIL_MASK) >> KREG_PSR_PIL_SHIFT, 230 grs[R_PSR] & KREG_PSR_S_MASK, grs[R_PSR] & KREG_PSR_PS_MASK, 231 grs[R_PSR] & KREG_PSR_ET_MASK, 232 (grs[R_PSR] & KREG_PSR_CWP_MASK) >> KREG_PSR_CWP_SHIFT); 233 #endif /* __sparcv9 */ 234 235 mdb_printf(" %%y = 0x%0?p\n", grs[R_Y]); 236 237 mdb_printf(" %%pc = 0x%0?p %A\n", GETREG2(R_PC)); 238 mdb_printf(" %%npc = 0x%0?p %A\n", GETREG2(R_nPC)); 239 240 mdb_printf(" %%sp = 0x%0?p\n", grs[R_SP]); 241 mdb_printf(" %%fp = 0x%0?p\n\n", grs[R_FP]); 242 243 #ifdef __sparcv9 244 mdb_printf(" %%asi = 0x%02lx\n", grs[R_ASI]); 245 mdb_printf("%%fprs = 0x%02lx\n", grs[R_FPRS]); 246 #else /* __sparcv9 */ 247 mdb_printf(" %%wim = 0x%08x\n", grs[R_WIM]); 248 mdb_printf(" %%tbr = 0x%08x\n", grs[R_TBR]); 249 #endif /* __sparcv9 */ 250 251 return (DCMD_OK); 252 } 253 254 /*ARGSUSED*/ 255 int 256 pt_fpregs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 257 { 258 mdb_tgt_t *t = mdb.m_target; 259 mdb_tgt_tid_t tid; 260 int is_v8plus, is_v9, i; 261 #ifdef __sparcv9 262 prgregset_t grs; 263 #endif 264 prfpregset_t fprs; 265 prxregset_t xrs; 266 uint32_t *regs; 267 int ns, nd, nq; 268 269 enum { 270 FPR_MIXED = 0x0, /* show single, double, and status */ 271 FPR_SINGLE = 0x1, /* show single-precision only */ 272 FPR_DOUBLE = 0x2, /* show double-precision only */ 273 FPR_QUAD = 0x4 /* show quad-precision only */ 274 }; 275 276 uint_t opts = FPR_MIXED; 277 278 /* 279 * The prfpregset structure only provides us with the FPU in the form 280 * of 32-bit integers, doubles, or quads. We use this union of the 281 * various types to display floats, doubles, and long doubles. 282 */ 283 union { 284 struct { 285 uint32_t i1; 286 uint32_t i2; 287 uint32_t i3; 288 uint32_t i4; 289 } ip; 290 float f; 291 double d; 292 long double ld; 293 } fpu; 294 295 if (mdb_getopts(argc, argv, 296 's', MDB_OPT_SETBITS, FPR_SINGLE, &opts, 297 'd', MDB_OPT_SETBITS, FPR_DOUBLE, &opts, 298 'q', MDB_OPT_SETBITS, FPR_QUAD, &opts, NULL) != argc) 299 return (DCMD_USAGE); 300 301 if (t->t_pshandle == NULL || Pstate(t->t_pshandle) == PS_UNDEAD) { 302 mdb_warn("no process active\n"); 303 return (DCMD_ERR); 304 } 305 306 if (Pstate(t->t_pshandle) == PS_LOST) { 307 mdb_warn("debugger has lost control of process\n"); 308 return (DCMD_ERR); 309 } 310 311 if (flags & DCMD_ADDRSPEC) 312 tid = (mdb_tgt_tid_t)addr; 313 else 314 tid = PTL_TID(t); 315 316 is_v9 = Pstatus(t->t_pshandle)->pr_dmodel == PR_MODEL_LP64; 317 is_v8plus = is_v9 == 0 && PTL_GETXREGS(t, tid, &xrs) == 0 && 318 xrs.pr_type == XR_TYPE_V8P; 319 320 #ifdef __sparcv9 321 if (is_v9 && opts == FPR_MIXED) { 322 if (PTL_GETREGS(t, tid, grs) == 0) 323 mdb_printf("fprs %lx\n", grs[R_FPRS]); 324 else 325 mdb_warn("failed to read fprs register"); 326 } 327 #endif 328 if (is_v8plus && opts == FPR_MIXED) 329 mdb_printf("fprs %x\n", xrs.pr_un.pr_v8p.pr_fprs); 330 331 if (PTL_GETFPREGS(t, tid, &fprs) != 0) { 332 mdb_warn("failed to get floating point registers"); 333 return (DCMD_ERR); 334 } 335 336 if (opts == FPR_MIXED) { 337 uint64_t fsr = fprs.pr_fsr; 338 if (is_v8plus) 339 fsr |= (uint64_t)xrs.pr_un.pr_v8p.pr_xfsr << 32; 340 mdb_printf("fsr %llx\n", fsr); 341 } 342 343 /* 344 * Set up the regs pointer to be a pointer to a contiguous chunk of 345 * memory containing all the floating pointer register data. Set 346 * ns, nd, and nq to indicate the number of registers of each type. 347 */ 348 if (is_v9) { 349 regs = fprs.pr_fr.pr_regs; 350 ns = 64; 351 nd = 32; 352 nq = 16; 353 } else if (is_v8plus) { 354 regs = mdb_alloc(sizeof (uint32_t) * 64, UM_SLEEP | UM_GC); 355 bcopy(fprs.pr_fr.pr_regs, regs, sizeof (uint32_t) * 32); 356 bcopy(xrs.pr_un.pr_v8p.pr_xfr.pr_regs, regs + 32, 357 sizeof (uint32_t) * 32); 358 ns = 64; 359 nd = 32; 360 nq = 16; 361 } else { 362 regs = fprs.pr_fr.pr_regs; 363 ns = 32; 364 nd = 16; 365 nq = 0; 366 } 367 368 if (opts == FPR_MIXED) { 369 for (i = 0; i < ns; i++) { 370 fpu.ip.i1 = regs[i]; 371 mdb_printf("f%-3d %08x %e", i, fpu.ip.i1, fpu.f); 372 if (i & 1) { 373 fpu.ip.i1 = regs[i - 1]; 374 fpu.ip.i2 = regs[i]; 375 mdb_printf(" %g", fpu.d); 376 } 377 mdb_printf("\n"); 378 } 379 } 380 381 if (opts & FPR_SINGLE) { 382 for (i = 0; i < ns; i++) { 383 fpu.ip.i1 = regs[i]; 384 mdb_printf("f%-3d %08x %e\n", i, fpu.ip.i1, fpu.f); 385 } 386 } 387 388 if (opts & FPR_DOUBLE) { 389 for (i = 0; i < nd; i++) { 390 fpu.ip.i1 = regs[i * 2 + 0]; 391 fpu.ip.i2 = regs[i * 2 + 1]; 392 mdb_printf("f%-3d %08x.%08x %g\n", i * 2, 393 fpu.ip.i1, fpu.ip.i2, fpu.d); 394 } 395 } 396 397 if (opts & FPR_QUAD) { 398 for (i = 0; i < nq; i++) { 399 fpu.ip.i1 = regs[i * 4 + 0]; 400 fpu.ip.i2 = regs[i * 4 + 1]; 401 fpu.ip.i3 = regs[i * 4 + 2]; 402 fpu.ip.i4 = regs[i * 4 + 3]; 403 mdb_printf("f%-3d %08x.%08x.%08x.%08x %s\n", i * 4, 404 fpu.ip.i1, fpu.ip.i2, fpu.ip.i3, fpu.ip.i4, 405 longdoubletos(&fpu.ld, 16, 'e')); 406 } 407 } 408 409 return (DCMD_OK); 410 } 411 412 /* 413 * Read a single floating-point register. If it's a v8 or v9 register, then 414 * we get its value from prfpregset_t. If it's a v8+ register, look in xregs. 415 */ 416 int 417 pt_getfpreg(mdb_tgt_t *t, mdb_tgt_tid_t tid, ushort_t rd_num, 418 ushort_t rd_flags, mdb_tgt_reg_t *rp) 419 { 420 mdb_tgt_reg_t rval; 421 prfpregset_t fprs; 422 prxregset_t xrs; 423 424 if (PTL_GETFPREGS(t, tid, &fprs) != 0) 425 return (-1); /* errno is set for us */ 426 427 if ((rd_flags & MDB_TGT_R_XREG) && PTL_GETXREGS(t, tid, &xrs) != 0) 428 return (-1); /* errno is set for us */ 429 430 if (rd_flags & MDB_TGT_R_FPU) { 431 switch (rd_num) { 432 case FPU_FSR: 433 rval = fprs.pr_fsr; 434 if (rd_flags & MDB_TGT_R_XREG) 435 rval |= (uint64_t) 436 xrs.pr_un.pr_v8p.pr_xfsr << 32; 437 break; 438 case FPU_FPRS: 439 if (rd_flags & MDB_TGT_R_XREG) 440 rval = xrs.pr_un.pr_v8p.pr_fprs; 441 break; 442 } 443 444 } else if (rd_flags & MDB_TGT_R_FPS) { 445 if (rd_flags & MDB_TGT_R_XREG) 446 rval = xrs.pr_un.pr_v8p.pr_xfr.pr_regs[rd_num - 32]; 447 else 448 rval = fprs.pr_fr.pr_regs[rd_num]; 449 450 } else if (rd_flags & MDB_TGT_R_FPD) { 451 if (rd_flags & MDB_TGT_R_XREG) 452 rval = ((uint64_t *) 453 xrs.pr_un.pr_v8p.pr_xfr.pr_dregs)[rd_num - 16]; 454 else 455 rval = ((uint64_t *)fprs.pr_fr.pr_dregs)[rd_num]; 456 } 457 458 *rp = rval; 459 return (0); 460 } 461 462 /* 463 * Write a single floating-point register. If it's a v8 or v9 register, then 464 * we set its value in prfpregset_t. If it's a v8+ register, modify the xregs. 465 */ 466 int 467 pt_putfpreg(mdb_tgt_t *t, mdb_tgt_tid_t tid, ushort_t rd_num, 468 ushort_t rd_flags, mdb_tgt_reg_t rval) 469 { 470 prfpregset_t fprs; 471 prxregset_t xrs; 472 473 if (PTL_GETFPREGS(t, tid, &fprs) != 0) 474 return (-1); /* errno is set for us */ 475 476 if ((rd_flags & MDB_TGT_R_XREG) && PTL_GETXREGS(t, tid, &xrs) != 0) 477 return (-1); /* errno is set for us */ 478 479 if (rd_flags & MDB_TGT_R_FPU) { 480 switch (rd_num) { 481 case FPU_FSR: 482 fprs.pr_fsr = (uint32_t)rval; 483 if (rd_flags & MDB_TGT_R_XREG) 484 xrs.pr_un.pr_v8p.pr_xfsr = rval >> 32; 485 break; 486 case FPU_FPRS: 487 if (rd_flags & MDB_TGT_R_XREG) 488 xrs.pr_un.pr_v8p.pr_fprs = rval; 489 break; 490 } 491 492 } else if (rd_flags & MDB_TGT_R_FPS) { 493 if (rd_flags & MDB_TGT_R_XREG) 494 xrs.pr_un.pr_v8p.pr_xfr.pr_regs[rd_num - 32] = rval; 495 else 496 fprs.pr_fr.pr_regs[rd_num] = rval; 497 498 } else if (rd_flags & MDB_TGT_R_FPD) { 499 if (rd_flags & MDB_TGT_R_XREG) 500 ((uint64_t *)xrs.pr_un.pr_v8p.pr_xfr.pr_dregs) 501 [rd_num - 16] = rval; 502 else 503 ((uint64_t *)fprs.pr_fr.pr_dregs)[rd_num] = rval; 504 } 505 506 if (PTL_SETFPREGS(t, tid, &fprs) != 0) 507 return (-1); /* errno is set for us */ 508 509 if ((rd_flags & MDB_TGT_R_XREG) && PTL_SETXREGS(t, tid, &xrs) != 0) 510 return (-1); /* errno is set for us */ 511 512 return (0); 513 } 514 515 /* 516 * Utility function for inserting a floating-point register description into 517 * the p_regs hash table of register descriptions. 518 */ 519 static void 520 pt_addfpreg(mdb_nv_t *nvp, uint_t rnum, uint_t rnam, char pref, ushort_t flags) 521 { 522 uintmax_t nval = MDB_TGT_R_NVAL(rnum, flags | MDB_TGT_R_EXPORT); 523 char name[8]; /* enough for "[fdq][0-9][0-9]\0" */ 524 525 (void) mdb_iob_snprintf(name, sizeof (name), "%c%u", pref, rnam); 526 (void) mdb_nv_insert(nvp, name, NULL, nval, MDB_NV_RDONLY); 527 } 528 529 /* 530 * Determine the ISA of the target and then insert the appropriate register 531 * description entries into p_regs. If the target is v8plus or v9, add the 532 * entire v9 floating-point model; otherwise just add the v8 registers. 533 */ 534 void 535 pt_addfpregs(mdb_tgt_t *t) 536 { 537 pt_data_t *pt = t->t_data; 538 struct ps_prochandle *P = t->t_pshandle; 539 prxregset_t xrs; 540 uint_t i; 541 542 uint_t fpuflag = MDB_TGT_R_FPU | MDB_TGT_R_EXPORT; 543 uint_t e_mach = pt->p_file ? pt->p_file->gf_ehdr.e_machine : EM_NONE; 544 uint_t model = P ? Pstatus(P)->pr_dmodel : PR_MODEL_UNKNOWN; 545 546 /* 547 * If the ELF file is SPARCv9 or the process or core is 64-bit, then 548 * add the SPARCv9 floating-point descriptions. Otherwise use v7/v8. 549 */ 550 if (e_mach == EM_SPARCV9 || model == PR_MODEL_LP64) { 551 for (i = 0; i < 64; i++) 552 pt_addfpreg(&pt->p_regs, i, i, 'f', MDB_TGT_R_FPS); 553 for (i = 0; i < 32; i++) 554 pt_addfpreg(&pt->p_regs, i, i * 2, 'd', MDB_TGT_R_FPD); 555 } else { 556 for (i = 0; i < 32; i++) 557 pt_addfpreg(&pt->p_regs, i, i, 'f', MDB_TGT_R_FPS); 558 for (i = 0; i < 16; i++) 559 pt_addfpreg(&pt->p_regs, i, i * 2, 'd', MDB_TGT_R_FPD); 560 } 561 562 /* 563 * If the ELF file is SPARCv8+ or the process or core has v8+ xregs, 564 * then include the additional v8plus register descriptions. 565 */ 566 if (e_mach == EM_SPARC32PLUS || (P != NULL && PTL_GETXREGS(t, 567 PTL_TID(t), &xrs) == 0 && xrs.pr_type == XR_TYPE_V8P)) { 568 569 for (i = 32; i < 64; i++) { 570 pt_addfpreg(&pt->p_regs, i, i, 'f', 571 MDB_TGT_R_FPS | MDB_TGT_R_XREG); 572 } 573 574 for (i = 16; i < 32; i++) { 575 pt_addfpreg(&pt->p_regs, i, i * 2, 'd', 576 MDB_TGT_R_FPD | MDB_TGT_R_XREG); 577 } 578 579 fpuflag |= MDB_TGT_R_XREG; /* fpu status regs are in xregs */ 580 581 (void) mdb_nv_insert(&pt->p_regs, "fsr", NULL, 582 MDB_TGT_R_NVAL(FPU_FSR, fpuflag), MDB_NV_RDONLY); 583 584 (void) mdb_nv_insert(&pt->p_regs, "fprs", NULL, 585 MDB_TGT_R_NVAL(FPU_FPRS, fpuflag), MDB_NV_RDONLY); 586 587 } else { 588 (void) mdb_nv_insert(&pt->p_regs, "fsr", NULL, 589 MDB_TGT_R_NVAL(FPU_FSR, fpuflag), MDB_NV_RDONLY); 590 } 591 } 592 593 int 594 pt_frameregs(void *arglim, uintptr_t pc, uint_t argc, const long *argv, 595 const mdb_tgt_gregset_t *gregs, boolean_t pc_faked) 596 { 597 char buf[BUFSIZ]; 598 const prgreg_t *pregs = &gregs->gregs[0]; 599 600 argc = MIN(argc, (uint_t)(uintptr_t)arglim); 601 602 if (pc_faked) 603 mdb_printf("%<b>%0?lr %s%</b>(", pregs[R_SP], "?"); 604 else 605 mdb_printf("%<b>%0?lr %a%</b>(", pregs[R_SP], pc); 606 607 if (argc != 0) { 608 mdb_printf("%lr", *argv++); 609 for (argc--; argc != 0; argc--) 610 mdb_printf(", %lr", *argv++); 611 } 612 613 mdb_printf(")\n"); 614 615 (void) mdb_inc_indent(2); 616 617 mdb_printf("%%l0-%%l3: %?lr %?lr %?lr %?lr\n", 618 pregs[R_L0], pregs[R_L1], pregs[R_L2], pregs[R_L3]); 619 620 mdb_printf("%%l4-%%l7: %?lr %?lr %?lr %?lr\n", 621 pregs[R_L4], pregs[R_L5], pregs[R_L6], pregs[R_L7]); 622 623 if (pregs[R_FP] != 0 && (pregs[R_FP] + STACK_BIAS) != 0) 624 if (mdb_dis_ins2str(mdb.m_disasm, mdb.m_target, MDB_TGT_AS_VIRT, 625 buf, sizeof (buf), pregs[R_I7]) != pregs[R_I7]) 626 mdb_printf("%-#25a%s\n", pregs[R_I7], buf); 627 628 (void) mdb_dec_indent(2); 629 mdb_printf("\n"); 630 631 return (0); 632 } 633 634 const char * 635 pt_disasm(const GElf_Ehdr *ehp) 636 { 637 #ifdef __sparcv9 638 const char *disname = "v9plus"; 639 #else 640 const char *disname = "v8"; 641 #endif 642 /* 643 * If e_machine is SPARC32+, the program has been compiled v8plus or 644 * v8plusa and we need to allow v9 and potentially VIS opcodes. 645 */ 646 if (ehp != NULL && ehp->e_machine == EM_SPARC32PLUS) { 647 if (ehp->e_flags & (EF_SPARC_SUN_US1 | EF_SPARC_SUN_US3)) 648 disname = "v9plus"; 649 else 650 disname = "v9"; 651 } 652 653 return (disname); 654 } 655 656 /* 657 * Macros and #defines for extracting and interpreting SPARC instruction set, 658 * used in pt_step_out() and pt_next() below. 659 */ 660 #define OP(machcode) ((machcode) >> 30) 661 #define OP2(machcode) (((machcode) >> 22) & 0x07) 662 #define OP3(machcode) (((machcode) >> 19) & 0x3f) 663 #define RD(machcode) (((machcode) >> 25) & 0x1f) 664 #define RS1(machcode) (((machcode) >> 14) & 0x1f) 665 #define RS2(machcode) ((machcode) & 0x1f) 666 667 #define OP_BRANCH 0x0 668 #define OP_ARITH 0x2 669 670 #define OP2_ILLTRAP 0x0 671 672 #define OP3_OR 0x02 673 #define OP3_SAVE 0x3c 674 #define OP3_RESTORE 0x3d 675 676 /* 677 * If we are stopped on a save instruction or at the first instruction of a 678 * known function, return %o7 as the step-out address; otherwise return the 679 * current frame's return address (%i7). Significantly better handling of 680 * step out in leaf routines could be accomplished by implementing more 681 * complex decoding of the current function and our current state. 682 */ 683 int 684 pt_step_out(mdb_tgt_t *t, uintptr_t *p) 685 { 686 const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp; 687 uintptr_t pc = psp->pr_reg[R_PC]; 688 uint32_t instr; 689 690 char buf[1]; 691 GElf_Sym s; 692 693 if (Pstate(t->t_pshandle) != PS_STOP) 694 return (set_errno(EMDB_TGTBUSY)); 695 696 instr = pt_read_instr(t); 697 698 if (mdb_tgt_lookup_by_addr(t, pc, MDB_TGT_SYM_FUZZY, 699 buf, sizeof (buf), &s, NULL) == 0 && s.st_value == pc) 700 *p = psp->pr_reg[R_O7] + 2 * sizeof (instr_t); 701 else if (OP(instr) == OP_ARITH && 702 OP3(instr) == OP3_SAVE) 703 *p = psp->pr_reg[R_O7] + 2 * sizeof (instr_t); 704 else 705 *p = psp->pr_reg[R_I7] + 2 * sizeof (instr_t); 706 707 return (0); 708 } 709 710 /* 711 * Step over call and jmpl by returning the address of the position where a 712 * temporary breakpoint can be set to catch return from the control transfer. 713 * This function does not currently provide advancing decoding of DCTI 714 * couples or any other complex special case; we just fall back to single-step. 715 */ 716 int 717 pt_next(mdb_tgt_t *t, uintptr_t *p) 718 { 719 const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp; 720 uintptr_t pc; 721 uintptr_t npc; 722 GElf_Sym func; 723 char name[1]; 724 instr_t instr; 725 726 if (Pstate(t->t_pshandle) != PS_STOP) 727 return (set_errno(EMDB_TGTBUSY)); 728 729 pc = psp->pr_reg[R_PC]; 730 npc = psp->pr_reg[R_nPC]; 731 instr = pt_read_instr(t); 732 733 if (mdb_tgt_lookup_by_addr(t, pc, MDB_TGT_SYM_FUZZY, 734 name, sizeof (name), &func, NULL) != 0) 735 return (-1); 736 737 if (npc < func.st_value || func.st_value + func.st_size <= npc) { 738 uint_t reg; 739 740 /* 741 * We're about to transfer control outside this function, 742 * so we want to stop when control returns from the other 743 * function. Normally the return address will be in %o7, 744 * tail-calls being the exception. We try to discover 745 * if this is a tail-call and compute the return address 746 * in that case. 747 */ 748 if (OP(instr) == OP_ARITH && 749 OP3(instr) == OP3_RESTORE) { 750 reg = R_I7; 751 752 } else if (OP(instr) == OP_ARITH && 753 OP3(instr) == OP3_OR && 754 RD(instr) == R_O7) { 755 756 if (RS1(instr) != R_G0) 757 return (set_errno(EAGAIN)); 758 reg = RS2(instr); 759 760 } else { 761 reg = R_O7; 762 } 763 764 *p = psp->pr_reg[reg] + 2 * sizeof (instr_t); 765 766 /* 767 * If a function returns a structure, the caller may place 768 * an illtrap whose const22 field represents the size of 769 * the structure immediately after the delay slot of the 770 * call (or jmpl) instruction. To handle this case, we 771 * check the instruction that we think we're going to 772 * return to, and advance past it if it's an illtrap 773 * instruction. Note that this applies to SPARC v7 and v8, 774 * but not v9. 775 */ 776 if (mdb_tgt_vread(t, &instr, sizeof (instr_t), *p) == 777 sizeof (instr_t) && 778 OP(instr) == OP_BRANCH && OP2(instr) == OP2_ILLTRAP) 779 *p += sizeof (instr_t); 780 781 return (0); 782 } 783 784 return (set_errno(EAGAIN)); 785 } 786