Print this page
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/mdb/intel/mdb/proc_amd64dep.c
+++ new/usr/src/cmd/mdb/intel/mdb/proc_amd64dep.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, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26 /*
27 27 * Copyright (c) 2018, Joyent, Inc.
28 28 * Copyright 2019 Doma Gergő Mihály <doma.gergo.mihaly@gmail.com>
29 29 * Copyright 2023 Oxide Computer Company
30 30 */
31 31
32 32 /*
33 33 * User Process Target Intel 64-bit component
34 34 *
35 35 * This file provides the ISA-dependent portion of the user process target.
36 36 * For more details on the implementation refer to mdb_proc.c.
37 37 */
38 38
39 39 #include <mdb/mdb_proc.h>
40 40 #include <mdb/mdb_kreg.h>
41 41 #include <mdb/mdb_err.h>
42 42 #include <mdb/mdb_isautil.h>
43 43 #include <mdb/mdb_amd64util.h>
44 44 #include <mdb/proc_x86util.h>
45 45 #include <mdb/mdb.h>
46 46
47 47 #include <sys/ucontext.h>
48 48 #include <sys/frame.h>
49 49 #include <libproc.h>
50 50 #include <sys/fp.h>
51 51 #include <ieeefp.h>
52 52 #include <sys/sysmacros.h>
53 53
54 54 #include <stddef.h>
55 55
56 56 const mdb_tgt_regdesc_t pt_regdesc[] = {
57 57 { "r15", REG_R15, MDB_TGT_R_EXPORT },
58 58 { "r15d", REG_R15, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
59 59 { "r15w", REG_R15, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
60 60 { "r15l", REG_R15, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
61 61 { "r14", REG_R14, MDB_TGT_R_EXPORT },
62 62 { "r14d", REG_R14, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
63 63 { "r14w", REG_R14, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
64 64 { "r14l", REG_R14, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
65 65 { "r13", REG_R13, MDB_TGT_R_EXPORT },
66 66 { "r13d", REG_R13, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
67 67 { "r13w", REG_R13, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
68 68 { "r13l", REG_R13, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
69 69 { "r12", REG_R12, MDB_TGT_R_EXPORT },
70 70 { "r12d", REG_R12, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
71 71 { "r12w", REG_R12, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
72 72 { "r12l", REG_R12, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
73 73 { "r11", REG_R11, MDB_TGT_R_EXPORT },
74 74 { "r11d", REG_R11, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
75 75 { "r11w", REG_R11, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
76 76 { "r11l", REG_R11, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
77 77 { "r10", REG_R10, MDB_TGT_R_EXPORT },
78 78 { "r10d", REG_R10, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
79 79 { "r10w", REG_R10, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
80 80 { "r10l", REG_R10, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
81 81 { "r9", REG_R9, MDB_TGT_R_EXPORT },
82 82 { "r9d", REG_R9, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
83 83 { "r9w", REG_R9, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
84 84 { "r9l", REG_R9, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
85 85 { "r8", REG_R8, MDB_TGT_R_EXPORT },
86 86 { "r8d", REG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
87 87 { "r8w", REG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
88 88 { "r8l", REG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
89 89 { "rdi", REG_RDI, MDB_TGT_R_EXPORT },
90 90 { "edi", REG_RDI, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
91 91 { "di", REG_RDI, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
92 92 { "dil", REG_RDI, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
93 93 { "rsi", REG_RSI, MDB_TGT_R_EXPORT },
94 94 { "esi", REG_RSI, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
95 95 { "si", REG_RSI, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
96 96 { "sil", REG_RSI, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
97 97 { "rbp", REG_RBP, MDB_TGT_R_EXPORT },
98 98 { "ebp", REG_RBP, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
99 99 { "bp", REG_RBP, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
100 100 { "bpl", REG_RBP, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
101 101 { "rbx", REG_RBX, MDB_TGT_R_EXPORT },
102 102 { "ebx", REG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
103 103 { "bx", REG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
104 104 { "bh", REG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H },
105 105 { "bl", REG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
106 106 { "rdx", REG_RDX, MDB_TGT_R_EXPORT },
107 107 { "edx", REG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
108 108 { "dx", REG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
109 109 { "dh", REG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H },
110 110 { "dl", REG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
111 111 { "rcx", REG_RCX, MDB_TGT_R_EXPORT },
112 112 { "ecx", REG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
113 113 { "cx", REG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
114 114 { "ch", REG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H },
115 115 { "cl", REG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
116 116 { "rax", REG_RAX, MDB_TGT_R_EXPORT },
117 117 { "eax", REG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
118 118 { "ax", REG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
119 119 { "ah", REG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H },
120 120 { "al", REG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
121 121 { "trapno", REG_TRAPNO, MDB_TGT_R_EXPORT },
122 122 { "err", REG_ERR, MDB_TGT_R_EXPORT },
123 123 { "rip", REG_RIP, MDB_TGT_R_EXPORT },
124 124 { "cs", REG_CS, MDB_TGT_R_EXPORT },
125 125 { "rflags", REG_RFL, MDB_TGT_R_EXPORT },
126 126 { "eflags", REG_RFL, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
127 127 { "rsp", REG_RSP, MDB_TGT_R_EXPORT },
128 128 { "esp", REG_RSP, MDB_TGT_R_EXPORT | MDB_TGT_R_32 },
129 129 { "sp", REG_RSP, MDB_TGT_R_EXPORT | MDB_TGT_R_16 },
130 130 { "spl", REG_RSP, MDB_TGT_R_EXPORT | MDB_TGT_R_8L },
131 131 { "ss", REG_SS, MDB_TGT_R_EXPORT },
132 132 { "fs", REG_FS, MDB_TGT_R_EXPORT },
133 133 { "gs", REG_GS, MDB_TGT_R_EXPORT },
134 134 { "es", REG_ES, MDB_TGT_R_EXPORT },
135 135 { "ds", REG_DS, MDB_TGT_R_EXPORT },
136 136 { "fsbase", REG_FSBASE, MDB_TGT_R_EXPORT },
137 137 { "gsbase", REG_GSBASE, MDB_TGT_R_EXPORT },
138 138 { NULL, 0, 0 }
139 139 };
140 140
141 141 /*
142 142 * We cannot rely on pr_instr, because if we hit a breakpoint or the user has
143 143 * artifically modified memory, it will no longer be correct.
144 144 */
145 145 static uint8_t
146 146 pt_read_instr(mdb_tgt_t *t)
147 147 {
148 148 const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp;
149 149 uint8_t ret = 0;
150 150
151 151 (void) mdb_tgt_aread(t, MDB_TGT_AS_VIRT_I, &ret, sizeof (ret),
152 152 psp->pr_reg[REG_RIP]);
153 153
154 154 return (ret);
155 155 }
156 156
157 157 /*ARGSUSED*/
158 158 int
159 159 pt_regs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
160 160 {
161 161 mdb_tgt_t *t = mdb.m_target;
162 162 mdb_tgt_tid_t tid;
163 163 prgregset_t grs;
164 164 prgreg_t rflags;
165 165 boolean_t from_ucontext = B_FALSE;
166 166
167 167 if (mdb_getopts(argc, argv,
168 168 'u', MDB_OPT_SETBITS, B_TRUE, &from_ucontext, NULL) != argc) {
169 169 return (DCMD_USAGE);
170 170 }
171 171
172 172 if (from_ucontext) {
173 173 int off;
174 174 int o0, o1;
175 175
176 176 if (!(flags & DCMD_ADDRSPEC)) {
177 177 mdb_warn("-u requires a ucontext_t address\n");
178 178 return (DCMD_ERR);
179 179 }
180 180
181 181 o0 = mdb_ctf_offsetof_by_name("ucontext_t", "uc_mcontext");
182 182 o1 = mdb_ctf_offsetof_by_name("mcontext_t", "gregs");
183 183 if (o0 == -1 || o1 == -1) {
184 184 off = offsetof(ucontext_t, uc_mcontext) +
185 185 offsetof(mcontext_t, gregs);
186 186 } else {
187 187 off = o0 + o1;
188 188 }
189 189
190 190 if (mdb_vread(&grs, sizeof (grs), addr + off) != sizeof (grs)) {
191 191 mdb_warn("failed to read from ucontext_t %p", addr);
192 192 return (DCMD_ERR);
193 193 }
194 194 goto print_regs;
195 195 }
196 196
197 197 if (t->t_pshandle == NULL || Pstate(t->t_pshandle) == PS_UNDEAD) {
198 198 mdb_warn("no process active\n");
199 199 return (DCMD_ERR);
200 200 }
201 201
202 202 if (Pstate(t->t_pshandle) == PS_LOST) {
203 203 mdb_warn("debugger has lost control of process\n");
204 204 return (DCMD_ERR);
205 205 }
206 206
207 207 if (flags & DCMD_ADDRSPEC)
208 208 tid = (mdb_tgt_tid_t)addr;
209 209 else
210 210 tid = PTL_TID(t);
211 211
212 212 if (PTL_GETREGS(t, tid, grs) != 0) {
213 213 mdb_warn("failed to get current register set");
214 214 return (DCMD_ERR);
215 215 }
216 216
217 217 print_regs:
218 218 rflags = grs[REG_RFL];
219 219
220 220 mdb_printf("%%rax = 0x%0?p\t%%r8 = 0x%0?p\n",
221 221 grs[REG_RAX], grs[REG_R8]);
222 222 mdb_printf("%%rbx = 0x%0?p\t%%r9 = 0x%0?p\n",
223 223 grs[REG_RBX], grs[REG_R9]);
224 224 mdb_printf("%%rcx = 0x%0?p\t%%r10 = 0x%0?p\n",
225 225 grs[REG_RCX], grs[REG_R10]);
226 226 mdb_printf("%%rdx = 0x%0?p\t%%r11 = 0x%0?p\n",
227 227 grs[REG_RDX], grs[REG_R11]);
228 228 mdb_printf("%%rsi = 0x%0?p\t%%r12 = 0x%0?p\n",
229 229 grs[REG_RSI], grs[REG_R12]);
230 230 mdb_printf("%%rdi = 0x%0?p\t%%r13 = 0x%0?p\n",
231 231 grs[REG_RDI], grs[REG_R13]);
232 232 mdb_printf(" %?s\t%%r14 = 0x%0?p\n",
233 233 "", grs[REG_R14]);
234 234 mdb_printf(" %?s\t%%r15 = 0x%0?p\n",
235 235 "", grs[REG_R15]);
236 236
237 237 mdb_printf("\n");
238 238
239 239 mdb_printf("%%cs = 0x%04x\t%%fs = 0x%04x\t%%gs = 0x%04x\n",
240 240 grs[REG_CS], grs[REG_FS], grs[REG_GS]);
241 241 mdb_printf("%%ds = 0x%04x\t%%es = 0x%04x\t%%ss = 0x%04x\n",
242 242 grs[REG_DS], grs[REG_ES], grs[REG_SS]);
243 243
244 244 mdb_printf("\n");
245 245
246 246 mdb_printf("%%rip = 0x%0?p %A\n", grs[REG_RIP], grs[REG_RIP]);
247 247 mdb_printf("%%rbp = 0x%0?p\n", grs[REG_RBP], grs[REG_RBP]);
248 248 mdb_printf("%%rsp = 0x%0?p\n", grs[REG_RSP], grs[REG_RSP]);
249 249
250 250 mdb_printf("\n");
251 251
252 252 mdb_printf("%%rflags = 0x%08x\n", rflags);
253 253
254 254 mdb_printf(" id=%u vip=%u vif=%u ac=%u vm=%u rf=%u nt=%u iopl=0x%x\n",
255 255 (rflags & KREG_EFLAGS_ID_MASK) >> KREG_EFLAGS_ID_SHIFT,
256 256 (rflags & KREG_EFLAGS_VIP_MASK) >> KREG_EFLAGS_VIP_SHIFT,
257 257 (rflags & KREG_EFLAGS_VIF_MASK) >> KREG_EFLAGS_VIF_SHIFT,
258 258 (rflags & KREG_EFLAGS_AC_MASK) >> KREG_EFLAGS_AC_SHIFT,
259 259 (rflags & KREG_EFLAGS_VM_MASK) >> KREG_EFLAGS_VM_SHIFT,
260 260 (rflags & KREG_EFLAGS_RF_MASK) >> KREG_EFLAGS_RF_SHIFT,
261 261 (rflags & KREG_EFLAGS_NT_MASK) >> KREG_EFLAGS_NT_SHIFT,
262 262 (rflags & KREG_EFLAGS_IOPL_MASK) >> KREG_EFLAGS_IOPL_SHIFT);
263 263
264 264 mdb_printf(" status=<%s,%s,%s,%s,%s,%s,%s,%s,%s>\n",
265 265 (rflags & KREG_EFLAGS_OF_MASK) ? "OF" : "of",
266 266 (rflags & KREG_EFLAGS_DF_MASK) ? "DF" : "df",
267 267 (rflags & KREG_EFLAGS_IF_MASK) ? "IF" : "if",
268 268 (rflags & KREG_EFLAGS_TF_MASK) ? "TF" : "tf",
269 269 (rflags & KREG_EFLAGS_SF_MASK) ? "SF" : "sf",
270 270 (rflags & KREG_EFLAGS_ZF_MASK) ? "ZF" : "zf",
271 271 (rflags & KREG_EFLAGS_AF_MASK) ? "AF" : "af",
272 272 (rflags & KREG_EFLAGS_PF_MASK) ? "PF" : "pf",
273 273 (rflags & KREG_EFLAGS_CF_MASK) ? "CF" : "cf");
274 274
275 275 mdb_printf("\n");
276 276
277 277 mdb_printf("%%gsbase = 0x%0?p\n", grs[REG_GSBASE]);
278 278 mdb_printf("%%fsbase = 0x%0?p\n", grs[REG_FSBASE]);
279 279 mdb_printf("%%trapno = 0x%x\n", grs[REG_TRAPNO]);
280 280 mdb_printf(" %%err = 0x%x\n", grs[REG_ERR]);
281 281
282 282 return (set_errno(ENOTSUP));
283 283 }
284 284
285 285 int
286 286 pt_fpregs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
287 287 {
288 288 int ret;
289 289 prfpregset_t fprs;
290 290 struct _fpchip_state fps;
291 291 char buf[256];
292 292 uint_t top;
293 293 size_t i;
294 294
295 295 /*
296 296 * Union for overlaying _fpreg structure on to quad-precision
297 297 * floating-point value (long double).
298 298 */
299 299 union {
300 300 struct _fpreg reg;
301 301 long double ld;
302 302 } fpru;
303 303
304 304 /*
305 305 * We use common code between 32-bit and 64-bit x86 to capture and print
306 306 * the extended vector state. The remaining classic 387 state is
307 307 * finicky and different enough that it is left to be dealt with on its
308 308 * own.
309 309 */
310 310 if ((ret = x86_pt_fpregs_common(addr, flags, argc, &fprs)) != DCMD_OK)
311 311 return (ret);
312 312
313 313 bcopy(&fprs.fp_reg_set.fpchip_state, &fps, sizeof (fps));
314 314 mdb_printf("387 and FP Control State\n");
315 315
316 316 fps.status &= 0xffff; /* saved status word is really 16 bits */
317 317
318 318 mdb_printf("cw 0x%04x (%s)\n", fps.cw,
319 319 fpcw2str(fps.cw, buf, sizeof (buf)));
320 320
321 321 top = (fps.sw & FPS_TOP) >> 11;
322 322 mdb_printf("sw 0x%04x (TOP=0t%u) (%s)\n", fps.sw,
323 323 top, fpsw2str(fps.sw, buf, sizeof (buf)));
324 324
325 325 mdb_printf("xcp sw 0x%04x (%s)\n\n", fps.status,
326 326 fpsw2str(fps.status, buf, sizeof (buf)));
327 327
328 328 mdb_printf("fop 0x%x\n", fps.fop);
329 329 mdb_printf("rip 0x%x\n", fps.rip);
330 330 mdb_printf("rdp 0x%x\n\n", fps.rdp);
331 331
332 332 for (i = 0; i < ARRAY_SIZE(fps.st); i++) {
333 333 /*
334 334 * Recall that we need to use the current TOP-of-stack value to
335 335 * associate the _st[] index back to a physical register number,
336 336 * since tag word indices are physical register numbers. Then
337 337 * to get the tag value, we shift over two bits for each tag
338 338 * index, and then grab the bottom two bits.
339 339 */
340 340 uint_t tag_index = (i + top) & 7;
341 341 uint_t tag_fctw = (fps.fctw >> tag_index) & 1;
342 342 uint_t tag_value;
343 343 uint_t exp;
344 344
345 345 /*
346 346 * AMD64 stores the tag in a compressed form. It is
347 347 * necessary to extract the original 2-bit tag value.
348 348 * See AMD64 Architecture Programmer's Manual Volume 2:
349 349 * System Programming, Chapter 11.
350 350 */
351 351
352 352 fpru.ld = fps.st[i].__fpr_pad._q;
353 353 exp = fpru.reg.exponent & 0x7fff;
354 354
355 355 if (tag_fctw == 0) {
356 356 tag_value = 3; /* empty */
357 357 } else if (exp == 0) {
358 358 if (fpru.reg.significand[0] == 0 &&
359 359 fpru.reg.significand[1] == 0 &&
360 360 fpru.reg.significand[2] == 0 &&
361 361 fpru.reg.significand[3] == 0)
362 362 tag_value = 1; /* zero */
363 363 else
364 364 tag_value = 2; /* special: denormal */
365 365 } else if (exp == 0x7fff) {
366 366 tag_value = 2; /* special: infinity or NaN */
367 367 } else if (fpru.reg.significand[3] & 0x8000) {
368 368 tag_value = 0; /* valid */
369 369 } else {
370 370 tag_value = 2; /* special: unnormal */
371 371 }
372 372
373 373 mdb_printf("%%st%d 0x%04x.%04x%04x%04x%04x = %lg %s\n",
374 374 i, fpru.reg.exponent,
375 375 fpru.reg.significand[3], fpru.reg.significand[2],
376 376 fpru.reg.significand[1], fpru.reg.significand[0],
377 377 fpru.ld, fptag2str(tag_value));
378 378 }
379 379
380 380 x86_pt_fpregs_sse_ctl(fps.mxcsr, fps.xstatus, buf, sizeof (buf));
381 381
382 382 return (DCMD_OK);
383 383 }
384 384
385 385 /*ARGSUSED*/
386 386 int
387 387 pt_getfpreg(mdb_tgt_t *t, mdb_tgt_tid_t tid, ushort_t rd_num,
388 388 ushort_t rd_flags, mdb_tgt_reg_t *rp)
389 389 {
390 390 return (set_errno(ENOTSUP));
391 391 }
392 392
393 393 /*ARGSUSED*/
394 394 int
395 395 pt_putfpreg(mdb_tgt_t *t, mdb_tgt_tid_t tid, ushort_t rd_num,
396 396 ushort_t rd_flags, mdb_tgt_reg_t rval)
397 397 {
398 398 return (set_errno(ENOTSUP));
399 399 }
400 400
401 401 /*ARGSUSED*/
402 402 void
403 403 pt_addfpregs(mdb_tgt_t *t)
404 404 {
405 405 /* not implemented */
406 406 }
407 407
408 408 /*ARGSUSED*/
409 409 int
410 410 pt_frameregs(void *arglim, uintptr_t pc, uint_t argc, const long *argv,
411 411 const mdb_tgt_gregset_t *gregs, boolean_t pc_faked)
412 412 {
413 413 return (set_errno(ENOTSUP));
414 414 }
415 415
416 416 /*ARGSUSED*/
417 417 const char *
418 418 pt_disasm(const GElf_Ehdr *ehp)
419 419 {
420 420 return ("amd64");
421 421 }
422 422
423 423 /*
424 424 * Determine the return address for the current frame.
425 425 */
426 426 int
427 427 pt_step_out(mdb_tgt_t *t, uintptr_t *p)
428 428 {
429 429 const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp;
430 430
431 431 if (Pstate(t->t_pshandle) != PS_STOP)
432 432 return (set_errno(EMDB_TGTBUSY));
433 433
434 434 return (mdb_amd64_step_out(t, p, psp->pr_reg[REG_RIP],
435 435 psp->pr_reg[REG_RBP], psp->pr_reg[REG_RSP], psp->pr_instr));
436 436 }
437 437
438 438 /*
439 439 * Return the address of the next instruction following a call, or return -1
440 440 * and set errno to EAGAIN if the target should just single-step.
441 441 */
442 442 int
443 443 pt_next(mdb_tgt_t *t, uintptr_t *p)
444 444 {
445 445 const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp;
446 446
447 447 if (Pstate(t->t_pshandle) != PS_STOP)
448 448 return (set_errno(EMDB_TGTBUSY));
449 449
450 450 return (mdb_amd64_next(t, p, psp->pr_reg[REG_RIP], pt_read_instr(t)));
451 451 }
|
↓ open down ↓ |
451 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX