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