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/Pcontrol.c
          +++ new/usr/src/lib/libproc/common/Pcontrol.c
↓ open down ↓ 17 lines elided ↑ open up ↑
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   *
  26   26   * Portions Copyright 2007 Chad Mynhier
  27   27   * Copyright 2012 DEY Storage Systems, Inc.  All rights reserved.
       28 + * Copyright (c) 2013 by Delphix. All rights reserved.
  28   29   */
  29   30  
  30   31  #include <assert.h>
  31   32  #include <stdio.h>
  32   33  #include <stdlib.h>
  33   34  #include <unistd.h>
  34   35  #include <ctype.h>
  35   36  #include <fcntl.h>
  36   37  #include <string.h>
  37   38  #include <strings.h>
  38   39  #include <memory.h>
  39   40  #include <errno.h>
  40   41  #include <dirent.h>
  41   42  #include <limits.h>
  42   43  #include <signal.h>
  43   44  #include <atomic.h>
       45 +#include <zone.h>
  44   46  #include <sys/types.h>
  45   47  #include <sys/uio.h>
  46   48  #include <sys/stat.h>
  47   49  #include <sys/resource.h>
  48   50  #include <sys/param.h>
  49   51  #include <sys/stack.h>
  50   52  #include <sys/fault.h>
  51   53  #include <sys/syscall.h>
  52   54  #include <sys/sysmacros.h>
       55 +#include <sys/systeminfo.h>
  53   56  
  54   57  #include "libproc.h"
  55   58  #include "Pcontrol.h"
  56   59  #include "Putil.h"
  57   60  #include "P32ton.h"
  58   61  
  59   62  int     _libproc_debug;         /* set non-zero to enable debugging printfs */
  60   63  int     _libproc_no_qsort;      /* set non-zero to inhibit sorting */
  61   64                                  /* of symbol tables */
  62   65  int     _libproc_incore_elf;    /* only use in-core elf data */
↓ open down ↓ 1 lines elided ↑ open up ↑
  64   67  sigset_t blockable_sigs;        /* signals to block when we need to be safe */
  65   68  static  int     minfd;  /* minimum file descriptor returned by dupfd(fd, 0) */
  66   69  char    procfs_path[PATH_MAX] = "/proc";
  67   70  
  68   71  /*
  69   72   * Function prototypes for static routines in this module.
  70   73   */
  71   74  static  void    deadcheck(struct ps_prochandle *);
  72   75  static  void    restore_tracing_flags(struct ps_prochandle *);
  73   76  static  void    Lfree_internal(struct ps_prochandle *, struct ps_lwphandle *);
       77 +static  prheader_t *read_lfile(struct ps_prochandle *, const char *);
  74   78  
  75   79  /*
  76      - * Read/write interface for live processes: just pread/pwrite the
  77      - * /proc/<pid>/as file:
       80 + * Ops vector functions for live processes.
  78   81   */
  79   82  
       83 +/*ARGSUSED*/
  80   84  static ssize_t
  81      -Pread_live(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr)
       85 +Pread_live(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr,
       86 +    void *data)
  82   87  {
  83   88          return (pread(P->asfd, buf, n, (off_t)addr));
  84   89  }
  85   90  
       91 +/*ARGSUSED*/
  86   92  static ssize_t
  87      -Pwrite_live(struct ps_prochandle *P, const void *buf, size_t n, uintptr_t addr)
       93 +Pwrite_live(struct ps_prochandle *P, const void *buf, size_t n, uintptr_t addr,
       94 +    void *data)
  88   95  {
  89   96          return (pwrite(P->asfd, buf, n, (off_t)addr));
  90   97  }
  91   98  
  92      -static const ps_rwops_t P_live_ops = { Pread_live, Pwrite_live };
       99 +/*ARGSUSED*/
      100 +static int
      101 +Pread_maps_live(struct ps_prochandle *P, prmap_t **Pmapp, ssize_t *nmapp,
      102 +    void *data)
      103 +{
      104 +        char mapfile[PATH_MAX];
      105 +        int mapfd;
      106 +        struct stat statb;
      107 +        ssize_t nmap;
      108 +        prmap_t *Pmap = NULL;
  93  109  
      110 +        (void) snprintf(mapfile, sizeof (mapfile), "%s/%d/map",
      111 +            procfs_path, (int)P->pid);
      112 +        if ((mapfd = open(mapfile, O_RDONLY)) < 0 ||
      113 +            fstat(mapfd, &statb) != 0 ||
      114 +            statb.st_size < sizeof (prmap_t) ||
      115 +            (Pmap = malloc(statb.st_size)) == NULL ||
      116 +            (nmap = pread(mapfd, Pmap, statb.st_size, 0L)) <= 0 ||
      117 +            (nmap /= sizeof (prmap_t)) == 0) {
      118 +                if (Pmap != NULL)
      119 +                        free(Pmap);
      120 +                if (mapfd >= 0)
      121 +                        (void) close(mapfd);
      122 +                Preset_maps(P); /* utter failure; destroy tables */
      123 +                return (-1);
      124 +        }
      125 +        (void) close(mapfd);
      126 +
      127 +        *Pmapp = Pmap;
      128 +        *nmapp = nmap;
      129 +
      130 +        return (0);
      131 +}
      132 +
      133 +/*ARGSUSED*/
      134 +static void
      135 +Pread_aux_live(struct ps_prochandle *P, auxv_t **auxvp, int *nauxp, void *data)
      136 +{
      137 +        char auxfile[64];
      138 +        int fd;
      139 +        struct stat statb;
      140 +        auxv_t *auxv;
      141 +        ssize_t naux;
      142 +
      143 +        (void) snprintf(auxfile, sizeof (auxfile), "%s/%d/auxv",
      144 +            procfs_path, (int)P->pid);
      145 +        if ((fd = open(auxfile, O_RDONLY)) < 0) {
      146 +                dprintf("%s: failed to open %s: %s\n",
      147 +                    __func__, auxfile, strerror(errno));
      148 +                return;
      149 +        }
      150 +
      151 +        if (fstat(fd, &statb) == 0 &&
      152 +            statb.st_size >= sizeof (auxv_t) &&
      153 +            (auxv = malloc(statb.st_size + sizeof (auxv_t))) != NULL) {
      154 +                if ((naux = read(fd, auxv, statb.st_size)) < 0 ||
      155 +                    (naux /= sizeof (auxv_t)) < 1) {
      156 +                        dprintf("%s: read failed: %s\n",
      157 +                            __func__, strerror(errno));
      158 +                        free(auxv);
      159 +                } else {
      160 +                        auxv[naux].a_type = AT_NULL;
      161 +                        auxv[naux].a_un.a_val = 0L;
      162 +
      163 +                        *auxvp = auxv;
      164 +                        *nauxp = (int)naux;
      165 +                }
      166 +        }
      167 +
      168 +        (void) close(fd);
      169 +}
      170 +
      171 +/*ARGSUSED*/
      172 +static int
      173 +Pcred_live(struct ps_prochandle *P, prcred_t *pcrp, int ngroups, void *data)
      174 +{
      175 +        return (proc_get_cred(P->pid, pcrp, ngroups));
      176 +}
      177 +
      178 +/*ARGSUSED*/
      179 +static int
      180 +Ppriv_live(struct ps_prochandle *P, prpriv_t **pprv, void *data)
      181 +{
      182 +        prpriv_t *pp;
      183 +
      184 +        pp = proc_get_priv(P->pid);
      185 +        if (pp == NULL) {
      186 +                return (-1);
      187 +        }
      188 +
      189 +        *pprv = pp;
      190 +        return (0);
      191 +}
      192 +
      193 +/*ARGSUSED*/
      194 +static const psinfo_t *
      195 +Ppsinfo_live(struct ps_prochandle *P, psinfo_t *psinfo, void *data)
      196 +{
      197 +        if (proc_get_psinfo(P->pid, psinfo) == -1)
      198 +                return (NULL);
      199 +
      200 +        return (psinfo);
      201 +}
      202 +
      203 +/*ARGSUSED*/
      204 +static prheader_t *
      205 +Plstatus_live(struct ps_prochandle *P, void *data)
      206 +{
      207 +        return (read_lfile(P, "lstatus"));
      208 +}
      209 +
      210 +/*ARGSUSED*/
      211 +static prheader_t *
      212 +Plpsinfo_live(struct ps_prochandle *P, void *data)
      213 +{
      214 +        return (read_lfile(P, "lpsinfo"));
      215 +}
      216 +
      217 +/*ARGSUSED*/
      218 +static char *
      219 +Pplatform_live(struct ps_prochandle *P, char *s, size_t n, void *data)
      220 +{
      221 +        if (sysinfo(SI_PLATFORM, s, n) == -1)
      222 +                return (NULL);
      223 +        return (s);
      224 +}
      225 +
      226 +/*ARGSUSED*/
      227 +static int
      228 +Puname_live(struct ps_prochandle *P, struct utsname *u, void *data)
      229 +{
      230 +        return (uname(u));
      231 +}
      232 +
      233 +/*ARGSUSED*/
      234 +static char *
      235 +Pzonename_live(struct ps_prochandle *P, char *s, size_t n, void *data)
      236 +{
      237 +        if (getzonenamebyid(P->status.pr_zoneid, s, n) < 0)
      238 +                return (NULL);
      239 +        s[n - 1] = '\0';
      240 +        return (s);
      241 +}
      242 +
  94  243  /*
      244 + * Callback function for Pfindexec().  We return a match if we can stat the
      245 + * suggested pathname and confirm its device and inode number match our
      246 + * previous information about the /proc/<pid>/object/a.out file.
      247 + */
      248 +static int
      249 +stat_exec(const char *path, void *arg)
      250 +{
      251 +        struct stat64 *stp = arg;
      252 +        struct stat64 st;
      253 +
      254 +        return (stat64(path, &st) == 0 && S_ISREG(st.st_mode) &&
      255 +            stp->st_dev == st.st_dev && stp->st_ino == st.st_ino);
      256 +}
      257 +
      258 +/*ARGSUSED*/
      259 +static char *
      260 +Pexecname_live(struct ps_prochandle *P, char *buf, size_t buflen, void *data)
      261 +{
      262 +        char exec_name[PATH_MAX];
      263 +        char cwd[PATH_MAX];
      264 +        char proc_cwd[64];
      265 +        struct stat64 st;
      266 +        int ret;
      267 +
      268 +        /*
      269 +         * Try to get the path information first.
      270 +         */
      271 +        (void) snprintf(exec_name, sizeof (exec_name),
      272 +            "%s/%d/path/a.out", procfs_path, (int)P->pid);
      273 +        if ((ret = readlink(exec_name, buf, buflen - 1)) > 0) {
      274 +                buf[ret] = '\0';
      275 +                (void) Pfindobj(P, buf, buf, buflen);
      276 +                return (buf);
      277 +        }
      278 +
      279 +        /*
      280 +         * Stat the executable file so we can compare Pfindexec's
      281 +         * suggestions to the actual device and inode number.
      282 +         */
      283 +        (void) snprintf(exec_name, sizeof (exec_name),
      284 +            "%s/%d/object/a.out", procfs_path, (int)P->pid);
      285 +
      286 +        if (stat64(exec_name, &st) != 0 || !S_ISREG(st.st_mode))
      287 +                return (NULL);
      288 +
      289 +        /*
      290 +         * Attempt to figure out the current working directory of the
      291 +         * target process.  This only works if the target process has
      292 +         * not changed its current directory since it was exec'd.
      293 +         */
      294 +        (void) snprintf(proc_cwd, sizeof (proc_cwd),
      295 +            "%s/%d/path/cwd", procfs_path, (int)P->pid);
      296 +
      297 +        if ((ret = readlink(proc_cwd, cwd, PATH_MAX - 1)) > 0)
      298 +                cwd[ret] = '\0';
      299 +
      300 +        (void) Pfindexec(P, ret > 0 ? cwd : NULL, stat_exec, &st);
      301 +
      302 +        return (NULL);
      303 +}
      304 +
      305 +#if defined(__i386) || defined(__amd64)
      306 +/*ARGSUSED*/
      307 +static int
      308 +Pldt_live(struct ps_prochandle *P, struct ssd *pldt, int nldt, void *data)
      309 +{
      310 +        return (proc_get_ldt(P->pid, pldt, nldt));
      311 +}
      312 +#endif
      313 +
      314 +static const ps_ops_t P_live_ops = {
      315 +        .pop_pread      = Pread_live,
      316 +        .pop_pwrite     = Pwrite_live,
      317 +        .pop_read_maps  = Pread_maps_live,
      318 +        .pop_read_aux   = Pread_aux_live,
      319 +        .pop_cred       = Pcred_live,
      320 +        .pop_priv       = Ppriv_live,
      321 +        .pop_psinfo     = Ppsinfo_live,
      322 +        .pop_lstatus    = Plstatus_live,
      323 +        .pop_lpsinfo    = Plpsinfo_live,
      324 +        .pop_platform   = Pplatform_live,
      325 +        .pop_uname      = Puname_live,
      326 +        .pop_zonename   = Pzonename_live,
      327 +        .pop_execname   = Pexecname_live,
      328 +#if defined(__i386) || defined(__amd64)
      329 +        .pop_ldt        = Pldt_live
      330 +#endif
      331 +};
      332 +
      333 +/*
  95  334   * This is the library's .init handler.
  96  335   */
  97  336  #pragma init(_libproc_init)
  98  337  void
  99  338  _libproc_init(void)
 100  339  {
 101  340          _libproc_debug = getenv("LIBPROC_DEBUG") != NULL;
 102  341          _libproc_no_qsort = getenv("LIBPROC_NO_QSORT") != NULL;
 103  342          _libproc_incore_elf = getenv("LIBPROC_INCORE_ELF") != NULL;
 104  343  
↓ open down ↓ 137 lines elided ↑ open up ↑
 242  481          (void) memset(P, 0, sizeof (*P));
 243  482          (void) mutex_init(&P->proc_lock, USYNC_THREAD, NULL);
 244  483          P->flags |= CREATED;
 245  484          P->state = PS_RUN;
 246  485          P->pid = pid;
 247  486          P->asfd = -1;
 248  487          P->ctlfd = -1;
 249  488          P->statfd = -1;
 250  489          P->agentctlfd = -1;
 251  490          P->agentstatfd = -1;
 252      -        P->ops = &P_live_ops;
      491 +        Pinit_ops(&P->ops, &P_live_ops);
 253  492          Pinitsym(P);
 254  493  
 255  494          /*
 256  495           * Open the /proc/pid files.
 257  496           */
 258  497          (void) snprintf(procname, sizeof (procname), "%s/%d/",
 259  498              procfs_path, (int)pid);
 260  499          fname = procname + strlen(procname);
 261  500          (void) set_minfd();
 262  501  
↓ open down ↓ 282 lines elided ↑ open up ↑
 545  784                  (void) close(P->asfd);
 546  785          if (P->statfd >= 0)
 547  786                  (void) close(P->statfd);
 548  787          (void) memset(P, 0, sizeof (*P));
 549  788          (void) mutex_init(&P->proc_lock, USYNC_THREAD, NULL);
 550  789          P->ctlfd = -1;
 551  790          P->asfd = -1;
 552  791          P->statfd = -1;
 553  792          P->agentctlfd = -1;
 554  793          P->agentstatfd = -1;
 555      -        P->ops = &P_live_ops;
      794 +        Pinit_ops(&P->ops, &P_live_ops);
 556  795          Pinitsym(P);
 557  796  
 558  797          /*
 559  798           * Open the /proc/pid files
 560  799           */
 561  800          (void) snprintf(procname, sizeof (procname), "%s/%d/",
 562  801              procfs_path, (int)pid);
 563  802          fname = procname + strlen(procname);
 564  803          (void) set_minfd();
 565  804  
↓ open down ↓ 360 lines elided ↑ open up ↑
 926 1165  
 927 1166  /*
 928 1167   * Free a process control structure.
 929 1168   * Close the file descriptors but don't do the Prelease logic.
 930 1169   */
 931 1170  void
 932 1171  Pfree(struct ps_prochandle *P)
 933 1172  {
 934 1173          uint_t i;
 935 1174  
 936      -        if (P->core != NULL) {
 937      -                extern void __priv_free_info(void *);
 938      -                lwp_info_t *nlwp, *lwp = list_next(&P->core->core_lwp_head);
 939      -
 940      -                for (i = 0; i < P->core->core_nlwp; i++, lwp = nlwp) {
 941      -                        nlwp = list_next(lwp);
 942      -#ifdef __sparc
 943      -                        if (lwp->lwp_gwins != NULL)
 944      -                                free(lwp->lwp_gwins);
 945      -                        if (lwp->lwp_xregs != NULL)
 946      -                                free(lwp->lwp_xregs);
 947      -                        if (lwp->lwp_asrs != NULL)
 948      -                                free(lwp->lwp_asrs);
 949      -#endif
 950      -                        free(lwp);
 951      -                }
 952      -
 953      -                if (P->core->core_platform != NULL)
 954      -                        free(P->core->core_platform);
 955      -                if (P->core->core_uts != NULL)
 956      -                        free(P->core->core_uts);
 957      -                if (P->core->core_cred != NULL)
 958      -                        free(P->core->core_cred);
 959      -                if (P->core->core_priv != NULL)
 960      -                        free(P->core->core_priv);
 961      -                if (P->core->core_privinfo != NULL)
 962      -                        __priv_free_info(P->core->core_privinfo);
 963      -                if (P->core->core_ppii != NULL)
 964      -                        free(P->core->core_ppii);
 965      -                if (P->core->core_zonename != NULL)
 966      -                        free(P->core->core_zonename);
 967      -#if defined(__i386) || defined(__amd64)
 968      -                if (P->core->core_ldt != NULL)
 969      -                        free(P->core->core_ldt);
 970      -#endif
 971      -
 972      -                free(P->core);
 973      -        }
 974      -
 975 1175          if (P->ucaddrs != NULL) {
 976 1176                  free(P->ucaddrs);
 977 1177                  P->ucaddrs = NULL;
 978 1178                  P->ucnelems = 0;
 979 1179          }
 980 1180  
 981 1181          (void) mutex_lock(&P->proc_lock);
 982 1182          if (P->hashtab != NULL) {
 983 1183                  struct ps_lwphandle *L;
 984 1184                  for (i = 0; i < HASHSIZE; i++) {
↓ open down ↓ 16 lines elided ↑ open up ↑
1001 1201                  (void) close(P->agentctlfd);
1002 1202          if (P->agentstatfd >= 0)
1003 1203                  (void) close(P->agentstatfd);
1004 1204          if (P->ctlfd >= 0)
1005 1205                  (void) close(P->ctlfd);
1006 1206          if (P->asfd >= 0)
1007 1207                  (void) close(P->asfd);
1008 1208          if (P->statfd >= 0)
1009 1209                  (void) close(P->statfd);
1010 1210          Preset_maps(P);
     1211 +        P->ops.pop_fini(P, P->data);
1011 1212  
1012 1213          /* clear out the structure as a precaution against reuse */
1013 1214          (void) memset(P, 0, sizeof (*P));
1014 1215          P->ctlfd = -1;
1015 1216          P->asfd = -1;
1016 1217          P->statfd = -1;
1017 1218          P->agentctlfd = -1;
1018 1219          P->agentstatfd = -1;
1019 1220  
1020 1221          free(P);
↓ open down ↓ 31 lines elided ↑ open up ↑
1052 1253  }
1053 1254  
1054 1255  /*
1055 1256   * Return a pointer to the process psinfo structure.
1056 1257   * Clients should not hold on to this pointer indefinitely.
1057 1258   * It will become invalid on Prelease().
1058 1259   */
1059 1260  const psinfo_t *
1060 1261  Ppsinfo(struct ps_prochandle *P)
1061 1262  {
1062      -        if (P->state == PS_IDLE) {
1063      -                errno = ENODATA;
1064      -                return (NULL);
1065      -        }
1066      -
1067      -        if (P->state != PS_DEAD && proc_get_psinfo(P->pid, &P->psinfo) == -1)
1068      -                return (NULL);
1069      -
1070      -        return (&P->psinfo);
     1263 +        return (P->ops.pop_psinfo(P, &P->psinfo, P->data));
1071 1264  }
1072 1265  
1073 1266  /*
1074 1267   * Return a pointer to the process status structure.
1075 1268   * Clients should not hold on to this pointer indefinitely.
1076 1269   * It will become invalid on Prelease().
1077 1270   */
1078 1271  const pstatus_t *
1079 1272  Pstatus(struct ps_prochandle *P)
1080 1273  {
1081 1274          return (&P->status);
1082 1275  }
1083 1276  
     1277 +static void
     1278 +Pread_status(struct ps_prochandle *P)
     1279 +{
     1280 +        P->ops.pop_status(P, &P->status, P->data);
     1281 +}
     1282 +
1084 1283  /*
1085 1284   * Fill in a pointer to a process credentials structure.  The ngroups parameter
1086 1285   * is the number of supplementary group entries allocated in the caller's cred
1087 1286   * structure.  It should equal zero or one unless extra space has been
1088 1287   * allocated for the group list by the caller.
1089 1288   */
1090 1289  int
1091 1290  Pcred(struct ps_prochandle *P, prcred_t *pcrp, int ngroups)
1092 1291  {
1093      -        if (P->state == PS_IDLE) {
1094      -                errno = ENODATA;
1095      -                return (-1);
1096      -        }
     1292 +        return (P->ops.pop_cred(P, pcrp, ngroups, P->data));
     1293 +}
1097 1294  
1098      -        if (P->state != PS_DEAD)
1099      -                return (proc_get_cred(P->pid, pcrp, ngroups));
     1295 +static prheader_t *
     1296 +Plstatus(struct ps_prochandle *P)
     1297 +{
     1298 +        return (P->ops.pop_lstatus(P, P->data));
     1299 +}
1100 1300  
1101      -        if (P->core->core_cred != NULL) {
1102      -                /*
1103      -                 * Avoid returning more supplementary group data than the
1104      -                 * caller has allocated in their buffer.  We expect them to
1105      -                 * check pr_ngroups afterward and potentially call us again.
1106      -                 */
1107      -                ngroups = MIN(ngroups, P->core->core_cred->pr_ngroups);
1108      -
1109      -                (void) memcpy(pcrp, P->core->core_cred,
1110      -                    sizeof (prcred_t) + (ngroups - 1) * sizeof (gid_t));
1111      -
1112      -                return (0);
1113      -        }
1114      -
1115      -        errno = ENODATA;
1116      -        return (-1);
     1301 +static prheader_t *
     1302 +Plpsinfo(struct ps_prochandle *P)
     1303 +{
     1304 +        return (P->ops.pop_lpsinfo(P, P->data));
1117 1305  }
1118 1306  
     1307 +
1119 1308  #if defined(__i386) || defined(__amd64)
1120 1309  /*
1121 1310   * Fill in a pointer to a process LDT structure.
1122 1311   * The caller provides a buffer of size 'nldt * sizeof (struct ssd)';
1123 1312   * If pldt == NULL or nldt == 0, we return the number of existing LDT entries.
1124 1313   * Otherwise we return the actual number of LDT entries fetched (<= nldt).
1125 1314   */
1126 1315  int
1127 1316  Pldt(struct ps_prochandle *P, struct ssd *pldt, int nldt)
1128 1317  {
1129      -        if (P->state == PS_IDLE) {
1130      -                errno = ENODATA;
1131      -                return (-1);
1132      -        }
     1318 +        return (P->ops.pop_ldt(P, pldt, nldt, P->data));
1133 1319  
1134      -        if (P->state != PS_DEAD)
1135      -                return (proc_get_ldt(P->pid, pldt, nldt));
1136      -
1137      -        if (pldt == NULL || nldt == 0)
1138      -                return (P->core->core_nldt);
1139      -
1140      -        if (P->core->core_ldt != NULL) {
1141      -                nldt = MIN(nldt, P->core->core_nldt);
1142      -
1143      -                (void) memcpy(pldt, P->core->core_ldt,
1144      -                    nldt * sizeof (struct ssd));
1145      -
1146      -                return (nldt);
1147      -        }
1148      -
1149      -        errno = ENODATA;
1150      -        return (-1);
1151 1320  }
1152 1321  #endif  /* __i386 */
1153 1322  
1154 1323  /*
1155      - * Fill in a pointer to a process privilege structure.
     1324 + * Return a malloced process privilege structure in *pprv.
1156 1325   */
1157      -ssize_t
1158      -Ppriv(struct ps_prochandle *P, prpriv_t *pprv, size_t size)
     1326 +int
     1327 +Ppriv(struct ps_prochandle *P, prpriv_t **pprv)
1159 1328  {
1160      -        if (P->state != PS_DEAD) {
1161      -                prpriv_t *pp = proc_get_priv(P->pid);
1162      -                if (pp != NULL) {
1163      -                        size = MIN(size, PRIV_PRPRIV_SIZE(pp));
1164      -                        (void) memcpy(pprv, pp, size);
1165      -                        free(pp);
1166      -                        return (size);
1167      -                }
1168      -                return (-1);
1169      -        }
1170      -
1171      -        if (P->core->core_priv != NULL) {
1172      -                size = MIN(P->core->core_priv_size, size);
1173      -                (void) memcpy(pprv, P->core->core_priv, size);
1174      -                return (size);
1175      -        }
1176      -        errno = ENODATA;
1177      -        return (-1);
     1329 +        return (P->ops.pop_priv(P, pprv, P->data));
1178 1330  }
1179 1331  
1180 1332  int
1181 1333  Psetpriv(struct ps_prochandle *P, prpriv_t *pprv)
1182 1334  {
1183 1335          int rc;
1184 1336          long *ctl;
1185 1337          size_t sz;
1186 1338  
1187 1339          if (P->state == PS_DEAD) {
↓ open down ↓ 19 lines elided ↑ open up ↑
1207 1359                  rc = 0;
1208 1360  
1209 1361          free(ctl);
1210 1362  
1211 1363          return (rc);
1212 1364  }
1213 1365  
1214 1366  void *
1215 1367  Pprivinfo(struct ps_prochandle *P)
1216 1368  {
     1369 +        core_info_t *core = P->data;
     1370 +
1217 1371          /* Use default from libc */
1218 1372          if (P->state != PS_DEAD)
1219 1373                  return (NULL);
1220 1374  
1221      -        return (P->core->core_privinfo);
     1375 +        return (core->core_privinfo);
1222 1376  }
1223 1377  
1224 1378  /*
1225 1379   * Ensure that all cached state is written to the process.
1226 1380   * The cached state is the LWP's signal mask and registers
1227 1381   * and the process's tracing flags.
1228 1382   */
1229 1383  void
1230 1384  Psync(struct ps_prochandle *P)
1231 1385  {
↓ open down ↓ 739 lines elided ↑ open up ↑
1971 2125          P->state = PS_RUN;
1972 2126          return (0);
1973 2127  }
1974 2128  
1975 2129  ssize_t
1976 2130  Pread(struct ps_prochandle *P,
1977 2131          void *buf,              /* caller's buffer */
1978 2132          size_t nbyte,           /* number of bytes to read */
1979 2133          uintptr_t address)      /* address in process */
1980 2134  {
1981      -        return (P->ops->p_pread(P, buf, nbyte, address));
     2135 +        return (P->ops.pop_pread(P, buf, nbyte, address, P->data));
1982 2136  }
1983 2137  
1984 2138  ssize_t
1985 2139  Pread_string(struct ps_prochandle *P,
1986      -        char *buf,              /* caller's buffer */
     2140 +        char *buf,              /* caller's buffer */
1987 2141          size_t size,            /* upper limit on bytes to read */
1988 2142          uintptr_t addr)         /* address in process */
1989 2143  {
1990 2144          enum { STRSZ = 40 };
1991 2145          char string[STRSZ + 1];
1992 2146          ssize_t leng = 0;
1993 2147          int nbyte;
1994 2148  
1995 2149          if (size < 2) {
1996 2150                  errno = EINVAL;
1997 2151                  return (-1);
1998 2152          }
1999 2153  
2000 2154          size--;                 /* ensure trailing null fits in buffer */
2001 2155  
2002 2156          *buf = '\0';
2003 2157          string[STRSZ] = '\0';
2004 2158  
2005 2159          for (nbyte = STRSZ; nbyte == STRSZ && leng < size; addr += STRSZ) {
2006      -                if ((nbyte = P->ops->p_pread(P, string, STRSZ, addr)) <= 0) {
     2160 +                if ((nbyte = P->ops.pop_pread(P, string, STRSZ, addr,
     2161 +                    P->data)) <= 0) {
2007 2162                          buf[leng] = '\0';
2008 2163                          return (leng ? leng : -1);
2009 2164                  }
2010 2165                  if ((nbyte = strlen(string)) > 0) {
2011 2166                          if (leng + nbyte > size)
2012 2167                                  nbyte = size - leng;
2013 2168                          (void) strncpy(buf + leng, string, nbyte);
2014 2169                          leng += nbyte;
2015 2170                  }
2016 2171          }
2017 2172          buf[leng] = '\0';
2018 2173          return (leng);
2019 2174  }
2020 2175  
2021 2176  ssize_t
2022 2177  Pwrite(struct ps_prochandle *P,
2023 2178          const void *buf,        /* caller's buffer */
2024 2179          size_t nbyte,           /* number of bytes to write */
2025 2180          uintptr_t address)      /* address in process */
2026 2181  {
2027      -        return (P->ops->p_pwrite(P, buf, nbyte, address));
     2182 +        return (P->ops.pop_pwrite(P, buf, nbyte, address, P->data));
2028 2183  }
2029 2184  
2030 2185  int
2031 2186  Pclearsig(struct ps_prochandle *P)
2032 2187  {
2033 2188          int ctlfd = (P->agentctlfd >= 0)? P->agentctlfd : P->ctlfd;
2034 2189          long ctl = PCCSIG;
2035 2190  
2036 2191          if (write(ctlfd, &ctl, sizeof (ctl)) != sizeof (ctl))
2037 2192                  return (-1);
↓ open down ↓ 720 lines elided ↑ open up ↑
2758 2913           * the pstatus_t contains the lwpstatus_t for the only LWP.
2759 2914           */
2760 2915          if (P->status.pr_nlwp <= 1)
2761 2916                  return (func(cd, &P->status.pr_lwp));
2762 2917  
2763 2918          /*
2764 2919           * For the core file multi-LWP case, we just iterate through the
2765 2920           * list of LWP structs we read in from the core file.
2766 2921           */
2767 2922          if (P->state == PS_DEAD) {
2768      -                lwp_info_t *lwp = list_prev(&P->core->core_lwp_head);
     2923 +                core_info_t *core = P->data;
     2924 +                lwp_info_t *lwp = list_prev(&core->core_lwp_head);
2769 2925                  uint_t i;
2770 2926  
2771      -                for (i = 0; i < P->core->core_nlwp; i++, lwp = list_prev(lwp)) {
     2927 +                for (i = 0; i < core->core_nlwp; i++, lwp = list_prev(lwp)) {
2772 2928                          if (lwp->lwp_psinfo.pr_sname != 'Z' &&
2773 2929                              (rv = func(cd, &lwp->lwp_status)) != 0)
2774 2930                                  break;
2775 2931                  }
2776 2932  
2777 2933                  return (rv);
2778 2934          }
2779 2935  
2780 2936          /*
2781 2937           * For the live process multi-LWP case, we have to work a little
2782 2938           * harder: the /proc/pid/lstatus file has the array of LWP structs.
2783 2939           */
2784      -        if ((Lhp = read_lfile(P, "lstatus")) == NULL)
     2940 +        if ((Lhp = Plstatus(P)) == NULL)
2785 2941                  return (-1);
2786 2942  
2787 2943          for (nlwp = Lhp->pr_nent, Lsp = (lwpstatus_t *)(uintptr_t)(Lhp + 1);
2788 2944              nlwp > 0;
2789 2945              nlwp--, Lsp = (lwpstatus_t *)((uintptr_t)Lsp + Lhp->pr_entsize)) {
2790 2946                  if ((rv = func(cd, Lsp)) != 0)
2791 2947                          break;
2792 2948          }
2793 2949  
2794 2950          free(Lhp);
↓ open down ↓ 34 lines elided ↑ open up ↑
2829 2985           * the psinfo_t contains the lwpsinfo_t for the only LWP.
2830 2986           */
2831 2987          if (P->status.pr_nlwp + P->status.pr_nzomb <= 1)
2832 2988                  return (func(cd, &P->status.pr_lwp, &P->psinfo.pr_lwp));
2833 2989  
2834 2990          /*
2835 2991           * For the core file multi-LWP case, we just iterate through the
2836 2992           * list of LWP structs we read in from the core file.
2837 2993           */
2838 2994          if (P->state == PS_DEAD) {
2839      -                lwp_info_t *lwp = list_prev(&P->core->core_lwp_head);
     2995 +                core_info_t *core = P->data;
     2996 +                lwp_info_t *lwp = list_prev(&core->core_lwp_head);
2840 2997                  uint_t i;
2841 2998  
2842      -                for (i = 0; i < P->core->core_nlwp; i++, lwp = list_prev(lwp)) {
     2999 +                for (i = 0; i < core->core_nlwp; i++, lwp = list_prev(lwp)) {
2843 3000                          sp = (lwp->lwp_psinfo.pr_sname == 'Z')? NULL :
2844 3001                              &lwp->lwp_status;
2845 3002                          if ((rv = func(cd, sp, &lwp->lwp_psinfo)) != 0)
2846 3003                                  break;
2847 3004                  }
2848 3005  
2849 3006                  return (rv);
2850 3007          }
2851 3008  
2852 3009          /*
2853      -         * For the live process multi-LWP case, we have to work a little
2854      -         * harder: the /proc/pid/lstatus file has the array of lwpstatus_t's
2855      -         * and the /proc/pid/lpsinfo file has the array of lwpsinfo_t's.
     3010 +         * For all other cases retrieve the array of lwpstatus_t's and
     3011 +         * lwpsinfo_t's.
2856 3012           */
2857      -        if ((Lhp = read_lfile(P, "lstatus")) == NULL)
     3013 +        if ((Lhp = Plstatus(P)) == NULL)
2858 3014                  return (-1);
2859      -        if ((Lphp = read_lfile(P, "lpsinfo")) == NULL) {
     3015 +        if ((Lphp = Plpsinfo(P)) == NULL) {
2860 3016                  free(Lhp);
2861 3017                  return (-1);
2862 3018          }
2863 3019  
2864 3020          /*
2865 3021           * If we are looking at a running process, or one we do not control,
2866 3022           * the active and zombie lwps in the process may have changed since
2867 3023           * we read the process status structure.  If so, just start over.
2868 3024           */
2869 3025          if (Lhp->pr_nent != P->status.pr_nlwp ||
↓ open down ↓ 43 lines elided ↑ open up ↑
2913 3069          }
2914 3070  
2915 3071          free(Lhp);
2916 3072          free(Lphp);
2917 3073          return (rv);
2918 3074  }
2919 3075  
2920 3076  core_content_t
2921 3077  Pcontent(struct ps_prochandle *P)
2922 3078  {
     3079 +        core_info_t *core = P->data;
     3080 +
2923 3081          if (P->state == PS_DEAD)
2924      -                return (P->core->core_content);
     3082 +                return (core->core_content);
2925 3083          if (P->state == PS_IDLE)
2926 3084                  return (CC_CONTENT_TEXT | CC_CONTENT_DATA | CC_CONTENT_CTF);
2927 3085  
2928 3086          return (CC_CONTENT_ALL);
2929 3087  }
2930 3088  
2931 3089  /*
2932 3090   * =================================================================
2933 3091   * The remainder of the functions in this file are for the
2934 3092   * control of individual LWPs in the controlled process.
↓ open down ↓ 785 lines elided ↑ open up ↑
3720 3878  
3721 3879          /*
3722 3880           * Update all the file_map pointers to refer to the new locations.
3723 3881           */
3724 3882          for (i = 0; i < P->map_count; i++) {
3725 3883                  mp = &P->mappings[i];
3726 3884                  if (mp->map_relocate)
3727 3885                          mp->map_file->file_map = mp;
3728 3886                  mp->map_relocate = 0;
3729 3887          }
     3888 +}
     3889 +
     3890 +struct ps_prochandle *
     3891 +Pgrab_ops(pid_t pid, void *data, const ps_ops_t *ops, int flags)
     3892 +{
     3893 +        struct ps_prochandle *P;
     3894 +
     3895 +        if ((P = calloc(1, sizeof (*P))) == NULL) {
     3896 +                return (NULL);
     3897 +        }
     3898 +
     3899 +        Pinit_ops(&P->ops, ops);
     3900 +        (void) mutex_init(&P->proc_lock, USYNC_THREAD, NULL);
     3901 +        P->pid = pid;
     3902 +        P->state = PS_STOP;
     3903 +        P->asfd = -1;
     3904 +        P->ctlfd = -1;
     3905 +        P->statfd = -1;
     3906 +        P->agentctlfd = -1;
     3907 +        P->agentstatfd = -1;
     3908 +        Pinitsym(P);
     3909 +        P->data = data;
     3910 +        Pread_status(P);
     3911 +
     3912 +        if (flags & PGRAB_INCORE) {
     3913 +                P->flags |= INCORE;
     3914 +        }
     3915 +
     3916 +        return (P);
3730 3917  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX