Print this page
15254 %ymm registers not restored after signal handler
15367 x86 getfpregs() summons corrupting %xmm ghosts
15333 want x86 /proc xregs support (libc_db, libproc, mdb, etc.)
15336 want libc functions for extended ucontext_t
15334 want ps_lwphandle-specific reg routines
15328 FPU_CW_INIT mistreats reserved bit
15335 i86pc fpu_subr.c isn't really platform-specific
15332 setcontext(2) isn't actually noreturn
15331 need <sys/stdalign.h>
Change-Id: I7060aa86042dfb989f77fc3323c065ea2eafa9ad
Conflicts:
usr/src/uts/common/fs/proc/prcontrol.c
usr/src/uts/intel/os/archdep.c
usr/src/uts/intel/sys/ucontext.h
usr/src/uts/intel/syscall/getcontext.c
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/libproc/common/Plwpregs.c
+++ new/usr/src/lib/libproc/common/Plwpregs.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 (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
|
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 /*
27 27 * Copyright 2018 Joyent, Inc.
28 28 * Copyright (c) 2013 by Delphix. All rights reserved.
29 + * Copyright 2023 Oxide Computer Company
29 30 */
30 31
31 32 #include <sys/types.h>
32 33 #include <sys/uio.h>
33 34 #include <string.h>
34 35 #include <errno.h>
35 36 #include <limits.h>
36 37
37 38 #include "Pcontrol.h"
38 39 #include "P32ton.h"
39 40
40 41 /*
41 42 * 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.
43 + * information from either a live process or core file opened with libproc. We
44 + * build up a few common routines for reading and writing register information,
45 + * and then the public functions are all trivial calls to these. It also
46 + * implements similar logic that is used with an lwp handle.
47 + *
48 + * The primary registers and floating point registers (e.g. regs,fpregs) are
49 + * retreived from the lwp and process status files. The library caches the
50 + * values of these files. When we perorm updates, we ensure that cached copies
51 + * are refreshed or updated as part of this.
45 52 */
46 53
47 54 /*
48 55 * Utility function to return a pointer to the structure of cached information
49 56 * about an lwp in the core file, given its lwpid.
50 57 */
51 58 static lwp_info_t *
52 59 getlwpcore(struct ps_prochandle *P, lwpid_t lwpid)
53 60 {
54 61 core_info_t *core = P->data;
55 62 lwp_info_t *lwp;
56 63
57 64 for (lwp = list_head(&core->core_lwp_head); lwp != NULL;
58 65 lwp = list_next(&core->core_lwp_head, lwp)) {
59 66 if (lwp->lwp_id == lwpid)
60 67 return (lwp);
61 68 }
62 69
63 - errno = EINVAL;
70 + errno = ENOENT;
64 71 return (NULL);
65 72 }
66 73
67 74 /*
68 75 * 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.
76 + * This function is used to slurp in lwpstatus, lwpname, lwpsinfo, spymaster,
77 + * and others.
70 78 */
71 79 static int
72 80 getlwpfile(struct ps_prochandle *P, lwpid_t lwpid,
73 81 const char *fbase, void *rp, size_t n)
74 82 {
75 83 char fname[PATH_MAX];
76 84 int fd;
77 85
78 86 (void) snprintf(fname, sizeof (fname), "%s/%d/lwp/%d/%s",
79 87 procfs_path, (int)P->status.pr_pid, (int)lwpid, fbase);
80 88
81 89 if ((fd = open(fname, O_RDONLY)) >= 0) {
82 90 if (read(fd, rp, n) > 0) {
83 91 (void) close(fd);
84 92 return (0);
85 93 }
94 +
95 + int e = errno;
86 96 (void) close(fd);
97 + errno = e;
87 98 }
88 99 return (-1);
89 100 }
90 101
91 102 /*
103 + * This is a variant of getlwpfile that has three different semantics:
104 + *
105 + * o It will stat the file to determine the size and allocate that for the
106 + * caller.
107 + * o If the stat size is zero (e.g. traditional xregs behavior when
108 + * unsupported) then it will return the libproc ENODATA error.
109 + * o It is an error if not all the data is read.
110 + *
111 + * Currently this is just used by xregs.
112 + */
113 +static int
114 +getlwpfile_alloc(struct ps_prochandle *P, lwpid_t lwpid, const char *fbase,
115 + void **datap, size_t *sizep)
116 +{
117 + char fname[PATH_MAX];
118 + int fd;
119 +
120 + (void) snprintf(fname, sizeof (fname), "%s/%d/lwp/%d/%s",
121 + procfs_path, (int)P->status.pr_pid, (int)lwpid, fbase);
122 +
123 + if ((fd = open(fname, O_RDONLY)) >= 0) {
124 + int e;
125 + struct stat st;
126 +
127 + if (fstat(fd, &st) == 0) {
128 + prxregset_t *prx;
129 +
130 + if (st.st_size == 0) {
131 + errno = ENODATA;
132 + goto clean;
133 + }
134 +
135 + prx = malloc(st.st_size);
136 + if (prx == NULL) {
137 + goto clean;
138 + }
139 +
140 + if (read(fd, prx, st.st_size) == st.st_size) {
141 + (void) close(fd);
142 + *datap = prx;
143 + *sizep = st.st_size;
144 + return (0);
145 + }
146 +
147 + free(prx);
148 + }
149 +clean:
150 + e = errno;
151 + (void) close(fd);
152 + errno = e;
153 + }
154 +
155 + return (-1);
156 +}
157 +
158 +/*
92 159 * Get the lwpstatus_t for an lwp from either the live process or our
93 160 * cached information from the core file. This is used to get the
94 161 * general-purpose registers or floating point registers.
95 162 */
96 163 int
97 164 getlwpstatus(struct ps_prochandle *P, lwpid_t lwpid, lwpstatus_t *lps)
98 165 {
99 166 lwp_info_t *lwp;
100 167
101 168 /*
102 169 * For both live processes and cores, our job is easy if the lwpid
103 170 * matches that of the representative lwp:
104 171 */
105 172 if (P->status.pr_lwp.pr_lwpid == lwpid) {
106 173 (void) memcpy(lps, &P->status.pr_lwp, sizeof (lwpstatus_t));
107 174 return (0);
108 175 }
109 176
110 177 /*
111 178 * If this is a live process, then just read the information out
112 179 * of the per-lwp status file:
113 180 */
114 181 if (P->state != PS_DEAD) {
115 182 return (getlwpfile(P, lwpid, "lwpstatus",
116 183 lps, sizeof (lwpstatus_t)));
117 184 }
118 185
119 186 /*
120 187 * If this is a core file, we need to iterate through our list of
121 188 * cached lwp information and then copy out the status.
|
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
122 189 */
123 190 if (P->data != NULL && (lwp = getlwpcore(P, lwpid)) != NULL) {
124 191 (void) memcpy(lps, &lwp->lwp_status, sizeof (lwpstatus_t));
125 192 return (0);
126 193 }
127 194
128 195 return (-1);
129 196 }
130 197
131 198 /*
199 + * libproc caches information about the registers for representative LWPs and
200 + * threads which we have the thread handle for. When we do a write to certain
201 + * files, we need to refresh state and take care of both the process and the
202 + * representative LWP's info. Because the xregs may or may not mutate the state
203 + * of the other regsiters, we just always do a refresh of the entire cached
204 + * psinfo.
205 + */
206 +static void
207 +refresh_status(struct ps_prochandle *P, lwpid_t lwpid, struct ps_lwphandle *L,
208 + long cmd, const void *rp, size_t n)
209 +{
210 + if (P->status.pr_lwp.pr_lwpid == lwpid) {
211 + if (cmd == PCSREG)
212 + (void) memcpy(P->status.pr_lwp.pr_reg, rp, n);
213 + else if (cmd == PCSFPREG)
214 + (void) memcpy(&P->status.pr_lwp.pr_fpreg, rp, n);
215 + else if (cmd == PCSXREG)
216 + (void) Pstopstatus(P, PCNULL, 0);
217 + }
218 +
219 + if (L != NULL) {
220 + if (cmd == PCSREG)
221 + (void) memcpy(&L->lwp_status.pr_reg, rp, n);
222 + else if (cmd == PCSFPREG)
223 + (void) memcpy(&L->lwp_status.pr_fpreg, rp, n);
224 + else if (cmd == PCSXREG)
225 + (void) Lstopstatus(L, PCNULL, 0);
226 + }
227 +}
228 +
229 +/*
132 230 * Utility function to modify lwp registers. This is done using either the
133 - * process control file or per-lwp control file as necessary.
231 + * process control file or per-lwp control file as necessary. This assumes that
232 + * we have a process-level hold on things, which may not always be true.
134 233 */
135 234 static int
136 -setlwpregs(struct ps_prochandle *P, lwpid_t lwpid, long cmd,
235 +setlwpregs_proc(struct ps_prochandle *P, lwpid_t lwpid, long cmd,
137 236 const void *rp, size_t n)
138 237 {
139 238 iovec_t iov[2];
140 239 char fname[PATH_MAX];
141 - int fd;
240 + struct ps_lwphandle *L;
241 + int fd = -1;
142 242
143 243 if (P->state != PS_STOP) {
144 244 errno = EBUSY;
145 245 return (-1);
146 246 }
147 247
148 248 iov[0].iov_base = (caddr_t)&cmd;
149 249 iov[0].iov_len = sizeof (long);
150 250 iov[1].iov_base = (caddr_t)rp;
151 251 iov[1].iov_len = n;
152 252
153 253 /*
254 + * If we have an lwp handle for this thread, then make sure that we use
255 + * that to update the state so cached information is updated. We sync
256 + * the thread ahead of the process.
257 + */
258 + if ((L = Lfind(P, lwpid)) != NULL) {
259 + Lsync(L);
260 + fd = L->lwp_ctlfd;
261 + }
262 +
263 + /*
154 264 * Writing the process control file writes the representative lwp.
155 265 * Psync before we write to make sure we are consistent with the
156 266 * primary interfaces. Similarly, make sure to update P->status
157 - * afterward if we are modifying one of its register sets.
267 + * afterward if we are modifying one of its register sets. On some
268 + * platforms the xregs modify the other register states. As a result,
269 + * always refresh the representative LWP's status.
158 270 */
159 271 if (P->status.pr_lwp.pr_lwpid == lwpid) {
160 272 Psync(P);
273 + fd = P->ctlfd;
274 + }
161 275
162 - if (writev(P->ctlfd, iov, 2) == -1)
276 + if (fd > -1) {
277 + if (writev(fd, iov, 2) == -1)
163 278 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 -
279 + refresh_status(P, lwpid, L, cmd, rp, n);
170 280 return (0);
171 281 }
172 282
173 283 /*
174 284 * If the lwp we want is not the representative lwp, we need to
175 285 * open the ctl file for that specific lwp.
176 286 */
177 287 (void) snprintf(fname, sizeof (fname), "%s/%d/lwp/%d/lwpctl",
178 288 procfs_path, (int)P->status.pr_pid, (int)lwpid);
179 289
180 290 if ((fd = open(fname, O_WRONLY)) >= 0) {
181 291 if (writev(fd, iov, 2) > 0) {
182 292 (void) close(fd);
183 293 return (0);
184 294 }
295 + int e = errno;
185 296 (void) close(fd);
297 + errno = e;
186 298 }
187 299 return (-1);
188 300 }
189 301
302 +/*
303 + * This is a variant of the above that only assumes we have a hold on the thread
304 + * as opposed to a process.
305 + */
306 +static int
307 +setlwpregs_lwp(struct ps_lwphandle *L, long cmd, const void *rp, size_t n)
308 +{
309 + iovec_t iov[2];
310 +
311 + if (L->lwp_state != PS_STOP) {
312 + errno = EBUSY;
313 + return (-1);
314 + }
315 +
316 + iov[0].iov_base = (caddr_t)&cmd;
317 + iov[0].iov_len = sizeof (long);
318 + iov[1].iov_base = (caddr_t)rp;
319 + iov[1].iov_len = n;
320 +
321 + Lsync(L);
322 + if (writev(L->lwp_ctlfd, iov, 2) == -1)
323 + return (-1);
324 + refresh_status(L->lwp_proc, L->lwp_id, L, cmd, rp, n);
325 +
326 + return (0);
327 +}
328 +
190 329 int
191 330 Plwp_getregs(struct ps_prochandle *P, lwpid_t lwpid, prgregset_t gregs)
192 331 {
193 332 lwpstatus_t lps;
194 333
195 334 if (getlwpstatus(P, lwpid, &lps) == -1)
196 335 return (-1);
197 336
198 337 (void) memcpy(gregs, lps.pr_reg, sizeof (prgregset_t));
199 338 return (0);
200 339 }
201 340
202 341 int
342 +Lgetregs(struct ps_lwphandle *L, prgregset_t *gregs)
343 +{
344 + (void) memcpy(gregs, L->lwp_status.pr_reg, sizeof (prgregset_t));
345 + return (0);
346 +}
347 +
348 +int
203 349 Plwp_setregs(struct ps_prochandle *P, lwpid_t lwpid, const prgregset_t gregs)
204 350 {
205 - return (setlwpregs(P, lwpid, PCSREG, gregs, sizeof (prgregset_t)));
351 + return (setlwpregs_proc(P, lwpid, PCSREG, gregs, sizeof (prgregset_t)));
206 352 }
207 353
208 354 int
355 +Lsetregs(struct ps_lwphandle *L, const prgregset_t *gregs)
356 +{
357 + return (setlwpregs_lwp(L, PCSREG, gregs, sizeof (prgregset_t)));
358 +}
359 +
360 +int
209 361 Plwp_getfpregs(struct ps_prochandle *P, lwpid_t lwpid, prfpregset_t *fpregs)
210 362 {
211 363 lwpstatus_t lps;
212 364
213 365 if (getlwpstatus(P, lwpid, &lps) == -1)
214 366 return (-1);
215 367
216 368 (void) memcpy(fpregs, &lps.pr_fpreg, sizeof (prfpregset_t));
217 369 return (0);
218 370 }
219 371
220 -int Plwp_setfpregs(struct ps_prochandle *P, lwpid_t lwpid,
372 +int
373 +Lgetfpregs(struct ps_lwphandle *L, prfpregset_t *fpregs)
374 +{
375 + (void) memcpy(fpregs, &L->lwp_status.pr_fpreg, sizeof (prfpregset_t));
376 + return (0);
377 +}
378 +
379 +int
380 +Plwp_setfpregs(struct ps_prochandle *P, lwpid_t lwpid,
221 381 const prfpregset_t *fpregs)
222 382 {
223 - return (setlwpregs(P, lwpid, PCSFPREG, fpregs, sizeof (prfpregset_t)));
383 + return (setlwpregs_proc(P, lwpid, PCSFPREG, fpregs,
384 + sizeof (prfpregset_t)));
224 385 }
225 386
226 -#if defined(sparc) || defined(__sparc)
227 387 int
228 -Plwp_getxregs(struct ps_prochandle *P, lwpid_t lwpid, prxregset_t *xregs)
388 +Lsetfpregs(struct ps_lwphandle *L, const prfpregset_t *fpregs)
229 389 {
390 + return (setlwpregs_lwp(L, PCSFPREG, fpregs, sizeof (prfpregset_t)));
391 +}
392 +
393 +/*
394 + * The reason that this is structured to take both the size and the process
395 + * handle is so that way we have enough information to tie this back to its
396 + * underlying source and we can eventually use umem with this.
397 + */
398 +void
399 +Plwp_freexregs(struct ps_prochandle *P __unused, prxregset_t *prx,
400 + size_t size __unused)
401 +{
402 + free(prx);
403 +}
404 +
405 +int
406 +Plwp_getxregs(struct ps_prochandle *P, lwpid_t lwpid, prxregset_t **xregs,
407 + size_t *sizep)
408 +{
230 409 lwp_info_t *lwp;
231 410
232 411 if (P->state == PS_IDLE) {
233 412 errno = ENODATA;
234 413 return (-1);
235 414 }
236 415
237 416 if (P->state != PS_DEAD) {
238 417 if (P->state != PS_STOP) {
239 418 errno = EBUSY;
240 419 return (-1);
241 420 }
242 421
243 - return (getlwpfile(P, lwpid, "xregs",
244 - xregs, sizeof (prxregset_t)));
422 + return (getlwpfile_alloc(P, lwpid, "xregs",
423 + (void **)xregs, sizep));
245 424 }
246 425
247 - if ((lwp = getlwpcore(P, lwpid)) != NULL && lwp->lwp_xregs != NULL) {
248 - (void) memcpy(xregs, lwp->lwp_xregs, sizeof (prxregset_t));
426 + if ((lwp = getlwpcore(P, lwpid)) != NULL && lwp->lwp_xregs != NULL &&
427 + lwp->lwp_xregsize > 0) {
428 + *xregs = malloc(lwp->lwp_xregsize);
429 + if (*xregs == NULL)
430 + return (-1);
431 + (void) memcpy(*xregs, lwp->lwp_xregs, lwp->lwp_xregsize);
432 + *sizep = lwp->lwp_xregsize;
249 433 return (0);
250 434 }
251 435
252 436 if (lwp != NULL)
253 437 errno = ENODATA;
254 438 return (-1);
255 439 }
256 440
257 441 int
258 -Plwp_setxregs(struct ps_prochandle *P, lwpid_t lwpid, const prxregset_t *xregs)
442 +Lgetxregs(struct ps_lwphandle *L, prxregset_t **xregs, size_t *sizep)
259 443 {
260 - return (setlwpregs(P, lwpid, PCSXREG, xregs, sizeof (prxregset_t)));
444 + lwp_info_t *lwp;
445 +
446 + if (L->lwp_state != PS_DEAD) {
447 + if (L->lwp_state != PS_STOP) {
448 + errno = EBUSY;
449 + return (-1);
450 + }
451 + return (getlwpfile_alloc(L->lwp_proc, L->lwp_id, "xregs",
452 + (void **)xregs, sizep));
453 + }
454 +
455 + if ((lwp = getlwpcore(L->lwp_proc, L->lwp_id)) != NULL &&
456 + lwp->lwp_xregs != NULL && lwp->lwp_xregsize > 0) {
457 + *xregs = malloc(lwp->lwp_xregsize);
458 + if (*xregs == NULL)
459 + return (-1);
460 + (void) memcpy(*xregs, lwp->lwp_xregs, lwp->lwp_xregsize);
461 + *sizep = lwp->lwp_xregsize;
462 + return (0);
463 + }
464 +
465 + if (lwp != NULL)
466 + errno = ENODATA;
467 + return (-1);
261 468 }
262 469
263 470 int
471 +Plwp_setxregs(struct ps_prochandle *P, lwpid_t lwpid, const prxregset_t *xregs,
472 + size_t len)
473 +{
474 + return (setlwpregs_proc(P, lwpid, PCSXREG, xregs, len));
475 +}
476 +
477 +int
478 +Lsetxregs(struct ps_lwphandle *L, const prxregset_t *xregs, size_t len)
479 +{
480 + return (setlwpregs_lwp(L, PCSXREG, xregs, len));
481 +}
482 +
483 +#if defined(sparc) || defined(__sparc)
484 +int
264 485 Plwp_getgwindows(struct ps_prochandle *P, lwpid_t lwpid, gwindows_t *gwins)
265 486 {
266 487 lwp_info_t *lwp;
267 488
268 489 if (P->state == PS_IDLE) {
269 490 errno = ENODATA;
270 491 return (-1);
271 492 }
272 493
273 494 if (P->state != PS_DEAD) {
274 495 if (P->state != PS_STOP) {
275 496 errno = EBUSY;
276 497 return (-1);
277 498 }
278 499
279 500 return (getlwpfile(P, lwpid, "gwindows",
280 501 gwins, sizeof (gwindows_t)));
281 502 }
282 503
283 504 if ((lwp = getlwpcore(P, lwpid)) != NULL && lwp->lwp_gwins != NULL) {
284 505 *gwins = *lwp->lwp_gwins;
285 506 return (0);
286 507 }
287 508
288 509 if (lwp != NULL)
289 510 errno = ENODATA;
290 511 return (-1);
291 512 }
292 513
293 514 #if defined(__sparcv9)
294 515 int
295 516 Plwp_getasrs(struct ps_prochandle *P, lwpid_t lwpid, asrset_t asrs)
296 517 {
297 518 lwp_info_t *lwp;
298 519
299 520 if (P->state == PS_IDLE) {
300 521 errno = ENODATA;
301 522 return (-1);
302 523 }
303 524
304 525 if (P->state != PS_DEAD) {
305 526 if (P->state != PS_STOP) {
306 527 errno = EBUSY;
307 528 return (-1);
308 529 }
309 530
310 531 return (getlwpfile(P, lwpid, "asrs", asrs, sizeof (asrset_t)));
311 532 }
312 533
313 534 if ((lwp = getlwpcore(P, lwpid)) != NULL && lwp->lwp_asrs != NULL) {
314 535 (void) memcpy(asrs, lwp->lwp_asrs, sizeof (asrset_t));
315 536 return (0);
316 537 }
|
↓ open down ↓ |
43 lines elided |
↑ open up ↑ |
317 538
318 539 if (lwp != NULL)
319 540 errno = ENODATA;
320 541 return (-1);
321 542
322 543 }
323 544
324 545 int
325 546 Plwp_setasrs(struct ps_prochandle *P, lwpid_t lwpid, const asrset_t asrs)
326 547 {
327 - return (setlwpregs(P, lwpid, PCSASRS, asrs, sizeof (asrset_t)));
548 + return (setlwpregs_proc(P, lwpid, PCSASRS, asrs, sizeof (asrset_t)));
328 549 }
329 550 #endif /* __sparcv9 */
330 551 #endif /* __sparc */
331 552
332 553 int
333 554 Plwp_getpsinfo(struct ps_prochandle *P, lwpid_t lwpid, lwpsinfo_t *lps)
334 555 {
335 556 lwp_info_t *lwp;
336 557
337 558 if (P->state == PS_IDLE) {
338 559 errno = ENODATA;
339 560 return (-1);
340 561 }
341 562
342 563 if (P->state != PS_DEAD) {
343 564 return (getlwpfile(P, lwpid, "lwpsinfo",
344 565 lps, sizeof (lwpsinfo_t)));
345 566 }
346 567
347 568 if ((lwp = getlwpcore(P, lwpid)) != NULL) {
348 569 (void) memcpy(lps, &lwp->lwp_psinfo, sizeof (lwpsinfo_t));
349 570 return (0);
350 571 }
351 572
352 573 return (-1);
353 574 }
354 575
355 576 int
356 577 Plwp_getname(struct ps_prochandle *P, lwpid_t lwpid,
357 578 char *buf, size_t bufsize)
358 579 {
359 580 char lwpname[THREAD_NAME_MAX];
360 581 char *from = NULL;
361 582 lwp_info_t *lwp;
362 583
363 584 if (P->state == PS_IDLE) {
364 585 errno = ENODATA;
365 586 return (-1);
366 587 }
367 588
368 589 if (P->state != PS_DEAD) {
369 590 if (getlwpfile(P, lwpid, "lwpname",
370 591 lwpname, sizeof (lwpname)) != 0)
371 592 return (-1);
372 593 from = lwpname;
373 594 } else {
374 595 if ((lwp = getlwpcore(P, lwpid)) == NULL)
375 596 return (-1);
376 597 from = lwp->lwp_name;
377 598 }
378 599
379 600 if (strlcpy(buf, from, bufsize) >= bufsize) {
380 601 errno = ENAMETOOLONG;
381 602 return (-1);
382 603 }
383 604
384 605 return (0);
385 606 }
386 607
387 608 int
388 609 Plwp_getspymaster(struct ps_prochandle *P, lwpid_t lwpid, psinfo_t *ps)
389 610 {
390 611 lwpstatus_t lps;
391 612
392 613 if (P->state == PS_IDLE) {
393 614 errno = ENODATA;
394 615 return (-1);
395 616 }
396 617
397 618 if (getlwpstatus(P, lwpid, &lps) != 0)
398 619 return (-1);
399 620
400 621 if (!(lps.pr_flags & PR_AGENT)) {
401 622 errno = EINVAL;
402 623 return (-1);
403 624 }
404 625
405 626 if (P->state != PS_DEAD) {
406 627 return (getlwpfile(P, lwpid, "spymaster",
407 628 ps, sizeof (psinfo_t)));
408 629 }
409 630
410 631 if (P->spymaster.pr_nlwp != 0) {
411 632 (void) memcpy(ps, &P->spymaster, sizeof (psinfo_t));
412 633 return (0);
413 634 }
414 635
415 636 errno = ENODATA;
416 637
417 638 return (-1);
418 639 }
419 640
420 641 int
421 642 Plwp_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp)
422 643 {
423 644 uintptr_t addr;
424 645
425 646 if (P->state == PS_IDLE) {
426 647 errno = ENODATA;
427 648 return (-1);
428 649 }
429 650
430 651 if (P->state != PS_DEAD) {
431 652 lwpstatus_t ls;
432 653 if (getlwpfile(P, lwpid, "lwpstatus", &ls, sizeof (ls)) != 0)
433 654 return (-1);
434 655 addr = ls.pr_ustack;
435 656 } else {
436 657 lwp_info_t *lwp;
437 658 if ((lwp = getlwpcore(P, lwpid)) == NULL)
438 659 return (-1);
439 660 addr = lwp->lwp_status.pr_ustack;
440 661 }
441 662
442 663
443 664 if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
444 665 if (Pread(P, stkp, sizeof (*stkp), addr) != sizeof (*stkp))
445 666 return (-1);
446 667 #ifdef _LP64
447 668 } else {
448 669 stack32_t stk32;
449 670
450 671 if (Pread(P, &stk32, sizeof (stk32), addr) != sizeof (stk32))
451 672 return (-1);
452 673
453 674 stack_32_to_n(&stk32, stkp);
454 675 #endif
455 676 }
456 677
457 678 return (0);
458 679 }
459 680
460 681 int
461 682 Plwp_main_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp)
462 683 {
463 684 uintptr_t addr;
464 685 lwpstatus_t ls;
465 686
466 687 if (P->state == PS_IDLE) {
467 688 errno = ENODATA;
468 689 return (-1);
469 690 }
470 691
471 692 if (P->state != PS_DEAD) {
472 693 if (getlwpfile(P, lwpid, "lwpstatus", &ls, sizeof (ls)) != 0)
473 694 return (-1);
474 695 } else {
475 696 lwp_info_t *lwp;
476 697 if ((lwp = getlwpcore(P, lwpid)) == NULL)
477 698 return (-1);
478 699 ls = lwp->lwp_status;
479 700 }
480 701
481 702 addr = ls.pr_ustack;
482 703
483 704 /*
484 705 * Read out the current stack; if the SS_ONSTACK flag is set then
485 706 * this LWP is operating on the alternate signal stack. We can
486 707 * recover the original stack from pr_oldcontext.
487 708 */
488 709 if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
489 710 if (Pread(P, stkp, sizeof (*stkp), addr) != sizeof (*stkp))
490 711 return (-1);
491 712
492 713 if (stkp->ss_flags & SS_ONSTACK)
493 714 goto on_altstack;
494 715 #ifdef _LP64
495 716 } else {
496 717 stack32_t stk32;
497 718
498 719 if (Pread(P, &stk32, sizeof (stk32), addr) != sizeof (stk32))
499 720 return (-1);
500 721
501 722 if (stk32.ss_flags & SS_ONSTACK)
502 723 goto on_altstack;
503 724
504 725 stack_32_to_n(&stk32, stkp);
505 726 #endif
506 727 }
507 728
508 729 return (0);
509 730
510 731 on_altstack:
511 732
512 733 if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
513 734 ucontext_t *ctxp = (void *)ls.pr_oldcontext;
514 735
515 736 if (Pread(P, stkp, sizeof (*stkp),
516 737 (uintptr_t)&ctxp->uc_stack) != sizeof (*stkp))
517 738 return (-1);
518 739 #ifdef _LP64
519 740 } else {
520 741 ucontext32_t *ctxp = (void *)ls.pr_oldcontext;
521 742 stack32_t stk32;
522 743
523 744 if (Pread(P, &stk32, sizeof (stk32),
524 745 (uintptr_t)&ctxp->uc_stack) != sizeof (stk32))
525 746 return (-1);
526 747
527 748 stack_32_to_n(&stk32, stkp);
528 749 #endif
529 750 }
530 751
531 752 return (0);
532 753 }
533 754
534 755 int
535 756 Plwp_alt_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp)
536 757 {
537 758 if (P->state == PS_IDLE) {
538 759 errno = ENODATA;
539 760 return (-1);
540 761 }
541 762
542 763 if (P->state != PS_DEAD) {
543 764 lwpstatus_t ls;
544 765
545 766 if (getlwpfile(P, lwpid, "lwpstatus", &ls, sizeof (ls)) != 0)
546 767 return (-1);
547 768
548 769 if (ls.pr_altstack.ss_flags & SS_DISABLE) {
549 770 errno = ENODATA;
550 771 return (-1);
551 772 }
552 773
553 774 *stkp = ls.pr_altstack;
554 775 } else {
555 776 lwp_info_t *lwp;
556 777
557 778 if ((lwp = getlwpcore(P, lwpid)) == NULL)
558 779 return (-1);
559 780
560 781 if (lwp->lwp_status.pr_altstack.ss_flags & SS_DISABLE) {
561 782 errno = ENODATA;
562 783 return (-1);
563 784 }
564 785
565 786 *stkp = lwp->lwp_status.pr_altstack;
566 787 }
567 788
568 789 return (0);
569 790 }
|
↓ open down ↓ |
232 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX