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