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