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 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 *
26 * Portions Copyright 2007 Chad Mynhier
27 * Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
28 * Copyright (c) 2013 by Delphix. All rights reserved.
29 * Copyright 2015, Joyent, Inc.
30 * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
31 * Copyright 2021 Oxide Computer Company
32 */
33
34 #include <assert.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <ctype.h>
39 #include <fcntl.h>
40 #include <string.h>
41 #include <strings.h>
42 #include <memory.h>
43 #include <errno.h>
44 #include <dirent.h>
45 #include <limits.h>
46 #include <signal.h>
47 #include <atomic.h>
48 #include <zone.h>
49 #include <sys/types.h>
50 #include <sys/uio.h>
51 #include <sys/stat.h>
3138 return (core->core_content);
3139 if (P->state == PS_IDLE)
3140 return (CC_CONTENT_TEXT | CC_CONTENT_DATA | CC_CONTENT_CTF);
3141
3142 return (CC_CONTENT_ALL);
3143 }
3144
3145 /*
3146 * =================================================================
3147 * The remainder of the functions in this file are for the
3148 * control of individual LWPs in the controlled process.
3149 * =================================================================
3150 */
3151
3152 /*
3153 * Find an entry in the process hash table for the specified lwpid.
3154 * The entry will either point to an existing struct ps_lwphandle
3155 * or it will point to an empty slot for a new struct ps_lwphandle.
3156 */
3157 static struct ps_lwphandle **
3158 Lfind(struct ps_prochandle *P, lwpid_t lwpid)
3159 {
3160 struct ps_lwphandle **Lp;
3161 struct ps_lwphandle *L;
3162
3163 for (Lp = &P->hashtab[lwpid % (HASHSIZE - 1)];
3164 (L = *Lp) != NULL; Lp = &L->lwp_hash)
3165 if (L->lwp_id == lwpid)
3166 break;
3167 return (Lp);
3168 }
3169
3170 /*
3171 * Grab an LWP contained within the controlled process.
3172 * Return an opaque pointer to its LWP control structure.
3173 * perr: pointer to error return code.
3174 */
3175 struct ps_lwphandle *
3176 Lgrab(struct ps_prochandle *P, lwpid_t lwpid, int *perr)
3177 {
3178 struct ps_lwphandle **Lp;
3179 struct ps_lwphandle *L;
3180 int fd;
3181 char procname[PATH_MAX];
3182 char *fname;
3183 int rc = 0;
3184
3185 (void) mutex_lock(&P->proc_lock);
3186
3187 if (P->state == PS_UNDEAD || P->state == PS_IDLE)
3188 rc = G_NOPROC;
3189 else if (P->hashtab == NULL &&
3190 (P->hashtab = calloc(HASHSIZE, sizeof (struct ps_lwphandle *)))
3191 == NULL)
3192 rc = G_STRANGE;
3193 else if (*(Lp = Lfind(P, lwpid)) != NULL)
3194 rc = G_BUSY;
3195 else if ((L = malloc(sizeof (struct ps_lwphandle))) == NULL)
3196 rc = G_STRANGE;
3197 if (rc) {
3198 *perr = rc;
3199 (void) mutex_unlock(&P->proc_lock);
3200 return (NULL);
3201 }
3202
3203 (void) memset(L, 0, sizeof (*L));
3204 L->lwp_ctlfd = -1;
3205 L->lwp_statfd = -1;
3206 L->lwp_proc = P;
3207 L->lwp_id = lwpid;
3208 *Lp = L; /* insert into the hash table */
3209
3210 if (P->state == PS_DEAD) { /* core file */
3211 if (getlwpstatus(P, lwpid, &L->lwp_status) == -1) {
3212 rc = G_NOPROC;
3213 goto err;
3315
3316 return (str);
3317 }
3318
3319 /*
3320 * Free an LWP control structure.
3321 */
3322 void
3323 Lfree(struct ps_lwphandle *L)
3324 {
3325 struct ps_prochandle *P = L->lwp_proc;
3326
3327 (void) mutex_lock(&P->proc_lock);
3328 Lfree_internal(P, L);
3329 (void) mutex_unlock(&P->proc_lock);
3330 }
3331
3332 static void
3333 Lfree_internal(struct ps_prochandle *P, struct ps_lwphandle *L)
3334 {
3335 *Lfind(P, L->lwp_id) = L->lwp_hash; /* delete from hash table */
3336 if (L->lwp_ctlfd >= 0)
3337 (void) close(L->lwp_ctlfd);
3338 if (L->lwp_statfd >= 0)
3339 (void) close(L->lwp_statfd);
3340
3341 /* clear out the structure as a precaution against reuse */
3342 (void) memset(L, 0, sizeof (*L));
3343 L->lwp_ctlfd = -1;
3344 L->lwp_statfd = -1;
3345
3346 free(L);
3347 }
3348
3349 /*
3350 * Return the state of the process, one of the PS_* values.
3351 */
3352 int
3353 Lstate(struct ps_lwphandle *L)
3354 {
3355 return (L->lwp_state);
3421 }
3422 if (L->lwp_flags & SETREGS) {
3423 cmd[1] = PCSREG;
3424 iov[n].iov_base = (caddr_t)&cmd[1];
3425 iov[n++].iov_len = sizeof (long);
3426 iov[n].iov_base = (caddr_t)&L->lwp_status.pr_reg[0];
3427 iov[n++].iov_len = sizeof (L->lwp_status.pr_reg);
3428 }
3429
3430 if (n == 0 || writev(ctlfd, iov, n) < 0)
3431 return; /* nothing to do or write failed */
3432
3433 L->lwp_flags &= ~(SETHOLD|SETREGS);
3434 }
3435
3436 /*
3437 * Wait for the specified LWP to stop or terminate.
3438 * Or, just get the current status (PCNULL).
3439 * Or, direct it to stop and get the current status (PCDSTOP).
3440 */
3441 static int
3442 Lstopstatus(struct ps_lwphandle *L,
3443 long request, /* PCNULL, PCDSTOP, PCSTOP, PCWSTOP */
3444 uint_t msec) /* if non-zero, timeout in milliseconds */
3445 {
3446 int ctlfd = L->lwp_ctlfd;
3447 long ctl[3];
3448 ssize_t rc;
3449 int err;
3450
3451 switch (L->lwp_state) {
3452 case PS_RUN:
3453 break;
3454 case PS_STOP:
3455 if (request != PCNULL && request != PCDSTOP)
3456 return (0);
3457 break;
3458 case PS_LOST:
3459 if (request != PCNULL) {
3460 errno = EAGAIN;
3461 return (-1);
|
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 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 *
26 * Portions Copyright 2007 Chad Mynhier
27 * Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
28 * Copyright (c) 2013 by Delphix. All rights reserved.
29 * Copyright 2015, Joyent, Inc.
30 * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
31 * Copyright 2023 Oxide Computer Company
32 */
33
34 #include <assert.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <ctype.h>
39 #include <fcntl.h>
40 #include <string.h>
41 #include <strings.h>
42 #include <memory.h>
43 #include <errno.h>
44 #include <dirent.h>
45 #include <limits.h>
46 #include <signal.h>
47 #include <atomic.h>
48 #include <zone.h>
49 #include <sys/types.h>
50 #include <sys/uio.h>
51 #include <sys/stat.h>
3138 return (core->core_content);
3139 if (P->state == PS_IDLE)
3140 return (CC_CONTENT_TEXT | CC_CONTENT_DATA | CC_CONTENT_CTF);
3141
3142 return (CC_CONTENT_ALL);
3143 }
3144
3145 /*
3146 * =================================================================
3147 * The remainder of the functions in this file are for the
3148 * control of individual LWPs in the controlled process.
3149 * =================================================================
3150 */
3151
3152 /*
3153 * Find an entry in the process hash table for the specified lwpid.
3154 * The entry will either point to an existing struct ps_lwphandle
3155 * or it will point to an empty slot for a new struct ps_lwphandle.
3156 */
3157 static struct ps_lwphandle **
3158 Lfind_slot(struct ps_prochandle *P, lwpid_t lwpid)
3159 {
3160 struct ps_lwphandle **Lp;
3161 struct ps_lwphandle *L;
3162
3163 for (Lp = &P->hashtab[lwpid % (HASHSIZE - 1)];
3164 (L = *Lp) != NULL; Lp = &L->lwp_hash)
3165 if (L->lwp_id == lwpid)
3166 break;
3167 return (Lp);
3168 }
3169
3170 /*
3171 * A wrapper around Lfind_slot() that is suitable for the rest of the internal
3172 * consumers who don't care about a slot, merely existence.
3173 */
3174 struct ps_lwphandle *
3175 Lfind(struct ps_prochandle *P, lwpid_t lwpid)
3176 {
3177 if (P->hashtab == NULL) {
3178 return (NULL);
3179 }
3180
3181 return (*Lfind_slot(P, lwpid));
3182 }
3183
3184 /*
3185 * Grab an LWP contained within the controlled process.
3186 * Return an opaque pointer to its LWP control structure.
3187 * perr: pointer to error return code.
3188 */
3189 struct ps_lwphandle *
3190 Lgrab(struct ps_prochandle *P, lwpid_t lwpid, int *perr)
3191 {
3192 struct ps_lwphandle **Lp;
3193 struct ps_lwphandle *L;
3194 int fd;
3195 char procname[PATH_MAX];
3196 char *fname;
3197 int rc = 0;
3198
3199 (void) mutex_lock(&P->proc_lock);
3200
3201 if (P->state == PS_UNDEAD || P->state == PS_IDLE)
3202 rc = G_NOPROC;
3203 else if (P->hashtab == NULL &&
3204 (P->hashtab = calloc(HASHSIZE, sizeof (struct ps_lwphandle *)))
3205 == NULL)
3206 rc = G_STRANGE;
3207 else if (*(Lp = Lfind_slot(P, lwpid)) != NULL)
3208 rc = G_BUSY;
3209 else if ((L = malloc(sizeof (struct ps_lwphandle))) == NULL)
3210 rc = G_STRANGE;
3211 if (rc) {
3212 *perr = rc;
3213 (void) mutex_unlock(&P->proc_lock);
3214 return (NULL);
3215 }
3216
3217 (void) memset(L, 0, sizeof (*L));
3218 L->lwp_ctlfd = -1;
3219 L->lwp_statfd = -1;
3220 L->lwp_proc = P;
3221 L->lwp_id = lwpid;
3222 *Lp = L; /* insert into the hash table */
3223
3224 if (P->state == PS_DEAD) { /* core file */
3225 if (getlwpstatus(P, lwpid, &L->lwp_status) == -1) {
3226 rc = G_NOPROC;
3227 goto err;
3329
3330 return (str);
3331 }
3332
3333 /*
3334 * Free an LWP control structure.
3335 */
3336 void
3337 Lfree(struct ps_lwphandle *L)
3338 {
3339 struct ps_prochandle *P = L->lwp_proc;
3340
3341 (void) mutex_lock(&P->proc_lock);
3342 Lfree_internal(P, L);
3343 (void) mutex_unlock(&P->proc_lock);
3344 }
3345
3346 static void
3347 Lfree_internal(struct ps_prochandle *P, struct ps_lwphandle *L)
3348 {
3349 *Lfind_slot(P, L->lwp_id) = L->lwp_hash; /* delete from hash table */
3350 if (L->lwp_ctlfd >= 0)
3351 (void) close(L->lwp_ctlfd);
3352 if (L->lwp_statfd >= 0)
3353 (void) close(L->lwp_statfd);
3354
3355 /* clear out the structure as a precaution against reuse */
3356 (void) memset(L, 0, sizeof (*L));
3357 L->lwp_ctlfd = -1;
3358 L->lwp_statfd = -1;
3359
3360 free(L);
3361 }
3362
3363 /*
3364 * Return the state of the process, one of the PS_* values.
3365 */
3366 int
3367 Lstate(struct ps_lwphandle *L)
3368 {
3369 return (L->lwp_state);
3435 }
3436 if (L->lwp_flags & SETREGS) {
3437 cmd[1] = PCSREG;
3438 iov[n].iov_base = (caddr_t)&cmd[1];
3439 iov[n++].iov_len = sizeof (long);
3440 iov[n].iov_base = (caddr_t)&L->lwp_status.pr_reg[0];
3441 iov[n++].iov_len = sizeof (L->lwp_status.pr_reg);
3442 }
3443
3444 if (n == 0 || writev(ctlfd, iov, n) < 0)
3445 return; /* nothing to do or write failed */
3446
3447 L->lwp_flags &= ~(SETHOLD|SETREGS);
3448 }
3449
3450 /*
3451 * Wait for the specified LWP to stop or terminate.
3452 * Or, just get the current status (PCNULL).
3453 * Or, direct it to stop and get the current status (PCDSTOP).
3454 */
3455 int
3456 Lstopstatus(struct ps_lwphandle *L,
3457 long request, /* PCNULL, PCDSTOP, PCSTOP, PCWSTOP */
3458 uint_t msec) /* if non-zero, timeout in milliseconds */
3459 {
3460 int ctlfd = L->lwp_ctlfd;
3461 long ctl[3];
3462 ssize_t rc;
3463 int err;
3464
3465 switch (L->lwp_state) {
3466 case PS_RUN:
3467 break;
3468 case PS_STOP:
3469 if (request != PCNULL && request != PCDSTOP)
3470 return (0);
3471 break;
3472 case PS_LOST:
3473 if (request != PCNULL) {
3474 errno = EAGAIN;
3475 return (-1);
|