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