/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
*/
#include <sys/privregs.h>
#include <mdb/mdb_target_impl.h>
#include <mdb/mdb_kreg_impl.h>
#include <mdb/mdb_debug.h>
#include <mdb/mdb_modapi.h>
#include <mdb/mdb_amd64util.h>
#include <saveargs.h>
/*
* This array is used by the getareg and putareg entry points, and also by our
* register variable discipline.
*/
{ NULL, 0, 0 }
};
void
{
mdb_printf("%%rax = 0x%0?p %15A %%r9 = 0x%0?p %A\n",
mdb_printf("%%rbx = 0x%0?p %15A %%r10 = 0x%0?p %A\n",
mdb_printf("%%rcx = 0x%0?p %15A %%r11 = 0x%0?p %A\n",
mdb_printf("%%rdx = 0x%0?p %15A %%r12 = 0x%0?p %A\n",
mdb_printf("%%rsi = 0x%0?p %15A %%r13 = 0x%0?p %A\n",
mdb_printf("%%rdi = 0x%0?p %15A %%r14 = 0x%0?p %A\n",
mdb_printf("%%r8 = 0x%0?p %15A %%r15 = 0x%0?p %A\n\n",
mdb_printf(" id=%u vip=%u vif=%u ac=%u vm=%u rf=%u nt=%u iopl=0x%x\n",
mdb_printf(" status=<%s,%s,%s,%s,%s,%s,%s,%s,%s>\n\n",
mdb_printf("%24s%%cs = 0x%04x\t%%ds = 0x%04x\t%%es = 0x%04x\n",
mdb_printf("%%trapno = 0x%x\t\t%%fs = 0x%04x\t%%gs = 0x%04x\n",
}
int
{
int err;
int i;
struct fr {
} fr;
GElf_Sym s;
int xpv_panic = 0;
#ifndef _KMDB
int xp;
xpv_panic = 1;
#endif
while (fp != 0) {
int args_style = 0;
err = EMDB_NOMAP;
goto badfp;
}
if (tortoise_fp == 0) {
tortoise_fp = fp;
} else {
/*
* Advance tortoise_fp every other frame, so we detect
*/
if (advance_tortoise != 0) {
tortoise_fp) != sizeof (tfr)) {
err = EMDB_NOMAP;
goto badfp;
}
}
if (fp == tortoise_fp) {
err = EMDB_STKFRAME;
goto badfp;
}
}
/*
* If the function returns a structure or union
* greater than 16 bytes in size %rdi contains the
* address in which to store the return value rather
* than for an argument.
*/
if ((return_type == CTF_K_STRUCT ||
return_type == CTF_K_UNION) &&
start_index = 1;
else
start_index = 0;
/*
* If any of the first 5 arguments are a structure
* less than 16 bytes in size, it will be passed
* spread across two argument registers, and we will
* not cope.
*/
argc = 0;
int t = mdb_ctf_type_kind(args_types[i]);
if (((t == CTF_K_STRUCT) ||
(t == CTF_K_UNION)) &&
argc = 0;
break;
}
}
} else {
argc = 0;
}
/*
* The number of instructions to search for argument saving is
* limited such that only instructions prior to %pc are
* considered such that we never read arguments from a
* function where the saving code has not in fact yet
* executed.
*/
argc = 0;
if ((argc != 0) &&
start_index)) != SAVEARGS_NO_ARGS)) {
/* Up to 6 arguments are passed via registers */
/*
* If Studio pushed a structure return address as an
* argument, we need to read one more argument than
* actually exists (the addr) to make everything line
* up.
*/
if (args_style == SAVEARGS_STRUCT_ARGS)
size += sizeof (long);
!= size)
return (-1); /* errno has been set for us */
/*
* Arrange the arguments in the right order for
* printing.
*/
for (i = 0; i < (reg_argc / 2); i++) {
long t = fr_argv[i];
}
sizeof (fr_argv) -
(reg_argc * sizeof (long)));
return (-1); /* errno has been set */
}
} else {
argc = 0;
}
break;
/*
* The Xen hypervisor marks a stack frame as belonging to
* an exception by inverting the bits of the pointer to
* that frame. We attempt to identify these frames by
* inverting the pointer and seeing if it is within 0xfff
* bytes of the last frame.
*/
if (xpv_panic)
}
return (0);
}
/*
* Determine the return address for the current frame. Typically this is the
* fr_savpc value from the current frame, but we also perform some special
* handling to see if we are stopped on one of the first two instructions of
* a typical function prologue, in which case %rbp will not be set up yet.
*/
int
{
GElf_Sym s;
enum {
};
}
}
return (0);
}
return (-1); /* errno is set for us */
}
/*ARGSUSED*/
int
{
enum {
};
/*
* If the opcode is a near call with relative displacement, assume the
* displacement is a rel32 from the next instruction.
*/
if (curinstr == M_CALL_REL) {
return (0);
}
/* Skip the rex prefix, if any */
sizeof (curinstr))
return (-1); /* errno is set for us */
}
if (curinstr != M_CALL_REG) {
/* It's not a call */
}
return (-1); /* errno is set for us */
*p = npc;
return (0);
}
/*ARGSUSED*/
int
const mdb_tgt_gregset_t *gregs)
{
if (argc != 0) {
}
mdb_printf(")\n");
return (0);
}
int
const mdb_tgt_gregset_t *gregs)
{
/*
* Historically adb limited stack trace argument display to a fixed-
* size number of arguments since no symbolic debugging info existed.
* On amd64 we can detect the true number of saved arguments so only
* respect an arglim of zero; otherwise display the entire argv[].
*/
if (arglim == 0)
argc = 0;
if (argc != 0) {
}
mdb_printf(")\n");
return (0);
}