xref: /illumos-gate/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c (revision d583b39bfb4e2571d3e41097c5c357ffe353ad45)
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 #include <sys/types.h>
28 #include <sys/reg.h>
29 #include <sys/privregs.h>
30 #include <sys/stack.h>
31 #include <sys/frame.h>
32 
33 #include <mdb/mdb_target_impl.h>
34 #include <mdb/mdb_kreg_impl.h>
35 #include <mdb/mdb_debug.h>
36 #include <mdb/mdb_modapi.h>
37 #include <mdb/mdb_amd64util.h>
38 #include <mdb/mdb_ctf.h>
39 #include <mdb/mdb_err.h>
40 #include <mdb/mdb.h>
41 
42 #include <saveargs.h>
43 
44 /*
45  * This array is used by the getareg and putareg entry points, and also by our
46  * register variable discipline.
47  */
48 
49 const mdb_tgt_regdesc_t mdb_amd64_kregs[] = {
50 	{ "savfp", KREG_SAVFP, MDB_TGT_R_EXPORT },
51 	{ "savpc", KREG_SAVPC, MDB_TGT_R_EXPORT },
52 	{ "rdi", KREG_RDI, MDB_TGT_R_EXPORT },
53 	{ "rsi", KREG_RSI, MDB_TGT_R_EXPORT },
54 	{ "rdx", KREG_RDX, MDB_TGT_R_EXPORT },
55 	{ "rcx", KREG_RCX, MDB_TGT_R_EXPORT },
56 	{ "r8", KREG_R8, MDB_TGT_R_EXPORT },
57 	{ "r9", KREG_R9, MDB_TGT_R_EXPORT },
58 	{ "rax", KREG_RAX, MDB_TGT_R_EXPORT },
59 	{ "rbx", KREG_RBX, MDB_TGT_R_EXPORT },
60 	{ "rbp", KREG_RBP, MDB_TGT_R_EXPORT },
61 	{ "r10", KREG_R10, MDB_TGT_R_EXPORT },
62 	{ "r11", KREG_R11, MDB_TGT_R_EXPORT },
63 	{ "r12", KREG_R12, MDB_TGT_R_EXPORT },
64 	{ "r13", KREG_R13, MDB_TGT_R_EXPORT },
65 	{ "r14", KREG_R14, MDB_TGT_R_EXPORT },
66 	{ "r15", KREG_R15, MDB_TGT_R_EXPORT },
67 	{ "ds", KREG_DS, MDB_TGT_R_EXPORT },
68 	{ "es", KREG_ES, MDB_TGT_R_EXPORT },
69 	{ "fs", KREG_FS, MDB_TGT_R_EXPORT },
70 	{ "gs", KREG_GS, MDB_TGT_R_EXPORT },
71 	{ "trapno", KREG_TRAPNO, MDB_TGT_R_EXPORT | MDB_TGT_R_PRIV },
72 	{ "err", KREG_ERR, MDB_TGT_R_EXPORT | MDB_TGT_R_PRIV },
73 	{ "rip", KREG_RIP, MDB_TGT_R_EXPORT },
74 	{ "cs", KREG_CS, MDB_TGT_R_EXPORT },
75 	{ "rflags", KREG_RFLAGS, MDB_TGT_R_EXPORT },
76 	{ "rsp", KREG_RSP, MDB_TGT_R_EXPORT },
77 	{ "ss", KREG_SS, MDB_TGT_R_EXPORT },
78 	{ NULL, 0, 0 }
79 };
80 
81 void
82 mdb_amd64_printregs(const mdb_tgt_gregset_t *gregs)
83 {
84 	const kreg_t *kregs = &gregs->kregs[0];
85 	kreg_t rflags = kregs[KREG_RFLAGS];
86 
87 #define	GETREG2(x) ((uintptr_t)kregs[(x)]), ((uintptr_t)kregs[(x)])
88 
89 	mdb_printf("%%rax = 0x%0?p %15A %%r9  = 0x%0?p %A\n",
90 	    GETREG2(KREG_RAX), GETREG2(KREG_R9));
91 	mdb_printf("%%rbx = 0x%0?p %15A %%r10 = 0x%0?p %A\n",
92 	    GETREG2(KREG_RBX), GETREG2(KREG_R10));
93 	mdb_printf("%%rcx = 0x%0?p %15A %%r11 = 0x%0?p %A\n",
94 	    GETREG2(KREG_RCX), GETREG2(KREG_R11));
95 	mdb_printf("%%rdx = 0x%0?p %15A %%r12 = 0x%0?p %A\n",
96 	    GETREG2(KREG_RDX), GETREG2(KREG_R12));
97 	mdb_printf("%%rsi = 0x%0?p %15A %%r13 = 0x%0?p %A\n",
98 	    GETREG2(KREG_RSI), GETREG2(KREG_R13));
99 	mdb_printf("%%rdi = 0x%0?p %15A %%r14 = 0x%0?p %A\n",
100 	    GETREG2(KREG_RDI), GETREG2(KREG_R14));
101 	mdb_printf("%%r8  = 0x%0?p %15A %%r15 = 0x%0?p %A\n\n",
102 	    GETREG2(KREG_R8), GETREG2(KREG_R15));
103 
104 	mdb_printf("%%rip = 0x%0?p %A\n", GETREG2(KREG_RIP));
105 	mdb_printf("%%rbp = 0x%0?p\n", kregs[KREG_RBP]);
106 	mdb_printf("%%rsp = 0x%0?p\n", kregs[KREG_RSP]);
107 
108 	mdb_printf("%%rflags = 0x%08x\n", rflags);
109 
110 	mdb_printf("  id=%u vip=%u vif=%u ac=%u vm=%u rf=%u nt=%u iopl=0x%x\n",
111 	    (rflags & KREG_EFLAGS_ID_MASK) >> KREG_EFLAGS_ID_SHIFT,
112 	    (rflags & KREG_EFLAGS_VIP_MASK) >> KREG_EFLAGS_VIP_SHIFT,
113 	    (rflags & KREG_EFLAGS_VIF_MASK) >> KREG_EFLAGS_VIF_SHIFT,
114 	    (rflags & KREG_EFLAGS_AC_MASK) >> KREG_EFLAGS_AC_SHIFT,
115 	    (rflags & KREG_EFLAGS_VM_MASK) >> KREG_EFLAGS_VM_SHIFT,
116 	    (rflags & KREG_EFLAGS_RF_MASK) >> KREG_EFLAGS_RF_SHIFT,
117 	    (rflags & KREG_EFLAGS_NT_MASK) >> KREG_EFLAGS_NT_SHIFT,
118 	    (rflags & KREG_EFLAGS_IOPL_MASK) >> KREG_EFLAGS_IOPL_SHIFT);
119 
120 	mdb_printf("  status=<%s,%s,%s,%s,%s,%s,%s,%s,%s>\n\n",
121 	    (rflags & KREG_EFLAGS_OF_MASK) ? "OF" : "of",
122 	    (rflags & KREG_EFLAGS_DF_MASK) ? "DF" : "df",
123 	    (rflags & KREG_EFLAGS_IF_MASK) ? "IF" : "if",
124 	    (rflags & KREG_EFLAGS_TF_MASK) ? "TF" : "tf",
125 	    (rflags & KREG_EFLAGS_SF_MASK) ? "SF" : "sf",
126 	    (rflags & KREG_EFLAGS_ZF_MASK) ? "ZF" : "zf",
127 	    (rflags & KREG_EFLAGS_AF_MASK) ? "AF" : "af",
128 	    (rflags & KREG_EFLAGS_PF_MASK) ? "PF" : "pf",
129 	    (rflags & KREG_EFLAGS_CF_MASK) ? "CF" : "cf");
130 
131 	mdb_printf("%24s%%cs = 0x%04x\t%%ds = 0x%04x\t%%es = 0x%04x\n",
132 	    " ", kregs[KREG_CS], kregs[KREG_DS], kregs[KREG_ES]);
133 
134 	mdb_printf("%%trapno = 0x%x\t\t%%fs = 0x%04x\t%%gs = 0x%04x\n",
135 	    kregs[KREG_TRAPNO], (kregs[KREG_FS] & 0xffff),
136 	    (kregs[KREG_GS] & 0xffff));
137 	mdb_printf("   %%err = 0x%x\n", kregs[KREG_ERR]);
138 }
139 
140 /*
141  * We expect all proper Solaris core files to have STACK_ALIGN-aligned stacks.
142  * Hence the name.  However, if the core file resulted from a
143  * hypervisor-initiated panic, the hypervisor's frames may only be 64-bit
144  * aligned instead of 128.
145  */
146 static int
147 fp_is_aligned(uintptr_t fp, int xpv_panic)
148 {
149 	if (!xpv_panic && (fp & (STACK_ALIGN -1)))
150 		return (0);
151 	if ((fp & sizeof (uintptr_t) - 1))
152 		return (0);
153 	return (1);
154 }
155 
156 int
157 mdb_amd64_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp,
158     mdb_tgt_stack_f *func, void *arg)
159 {
160 	mdb_tgt_gregset_t gregs;
161 	kreg_t *kregs = &gregs.kregs[0];
162 	int got_pc = (gsp->kregs[KREG_RIP] != 0);
163 	uint_t argc, reg_argc;
164 	long fr_argv[32];
165 	int start_index; /* index to save_instr where to start comparison */
166 	int i;
167 
168 	struct {
169 		uintptr_t fr_savfp;
170 		uintptr_t fr_savpc;
171 	} fr;
172 
173 	uintptr_t fp = gsp->kregs[KREG_RBP];
174 	uintptr_t pc = gsp->kregs[KREG_RIP];
175 	uintptr_t lastfp, curpc;
176 
177 	ssize_t size;
178 	ssize_t insnsize;
179 	uint8_t ins[SAVEARGS_INSN_SEQ_LEN];
180 
181 	GElf_Sym s;
182 	mdb_syminfo_t sip;
183 	mdb_ctf_funcinfo_t mfp;
184 	int xpv_panic = 0;
185 #ifndef	_KMDB
186 	int xp;
187 
188 	if ((mdb_readsym(&xp, sizeof (xp), "xpv_panicking") != -1) && (xp > 0))
189 		xpv_panic = 1;
190 #endif
191 
192 	bcopy(gsp, &gregs, sizeof (gregs));
193 
194 	while (fp != 0) {
195 		int args_style = 0;
196 
197 		curpc = pc;
198 
199 		if (!fp_is_aligned(fp, xpv_panic))
200 			return (set_errno(EMDB_STKALIGN));
201 
202 		if (mdb_tgt_vread(t, &fr, sizeof (fr), fp) != sizeof (fr))
203 			return (-1);	/* errno has been set for us */
204 
205 		if ((mdb_tgt_lookup_by_addr(t, pc, MDB_TGT_SYM_FUZZY,
206 		    NULL, 0, &s, &sip) == 0) &&
207 		    (mdb_ctf_func_info(&s, &sip, &mfp) == 0)) {
208 			int return_type = mdb_ctf_type_kind(mfp.mtf_return);
209 			mdb_ctf_id_t args_types[5];
210 
211 			argc = mfp.mtf_argc;
212 
213 			/*
214 			 * If the function returns a structure or union
215 			 * greater than 16 bytes in size %rdi contains the
216 			 * address in which to store the return value rather
217 			 * than for an argument.
218 			 */
219 			if ((return_type == CTF_K_STRUCT ||
220 			    return_type == CTF_K_UNION) &&
221 			    mdb_ctf_type_size(mfp.mtf_return) > 16)
222 				start_index = 1;
223 			else
224 				start_index = 0;
225 
226 			/*
227 			 * If any of the first 5 arguments are a structure
228 			 * less than 16 bytes in size, it will be passed
229 			 * spread across two argument registers, and we will
230 			 * not cope.
231 			 */
232 			if (mdb_ctf_func_args(&mfp, 5, args_types) == CTF_ERR)
233 				argc = 0;
234 
235 			for (i = 0; i < MIN(5, argc); i++) {
236 				int t = mdb_ctf_type_kind(args_types[i]);
237 
238 				if (((t == CTF_K_STRUCT) ||
239 				    (t == CTF_K_UNION)) &&
240 				    mdb_ctf_type_size(args_types[i]) <= 16) {
241 					argc = 0;
242 					break;
243 				}
244 			}
245 		} else {
246 			argc = 0;
247 		}
248 
249 		/*
250 		 * The number of instructions to search for argument saving is
251 		 * limited such that only instructions prior to %pc are
252 		 * considered such that we never read arguments from a
253 		 * function where the saving code has not in fact yet
254 		 * executed.
255 		 */
256 		insnsize = MIN(MIN(s.st_size, SAVEARGS_INSN_SEQ_LEN),
257 		    pc - s.st_value);
258 
259 		if (mdb_tgt_vread(t, ins, insnsize, s.st_value) != insnsize)
260 			argc = 0;
261 
262 		if ((argc != 0) &&
263 		    ((args_style = saveargs_has_args(ins, insnsize, argc,
264 		    start_index)) != SAVEARGS_NO_ARGS)) {
265 			/* Up to 6 arguments are passed via registers */
266 			reg_argc = MIN((6 - start_index), mfp.mtf_argc);
267 			size = reg_argc * sizeof (long);
268 
269 			/*
270 			 * If Studio pushed a structure return address as an
271 			 * argument, we need to read one more argument than
272 			 * actually exists (the addr) to make everything line
273 			 * up.
274 			 */
275 			if (args_style == SAVEARGS_STRUCT_ARGS)
276 				size += sizeof (long);
277 
278 			if (mdb_tgt_vread(t, fr_argv, size, (fp - size))
279 			    != size)
280 				return (-1);	/* errno has been set for us */
281 
282 			/*
283 			 * Arrange the arguments in the right order for
284 			 * printing.
285 			 */
286 			for (i = 0; i < (reg_argc / 2); i++) {
287 				long t = fr_argv[i];
288 
289 				fr_argv[i] = fr_argv[reg_argc - i - 1];
290 				fr_argv[reg_argc - i - 1] = t;
291 			}
292 
293 			if (argc > reg_argc) {
294 				size = MIN((argc - reg_argc) * sizeof (long),
295 				    sizeof (fr_argv) -
296 				    (reg_argc * sizeof (long)));
297 
298 				if (mdb_tgt_vread(t, &fr_argv[reg_argc], size,
299 				    fp + sizeof (fr)) != size)
300 					return (-1); /* errno has been set */
301 			}
302 		} else {
303 			argc = 0;
304 		}
305 
306 		if (got_pc && func(arg, pc, argc, fr_argv, &gregs) != 0)
307 			break;
308 
309 		kregs[KREG_RSP] = kregs[KREG_RBP];
310 
311 		lastfp = fp;
312 		fp = fr.fr_savfp;
313 		/*
314 		 * The Xen hypervisor marks a stack frame as belonging to
315 		 * an exception by inverting the bits of the pointer to
316 		 * that frame.  We attempt to identify these frames by
317 		 * inverting the pointer and seeing if it is within 0xfff
318 		 * bytes of the last frame.
319 		 */
320 		if (xpv_panic)
321 			if ((fp != 0) && (fp < lastfp) &&
322 			    ((lastfp ^ ~fp) < 0xfff))
323 			fp = ~fp;
324 
325 		kregs[KREG_RBP] = fp;
326 		kregs[KREG_RIP] = pc = fr.fr_savpc;
327 
328 		if (curpc == pc)
329 			break;
330 
331 		got_pc = (pc != 0);
332 	}
333 
334 	return (0);
335 }
336 
337 /*
338  * Determine the return address for the current frame.  Typically this is the
339  * fr_savpc value from the current frame, but we also perform some special
340  * handling to see if we are stopped on one of the first two instructions of
341  * a typical function prologue, in which case %rbp will not be set up yet.
342  */
343 int
344 mdb_amd64_step_out(mdb_tgt_t *t, uintptr_t *p, kreg_t pc, kreg_t fp, kreg_t sp,
345     mdb_instr_t curinstr)
346 {
347 	struct frame fr;
348 	GElf_Sym s;
349 	char buf[1];
350 
351 	enum {
352 		M_PUSHQ_RBP	= 0x55,	/* pushq %rbp */
353 		M_REX_W		= 0x48, /* REX prefix with only W set */
354 		M_MOVL_RBP	= 0x8b	/* movq %rsp, %rbp with prefix */
355 	};
356 
357 	if (mdb_tgt_lookup_by_addr(t, pc, MDB_TGT_SYM_FUZZY,
358 	    buf, 0, &s, NULL) == 0) {
359 		if (pc == s.st_value && curinstr == M_PUSHQ_RBP)
360 			fp = sp - 8;
361 		else if (pc == s.st_value + 1 && curinstr == M_REX_W) {
362 			if (mdb_tgt_vread(t, &curinstr, sizeof (curinstr),
363 			    pc + 1) == sizeof (curinstr) && curinstr ==
364 			    M_MOVL_RBP)
365 				fp = sp;
366 		}
367 	}
368 
369 	if (mdb_tgt_vread(t, &fr, sizeof (fr), fp) == sizeof (fr)) {
370 		*p = fr.fr_savpc;
371 		return (0);
372 	}
373 
374 	return (-1); /* errno is set for us */
375 }
376 
377 /*ARGSUSED*/
378 int
379 mdb_amd64_next(mdb_tgt_t *t, uintptr_t *p, kreg_t pc, mdb_instr_t curinstr)
380 {
381 	mdb_tgt_addr_t npc;
382 	mdb_tgt_addr_t callpc;
383 
384 	enum {
385 		M_CALL_REL = 0xe8, /* call near with relative displacement */
386 		M_CALL_REG = 0xff, /* call near indirect or call far register */
387 
388 		M_REX_LO = 0x40,
389 		M_REX_HI = 0x4f
390 	};
391 
392 	/*
393 	 * If the opcode is a near call with relative displacement, assume the
394 	 * displacement is a rel32 from the next instruction.
395 	 */
396 	if (curinstr == M_CALL_REL) {
397 		*p = pc + sizeof (mdb_instr_t) + sizeof (uint32_t);
398 		return (0);
399 	}
400 
401 	/* Skip the rex prefix, if any */
402 	callpc = pc;
403 	while (curinstr >= M_REX_LO && curinstr <= M_REX_HI) {
404 		if (mdb_tgt_vread(t, &curinstr, sizeof (curinstr), ++callpc) !=
405 		    sizeof (curinstr))
406 			return (-1); /* errno is set for us */
407 	}
408 
409 	if (curinstr != M_CALL_REG) {
410 		/* It's not a call */
411 		return (set_errno(EAGAIN));
412 	}
413 
414 	if ((npc = mdb_dis_nextins(mdb.m_disasm, t, MDB_TGT_AS_VIRT, pc)) == pc)
415 		return (-1); /* errno is set for us */
416 
417 	*p = npc;
418 	return (0);
419 }
420 
421 /*ARGSUSED*/
422 int
423 mdb_amd64_kvm_frame(void *arglim, uintptr_t pc, uint_t argc, const long *argv,
424     const mdb_tgt_gregset_t *gregs)
425 {
426 	argc = MIN(argc, (uintptr_t)arglim);
427 	mdb_printf("%a(", pc);
428 
429 	if (argc != 0) {
430 		mdb_printf("%lr", *argv++);
431 		for (argc--; argc != 0; argc--)
432 			mdb_printf(", %lr", *argv++);
433 	}
434 
435 	mdb_printf(")\n");
436 	return (0);
437 }
438 
439 int
440 mdb_amd64_kvm_framev(void *arglim, uintptr_t pc, uint_t argc, const long *argv,
441     const mdb_tgt_gregset_t *gregs)
442 {
443 	/*
444 	 * Historically adb limited stack trace argument display to a fixed-
445 	 * size number of arguments since no symbolic debugging info existed.
446 	 * On amd64 we can detect the true number of saved arguments so only
447 	 * respect an arglim of zero; otherwise display the entire argv[].
448 	 */
449 	if (arglim == 0)
450 		argc = 0;
451 
452 	mdb_printf("%0?lr %a(", gregs->kregs[KREG_RBP], pc);
453 
454 	if (argc != 0) {
455 		mdb_printf("%lr", *argv++);
456 		for (argc--; argc != 0; argc--)
457 			mdb_printf(", %lr", *argv++);
458 	}
459 
460 	mdb_printf(")\n");
461 	return (0);
462 }
463