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 55 const 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 144 void 145 mdb_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 204 int 205 mdb_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 412 badfp: 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 */ 423 int 424 mdb_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*/ 459 int 460 mdb_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*/ 504 int 505 mdb_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 521 int 522 mdb_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