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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26/*
27 * Copyright (c) 2018, Joyent, Inc.  All rights reserved.
28 * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
29 * Copyright (c) 2013 by Delphix. All rights reserved.
30 */
31
32#include <sys/types.h>
33#include <sys/reg.h>
34#include <sys/privregs.h>
35#include <sys/stack.h>
36#include <sys/frame.h>
37
38#include <mdb/mdb_target_impl.h>
39#include <mdb/mdb_kreg_impl.h>
40#include <mdb/mdb_debug.h>
41#include <mdb/mdb_modapi.h>
42#include <mdb/mdb_isautil.h>
43#include <mdb/mdb_amd64util.h>
44#include <mdb/mdb_ctf.h>
45#include <mdb/mdb_err.h>
46#include <mdb/mdb.h>
47
48#include <saveargs.h>
49
50/*
51 * This array is used by the getareg and putareg entry points, and also by our
52 * register variable discipline.
53 */
54
55const mdb_tgt_regdesc_t mdb_amd64_kregs[] = {
56	{ "savfp", KREG_SAVFP, MDB_TGT_R_EXPORT },
57	{ "savpc", KREG_SAVPC, MDB_TGT_R_EXPORT },
58	{ "rdi", KREG_RDI, MDB_TGT_R_EXPORT },
59	{ "edi", KREG_RDI, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
60	{ "di",  KREG_RDI, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
61	{ "dil", KREG_RDI, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
62	{ "rsi", KREG_RSI, MDB_TGT_R_EXPORT },
63	{ "esi", KREG_RSI, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
64	{ "si",  KREG_RSI, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
65	{ "sil", KREG_RSI, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
66	{ "rdx", KREG_RDX, MDB_TGT_R_EXPORT },
67	{ "edx", KREG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
68	{ "dx",  KREG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
69	{ "dh",  KREG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H },
70	{ "dl",  KREG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
71	{ "rcx", KREG_RCX, MDB_TGT_R_EXPORT },
72	{ "ecx", KREG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
73	{ "cx",  KREG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
74	{ "ch",  KREG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H },
75	{ "cl",  KREG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
76	{ "r8", KREG_R8, MDB_TGT_R_EXPORT },
77	{ "r8d", KREG_R8,  MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
78	{ "r8w", KREG_R8,  MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
79	{ "r8l", KREG_R8,  MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
80	{ "r9", KREG_R9, MDB_TGT_R_EXPORT },
81	{ "r9d", KREG_R8,  MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
82	{ "r9w", KREG_R8,  MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
83	{ "r9l", KREG_R8,  MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
84	{ "rax", KREG_RAX, MDB_TGT_R_EXPORT },
85	{ "eax", KREG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
86	{ "ax",  KREG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
87	{ "ah",  KREG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H },
88	{ "al",  KREG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
89	{ "rbx", KREG_RBX, MDB_TGT_R_EXPORT },
90	{ "ebx", KREG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
91	{ "bx",  KREG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
92	{ "bh",  KREG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H },
93	{ "bl",  KREG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
94	{ "rbp", KREG_RBP, MDB_TGT_R_EXPORT },
95	{ "ebp", KREG_RBP, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
96	{ "bp",  KREG_RBP, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
97	{ "bpl", KREG_RBP, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
98	{ "r10", KREG_R10, MDB_TGT_R_EXPORT },
99	{ "r10d", KREG_R10, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
100	{ "r10w", KREG_R10, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
101	{ "r10l", KREG_R10, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
102	{ "r11", KREG_R11, MDB_TGT_R_EXPORT },
103	{ "r11d", KREG_R11, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
104	{ "r11w", KREG_R11, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
105	{ "r11l", KREG_R11, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
106	{ "r12", KREG_R12, MDB_TGT_R_EXPORT },
107	{ "r12d", KREG_R12, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
108	{ "r12w", KREG_R12, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
109	{ "r12l", KREG_R12, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
110	{ "r13", KREG_R13, MDB_TGT_R_EXPORT },
111	{ "r13d", KREG_R13, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
112	{ "r13w", KREG_R13, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
113	{ "r13l", KREG_R13, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
114	{ "r14", KREG_R14, MDB_TGT_R_EXPORT },
115	{ "r14d", KREG_R14, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
116	{ "r14w", KREG_R14, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
117	{ "r14l", KREG_R14, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
118	{ "r15", KREG_R15, MDB_TGT_R_EXPORT },
119	{ "r15d", KREG_R15, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
120	{ "r15w", KREG_R15, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
121	{ "r15l", KREG_R15, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
122	{ "ds", KREG_DS, MDB_TGT_R_EXPORT },
123	{ "es", KREG_ES, MDB_TGT_R_EXPORT },
124	{ "fs", KREG_FS, MDB_TGT_R_EXPORT },
125	{ "gs", KREG_GS, MDB_TGT_R_EXPORT },
126	{ "trapno", KREG_TRAPNO, MDB_TGT_R_EXPORT | MDB_TGT_R_PRIV },
127	{ "err", KREG_ERR, MDB_TGT_R_EXPORT | MDB_TGT_R_PRIV },
128	{ "rip", KREG_RIP, MDB_TGT_R_EXPORT },
129	{ "cs", KREG_CS, MDB_TGT_R_EXPORT },
130	{ "rflags", KREG_RFLAGS, MDB_TGT_R_EXPORT },
131	{ "eflags", KREG_RFLAGS, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
132	{ "rsp", KREG_RSP, MDB_TGT_R_EXPORT },
133	{ "esp", KREG_RSP, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
134	{ "sp",  KREG_RSP, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
135	{ "spl", KREG_RSP, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
136	{ "ss", KREG_SS, MDB_TGT_R_EXPORT },
137	{ "gsbase", KREG_GSBASE, MDB_TGT_R_EXPORT },
138	{ "kgsbase", KREG_KGSBASE, MDB_TGT_R_EXPORT },
139	{ "cr2", KREG_CR2, MDB_TGT_R_EXPORT },
140	{ "cr3", KREG_CR3, MDB_TGT_R_EXPORT },
141	{ NULL, 0, 0 }
142};
143
144void
145mdb_amd64_printregs(const mdb_tgt_gregset_t *gregs)
146{
147	const kreg_t *kregs = &gregs->kregs[0];
148	kreg_t rflags = kregs[KREG_RFLAGS];
149
150#define	GETREG2(x) ((uintptr_t)kregs[(x)]), ((uintptr_t)kregs[(x)])
151
152	mdb_printf("%%rax = 0x%0?p %15A %%r9  = 0x%0?p %A\n",
153	    GETREG2(KREG_RAX), GETREG2(KREG_R9));
154	mdb_printf("%%rbx = 0x%0?p %15A %%r10 = 0x%0?p %A\n",
155	    GETREG2(KREG_RBX), GETREG2(KREG_R10));
156	mdb_printf("%%rcx = 0x%0?p %15A %%r11 = 0x%0?p %A\n",
157	    GETREG2(KREG_RCX), GETREG2(KREG_R11));
158	mdb_printf("%%rdx = 0x%0?p %15A %%r12 = 0x%0?p %A\n",
159	    GETREG2(KREG_RDX), GETREG2(KREG_R12));
160	mdb_printf("%%rsi = 0x%0?p %15A %%r13 = 0x%0?p %A\n",
161	    GETREG2(KREG_RSI), GETREG2(KREG_R13));
162	mdb_printf("%%rdi = 0x%0?p %15A %%r14 = 0x%0?p %A\n",
163	    GETREG2(KREG_RDI), GETREG2(KREG_R14));
164	mdb_printf("%%r8  = 0x%0?p %15A %%r15 = 0x%0?p %A\n\n",
165	    GETREG2(KREG_R8), GETREG2(KREG_R15));
166
167	mdb_printf("%%rip = 0x%0?p %A\n", GETREG2(KREG_RIP));
168	mdb_printf("%%rbp = 0x%0?p\n", kregs[KREG_RBP]);
169	mdb_printf("%%rsp = 0x%0?p\n", kregs[KREG_RSP]);
170
171	mdb_printf("%%rflags = 0x%08x\n", rflags);
172
173	mdb_printf("  id=%u vip=%u vif=%u ac=%u vm=%u rf=%u nt=%u iopl=0x%x\n",
174	    (rflags & KREG_EFLAGS_ID_MASK) >> KREG_EFLAGS_ID_SHIFT,
175	    (rflags & KREG_EFLAGS_VIP_MASK) >> KREG_EFLAGS_VIP_SHIFT,
176	    (rflags & KREG_EFLAGS_VIF_MASK) >> KREG_EFLAGS_VIF_SHIFT,
177	    (rflags & KREG_EFLAGS_AC_MASK) >> KREG_EFLAGS_AC_SHIFT,
178	    (rflags & KREG_EFLAGS_VM_MASK) >> KREG_EFLAGS_VM_SHIFT,
179	    (rflags & KREG_EFLAGS_RF_MASK) >> KREG_EFLAGS_RF_SHIFT,
180	    (rflags & KREG_EFLAGS_NT_MASK) >> KREG_EFLAGS_NT_SHIFT,
181	    (rflags & KREG_EFLAGS_IOPL_MASK) >> KREG_EFLAGS_IOPL_SHIFT);
182
183	mdb_printf("  status=<%s,%s,%s,%s,%s,%s,%s,%s,%s>\n\n",
184	    (rflags & KREG_EFLAGS_OF_MASK) ? "OF" : "of",
185	    (rflags & KREG_EFLAGS_DF_MASK) ? "DF" : "df",
186	    (rflags & KREG_EFLAGS_IF_MASK) ? "IF" : "if",
187	    (rflags & KREG_EFLAGS_TF_MASK) ? "TF" : "tf",
188	    (rflags & KREG_EFLAGS_SF_MASK) ? "SF" : "sf",
189	    (rflags & KREG_EFLAGS_ZF_MASK) ? "ZF" : "zf",
190	    (rflags & KREG_EFLAGS_AF_MASK) ? "AF" : "af",
191	    (rflags & KREG_EFLAGS_PF_MASK) ? "PF" : "pf",
192	    (rflags & KREG_EFLAGS_CF_MASK) ? "CF" : "cf");
193
194	mdb_printf("%%cs = 0x%04x\t%%ds = 0x%04x\t"
195	    "%%es = 0x%04x\t%%fs = 0x%04x\n", kregs[KREG_CS], kregs[KREG_DS],
196	    kregs[KREG_ES], kregs[KREG_FS] & 0xffff);
197	mdb_printf("%%gs = 0x%04x\t%%gsbase = 0x%lx\t%%kgsbase = 0x%lx\n",
198	    kregs[KREG_GS] & 0xffff, kregs[KREG_GSBASE], kregs[KREG_KGSBASE]);
199	mdb_printf("%%trapno = 0x%x\t%%err = 0x%x\t%%cr2 = 0x%lx\t"
200	    "%%cr3 = 0x%lx\n", kregs[KREG_TRAPNO], kregs[KREG_ERR],
201	    kregs[KREG_CR2], kregs[KREG_CR3]);
202}
203
204int
205mdb_amd64_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp,
206    mdb_tgt_stack_f *func, void *arg)
207{
208	mdb_tgt_gregset_t gregs;
209	kreg_t *kregs = &gregs.kregs[0];
210	int got_pc = (gsp->kregs[KREG_RIP] != 0);
211	uint_t argc, reg_argc;
212	long fr_argv[32];
213	int start_index; /* index to save_instr where to start comparison */
214	int err;
215	int i;
216
217	struct fr {
218		uintptr_t fr_savfp;
219		uintptr_t fr_savpc;
220	} fr;
221
222	uintptr_t fp = gsp->kregs[KREG_RBP];
223	uintptr_t pc = gsp->kregs[KREG_RIP];
224	uintptr_t lastfp = 0;
225
226	ssize_t size;
227	ssize_t insnsize;
228	uint8_t ins[SAVEARGS_INSN_SEQ_LEN];
229
230	GElf_Sym s;
231	mdb_syminfo_t sip;
232	mdb_ctf_funcinfo_t mfp;
233	int xpv_panic = 0;
234	int advance_tortoise = 1;
235	uintptr_t tortoise_fp = 0;
236#ifndef	_KMDB
237	int xp;
238
239	if ((mdb_readsym(&xp, sizeof (xp), "xpv_panicking") != -1) && (xp > 0))
240		xpv_panic = 1;
241#endif
242
243	bcopy(gsp, &gregs, sizeof (gregs));
244
245	while (fp != 0) {
246		int args_style = 0;
247
248		if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, &fr, sizeof (fr), fp) !=
249		    sizeof (fr)) {
250			err = EMDB_NOMAP;
251			goto badfp;
252		}
253
254		if (tortoise_fp == 0) {
255			tortoise_fp = fp;
256		} else {
257			/*
258			 * Advance tortoise_fp every other frame, so we detect
259			 * cycles with Floyd's tortoise/hare.
260			 */
261			if (advance_tortoise != 0) {
262				struct fr tfr;
263
264				if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, &tfr,
265				    sizeof (tfr), tortoise_fp) !=
266				    sizeof (tfr)) {
267					err = EMDB_NOMAP;
268					goto badfp;
269				}
270
271				tortoise_fp = tfr.fr_savfp;
272			}
273
274			if (fp == tortoise_fp) {
275				err = EMDB_STKFRAME;
276				goto badfp;
277			}
278		}
279
280		advance_tortoise = !advance_tortoise;
281
282		if ((mdb_tgt_lookup_by_addr(t, pc, MDB_TGT_SYM_FUZZY,
283		    NULL, 0, &s, &sip) == 0) &&
284		    (mdb_ctf_func_info(&s, &sip, &mfp) == 0)) {
285			int return_type = mdb_ctf_type_kind(mfp.mtf_return);
286			mdb_ctf_id_t args_types[5];
287
288			argc = mfp.mtf_argc;
289
290			/*
291			 * If the function returns a structure or union
292			 * greater than 16 bytes in size %rdi contains the
293			 * address in which to store the return value rather
294			 * than for an argument.
295			 */
296			if ((return_type == CTF_K_STRUCT ||
297			    return_type == CTF_K_UNION) &&
298			    mdb_ctf_type_size(mfp.mtf_return) > 16)
299				start_index = 1;
300			else
301				start_index = 0;
302
303			/*
304			 * If any of the first 5 arguments are a structure
305			 * less than 16 bytes in size, it will be passed
306			 * spread across two argument registers, and we will
307			 * not cope.
308			 */
309			if (mdb_ctf_func_args(&mfp, 5, args_types) == CTF_ERR)
310				argc = 0;
311
312			for (i = 0; i < MIN(5, argc); i++) {
313				int t = mdb_ctf_type_kind(args_types[i]);
314
315				if (((t == CTF_K_STRUCT) ||
316				    (t == CTF_K_UNION)) &&
317				    mdb_ctf_type_size(args_types[i]) <= 16) {
318					argc = 0;
319					break;
320				}
321			}
322		} else {
323			argc = 0;
324		}
325
326		/*
327		 * The number of instructions to search for argument saving is
328		 * limited such that only instructions prior to %pc are
329		 * considered such that we never read arguments from a
330		 * function where the saving code has not in fact yet
331		 * executed.
332		 */
333		insnsize = MIN(MIN(s.st_size, SAVEARGS_INSN_SEQ_LEN),
334		    pc - s.st_value);
335
336		if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_I, ins, insnsize,
337		    s.st_value) != insnsize)
338			argc = 0;
339
340		if ((argc != 0) &&
341		    ((args_style = saveargs_has_args(ins, insnsize, argc,
342		    start_index)) != SAVEARGS_NO_ARGS)) {
343			/* Up to 6 arguments are passed via registers */
344			reg_argc = MIN((6 - start_index), mfp.mtf_argc);
345			size = reg_argc * sizeof (long);
346
347			/*
348			 * If Studio pushed a structure return address as an
349			 * argument, we need to read one more argument than
350			 * actually exists (the addr) to make everything line
351			 * up.
352			 */
353			if (args_style == SAVEARGS_STRUCT_ARGS)
354				size += sizeof (long);
355
356			if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, fr_argv, size,
357			    (fp - size)) != size)
358				return (-1);	/* errno has been set for us */
359
360			/*
361			 * Arrange the arguments in the right order for
362			 * printing.
363			 */
364			for (i = 0; i < (reg_argc / 2); i++) {
365				long t = fr_argv[i];
366
367				fr_argv[i] = fr_argv[reg_argc - i - 1];
368				fr_argv[reg_argc - i - 1] = t;
369			}
370
371			if (argc > reg_argc) {
372				size = MIN((argc - reg_argc) * sizeof (long),
373				    sizeof (fr_argv) -
374				    (reg_argc * sizeof (long)));
375
376				if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S,
377				    &fr_argv[reg_argc], size,
378				    fp + sizeof (fr)) != size)
379					return (-1); /* errno has been set */
380			}
381		} else {
382			argc = 0;
383		}
384
385		if (got_pc && func(arg, pc, argc, fr_argv, &gregs) != 0)
386			break;
387
388		kregs[KREG_RSP] = kregs[KREG_RBP];
389
390		lastfp = fp;
391		fp = fr.fr_savfp;
392		/*
393		 * The Xen hypervisor marks a stack frame as belonging to
394		 * an exception by inverting the bits of the pointer to
395		 * that frame.  We attempt to identify these frames by
396		 * inverting the pointer and seeing if it is within 0xfff
397		 * bytes of the last frame.
398		 */
399		if (xpv_panic)
400			if ((fp != 0) && (fp < lastfp) &&
401			    ((lastfp ^ ~fp) < 0xfff))
402				fp = ~fp;
403
404		kregs[KREG_RBP] = fp;
405		kregs[KREG_RIP] = pc = fr.fr_savpc;
406
407		got_pc = (pc != 0);
408	}
409
410	return (0);
411
412badfp:
413	mdb_printf("%p [%s]", fp, mdb_strerror(err));
414	return (set_errno(err));
415}
416
417/*
418 * Determine the return address for the current frame.  Typically this is the
419 * fr_savpc value from the current frame, but we also perform some special
420 * handling to see if we are stopped on one of the first two instructions of
421 * a typical function prologue, in which case %rbp will not be set up yet.
422 */
423int
424mdb_amd64_step_out(mdb_tgt_t *t, uintptr_t *p, kreg_t pc, kreg_t fp, kreg_t sp,
425    mdb_instr_t curinstr)
426{
427	struct frame fr;
428	GElf_Sym s;
429	char buf[1];
430
431	enum {
432		M_PUSHQ_RBP	= 0x55,	/* pushq %rbp */
433		M_REX_W		= 0x48, /* REX prefix with only W set */
434		M_MOVL_RBP	= 0x8b	/* movq %rsp, %rbp with prefix */
435	};
436
437	if (mdb_tgt_lookup_by_addr(t, pc, MDB_TGT_SYM_FUZZY,
438	    buf, 0, &s, NULL) == 0) {
439		if (pc == s.st_value && curinstr == M_PUSHQ_RBP)
440			fp = sp - 8;
441		else if (pc == s.st_value + 1 && curinstr == M_REX_W) {
442			if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_I, &curinstr,
443			    sizeof (curinstr), pc + 1) == sizeof (curinstr) &&
444			    curinstr == M_MOVL_RBP)
445				fp = sp;
446		}
447	}
448
449	if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, &fr, sizeof (fr), fp) ==
450	    sizeof (fr)) {
451		*p = fr.fr_savpc;
452		return (0);
453	}
454
455	return (-1); /* errno is set for us */
456}
457
458/*ARGSUSED*/
459int
460mdb_amd64_next(mdb_tgt_t *t, uintptr_t *p, kreg_t pc, mdb_instr_t curinstr)
461{
462	mdb_tgt_addr_t npc;
463	mdb_tgt_addr_t callpc;
464
465	enum {
466		M_CALL_REL = 0xe8, /* call near with relative displacement */
467		M_CALL_REG = 0xff, /* call near indirect or call far register */
468
469		M_REX_LO = 0x40,
470		M_REX_HI = 0x4f
471	};
472
473	/*
474	 * If the opcode is a near call with relative displacement, assume the
475	 * displacement is a rel32 from the next instruction.
476	 */
477	if (curinstr == M_CALL_REL) {
478		*p = pc + sizeof (mdb_instr_t) + sizeof (uint32_t);
479		return (0);
480	}
481
482	/* Skip the rex prefix, if any */
483	callpc = pc;
484	while (curinstr >= M_REX_LO && curinstr <= M_REX_HI) {
485		if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_I, &curinstr,
486		    sizeof (curinstr), ++callpc) != sizeof (curinstr))
487			return (-1); /* errno is set for us */
488	}
489
490	if (curinstr != M_CALL_REG) {
491		/* It's not a call */
492		return (set_errno(EAGAIN));
493	}
494
495	npc = mdb_dis_nextins(mdb.m_disasm, t, MDB_TGT_AS_VIRT_I, pc);
496	if (npc == pc)
497		return (-1); /* errno is set for us */
498
499	*p = npc;
500	return (0);
501}
502
503/*ARGSUSED*/
504int
505mdb_amd64_kvm_frame(void *arglim, uintptr_t pc, uint_t argc, const long *argv,
506    const mdb_tgt_gregset_t *gregs)
507{
508	argc = MIN(argc, (uintptr_t)arglim);
509	mdb_printf("%a(", pc);
510
511	if (argc != 0) {
512		mdb_printf("%lr", *argv++);
513		for (argc--; argc != 0; argc--)
514			mdb_printf(", %lr", *argv++);
515	}
516
517	mdb_printf(")\n");
518	return (0);
519}
520
521int
522mdb_amd64_kvm_framev(void *arglim, uintptr_t pc, uint_t argc, const long *argv,
523    const mdb_tgt_gregset_t *gregs)
524{
525	/*
526	 * Historically adb limited stack trace argument display to a fixed-
527	 * size number of arguments since no symbolic debugging info existed.
528	 * On amd64 we can detect the true number of saved arguments so only
529	 * respect an arglim of zero; otherwise display the entire argv[].
530	 */
531	if (arglim == 0)
532		argc = 0;
533
534	mdb_printf("%0?lr %a(", gregs->kregs[KREG_RBP], pc);
535
536	if (argc != 0) {
537		mdb_printf("%lr", *argv++);
538		for (argc--; argc != 0; argc--)
539			mdb_printf(", %lr", *argv++);
540	}
541
542	mdb_printf(")\n");
543	return (0);
544}
545