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 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <sys/types.h>
30 #include <sys/reg.h>
31 #include <sys/privregs.h>
32 #include <sys/stack.h>
33 #include <sys/frame.h>
34
35 #include <mdb/mdb_target_impl.h>
36 #include <mdb/mdb_kreg_impl.h>
37 #include <mdb/mdb_debug.h>
38 #include <mdb/mdb_modapi.h>
39 #include <mdb/mdb_amd64util.h>
40 #include <mdb/mdb_ctf.h>
41 #include <mdb/mdb_err.h>
42 #include <mdb/mdb.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
mdb_amd64_printregs(const mdb_tgt_gregset_t * gregs)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 * Sun Studio 10 patch compiler and gcc 3.4.3 Sun branch implemented a
142 * "-save_args" option on amd64. When the option is specified, INTEGER
143 * type function arguments passed via registers will be saved on the stack
144 * immediately after %rbp, and will not be modified through out the life
145 * of the routine.
146 *
147 * +--------+
148 * %rbp --> | %rbp |
149 * +--------+
150 * -0x8(%rbp) | %rdi |
151 * +--------+
152 * -0x10(%rbp) | %rsi |
153 * +--------+
154 * -0x18(%rbp) | %rdx |
155 * +--------+
156 * -0x20(%rbp) | %rcx |
157 * +--------+
158 * -0x28(%rbp) | %r8 |
159 * +--------+
160 * -0x30(%rbp) | %r9 |
161 * +--------+
162 *
163 *
164 * For example, for the following function,
165 *
166 * void
167 * foo(int a1, int a2, int a3, int a4, int a5, int a6, int a7)
168 * {
169 * ...
170 * }
171 *
172 * Disassembled code will look something like the following:
173 *
174 * pushq %rbp
175 * movq %rsp, %rbp
176 * subq $imm8, %rsp **
177 * movq %rdi, -0x8(%rbp)
178 * movq %rsi, -0x10(%rbp)
179 * movq %rdx, -0x18(%rbp)
180 * movq %rcx, -0x20(%rbp)
181 * movq %r8, -0x28(%rbp)
182 * movq %r9, -0x30(%rbp)
183 * ...
184 * or
185 * pushq %rbp
186 * movq %rsp, %rbp
187 * subq $imm8, %rsp **
188 * movq %r9, -0x30(%rbp)
189 * movq %r8, -0x28(%rbp)
190 * movq %rcx, -0x20(%rbp)
191 * movq %rdx, -0x18(%rbp)
192 * movq %rsi, -0x10(%rbp)
193 * movq %rdi, -0x8(%rbp)
194 * ...
195 *
196 * **: The space being reserved is in addition to what the current
197 * function prolog already reserves.
198 *
199 * If there are odd number of arguments to a function, additional space is
200 * reserved on the stack to maintain 16-byte alignment. For example,
201 *
202 * argc == 0: no argument saving.
203 * argc == 3: save 3, but space for 4 is reserved
204 * argc == 7: save 6.
205 */
206
207 /*
208 * The longest instruction sequence in bytes before all 6 arguments are
209 * saved on the stack. This value depends on compiler implementation,
210 * therefore it should be examined periodically to guarantee accuracy.
211 */
212 #define SEQ_LEN 80
213
214 /*
215 * Size of the instruction sequence arrays. It should correspond to
216 * the maximum number of arguments passed via registers.
217 */
218 #define INSTR_ARRAY_SIZE 6
219
220 #define INSTR4(ins, off) \
221 (ins[(off)] + (ins[(off) + 1] << 8) + (ins[(off + 2)] << 16) + \
222 (ins[(off) + 3] << 24))
223
224 /*
225 * Sun Studio 10 patch implementation saves %rdi first;
226 * GCC 3.4.3 Sun branch implementation saves them in reverse order.
227 */
228 static const uint32_t save_instr[INSTR_ARRAY_SIZE] = {
229 0xf87d8948, /* movq %rdi, -0x8(%rbp) */
230 0xf0758948, /* movq %rsi, -0x10(%rbp) */
231 0xe8558948, /* movq %rdx, -0x18(%rbp) */
232 0xe04d8948, /* movq %rcx, -0x20(%rbp) */
233 0xd845894c, /* movq %r8, -0x28(%rbp) */
234 0xd04d894c /* movq %r9, -0x30(%rbp) */
235 };
236
237 static const uint32_t save_fp_instr[] = {
238 0xe5894855, /* pushq %rbp; movq %rsp,%rbp, encoding 1 */
239 0xec8b4855, /* pushq %rbp; movq %rsp,%rbp, encoding 2 */
240 0xe58948cc, /* int $0x3; movq %rsp,%rbp, encoding 1 */
241 0xec8b48cc, /* int $0x3; movq %rsp,%rbp, encoding 2 */
242 NULL
243 };
244
245 /*
246 * Look for the above instruction sequences as indicators for register
247 * arguments being available on the stack.
248 */
249 static int
is_argsaved(mdb_tgt_t * t,uintptr_t fstart,uint64_t size,uint_t argc,int start_index)250 is_argsaved(mdb_tgt_t *t, uintptr_t fstart, uint64_t size, uint_t argc,
251 int start_index)
252 {
253 uint8_t ins[SEQ_LEN];
254 int i, j;
255 uint32_t n;
256
257 size = MIN(size, SEQ_LEN);
258 argc = MIN((start_index + argc), INSTR_ARRAY_SIZE);
259
260 if (mdb_tgt_vread(t, ins, size, fstart) != size)
261 return (0);
262
263 /*
264 * Make sure framepointer has been saved.
265 */
266 n = INSTR4(ins, 0);
267 for (i = 0; save_fp_instr[i] != NULL; i++) {
268 if (n == save_fp_instr[i])
269 break;
270 }
271
272 if (save_fp_instr[i] == NULL)
273 return (0);
274
275 /*
276 * Compare against Sun Studio implementation
277 */
278 for (i = 8, j = start_index; i < size - 4; i++) {
279 n = INSTR4(ins, i);
280
281 if (n == save_instr[j]) {
282 i += 3;
283 if (++j >= argc)
284 return (1);
285 }
286 }
287
288 /*
289 * Compare against GCC implementation
290 */
291 for (i = 8, j = argc - 1; i < size - 4; i++) {
292 n = INSTR4(ins, i);
293
294 if (n == save_instr[j]) {
295 i += 3;
296 if (--j < start_index)
297 return (1);
298 }
299 }
300
301 return (0);
302 }
303
304 /*
305 * We expect all proper Solaris core files to have STACK_ALIGN-aligned stacks.
306 * Hence the name. However, if the core file resulted from a
307 * hypervisor-initiated panic, the hypervisor's frames may only be 64-bit
308 * aligned instead of 128.
309 */
310 static int
fp_is_aligned(uintptr_t fp,int xpv_panic)311 fp_is_aligned(uintptr_t fp, int xpv_panic)
312 {
313 if (!xpv_panic && (fp & (STACK_ALIGN -1)))
314 return (0);
315 if ((fp & sizeof (uintptr_t) - 1))
316 return (0);
317 return (1);
318 }
319
320 int
mdb_amd64_kvm_stack_iter(mdb_tgt_t * t,const mdb_tgt_gregset_t * gsp,mdb_tgt_stack_f * func,void * arg)321 mdb_amd64_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp,
322 mdb_tgt_stack_f *func, void *arg)
323 {
324 mdb_tgt_gregset_t gregs;
325 kreg_t *kregs = &gregs.kregs[0];
326 int got_pc = (gsp->kregs[KREG_RIP] != 0);
327 uint_t argc, reg_argc;
328 long fr_argv[32];
329 int start_index; /* index to save_instr where to start comparison */
330 int i;
331
332 struct {
333 uintptr_t fr_savfp;
334 uintptr_t fr_savpc;
335 } fr;
336
337 uintptr_t fp = gsp->kregs[KREG_RBP];
338 uintptr_t pc = gsp->kregs[KREG_RIP];
339 uintptr_t lastfp, curpc;
340
341 ssize_t size;
342
343 GElf_Sym s;
344 mdb_syminfo_t sip;
345 mdb_ctf_funcinfo_t mfp;
346 int xpv_panic = 0;
347 #ifndef _KMDB
348 int xp;
349
350 if ((mdb_readsym(&xp, sizeof (xp), "xpv_panicking") != -1) && (xp > 0))
351 xpv_panic = 1;
352 #endif
353
354 bcopy(gsp, &gregs, sizeof (gregs));
355
356 while (fp != 0) {
357
358 curpc = pc;
359
360 if (!fp_is_aligned(fp, xpv_panic))
361 return (set_errno(EMDB_STKALIGN));
362
363 if (mdb_tgt_vread(t, &fr, sizeof (fr), fp) != sizeof (fr))
364 return (-1); /* errno has been set for us */
365
366 if ((mdb_tgt_lookup_by_addr(t, pc, MDB_TGT_SYM_FUZZY,
367 NULL, 0, &s, &sip) == 0) &&
368 (mdb_ctf_func_info(&s, &sip, &mfp) == 0)) {
369 int return_type = mdb_ctf_type_kind(mfp.mtf_return);
370 argc = mfp.mtf_argc;
371 /*
372 * If the function returns a structure or union,
373 * %rdi contains the address in which to store the
374 * return value rather than for an argument.
375 */
376 if (return_type == CTF_K_STRUCT ||
377 return_type == CTF_K_UNION)
378 start_index = 1;
379 else
380 start_index = 0;
381 } else {
382 argc = 0;
383 }
384
385 if (argc != 0 && is_argsaved(t, s.st_value, s.st_size,
386 argc, start_index)) {
387
388 /* Upto to 6 arguments are passed via registers */
389 reg_argc = MIN(6, mfp.mtf_argc);
390 size = reg_argc * sizeof (long);
391
392 if (mdb_tgt_vread(t, fr_argv, size, (fp - size))
393 != size)
394 return (-1); /* errno has been set for us */
395
396 /*
397 * Arrange the arguments in the right order for
398 * printing.
399 */
400 for (i = 0; i < (reg_argc >> 1); i++) {
401 long t = fr_argv[i];
402
403 fr_argv[i] = fr_argv[reg_argc - i - 1];
404 fr_argv[reg_argc - i - 1] = t;
405 }
406
407 if (argc > 6) {
408 size = (argc - 6) * sizeof (long);
409 if (mdb_tgt_vread(t, &fr_argv[6], size,
410 fp + sizeof (fr)) != size)
411 return (-1); /* errno has been set */
412 }
413 } else
414 argc = 0;
415
416 if (got_pc && func(arg, pc, argc, fr_argv, &gregs) != 0)
417 break;
418
419 kregs[KREG_RSP] = kregs[KREG_RBP];
420
421 lastfp = fp;
422 fp = fr.fr_savfp;
423 /*
424 * The Xen hypervisor marks a stack frame as belonging to
425 * an exception by inverting the bits of the pointer to
426 * that frame. We attempt to identify these frames by
427 * inverting the pointer and seeing if it is within 0xfff
428 * bytes of the last frame.
429 */
430 if (xpv_panic)
431 if ((fp != 0) && (fp < lastfp) &&
432 ((lastfp ^ ~fp) < 0xfff))
433 fp = ~fp;
434
435 kregs[KREG_RBP] = fp;
436 kregs[KREG_RIP] = pc = fr.fr_savpc;
437
438 if (curpc == pc)
439 break;
440
441 got_pc = (pc != 0);
442 }
443
444 return (0);
445 }
446
447 /*
448 * Determine the return address for the current frame. Typically this is the
449 * fr_savpc value from the current frame, but we also perform some special
450 * handling to see if we are stopped on one of the first two instructions of
451 * a typical function prologue, in which case %rbp will not be set up yet.
452 */
453 int
mdb_amd64_step_out(mdb_tgt_t * t,uintptr_t * p,kreg_t pc,kreg_t fp,kreg_t sp,mdb_instr_t curinstr)454 mdb_amd64_step_out(mdb_tgt_t *t, uintptr_t *p, kreg_t pc, kreg_t fp, kreg_t sp,
455 mdb_instr_t curinstr)
456 {
457 struct frame fr;
458 GElf_Sym s;
459 char buf[1];
460
461 enum {
462 M_PUSHQ_RBP = 0x55, /* pushq %rbp */
463 M_REX_W = 0x48, /* REX prefix with only W set */
464 M_MOVL_RBP = 0x8b /* movq %rsp, %rbp with prefix */
465 };
466
467 if (mdb_tgt_lookup_by_addr(t, pc, MDB_TGT_SYM_FUZZY,
468 buf, 0, &s, NULL) == 0) {
469 if (pc == s.st_value && curinstr == M_PUSHQ_RBP)
470 fp = sp - 8;
471 else if (pc == s.st_value + 1 && curinstr == M_REX_W) {
472 if (mdb_tgt_vread(t, &curinstr, sizeof (curinstr),
473 pc + 1) == sizeof (curinstr) && curinstr ==
474 M_MOVL_RBP)
475 fp = sp;
476 }
477 }
478
479 if (mdb_tgt_vread(t, &fr, sizeof (fr), fp) == sizeof (fr)) {
480 *p = fr.fr_savpc;
481 return (0);
482 }
483
484 return (-1); /* errno is set for us */
485 }
486
487 /*ARGSUSED*/
488 int
mdb_amd64_next(mdb_tgt_t * t,uintptr_t * p,kreg_t pc,mdb_instr_t curinstr)489 mdb_amd64_next(mdb_tgt_t *t, uintptr_t *p, kreg_t pc, mdb_instr_t curinstr)
490 {
491 mdb_tgt_addr_t npc;
492 mdb_tgt_addr_t callpc;
493
494 enum {
495 M_CALL_REL = 0xe8, /* call near with relative displacement */
496 M_CALL_REG = 0xff, /* call near indirect or call far register */
497
498 M_REX_LO = 0x40,
499 M_REX_HI = 0x4f
500 };
501
502 /*
503 * If the opcode is a near call with relative displacement, assume the
504 * displacement is a rel32 from the next instruction.
505 */
506 if (curinstr == M_CALL_REL) {
507 *p = pc + sizeof (mdb_instr_t) + sizeof (uint32_t);
508 return (0);
509 }
510
511 /* Skip the rex prefix, if any */
512 callpc = pc;
513 while (curinstr >= M_REX_LO && curinstr <= M_REX_HI) {
514 if (mdb_tgt_vread(t, &curinstr, sizeof (curinstr), ++callpc) !=
515 sizeof (curinstr))
516 return (-1); /* errno is set for us */
517 }
518
519 if (curinstr != M_CALL_REG) {
520 /* It's not a call */
521 return (set_errno(EAGAIN));
522 }
523
524 if ((npc = mdb_dis_nextins(mdb.m_disasm, t, MDB_TGT_AS_VIRT, pc)) == pc)
525 return (-1); /* errno is set for us */
526
527 *p = npc;
528 return (0);
529 }
530
531 /*ARGSUSED*/
532 int
mdb_amd64_kvm_frame(void * arglim,uintptr_t pc,uint_t argc,const long * argv,const mdb_tgt_gregset_t * gregs)533 mdb_amd64_kvm_frame(void *arglim, uintptr_t pc, uint_t argc, const long *argv,
534 const mdb_tgt_gregset_t *gregs)
535 {
536 argc = MIN(argc, (uintptr_t)arglim);
537 mdb_printf("%a(", pc);
538
539 if (argc != 0) {
540 mdb_printf("%lr", *argv++);
541 for (argc--; argc != 0; argc--)
542 mdb_printf(", %lr", *argv++);
543 }
544
545 mdb_printf(")\n");
546 return (0);
547 }
548
549 int
mdb_amd64_kvm_framev(void * arglim,uintptr_t pc,uint_t argc,const long * argv,const mdb_tgt_gregset_t * gregs)550 mdb_amd64_kvm_framev(void *arglim, uintptr_t pc, uint_t argc, const long *argv,
551 const mdb_tgt_gregset_t *gregs)
552 {
553 /*
554 * Historically adb limited stack trace argument display to a fixed-
555 * size number of arguments since no symbolic debugging info existed.
556 * On amd64 we can detect the true number of saved arguments so only
557 * respect an arglim of zero; otherwise display the entire argv[].
558 */
559 if (arglim == 0)
560 argc = 0;
561
562 mdb_printf("%0?lr %a(", gregs->kregs[KREG_RBP], pc);
563
564 if (argc != 0) {
565 mdb_printf("%lr", *argv++);
566 for (argc--; argc != 0; argc--)
567 mdb_printf(", %lr", *argv++);
568 }
569
570 mdb_printf(")\n");
571 return (0);
572 }
573