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  * Copyright (c) 2013 by Delphix. All rights reserved.
  27  */
  28 
  29 #include <stdarg.h>
  30 #include <string.h>
  31 #include "Pcontrol.h"
  32 
  33 /*
  34  * This file implements the process services declared in <proc_service.h>.
  35  * This enables libproc to be used in conjunction with libc_db and
  36  * librtld_db.  As most of these facilities are already provided by
  37  * (more elegant) interfaces in <libproc.h>, we can just call those.
  38  *
  39  * NOTE: We explicitly do *not* implement the functions ps_kill() and
  40  * ps_lrolltoaddr() in this library.  The very existence of these functions
  41  * causes libc_db to create an "agent thread" in the target process.
  42  * The only way to turn off this behavior is to omit these functions.
  43  */
  44 
  45 #pragma weak ps_pdread = ps_pread
  46 #pragma weak ps_ptread = ps_pread
  47 #pragma weak ps_pdwrite = ps_pwrite
  48 #pragma weak ps_ptwrite = ps_pwrite
  49 
  50 ps_err_e
  51 ps_pdmodel(struct ps_prochandle *P, int *modelp)
  52 {
  53         *modelp = P->status.pr_dmodel;
  54         return (PS_OK);
  55 }
  56 
  57 ps_err_e
  58 ps_pread(struct ps_prochandle *P, psaddr_t addr, void *buf, size_t size)
  59 {
  60         if (P->ops.pop_pread(P, buf, size, addr, P->data) != size)
  61                 return (PS_BADADDR);
  62         return (PS_OK);
  63 }
  64 
  65 ps_err_e
  66 ps_pwrite(struct ps_prochandle *P, psaddr_t addr, const void *buf, size_t size)
  67 {
  68         if (P->ops.pop_pwrite(P, buf, size, addr, P->data) != size)
  69                 return (PS_BADADDR);
  70         return (PS_OK);
  71 }
  72 
  73 /*
  74  * libc_db calls matched pairs of ps_pstop()/ps_pcontinue()
  75  * in the belief that the client may have left the process
  76  * running while calling in to the libc_db interfaces.
  77  *
  78  * We interpret the meaning of these functions to be an inquiry
  79  * as to whether the process is stopped, not an action to be
  80  * performed to make it stopped.  For similar reasons, we also
  81  * return PS_OK for core files in order to allow libc_db to
  82  * operate on these as well.
  83  */
  84 ps_err_e
  85 ps_pstop(struct ps_prochandle *P)
  86 {
  87         if (P->state != PS_STOP && P->state != PS_DEAD)
  88                 return (PS_ERR);
  89         return (PS_OK);
  90 }
  91 
  92 ps_err_e
  93 ps_pcontinue(struct ps_prochandle *P)
  94 {
  95         if (P->state != PS_STOP && P->state != PS_DEAD)
  96                 return (PS_ERR);
  97         return (PS_OK);
  98 }
  99 
 100 /*
 101  * ps_lstop() and ps_lcontinue() are not called by any code in libc_db
 102  * or librtld_db.  We make them behave like ps_pstop() and ps_pcontinue().
 103  */
 104 /* ARGSUSED1 */
 105 ps_err_e
 106 ps_lstop(struct ps_prochandle *P, lwpid_t lwpid)
 107 {
 108         if (P->state != PS_STOP && P->state != PS_DEAD)
 109                 return (PS_ERR);
 110         return (PS_OK);
 111 }
 112 
 113 /* ARGSUSED1 */
 114 ps_err_e
 115 ps_lcontinue(struct ps_prochandle *P, lwpid_t lwpid)
 116 {
 117         if (P->state != PS_STOP && P->state != PS_DEAD)
 118                 return (PS_ERR);
 119         return (PS_OK);
 120 }
 121 
 122 ps_err_e
 123 ps_lgetregs(struct ps_prochandle *P, lwpid_t lwpid, prgregset_t regs)
 124 {
 125         if (P->state != PS_STOP && P->state != PS_DEAD)
 126                 return (PS_ERR);
 127 
 128         if (Plwp_getregs(P, lwpid, regs) == 0)
 129                 return (PS_OK);
 130 
 131         return (PS_BADLID);
 132 }
 133 
 134 ps_err_e
 135 ps_lsetregs(struct ps_prochandle *P, lwpid_t lwpid, const prgregset_t regs)
 136 {
 137         if (P->state != PS_STOP)
 138                 return (PS_ERR);
 139 
 140         if (Plwp_setregs(P, lwpid, regs) == 0)
 141                 return (PS_OK);
 142 
 143         return (PS_BADLID);
 144 }
 145 
 146 ps_err_e
 147 ps_lgetfpregs(struct ps_prochandle *P, lwpid_t lwpid, prfpregset_t *regs)
 148 {
 149         if (P->state != PS_STOP && P->state != PS_DEAD)
 150                 return (PS_ERR);
 151 
 152         if (Plwp_getfpregs(P, lwpid, regs) == 0)
 153                 return (PS_OK);
 154 
 155         return (PS_BADLID);
 156 }
 157 
 158 ps_err_e
 159 ps_lsetfpregs(struct ps_prochandle *P, lwpid_t lwpid, const prfpregset_t *regs)
 160 {
 161         if (P->state != PS_STOP)
 162                 return (PS_ERR);
 163 
 164         if (Plwp_setfpregs(P, lwpid, regs) == 0)
 165                 return (PS_OK);
 166 
 167         return (PS_BADLID);
 168 }
 169 
 170 #if defined(sparc) || defined(__sparc)
 171 
 172 ps_err_e
 173 ps_lgetxregsize(struct ps_prochandle *P, lwpid_t lwpid, int *xrsize)
 174 {
 175         char fname[PATH_MAX];
 176         struct stat statb;
 177 
 178         if (P->state == PS_DEAD) {
 179                 core_info_t *core = P->data;
 180                 lwp_info_t *lwp = list_next(&core->core_lwp_head);
 181                 uint_t i;
 182 
 183                 for (i = 0; i < core->core_nlwp; i++, lwp = list_next(lwp)) {
 184                         if (lwp->lwp_id == lwpid) {
 185                                 if (lwp->lwp_xregs != NULL)
 186                                         *xrsize = sizeof (prxregset_t);
 187                                 else
 188                                         *xrsize = 0;
 189                                 return (PS_OK);
 190                         }
 191                 }
 192 
 193                 return (PS_BADLID);
 194         }
 195 
 196         (void) snprintf(fname, sizeof (fname), "%s/%d/lwp/%d/xregs",
 197             procfs_path, (int)P->status.pr_pid, (int)lwpid);
 198 
 199         if (stat(fname, &statb) != 0)
 200                 return (PS_BADLID);
 201 
 202         *xrsize = (int)statb.st_size;
 203         return (PS_OK);
 204 }
 205 
 206 ps_err_e
 207 ps_lgetxregs(struct ps_prochandle *P, lwpid_t lwpid, caddr_t xregs)
 208 {
 209         if (P->state != PS_STOP && P->state != PS_DEAD)
 210                 return (PS_ERR);
 211 
 212         /* LINTED - alignment */
 213         if (Plwp_getxregs(P, lwpid, (prxregset_t *)xregs) == 0)
 214                 return (PS_OK);
 215 
 216         return (PS_BADLID);
 217 }
 218 
 219 ps_err_e
 220 ps_lsetxregs(struct ps_prochandle *P, lwpid_t lwpid, caddr_t xregs)
 221 {
 222         if (P->state != PS_STOP)
 223                 return (PS_ERR);
 224 
 225         /* LINTED - alignment */
 226         if (Plwp_setxregs(P, lwpid, (prxregset_t *)xregs) == 0)
 227                 return (PS_OK);
 228 
 229         return (PS_BADLID);
 230 }
 231 
 232 #endif  /* sparc */
 233 
 234 #if defined(__i386) || defined(__amd64)
 235 
 236 ps_err_e
 237 ps_lgetLDT(struct ps_prochandle *P, lwpid_t lwpid, struct ssd *ldt)
 238 {
 239 #if defined(__amd64) && defined(_LP64)
 240         if (P->status.pr_dmodel != PR_MODEL_NATIVE) {
 241 #endif
 242         prgregset_t regs;
 243         struct ssd *ldtarray;
 244         ps_err_e error;
 245         uint_t gs;
 246         int nldt;
 247         int i;
 248 
 249         if (P->state != PS_STOP && P->state != PS_DEAD)
 250                 return (PS_ERR);
 251 
 252         /*
 253          * We need to get the ldt entry that matches the
 254          * value in the lwp's GS register.
 255          */
 256         if ((error = ps_lgetregs(P, lwpid, regs)) != PS_OK)
 257                 return (error);
 258 
 259         gs = regs[GS];
 260 
 261         if ((nldt = Pldt(P, NULL, 0)) <= 0 ||
 262             (ldtarray = malloc(nldt * sizeof (struct ssd))) == NULL)
 263                 return (PS_ERR);
 264         if ((nldt = Pldt(P, ldtarray, nldt)) <= 0) {
 265                 free(ldtarray);
 266                 return (PS_ERR);
 267         }
 268 
 269         for (i = 0; i < nldt; i++) {
 270                 if (gs == ldtarray[i].sel) {
 271                         *ldt = ldtarray[i];
 272                         break;
 273                 }
 274         }
 275         free(ldtarray);
 276 
 277         if (i < nldt)
 278                 return (PS_OK);
 279 #if defined(__amd64) && defined(_LP64)
 280         }
 281 #endif
 282 
 283         return (PS_ERR);
 284 }
 285 
 286 #endif  /* __i386 || __amd64 */
 287 
 288 /*
 289  * Libthread_db doesn't use this function currently, but librtld_db uses
 290  * it for its debugging output.  We turn this on via rd_log if our debugging
 291  * switch is on, and then echo the messages sent to ps_plog to stderr.
 292  */
 293 void
 294 ps_plog(const char *fmt, ...)
 295 {
 296         va_list ap;
 297 
 298         if (_libproc_debug && fmt != NULL && *fmt != '\0') {
 299                 va_start(ap, fmt);
 300                 (void) vfprintf(stderr, fmt, ap);
 301                 va_end(ap);
 302                 if (fmt[strlen(fmt) - 1] != '\n')
 303                         (void) fputc('\n', stderr);
 304         }
 305 }
 306 
 307 /*
 308  * Store a pointer to our internal copy of the aux vector at the address
 309  * specified by the caller.  It should not hold on to this data for too long.
 310  */
 311 ps_err_e
 312 ps_pauxv(struct ps_prochandle *P, const auxv_t **aux)
 313 {
 314         if (P->auxv == NULL)
 315                 Preadauxvec(P);
 316 
 317         if (P->auxv == NULL)
 318                 return (PS_ERR);
 319 
 320         *aux = (const auxv_t *)P->auxv;
 321         return (PS_OK);
 322 }
 323 
 324 ps_err_e
 325 ps_pbrandname(struct ps_prochandle *P, char *buf, size_t len)
 326 {
 327         return (Pbrandname(P, buf, len) ? PS_OK : PS_ERR);
 328 }
 329 
 330 /*
 331  * Search for a symbol by name and return the corresponding address.
 332  */
 333 ps_err_e
 334 ps_pglobal_lookup(struct ps_prochandle *P, const char *object_name,
 335         const char *sym_name, psaddr_t *sym_addr)
 336 {
 337         GElf_Sym sym;
 338 
 339         if (Plookup_by_name(P, object_name, sym_name, &sym) == 0) {
 340                 dprintf("pglobal_lookup <%s> -> %p\n",
 341                     sym_name, (void *)(uintptr_t)sym.st_value);
 342                 *sym_addr = (psaddr_t)sym.st_value;
 343                 return (PS_OK);
 344         }
 345 
 346         return (PS_NOSYM);
 347 }
 348 
 349 /*
 350  * Search for a symbol by name and return the corresponding symbol
 351  * information.  If we're compiled _LP64, we just call Plookup_by_name
 352  * and return because ps_sym_t is defined to be an Elf64_Sym, which
 353  * is the same as a GElf_Sym.  In the _ILP32 case, we have to convert
 354  * Plookup_by_name's result back to a ps_sym_t (which is an Elf32_Sym).
 355  */
 356 ps_err_e
 357 ps_pglobal_sym(struct ps_prochandle *P, const char *object_name,
 358         const char *sym_name, ps_sym_t *symp)
 359 {
 360 #if defined(_ILP32)
 361         GElf_Sym sym;
 362 
 363         if (Plookup_by_name(P, object_name, sym_name, &sym) == 0) {
 364                 symp->st_name = (Elf32_Word)sym.st_name;
 365                 symp->st_value = (Elf32_Addr)sym.st_value;
 366                 symp->st_size = (Elf32_Word)sym.st_size;
 367                 symp->st_info = ELF32_ST_INFO(
 368                     GELF_ST_BIND(sym.st_info), GELF_ST_TYPE(sym.st_info));
 369                 symp->st_other = sym.st_other;
 370                 symp->st_shndx = sym.st_shndx;
 371                 return (PS_OK);
 372         }
 373 
 374 #elif defined(_LP64)
 375         if (Plookup_by_name(P, object_name, sym_name, symp) == 0)
 376                 return (PS_OK);
 377 #endif
 378         return (PS_NOSYM);
 379 }