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