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