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