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