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