/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* User Process Target SPARC v7 and v9 component
*
* This file provides the ISA-dependent portion of the user process target
* for both the sparcv7 and sparcv9 ISAs. For more details on the
* implementation refer to mdb_proc.c.
*/
#ifdef __sparcv9
#define __sparcv9cpu
#endif
#include <mdb/mdb_proc.h>
#include <mdb/mdb_kreg.h>
#include <mdb/mdb_stdlib.h>
#include <sys/elf_SPARC.h>
#include <libproc.h>
#ifndef STACK_BIAS
#define STACK_BIAS 0
#endif
#ifdef __sparcv9
#else
#endif
{ "y", R_Y, 0 },
#ifdef __sparcv9
#else
#endif
{ NULL, 0, 0 }
};
/*
* We cannot rely on pr_instr, because if we hit a breakpoint or the user has
* artifically modified memory, it will no longer be correct.
*/
static uint32_t
{
return (ret);
}
/*ARGSUSED*/
int
{
int rwidth, i;
#endif
if (argc != 0)
return (DCMD_USAGE);
mdb_warn("no process active\n");
return (DCMD_ERR);
}
mdb_warn("debugger has lost control of process\n");
return (DCMD_ERR);
}
if (flags & DCMD_ADDRSPEC)
else
mdb_warn("failed to get current register set");
return (DCMD_ERR);
}
for (i = 0; i < 8; i++) {
}
rwidth = 16;
else
rwidth = 8;
/*
* If we are debugging a 32-bit SPARC process on an UltraSPARC CPU,
* the globals and outs can have 32 upper bits hiding in the xregs.
*/
for (i = 0; i < 8; i++) {
}
}
#endif /* __sparc && _ILP32 */
for (i = 0; i < 8; i++) {
mdb_printf("%%g%d = 0x%0*llx %15llA %%l%d = 0x%0?p %A\n",
}
for (i = 0; i < 8; i++) {
mdb_printf("%%o%d = 0x%0*llx %15llA %%i%d = 0x%0?p %A\n",
}
mdb_printf("\n");
#ifdef __sparcv9
#else /* __sparcv9 */
mdb_printf(" %%psr = 0x%08x impl=0x%x ver=0x%x icc=%c%c%c%c\n"
" ec=%u ef=%u pil=%u s=%u ps=%u et=%u cwp=0x%x\n",
#endif /* __sparcv9 */
#ifdef __sparcv9
#else /* __sparcv9 */
#endif /* __sparcv9 */
return (DCMD_OK);
}
/*ARGSUSED*/
int
{
#ifdef __sparcv9
#endif
enum {
};
/*
* The prfpregset structure only provides us with the FPU in the form
* of 32-bit integers, doubles, or quads. We use this union of the
* various types to display floats, doubles, and long doubles.
*/
union {
struct {
} ip;
float f;
double d;
long double ld;
} fpu;
return (DCMD_USAGE);
mdb_warn("no process active\n");
return (DCMD_ERR);
}
mdb_warn("debugger has lost control of process\n");
return (DCMD_ERR);
}
if (flags & DCMD_ADDRSPEC)
else
#ifdef __sparcv9
else
mdb_warn("failed to read fprs register");
}
#endif
mdb_warn("failed to get floating point registers");
return (DCMD_ERR);
}
if (is_v8plus)
}
/*
* Set up the regs pointer to be a pointer to a contiguous chunk of
* memory containing all the floating pointer register data. Set
* ns, nd, and nq to indicate the number of registers of each type.
*/
if (is_v9) {
ns = 64;
nd = 32;
nq = 16;
} else if (is_v8plus) {
sizeof (uint32_t) * 32);
ns = 64;
nd = 32;
nq = 16;
} else {
ns = 32;
nd = 16;
nq = 0;
}
for (i = 0; i < ns; i++) {
if (i & 1) {
}
mdb_printf("\n");
}
}
if (opts & FPR_SINGLE) {
for (i = 0; i < ns; i++) {
}
}
if (opts & FPR_DOUBLE) {
for (i = 0; i < nd; i++) {
}
}
for (i = 0; i < nq; i++) {
}
}
return (DCMD_OK);
}
/*
* Read a single floating-point register. If it's a v8 or v9 register, then
* we get its value from prfpregset_t. If it's a v8+ register, look in xregs.
*/
int
{
return (-1); /* errno is set for us */
return (-1); /* errno is set for us */
if (rd_flags & MDB_TGT_R_FPU) {
switch (rd_num) {
case FPU_FSR:
if (rd_flags & MDB_TGT_R_XREG)
break;
case FPU_FPRS:
if (rd_flags & MDB_TGT_R_XREG)
break;
}
} else if (rd_flags & MDB_TGT_R_FPS) {
if (rd_flags & MDB_TGT_R_XREG)
else
} else if (rd_flags & MDB_TGT_R_FPD) {
if (rd_flags & MDB_TGT_R_XREG)
else
}
return (0);
}
/*
* Write a single floating-point register. If it's a v8 or v9 register, then
* we set its value in prfpregset_t. If it's a v8+ register, modify the xregs.
*/
int
{
return (-1); /* errno is set for us */
return (-1); /* errno is set for us */
if (rd_flags & MDB_TGT_R_FPU) {
switch (rd_num) {
case FPU_FSR:
if (rd_flags & MDB_TGT_R_XREG)
break;
case FPU_FPRS:
if (rd_flags & MDB_TGT_R_XREG)
break;
}
} else if (rd_flags & MDB_TGT_R_FPS) {
if (rd_flags & MDB_TGT_R_XREG)
else
} else if (rd_flags & MDB_TGT_R_FPD) {
if (rd_flags & MDB_TGT_R_XREG)
else
}
return (-1); /* errno is set for us */
return (-1); /* errno is set for us */
return (0);
}
/*
* Utility function for inserting a floating-point register description into
* the p_regs hash table of register descriptions.
*/
static void
{
}
/*
* Determine the ISA of the target and then insert the appropriate register
* description entries into p_regs. If the target is v8plus or v9, add the
* entire v9 floating-point model; otherwise just add the v8 registers.
*/
void
{
struct ps_prochandle *P = t->t_pshandle;
uint_t i;
/*
* If the ELF file is SPARCv9 or the process or core is 64-bit, then
*/
for (i = 0; i < 64; i++)
for (i = 0; i < 32; i++)
} else {
for (i = 0; i < 32; i++)
for (i = 0; i < 16; i++)
}
/*
* If the ELF file is SPARCv8+ or the process or core has v8+ xregs,
* then include the additional v8plus register descriptions.
*/
for (i = 32; i < 64; i++) {
}
for (i = 16; i < 32; i++) {
}
} else {
}
}
int
{
if (pc_faked)
else
if (argc != 0) {
}
mdb_printf(")\n");
(void) mdb_inc_indent(2);
mdb_printf("%%l0-%%l3: %?lr %?lr %?lr %?lr\n",
mdb_printf("%%l4-%%l7: %?lr %?lr %?lr %?lr\n",
(void) mdb_dec_indent(2);
mdb_printf("\n");
return (0);
}
const char *
{
#ifdef __sparcv9
#else
const char *disname = "v8";
#endif
/*
* If e_machine is SPARC32+, the program has been compiled v8plus or
* v8plusa and we need to allow v9 and potentially VIS opcodes.
*/
disname = "v9plus";
else
disname = "v9";
}
return (disname);
}
/*
* Macros and #defines for extracting and interpreting SPARC instruction set,
* used in pt_step_out() and pt_next() below.
*/
/*
* If we are stopped on a save instruction or at the first instruction of a
* known function, return %o7 as the step-out address; otherwise return the
* current frame's return address (%i7). Significantly better handling of
* step out in leaf routines could be accomplished by implementing more
* complex decoding of the current function and our current state.
*/
int
{
GElf_Sym s;
return (set_errno(EMDB_TGTBUSY));
instr = pt_read_instr(t);
else
return (0);
}
/*
* Step over call and jmpl by returning the address of the position where a
* temporary breakpoint can be set to catch return from the control transfer.
* This function does not currently provide advancing decoding of DCTI
* couples or any other complex special case; we just fall back to single-step.
*/
int
{
return (set_errno(EMDB_TGTBUSY));
instr = pt_read_instr(t);
return (-1);
/*
* We're about to transfer control outside this function,
* so we want to stop when control returns from the other
* function. Normally the return address will be in %o7,
* tail-calls being the exception. We try to discover
* if this is a tail-call and compute the return address
* in that case.
*/
} else {
}
/*
* If a function returns a structure, the caller may place
* an illtrap whose const22 field represents the size of
* the structure immediately after the delay slot of the
* call (or jmpl) instruction. To handle this case, we
* check the instruction that we think we're going to
* return to, and advance past it if it's an illtrap
* instruction. Note that this applies to SPARC v7 and v8,
* but not v9.
*/
sizeof (instr_t) &&
*p += sizeof (instr_t);
return (0);
}
}