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.
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.
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]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
28 * Copyright (c) 2013 by Delphix. All rights reserved.
31 #include <sys/types.h>
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.
48 * Utility function to return a pointer to the structure of cached information
49 * about an lwp in the core file, given its lwpid.
52 getlwpcore(struct ps_prochandle
*P
, lwpid_t lwpid
)
54 core_info_t
*core
= P
->data
;
55 lwp_info_t
*lwp
= list_next(&core
->core_lwp_head
);
58 for (i
= 0; i
< core
->core_nlwp
; i
++, lwp
= list_next(lwp
)) {
59 if (lwp
->lwp_id
== lwpid
)
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.
72 getlwpfile(struct ps_prochandle
*P
, lwpid_t lwpid
,
73 const char *fbase
, void *rp
, size_t n
)
78 (void) snprintf(fname
, sizeof (fname
), "%s/%d/lwp/%d/%s",
79 procfs_path
, (int)P
->status
.pr_pid
, (int)lwpid
, fbase
);
81 if ((fd
= open(fname
, O_RDONLY
)) >= 0) {
82 if (read(fd
, rp
, n
) > 0) {
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.
97 getlwpstatus(struct ps_prochandle
*P
, lwpid_t lwpid
, lwpstatus_t
*lps
)
102 * For both live processes and cores, our job is easy if the lwpid
103 * matches that of the representative lwp:
105 if (P
->status
.pr_lwp
.pr_lwpid
== lwpid
) {
106 (void) memcpy(lps
, &P
->status
.pr_lwp
, sizeof (lwpstatus_t
));
111 * If this is a live process, then just read the information out
112 * of the per-lwp status file:
114 if (P
->state
!= PS_DEAD
) {
115 return (getlwpfile(P
, lwpid
, "lwpstatus",
116 lps
, sizeof (lwpstatus_t
)));
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.
123 if (P
->data
!= NULL
&& (lwp
= getlwpcore(P
, lwpid
)) != NULL
) {
124 (void) memcpy(lps
, &lwp
->lwp_status
, sizeof (lwpstatus_t
));
132 * Utility function to modify lwp registers. This is done using either the
133 * process control file or per-lwp control file as necessary.
136 setlwpregs(struct ps_prochandle
*P
, lwpid_t lwpid
, long cmd
,
137 const void *rp
, size_t n
)
140 char fname
[PATH_MAX
];
143 if (P
->state
!= PS_STOP
) {
148 iov
[0].iov_base
= (caddr_t
)&cmd
;
149 iov
[0].iov_len
= sizeof (long);
150 iov
[1].iov_base
= (caddr_t
)rp
;
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.
159 if (P
->status
.pr_lwp
.pr_lwpid
== lwpid
) {
162 if (writev(P
->ctlfd
, iov
, 2) == -1)
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
);
174 * If the lwp we want is not the representative lwp, we need to
175 * open the ctl file for that specific lwp.
177 (void) snprintf(fname
, sizeof (fname
), "%s/%d/lwp/%d/lwpctl",
178 procfs_path
, (int)P
->status
.pr_pid
, (int)lwpid
);
180 if ((fd
= open(fname
, O_WRONLY
)) >= 0) {
181 if (writev(fd
, iov
, 2) > 0) {
191 Plwp_getregs(struct ps_prochandle
*P
, lwpid_t lwpid
, prgregset_t gregs
)
195 if (getlwpstatus(P
, lwpid
, &lps
) == -1)
198 (void) memcpy(gregs
, lps
.pr_reg
, sizeof (prgregset_t
));
203 Plwp_setregs(struct ps_prochandle
*P
, lwpid_t lwpid
, const prgregset_t gregs
)
205 return (setlwpregs(P
, lwpid
, PCSREG
, gregs
, sizeof (prgregset_t
)));
209 Plwp_getfpregs(struct ps_prochandle
*P
, lwpid_t lwpid
, prfpregset_t
*fpregs
)
213 if (getlwpstatus(P
, lwpid
, &lps
) == -1)
216 (void) memcpy(fpregs
, &lps
.pr_fpreg
, sizeof (prfpregset_t
));
220 int Plwp_setfpregs(struct ps_prochandle
*P
, lwpid_t lwpid
,
221 const prfpregset_t
*fpregs
)
223 return (setlwpregs(P
, lwpid
, PCSFPREG
, fpregs
, sizeof (prfpregset_t
)));
226 #if defined(sparc) || defined(__sparc)
228 Plwp_getxregs(struct ps_prochandle
*P
, lwpid_t lwpid
, prxregset_t
*xregs
)
232 if (P
->state
== PS_IDLE
) {
237 if (P
->state
!= PS_DEAD
) {
238 if (P
->state
!= PS_STOP
) {
243 return (getlwpfile(P
, lwpid
, "xregs",
244 xregs
, sizeof (prxregset_t
)));
247 if ((lwp
= getlwpcore(P
, lwpid
)) != NULL
&& lwp
->lwp_xregs
!= NULL
) {
248 (void) memcpy(xregs
, lwp
->lwp_xregs
, sizeof (prxregset_t
));
258 Plwp_setxregs(struct ps_prochandle
*P
, lwpid_t lwpid
, const prxregset_t
*xregs
)
260 return (setlwpregs(P
, lwpid
, PCSXREG
, xregs
, sizeof (prxregset_t
)));
264 Plwp_getgwindows(struct ps_prochandle
*P
, lwpid_t lwpid
, gwindows_t
*gwins
)
268 if (P
->state
== PS_IDLE
) {
273 if (P
->state
!= PS_DEAD
) {
274 if (P
->state
!= PS_STOP
) {
279 return (getlwpfile(P
, lwpid
, "gwindows",
280 gwins
, sizeof (gwindows_t
)));
283 if ((lwp
= getlwpcore(P
, lwpid
)) != NULL
&& lwp
->lwp_gwins
!= NULL
) {
284 *gwins
= *lwp
->lwp_gwins
;
293 #if defined(__sparcv9)
295 Plwp_getasrs(struct ps_prochandle
*P
, lwpid_t lwpid
, asrset_t asrs
)
299 if (P
->state
== PS_IDLE
) {
304 if (P
->state
!= PS_DEAD
) {
305 if (P
->state
!= PS_STOP
) {
310 return (getlwpfile(P
, lwpid
, "asrs", asrs
, sizeof (asrset_t
)));
313 if ((lwp
= getlwpcore(P
, lwpid
)) != NULL
&& lwp
->lwp_asrs
!= NULL
) {
314 (void) memcpy(asrs
, lwp
->lwp_asrs
, sizeof (asrset_t
));
325 Plwp_setasrs(struct ps_prochandle
*P
, lwpid_t lwpid
, const asrset_t asrs
)
327 return (setlwpregs(P
, lwpid
, PCSASRS
, asrs
, sizeof (asrset_t
)));
329 #endif /* __sparcv9 */
333 Plwp_getpsinfo(struct ps_prochandle
*P
, lwpid_t lwpid
, lwpsinfo_t
*lps
)
337 if (P
->state
== PS_IDLE
) {
342 if (P
->state
!= PS_DEAD
) {
343 return (getlwpfile(P
, lwpid
, "lwpsinfo",
344 lps
, sizeof (lwpsinfo_t
)));
347 if ((lwp
= getlwpcore(P
, lwpid
)) != NULL
) {
348 (void) memcpy(lps
, &lwp
->lwp_psinfo
, sizeof (lwpsinfo_t
));
356 Plwp_getspymaster(struct ps_prochandle
*P
, lwpid_t lwpid
, psinfo_t
*ps
)
360 if (P
->state
== PS_IDLE
) {
365 if (getlwpstatus(P
, lwpid
, &lps
) != 0)
368 if (!(lps
.pr_flags
& PR_AGENT
)) {
373 if (P
->state
!= PS_DEAD
) {
374 return (getlwpfile(P
, lwpid
, "spymaster",
375 ps
, sizeof (psinfo_t
)));
378 if (P
->spymaster
.pr_nlwp
!= 0) {
379 (void) memcpy(ps
, &P
->spymaster
, sizeof (psinfo_t
));
389 Plwp_stack(struct ps_prochandle
*P
, lwpid_t lwpid
, stack_t
*stkp
)
393 if (P
->state
== PS_IDLE
) {
398 if (P
->state
!= PS_DEAD
) {
400 if (getlwpfile(P
, lwpid
, "lwpstatus", &ls
, sizeof (ls
)) != 0)
405 if ((lwp
= getlwpcore(P
, lwpid
)) == NULL
)
407 addr
= lwp
->lwp_status
.pr_ustack
;
411 if (P
->status
.pr_dmodel
== PR_MODEL_NATIVE
) {
412 if (Pread(P
, stkp
, sizeof (*stkp
), addr
) != sizeof (*stkp
))
418 if (Pread(P
, &stk32
, sizeof (stk32
), addr
) != sizeof (stk32
))
421 stack_32_to_n(&stk32
, stkp
);
429 Plwp_main_stack(struct ps_prochandle
*P
, lwpid_t lwpid
, stack_t
*stkp
)
434 if (P
->state
== PS_IDLE
) {
439 if (P
->state
!= PS_DEAD
) {
440 if (getlwpfile(P
, lwpid
, "lwpstatus", &ls
, sizeof (ls
)) != 0)
444 if ((lwp
= getlwpcore(P
, lwpid
)) == NULL
)
446 ls
= lwp
->lwp_status
;
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.
456 if (P
->status
.pr_dmodel
== PR_MODEL_NATIVE
) {
457 if (Pread(P
, stkp
, sizeof (*stkp
), addr
) != sizeof (*stkp
))
460 if (stkp
->ss_flags
& SS_ONSTACK
)
466 if (Pread(P
, &stk32
, sizeof (stk32
), addr
) != sizeof (stk32
))
469 if (stk32
.ss_flags
& SS_ONSTACK
)
472 stack_32_to_n(&stk32
, stkp
);
480 if (P
->status
.pr_dmodel
== PR_MODEL_NATIVE
) {
481 ucontext_t
*ctxp
= (void *)ls
.pr_oldcontext
;
483 if (Pread(P
, stkp
, sizeof (*stkp
),
484 (uintptr_t)&ctxp
->uc_stack
) != sizeof (*stkp
))
488 ucontext32_t
*ctxp
= (void *)ls
.pr_oldcontext
;
491 if (Pread(P
, &stk32
, sizeof (stk32
),
492 (uintptr_t)&ctxp
->uc_stack
) != sizeof (stk32
))
495 stack_32_to_n(&stk32
, stkp
);
503 Plwp_alt_stack(struct ps_prochandle
*P
, lwpid_t lwpid
, stack_t
*stkp
)
505 if (P
->state
== PS_IDLE
) {
510 if (P
->state
!= PS_DEAD
) {
513 if (getlwpfile(P
, lwpid
, "lwpstatus", &ls
, sizeof (ls
)) != 0)
516 if (ls
.pr_altstack
.ss_flags
& SS_DISABLE
) {
521 *stkp
= ls
.pr_altstack
;
525 if ((lwp
= getlwpcore(P
, lwpid
)) == NULL
)
528 if (lwp
->lwp_status
.pr_altstack
.ss_flags
& SS_DISABLE
) {
533 *stkp
= lwp
->lwp_status
.pr_altstack
;