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                 lwp_info_t *lwp = list_next(&P->core->core_lwp_head);
 180                 uint_t i;
 181 
 182                 for (i = 0; i < P->core->core_nlwp; i++, lwp = list_next(lwp)) {
 183                         if (lwp->lwp_id == lwpid) {
 184                                 if (lwp->lwp_xregs != NULL)
 185                                         *xrsize = sizeof (prxregset_t);
 186                                 else
 187                                         *xrsize = 0;
 188                                 return (PS_OK);
 189                         }
 190                 }
 191 
 192                 return (PS_BADLID);
 193         }
 194 
 195         (void) snprintf(fname, sizeof (fname), "%s/%d/lwp/%d/xregs",
 196             procfs_path, (int)P->status.pr_pid, (int)lwpid);
 197 
 198         if (stat(fname, &statb) != 0)
 199                 return (PS_BADLID);
 200 
 201         *xrsize = (int)statb.st_size;
 202         return (PS_OK);
 203 }
 204 
 205 ps_err_e
 206 ps_lgetxregs(struct ps_prochandle *P, lwpid_t lwpid, caddr_t xregs)
 207 {
 208         if (P->state != PS_STOP && P->state != PS_DEAD)
 209                 return (PS_ERR);
 210 
 211         /* LINTED - alignment */
 212         if (Plwp_getxregs(P, lwpid, (prxregset_t *)xregs) == 0)
 213                 return (PS_OK);
 214 
 215         return (PS_BADLID);
 216 }
 217 
 218 ps_err_e
 219 ps_lsetxregs(struct ps_prochandle *P, lwpid_t lwpid, caddr_t xregs)
 220 {
 221         if (P->state != PS_STOP)
 222                 return (PS_ERR);
 223 
 224         /* LINTED - alignment */
 225         if (Plwp_setxregs(P, lwpid, (prxregset_t *)xregs) == 0)
 226                 return (PS_OK);
 227 
 228         return (PS_BADLID);
 229 }
 230 
 231 #endif  /* sparc */
 232 
 233 #if defined(__i386) || defined(__amd64)
 234 
 235 ps_err_e
 236 ps_lgetLDT(struct ps_prochandle *P, lwpid_t lwpid, struct ssd *ldt)
 237 {
 238 #if defined(__amd64) && defined(_LP64)
 239         if (P->status.pr_dmodel != PR_MODEL_NATIVE) {
 240 #endif
 241         prgregset_t regs;
 242         struct ssd *ldtarray;
 243         ps_err_e error;
 244         uint_t gs;
 245         int nldt;
 246         int i;
 247 
 248         if (P->state != PS_STOP && P->state != PS_DEAD)
 249                 return (PS_ERR);
 250 
 251         /*
 252          * We need to get the ldt entry that matches the
 253          * value in the lwp's GS register.
 254          */
 255         if ((error = ps_lgetregs(P, lwpid, regs)) != PS_OK)
 256                 return (error);
 257 
 258         gs = regs[GS];
 259 
 260         if ((nldt = Pldt(P, NULL, 0)) <= 0 ||
 261             (ldtarray = malloc(nldt * sizeof (struct ssd))) == NULL)
 262                 return (PS_ERR);
 263         if ((nldt = Pldt(P, ldtarray, nldt)) <= 0) {
 264                 free(ldtarray);
 265                 return (PS_ERR);
 266         }
 267 
 268         for (i = 0; i < nldt; i++) {
 269                 if (gs == ldtarray[i].sel) {
 270                         *ldt = ldtarray[i];
 271                         break;
 272                 }
 273         }
 274         free(ldtarray);
 275 
 276         if (i < nldt)
 277                 return (PS_OK);
 278 #if defined(__amd64) && defined(_LP64)
 279         }
 280 #endif
 281 
 282         return (PS_ERR);
 283 }
 284 
 285 #endif  /* __i386 || __amd64 */
 286 
 287 /*
 288  * Libthread_db doesn't use this function currently, but librtld_db uses
 289  * it for its debugging output.  We turn this on via rd_log if our debugging
 290  * switch is on, and then echo the messages sent to ps_plog to stderr.
 291  */
 292 void
 293 ps_plog(const char *fmt, ...)
 294 {
 295         va_list ap;
 296 
 297         if (_libproc_debug && fmt != NULL && *fmt != '\0') {
 298                 va_start(ap, fmt);
 299                 (void) vfprintf(stderr, fmt, ap);
 300                 va_end(ap);
 301                 if (fmt[strlen(fmt) - 1] != '\n')
 302                         (void) fputc('\n', stderr);
 303         }
 304 }
 305 
 306 /*
 307  * Store a pointer to our internal copy of the aux vector at the address
 308  * specified by the caller.  It should not hold on to this data for too long.
 309  */
 310 ps_err_e
 311 ps_pauxv(struct ps_prochandle *P, const auxv_t **aux)
 312 {
 313         if (P->auxv == NULL)
 314                 Preadauxvec(P);
 315 
 316         if (P->auxv == NULL)
 317                 return (PS_ERR);
 318 
 319         *aux = (const auxv_t *)P->auxv;
 320         return (PS_OK);
 321 }
 322 
 323 ps_err_e
 324 ps_pbrandname(struct ps_prochandle *P, char *buf, size_t len)
 325 {
 326         return (Pbrandname(P, buf, len) ? PS_OK : PS_ERR);
 327 }
 328 
 329 /*
 330  * Search for a symbol by name and return the corresponding address.
 331  */
 332 ps_err_e
 333 ps_pglobal_lookup(struct ps_prochandle *P, const char *object_name,
 334         const char *sym_name, psaddr_t *sym_addr)
 335 {
 336         GElf_Sym sym;
 337 
 338         if (Plookup_by_name(P, object_name, sym_name, &sym) == 0) {
 339                 dprintf("pglobal_lookup <%s> -> %p\n",
 340                     sym_name, (void *)(uintptr_t)sym.st_value);
 341                 *sym_addr = (psaddr_t)sym.st_value;
 342                 return (PS_OK);
 343         }
 344 
 345         return (PS_NOSYM);
 346 }
 347 
 348 /*
 349  * Search for a symbol by name and return the corresponding symbol
 350  * information.  If we're compiled _LP64, we just call Plookup_by_name
 351  * and return because ps_sym_t is defined to be an Elf64_Sym, which
 352  * is the same as a GElf_Sym.  In the _ILP32 case, we have to convert
 353  * Plookup_by_name's result back to a ps_sym_t (which is an Elf32_Sym).
 354  */
 355 ps_err_e
 356 ps_pglobal_sym(struct ps_prochandle *P, const char *object_name,
 357         const char *sym_name, ps_sym_t *symp)
 358 {
 359 #if defined(_ILP32)
 360         GElf_Sym sym;
 361 
 362         if (Plookup_by_name(P, object_name, sym_name, &sym) == 0) {
 363                 symp->st_name = (Elf32_Word)sym.st_name;
 364                 symp->st_value = (Elf32_Addr)sym.st_value;
 365                 symp->st_size = (Elf32_Word)sym.st_size;
 366                 symp->st_info = ELF32_ST_INFO(
 367                     GELF_ST_BIND(sym.st_info), GELF_ST_TYPE(sym.st_info));
 368                 symp->st_other = sym.st_other;
 369                 symp->st_shndx = sym.st_shndx;
 370                 return (PS_OK);
 371         }
 372 
 373 #elif defined(_LP64)
 374         if (Plookup_by_name(P, object_name, sym_name, symp) == 0)
 375                 return (PS_OK);
 376 #endif
 377         return (PS_NOSYM);
 378 }