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 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
28 * Copyright (c) 2013 by Delphix. All rights reserved.
29 */
30
31 #include <sys/types.h>
32 #include <sys/uio.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <limits.h>
36
37 #include "Pcontrol.h"
38 #include "P32ton.h"
39
40 /*
41 * This file implements the routines to read and write per-lwp register
42 * information from either a live process or core file opened with libproc.
43 * We build up a few common routines for reading and writing register
44 * information, and then the public functions are all trivial calls to these.
45 */
46
47 /*
48 * Utility function to return a pointer to the structure of cached information
49 * about an lwp in the core file, given its lwpid.
50 */
51 static lwp_info_t *
getlwpcore(struct ps_prochandle * P,lwpid_t lwpid)52 getlwpcore(struct ps_prochandle *P, lwpid_t lwpid)
53 {
54 core_info_t *core = P->data;
55 lwp_info_t *lwp = list_next(&core->core_lwp_head);
56 uint_t i;
57
58 for (i = 0; i < core->core_nlwp; i++, lwp = list_next(lwp)) {
59 if (lwp->lwp_id == lwpid)
60 return (lwp);
61 }
62
63 errno = EINVAL;
64 return (NULL);
65 }
66
67 /*
68 * Utility function to open and read the contents of a per-lwp /proc file.
69 * This function is used to slurp in lwpstatus, xregs, and asrs.
70 */
71 static int
getlwpfile(struct ps_prochandle * P,lwpid_t lwpid,const char * fbase,void * rp,size_t n)72 getlwpfile(struct ps_prochandle *P, lwpid_t lwpid,
73 const char *fbase, void *rp, size_t n)
74 {
75 char fname[PATH_MAX];
76 int fd;
77
78 (void) snprintf(fname, sizeof (fname), "%s/%d/lwp/%d/%s",
79 procfs_path, (int)P->status.pr_pid, (int)lwpid, fbase);
80
81 if ((fd = open(fname, O_RDONLY)) >= 0) {
82 if (read(fd, rp, n) > 0) {
83 (void) close(fd);
84 return (0);
85 }
86 (void) close(fd);
87 }
88 return (-1);
89 }
90
91 /*
92 * Get the lwpstatus_t for an lwp from either the live process or our
93 * cached information from the core file. This is used to get the
94 * general-purpose registers or floating point registers.
95 */
96 int
getlwpstatus(struct ps_prochandle * P,lwpid_t lwpid,lwpstatus_t * lps)97 getlwpstatus(struct ps_prochandle *P, lwpid_t lwpid, lwpstatus_t *lps)
98 {
99 lwp_info_t *lwp;
100
101 /*
102 * For both live processes and cores, our job is easy if the lwpid
103 * matches that of the representative lwp:
104 */
105 if (P->status.pr_lwp.pr_lwpid == lwpid) {
106 (void) memcpy(lps, &P->status.pr_lwp, sizeof (lwpstatus_t));
107 return (0);
108 }
109
110 /*
111 * If this is a live process, then just read the information out
112 * of the per-lwp status file:
113 */
114 if (P->state != PS_DEAD) {
115 return (getlwpfile(P, lwpid, "lwpstatus",
116 lps, sizeof (lwpstatus_t)));
117 }
118
119 /*
120 * If this is a core file, we need to iterate through our list of
121 * cached lwp information and then copy out the status.
122 */
123 if (P->data != NULL && (lwp = getlwpcore(P, lwpid)) != NULL) {
124 (void) memcpy(lps, &lwp->lwp_status, sizeof (lwpstatus_t));
125 return (0);
126 }
127
128 return (-1);
129 }
130
131 /*
132 * Utility function to modify lwp registers. This is done using either the
133 * process control file or per-lwp control file as necessary.
134 */
135 static int
setlwpregs(struct ps_prochandle * P,lwpid_t lwpid,long cmd,const void * rp,size_t n)136 setlwpregs(struct ps_prochandle *P, lwpid_t lwpid, long cmd,
137 const void *rp, size_t n)
138 {
139 iovec_t iov[2];
140 char fname[PATH_MAX];
141 int fd;
142
143 if (P->state != PS_STOP) {
144 errno = EBUSY;
145 return (-1);
146 }
147
148 iov[0].iov_base = (caddr_t)&cmd;
149 iov[0].iov_len = sizeof (long);
150 iov[1].iov_base = (caddr_t)rp;
151 iov[1].iov_len = n;
152
153 /*
154 * Writing the process control file writes the representative lwp.
155 * Psync before we write to make sure we are consistent with the
156 * primary interfaces. Similarly, make sure to update P->status
157 * afterward if we are modifying one of its register sets.
158 */
159 if (P->status.pr_lwp.pr_lwpid == lwpid) {
160 Psync(P);
161
162 if (writev(P->ctlfd, iov, 2) == -1)
163 return (-1);
164
165 if (cmd == PCSREG)
166 (void) memcpy(P->status.pr_lwp.pr_reg, rp, n);
167 else if (cmd == PCSFPREG)
168 (void) memcpy(&P->status.pr_lwp.pr_fpreg, rp, n);
169
170 return (0);
171 }
172
173 /*
174 * If the lwp we want is not the representative lwp, we need to
175 * open the ctl file for that specific lwp.
176 */
177 (void) snprintf(fname, sizeof (fname), "%s/%d/lwp/%d/lwpctl",
178 procfs_path, (int)P->status.pr_pid, (int)lwpid);
179
180 if ((fd = open(fname, O_WRONLY)) >= 0) {
181 if (writev(fd, iov, 2) > 0) {
182 (void) close(fd);
183 return (0);
184 }
185 (void) close(fd);
186 }
187 return (-1);
188 }
189
190 int
Plwp_getregs(struct ps_prochandle * P,lwpid_t lwpid,prgregset_t gregs)191 Plwp_getregs(struct ps_prochandle *P, lwpid_t lwpid, prgregset_t gregs)
192 {
193 lwpstatus_t lps;
194
195 if (getlwpstatus(P, lwpid, &lps) == -1)
196 return (-1);
197
198 (void) memcpy(gregs, lps.pr_reg, sizeof (prgregset_t));
199 return (0);
200 }
201
202 int
Plwp_setregs(struct ps_prochandle * P,lwpid_t lwpid,const prgregset_t gregs)203 Plwp_setregs(struct ps_prochandle *P, lwpid_t lwpid, const prgregset_t gregs)
204 {
205 return (setlwpregs(P, lwpid, PCSREG, gregs, sizeof (prgregset_t)));
206 }
207
208 int
Plwp_getfpregs(struct ps_prochandle * P,lwpid_t lwpid,prfpregset_t * fpregs)209 Plwp_getfpregs(struct ps_prochandle *P, lwpid_t lwpid, prfpregset_t *fpregs)
210 {
211 lwpstatus_t lps;
212
213 if (getlwpstatus(P, lwpid, &lps) == -1)
214 return (-1);
215
216 (void) memcpy(fpregs, &lps.pr_fpreg, sizeof (prfpregset_t));
217 return (0);
218 }
219
Plwp_setfpregs(struct ps_prochandle * P,lwpid_t lwpid,const prfpregset_t * fpregs)220 int Plwp_setfpregs(struct ps_prochandle *P, lwpid_t lwpid,
221 const prfpregset_t *fpregs)
222 {
223 return (setlwpregs(P, lwpid, PCSFPREG, fpregs, sizeof (prfpregset_t)));
224 }
225
226 #if defined(sparc) || defined(__sparc)
227 int
Plwp_getxregs(struct ps_prochandle * P,lwpid_t lwpid,prxregset_t * xregs)228 Plwp_getxregs(struct ps_prochandle *P, lwpid_t lwpid, prxregset_t *xregs)
229 {
230 lwp_info_t *lwp;
231
232 if (P->state == PS_IDLE) {
233 errno = ENODATA;
234 return (-1);
235 }
236
237 if (P->state != PS_DEAD) {
238 if (P->state != PS_STOP) {
239 errno = EBUSY;
240 return (-1);
241 }
242
243 return (getlwpfile(P, lwpid, "xregs",
244 xregs, sizeof (prxregset_t)));
245 }
246
247 if ((lwp = getlwpcore(P, lwpid)) != NULL && lwp->lwp_xregs != NULL) {
248 (void) memcpy(xregs, lwp->lwp_xregs, sizeof (prxregset_t));
249 return (0);
250 }
251
252 if (lwp != NULL)
253 errno = ENODATA;
254 return (-1);
255 }
256
257 int
Plwp_setxregs(struct ps_prochandle * P,lwpid_t lwpid,const prxregset_t * xregs)258 Plwp_setxregs(struct ps_prochandle *P, lwpid_t lwpid, const prxregset_t *xregs)
259 {
260 return (setlwpregs(P, lwpid, PCSXREG, xregs, sizeof (prxregset_t)));
261 }
262
263 int
Plwp_getgwindows(struct ps_prochandle * P,lwpid_t lwpid,gwindows_t * gwins)264 Plwp_getgwindows(struct ps_prochandle *P, lwpid_t lwpid, gwindows_t *gwins)
265 {
266 lwp_info_t *lwp;
267
268 if (P->state == PS_IDLE) {
269 errno = ENODATA;
270 return (-1);
271 }
272
273 if (P->state != PS_DEAD) {
274 if (P->state != PS_STOP) {
275 errno = EBUSY;
276 return (-1);
277 }
278
279 return (getlwpfile(P, lwpid, "gwindows",
280 gwins, sizeof (gwindows_t)));
281 }
282
283 if ((lwp = getlwpcore(P, lwpid)) != NULL && lwp->lwp_gwins != NULL) {
284 *gwins = *lwp->lwp_gwins;
285 return (0);
286 }
287
288 if (lwp != NULL)
289 errno = ENODATA;
290 return (-1);
291 }
292
293 #if defined(__sparcv9)
294 int
Plwp_getasrs(struct ps_prochandle * P,lwpid_t lwpid,asrset_t asrs)295 Plwp_getasrs(struct ps_prochandle *P, lwpid_t lwpid, asrset_t asrs)
296 {
297 lwp_info_t *lwp;
298
299 if (P->state == PS_IDLE) {
300 errno = ENODATA;
301 return (-1);
302 }
303
304 if (P->state != PS_DEAD) {
305 if (P->state != PS_STOP) {
306 errno = EBUSY;
307 return (-1);
308 }
309
310 return (getlwpfile(P, lwpid, "asrs", asrs, sizeof (asrset_t)));
311 }
312
313 if ((lwp = getlwpcore(P, lwpid)) != NULL && lwp->lwp_asrs != NULL) {
314 (void) memcpy(asrs, lwp->lwp_asrs, sizeof (asrset_t));
315 return (0);
316 }
317
318 if (lwp != NULL)
319 errno = ENODATA;
320 return (-1);
321
322 }
323
324 int
Plwp_setasrs(struct ps_prochandle * P,lwpid_t lwpid,const asrset_t asrs)325 Plwp_setasrs(struct ps_prochandle *P, lwpid_t lwpid, const asrset_t asrs)
326 {
327 return (setlwpregs(P, lwpid, PCSASRS, asrs, sizeof (asrset_t)));
328 }
329 #endif /* __sparcv9 */
330 #endif /* __sparc */
331
332 int
Plwp_getpsinfo(struct ps_prochandle * P,lwpid_t lwpid,lwpsinfo_t * lps)333 Plwp_getpsinfo(struct ps_prochandle *P, lwpid_t lwpid, lwpsinfo_t *lps)
334 {
335 lwp_info_t *lwp;
336
337 if (P->state == PS_IDLE) {
338 errno = ENODATA;
339 return (-1);
340 }
341
342 if (P->state != PS_DEAD) {
343 return (getlwpfile(P, lwpid, "lwpsinfo",
344 lps, sizeof (lwpsinfo_t)));
345 }
346
347 if ((lwp = getlwpcore(P, lwpid)) != NULL) {
348 (void) memcpy(lps, &lwp->lwp_psinfo, sizeof (lwpsinfo_t));
349 return (0);
350 }
351
352 return (-1);
353 }
354
355 int
Plwp_getspymaster(struct ps_prochandle * P,lwpid_t lwpid,psinfo_t * ps)356 Plwp_getspymaster(struct ps_prochandle *P, lwpid_t lwpid, psinfo_t *ps)
357 {
358 lwpstatus_t lps;
359
360 if (P->state == PS_IDLE) {
361 errno = ENODATA;
362 return (-1);
363 }
364
365 if (getlwpstatus(P, lwpid, &lps) != 0)
366 return (-1);
367
368 if (!(lps.pr_flags & PR_AGENT)) {
369 errno = EINVAL;
370 return (-1);
371 }
372
373 if (P->state != PS_DEAD) {
374 return (getlwpfile(P, lwpid, "spymaster",
375 ps, sizeof (psinfo_t)));
376 }
377
378 if (P->spymaster.pr_nlwp != 0) {
379 (void) memcpy(ps, &P->spymaster, sizeof (psinfo_t));
380 return (0);
381 }
382
383 errno = ENODATA;
384
385 return (-1);
386 }
387
388 int
Plwp_stack(struct ps_prochandle * P,lwpid_t lwpid,stack_t * stkp)389 Plwp_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp)
390 {
391 uintptr_t addr;
392
393 if (P->state == PS_IDLE) {
394 errno = ENODATA;
395 return (-1);
396 }
397
398 if (P->state != PS_DEAD) {
399 lwpstatus_t ls;
400 if (getlwpfile(P, lwpid, "lwpstatus", &ls, sizeof (ls)) != 0)
401 return (-1);
402 addr = ls.pr_ustack;
403 } else {
404 lwp_info_t *lwp;
405 if ((lwp = getlwpcore(P, lwpid)) == NULL)
406 return (-1);
407 addr = lwp->lwp_status.pr_ustack;
408 }
409
410
411 if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
412 if (Pread(P, stkp, sizeof (*stkp), addr) != sizeof (*stkp))
413 return (-1);
414 #ifdef _LP64
415 } else {
416 stack32_t stk32;
417
418 if (Pread(P, &stk32, sizeof (stk32), addr) != sizeof (stk32))
419 return (-1);
420
421 stack_32_to_n(&stk32, stkp);
422 #endif
423 }
424
425 return (0);
426 }
427
428 int
Plwp_main_stack(struct ps_prochandle * P,lwpid_t lwpid,stack_t * stkp)429 Plwp_main_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp)
430 {
431 uintptr_t addr;
432 lwpstatus_t ls;
433
434 if (P->state == PS_IDLE) {
435 errno = ENODATA;
436 return (-1);
437 }
438
439 if (P->state != PS_DEAD) {
440 if (getlwpfile(P, lwpid, "lwpstatus", &ls, sizeof (ls)) != 0)
441 return (-1);
442 } else {
443 lwp_info_t *lwp;
444 if ((lwp = getlwpcore(P, lwpid)) == NULL)
445 return (-1);
446 ls = lwp->lwp_status;
447 }
448
449 addr = ls.pr_ustack;
450
451 /*
452 * Read out the current stack; if the SS_ONSTACK flag is set then
453 * this LWP is operating on the alternate signal stack. We can
454 * recover the original stack from pr_oldcontext.
455 */
456 if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
457 if (Pread(P, stkp, sizeof (*stkp), addr) != sizeof (*stkp))
458 return (-1);
459
460 if (stkp->ss_flags & SS_ONSTACK)
461 goto on_altstack;
462 #ifdef _LP64
463 } else {
464 stack32_t stk32;
465
466 if (Pread(P, &stk32, sizeof (stk32), addr) != sizeof (stk32))
467 return (-1);
468
469 if (stk32.ss_flags & SS_ONSTACK)
470 goto on_altstack;
471
472 stack_32_to_n(&stk32, stkp);
473 #endif
474 }
475
476 return (0);
477
478 on_altstack:
479
480 if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
481 ucontext_t *ctxp = (void *)ls.pr_oldcontext;
482
483 if (Pread(P, stkp, sizeof (*stkp),
484 (uintptr_t)&ctxp->uc_stack) != sizeof (*stkp))
485 return (-1);
486 #ifdef _LP64
487 } else {
488 ucontext32_t *ctxp = (void *)ls.pr_oldcontext;
489 stack32_t stk32;
490
491 if (Pread(P, &stk32, sizeof (stk32),
492 (uintptr_t)&ctxp->uc_stack) != sizeof (stk32))
493 return (-1);
494
495 stack_32_to_n(&stk32, stkp);
496 #endif
497 }
498
499 return (0);
500 }
501
502 int
Plwp_alt_stack(struct ps_prochandle * P,lwpid_t lwpid,stack_t * stkp)503 Plwp_alt_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp)
504 {
505 if (P->state == PS_IDLE) {
506 errno = ENODATA;
507 return (-1);
508 }
509
510 if (P->state != PS_DEAD) {
511 lwpstatus_t ls;
512
513 if (getlwpfile(P, lwpid, "lwpstatus", &ls, sizeof (ls)) != 0)
514 return (-1);
515
516 if (ls.pr_altstack.ss_flags & SS_DISABLE) {
517 errno = ENODATA;
518 return (-1);
519 }
520
521 *stkp = ls.pr_altstack;
522 } else {
523 lwp_info_t *lwp;
524
525 if ((lwp = getlwpcore(P, lwpid)) == NULL)
526 return (-1);
527
528 if (lwp->lwp_status.pr_altstack.ss_flags & SS_DISABLE) {
529 errno = ENODATA;
530 return (-1);
531 }
532
533 *stkp = lwp->lwp_status.pr_altstack;
534 }
535
536 return (0);
537 }
538