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