xref: /onnv-gate/usr/src/cmd/sgs/librtld_db/demo/common/ps.c (revision 12927:a27c46eb192b)
1*12927SRod.Evans@Sun.COM /*
2*12927SRod.Evans@Sun.COM  * CDDL HEADER START
3*12927SRod.Evans@Sun.COM  *
4*12927SRod.Evans@Sun.COM  * The contents of this file are subject to the terms of the
5*12927SRod.Evans@Sun.COM  * Common Development and Distribution License (the "License").
6*12927SRod.Evans@Sun.COM  * You may not use this file except in compliance with the License.
7*12927SRod.Evans@Sun.COM  *
8*12927SRod.Evans@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*12927SRod.Evans@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*12927SRod.Evans@Sun.COM  * See the License for the specific language governing permissions
11*12927SRod.Evans@Sun.COM  * and limitations under the License.
12*12927SRod.Evans@Sun.COM  *
13*12927SRod.Evans@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*12927SRod.Evans@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*12927SRod.Evans@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*12927SRod.Evans@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*12927SRod.Evans@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*12927SRod.Evans@Sun.COM  *
19*12927SRod.Evans@Sun.COM  * CDDL HEADER END
20*12927SRod.Evans@Sun.COM  */
21*12927SRod.Evans@Sun.COM 
22*12927SRod.Evans@Sun.COM /*
23*12927SRod.Evans@Sun.COM  * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
24*12927SRod.Evans@Sun.COM  */
25*12927SRod.Evans@Sun.COM 
26*12927SRod.Evans@Sun.COM #include <stdio.h>
27*12927SRod.Evans@Sun.COM #include <stdlib.h>
28*12927SRod.Evans@Sun.COM #include <unistd.h>
29*12927SRod.Evans@Sun.COM #include <sys/uio.h>
30*12927SRod.Evans@Sun.COM #include <fcntl.h>
31*12927SRod.Evans@Sun.COM #include <string.h>
32*12927SRod.Evans@Sun.COM #include <errno.h>
33*12927SRod.Evans@Sun.COM #include <sys/types.h>
34*12927SRod.Evans@Sun.COM #include <sys/signal.h>
35*12927SRod.Evans@Sun.COM #include <sys/fault.h>
36*12927SRod.Evans@Sun.COM #include <sys/syscall.h>
37*12927SRod.Evans@Sun.COM #include <procfs.h>
38*12927SRod.Evans@Sun.COM #include <sys/auxv.h>
39*12927SRod.Evans@Sun.COM #include <sys/stat.h>
40*12927SRod.Evans@Sun.COM #include <sys/mman.h>
41*12927SRod.Evans@Sun.COM #include <libelf.h>
42*12927SRod.Evans@Sun.COM #include <sys/param.h>
43*12927SRod.Evans@Sun.COM #include <sys/machelf.h>
44*12927SRod.Evans@Sun.COM #include <stdarg.h>
45*12927SRod.Evans@Sun.COM 
46*12927SRod.Evans@Sun.COM #include <proc_service.h>
47*12927SRod.Evans@Sun.COM 
48*12927SRod.Evans@Sun.COM #include "rdb.h"
49*12927SRod.Evans@Sun.COM #include "disasm.h"
50*12927SRod.Evans@Sun.COM 
51*12927SRod.Evans@Sun.COM #if	!defined(_LP64)
52*12927SRod.Evans@Sun.COM static void
gelf_sym_to_elf32(GElf_Sym * src,Elf32_Sym * dst)53*12927SRod.Evans@Sun.COM gelf_sym_to_elf32(GElf_Sym *src, Elf32_Sym *dst)
54*12927SRod.Evans@Sun.COM {
55*12927SRod.Evans@Sun.COM 	dst->st_name	= src->st_name;
56*12927SRod.Evans@Sun.COM 	dst->st_value	= src->st_value;
57*12927SRod.Evans@Sun.COM 	dst->st_size	= src->st_size;
58*12927SRod.Evans@Sun.COM 	dst->st_info	= ELF32_ST_INFO(GELF_ST_BIND(src->st_info),
59*12927SRod.Evans@Sun.COM 	    GELF_ST_TYPE(src->st_info));
60*12927SRod.Evans@Sun.COM 	dst->st_other	= src->st_other;
61*12927SRod.Evans@Sun.COM 	dst->st_shndx	= src->st_shndx;
62*12927SRod.Evans@Sun.COM }
63*12927SRod.Evans@Sun.COM #endif
64*12927SRod.Evans@Sun.COM 
65*12927SRod.Evans@Sun.COM #define	PROCSIZE	20
66*12927SRod.Evans@Sun.COM 
67*12927SRod.Evans@Sun.COM static void
get_ldbase(struct ps_prochandle * procp)68*12927SRod.Evans@Sun.COM get_ldbase(struct ps_prochandle *procp)
69*12927SRod.Evans@Sun.COM {
70*12927SRod.Evans@Sun.COM 	int		pauxvfd;
71*12927SRod.Evans@Sun.COM 	char		pname[PROCSIZE];
72*12927SRod.Evans@Sun.COM 	struct stat	stbuf;
73*12927SRod.Evans@Sun.COM 	void		*auxvptr, *auxvtail;
74*12927SRod.Evans@Sun.COM 	auxv_t		*auxvp;
75*12927SRod.Evans@Sun.COM 	uint_t		entsize;
76*12927SRod.Evans@Sun.COM 
77*12927SRod.Evans@Sun.COM 	(void) snprintf(pname, PROCSIZE, "/proc/%d/auxv",
78*12927SRod.Evans@Sun.COM 	    EC_SWORD(procp->pp_pid));
79*12927SRod.Evans@Sun.COM 	if ((pauxvfd = open(pname, O_RDONLY)) == -1)
80*12927SRod.Evans@Sun.COM 		perr("open auxv");
81*12927SRod.Evans@Sun.COM 
82*12927SRod.Evans@Sun.COM 	if (fstat(pauxvfd, &stbuf) == -1)
83*12927SRod.Evans@Sun.COM 		perr("stat auxv");
84*12927SRod.Evans@Sun.COM 
85*12927SRod.Evans@Sun.COM 	auxvptr = malloc(stbuf.st_size);
86*12927SRod.Evans@Sun.COM 	if (read(pauxvfd, auxvptr, stbuf.st_size) == -1)
87*12927SRod.Evans@Sun.COM 		perr("gldb: reading auxv");
88*12927SRod.Evans@Sun.COM 
89*12927SRod.Evans@Sun.COM 	(void) close(pauxvfd);
90*12927SRod.Evans@Sun.COM 
91*12927SRod.Evans@Sun.COM 	procp->pp_auxvp = auxvptr;
92*12927SRod.Evans@Sun.COM 	auxvtail = (void *)((uintptr_t)auxvptr + stbuf.st_size);
93*12927SRod.Evans@Sun.COM 
94*12927SRod.Evans@Sun.COM #if defined(_LP64)
95*12927SRod.Evans@Sun.COM 	if (procp->pp_dmodel == PR_MODEL_ILP32)
96*12927SRod.Evans@Sun.COM 		entsize = sizeof (auxv32_t);
97*12927SRod.Evans@Sun.COM 	else
98*12927SRod.Evans@Sun.COM #endif
99*12927SRod.Evans@Sun.COM 		entsize = sizeof (auxv_t);
100*12927SRod.Evans@Sun.COM 
101*12927SRod.Evans@Sun.COM 	while (auxvptr < auxvtail) {
102*12927SRod.Evans@Sun.COM 		auxvp = auxvptr;
103*12927SRod.Evans@Sun.COM 		if (auxvp->a_type == AT_BASE) {
104*12927SRod.Evans@Sun.COM #if defined(_LP64)
105*12927SRod.Evans@Sun.COM 			if (procp->pp_dmodel == PR_MODEL_ILP32)
106*12927SRod.Evans@Sun.COM 				procp->pp_ldsobase =
107*12927SRod.Evans@Sun.COM 				    ((uintptr_t)((auxv32_t *)auxvp)->
108*12927SRod.Evans@Sun.COM 				    a_un.a_val);
109*12927SRod.Evans@Sun.COM 			else
110*12927SRod.Evans@Sun.COM #endif
111*12927SRod.Evans@Sun.COM 				procp->pp_ldsobase =  auxvp->a_un.a_val;
112*12927SRod.Evans@Sun.COM 		} else if (auxvp->a_type == AT_PHDR) {
113*12927SRod.Evans@Sun.COM #if defined(_LP64)
114*12927SRod.Evans@Sun.COM 			if (procp->pp_dmodel == PR_MODEL_ILP32)
115*12927SRod.Evans@Sun.COM 				procp->pp_execphdr =
116*12927SRod.Evans@Sun.COM 				    ((uintptr_t)((auxv32_t *)auxvp)->
117*12927SRod.Evans@Sun.COM 				    a_un.a_val);
118*12927SRod.Evans@Sun.COM 			else
119*12927SRod.Evans@Sun.COM #endif
120*12927SRod.Evans@Sun.COM 				procp->pp_execphdr =  auxvp->a_un.a_val;
121*12927SRod.Evans@Sun.COM 		}
122*12927SRod.Evans@Sun.COM 		auxvptr = (void *)((uintptr_t)auxvptr + entsize);
123*12927SRod.Evans@Sun.COM 	}
124*12927SRod.Evans@Sun.COM }
125*12927SRod.Evans@Sun.COM 
126*12927SRod.Evans@Sun.COM retc_t
ps_init(int pctlfd,int pstatusfd,pid_t pid,struct ps_prochandle * procp)127*12927SRod.Evans@Sun.COM ps_init(int pctlfd, int pstatusfd, pid_t pid, struct ps_prochandle *procp)
128*12927SRod.Evans@Sun.COM {
129*12927SRod.Evans@Sun.COM 	rd_notify_t	rd_notify;
130*12927SRod.Evans@Sun.COM 	char		procname[PROCSIZE];
131*12927SRod.Evans@Sun.COM 	long		oper, pflags;
132*12927SRod.Evans@Sun.COM 	struct iovec	piov[2];
133*12927SRod.Evans@Sun.COM 
134*12927SRod.Evans@Sun.COM 	procp->pp_pid = pid;
135*12927SRod.Evans@Sun.COM 	procp->pp_ctlfd = pctlfd;
136*12927SRod.Evans@Sun.COM 	procp->pp_statusfd = pstatusfd;
137*12927SRod.Evans@Sun.COM 
138*12927SRod.Evans@Sun.COM 	(void) snprintf(procname, PROCSIZE, "/proc/%d/map",
139*12927SRod.Evans@Sun.COM 	    EC_SWORD(procp->pp_pid));
140*12927SRod.Evans@Sun.COM 	if ((procp->pp_mapfd = open(procname, O_RDONLY)) == -1)
141*12927SRod.Evans@Sun.COM 		perr("psi: open of /proc/dpid/map failed");
142*12927SRod.Evans@Sun.COM 
143*12927SRod.Evans@Sun.COM 	(void) snprintf(procname, PROCSIZE, "/proc/%d/as",
144*12927SRod.Evans@Sun.COM 	    EC_SWORD(procp->pp_pid));
145*12927SRod.Evans@Sun.COM 	if ((procp->pp_asfd = open(procname, O_RDWR)) == -1)
146*12927SRod.Evans@Sun.COM 		perr("psi: open of /proc/dpid/as failed");
147*12927SRod.Evans@Sun.COM 
148*12927SRod.Evans@Sun.COM 	if (ps_pdmodel(procp, &procp->pp_dmodel) != PS_OK)
149*12927SRod.Evans@Sun.COM 		perr("psi: data model");
150*12927SRod.Evans@Sun.COM 
151*12927SRod.Evans@Sun.COM #if	!defined(_LP64)
152*12927SRod.Evans@Sun.COM 	if (procp->pp_dmodel == PR_MODEL_LP64)
153*12927SRod.Evans@Sun.COM 		perr("psi:  run 64-bit rdb to debug a 64-bit process");
154*12927SRod.Evans@Sun.COM #endif
155*12927SRod.Evans@Sun.COM 	get_ldbase(procp);
156*12927SRod.Evans@Sun.COM 
157*12927SRod.Evans@Sun.COM 	(void) load_map(procp, (caddr_t)procp->pp_ldsobase,
158*12927SRod.Evans@Sun.COM 	    &(procp->pp_ldsomap));
159*12927SRod.Evans@Sun.COM 	procp->pp_ldsomap.mi_addr += procp->pp_ldsobase;
160*12927SRod.Evans@Sun.COM 	procp->pp_ldsomap.mi_end += procp->pp_ldsobase;
161*12927SRod.Evans@Sun.COM 	procp->pp_ldsomap.mi_name = "<procfs: interp>";
162*12927SRod.Evans@Sun.COM 
163*12927SRod.Evans@Sun.COM 	(void) load_map(procp, (caddr_t)procp->pp_execphdr,
164*12927SRod.Evans@Sun.COM 	    &(procp->pp_execmap));
165*12927SRod.Evans@Sun.COM 	procp->pp_execmap.mi_name = "<procfs: exec>";
166*12927SRod.Evans@Sun.COM 
167*12927SRod.Evans@Sun.COM 	procp->pp_breakpoints = NULL;
168*12927SRod.Evans@Sun.COM 	procp->pp_flags = FLG_PP_PACT | FLG_PP_PLTSKIP;
169*12927SRod.Evans@Sun.COM 	procp->pp_lmaplist.ml_head = NULL;
170*12927SRod.Evans@Sun.COM 	procp->pp_lmaplist.ml_tail = NULL;
171*12927SRod.Evans@Sun.COM 	if ((procp->pp_rap = rd_new(procp)) == NULL) {
172*12927SRod.Evans@Sun.COM 		(void) fprintf(stderr, "rdb: rtld_db: rd_new() call failed\n");
173*12927SRod.Evans@Sun.COM 		exit(1);
174*12927SRod.Evans@Sun.COM 	}
175*12927SRod.Evans@Sun.COM 	(void) rd_event_enable(procp->pp_rap, 1);
176*12927SRod.Evans@Sun.COM 
177*12927SRod.Evans@Sun.COM 	/*
178*12927SRod.Evans@Sun.COM 	 * For those architectures that increment the PC on
179*12927SRod.Evans@Sun.COM 	 * a breakpoint fault we enable the PR_BPTADJ adjustments.
180*12927SRod.Evans@Sun.COM 	 */
181*12927SRod.Evans@Sun.COM 	oper = PCSET;
182*12927SRod.Evans@Sun.COM 	pflags = PR_BPTADJ;
183*12927SRod.Evans@Sun.COM 	piov[0].iov_base = (caddr_t)(&oper);
184*12927SRod.Evans@Sun.COM 	piov[0].iov_len = sizeof (oper);
185*12927SRod.Evans@Sun.COM 	piov[1].iov_base = (caddr_t)(&pflags);
186*12927SRod.Evans@Sun.COM 	piov[1].iov_len = sizeof (pflags);
187*12927SRod.Evans@Sun.COM 	if (writev(procp->pp_ctlfd, piov, 2) == -1)
188*12927SRod.Evans@Sun.COM 		perr("psinit: PCSET(PR_BTPADJ)");
189*12927SRod.Evans@Sun.COM 
190*12927SRod.Evans@Sun.COM 	/*
191*12927SRod.Evans@Sun.COM 	 * Set breakpoints for special handshakes between librtld_db.so
192*12927SRod.Evans@Sun.COM 	 * and the debugger.  These include:
193*12927SRod.Evans@Sun.COM 	 *	PREINIT		- before .init processing.
194*12927SRod.Evans@Sun.COM 	 *	POSTINIT	- after .init processing
195*12927SRod.Evans@Sun.COM 	 *	DLACTIVITY	- link_maps status has changed
196*12927SRod.Evans@Sun.COM 	 */
197*12927SRod.Evans@Sun.COM 	if (rd_event_addr(procp->pp_rap, RD_PREINIT, &rd_notify) == RD_OK) {
198*12927SRod.Evans@Sun.COM 		if (set_breakpoint(procp, rd_notify.u.bptaddr,
199*12927SRod.Evans@Sun.COM 		    FLG_BP_RDPREINIT) != RET_OK)
200*12927SRod.Evans@Sun.COM 			(void) fprintf(stderr,
201*12927SRod.Evans@Sun.COM 			    "psi: failed to set BP for preinit at: 0x%lx\n",
202*12927SRod.Evans@Sun.COM 			    rd_notify.u.bptaddr);
203*12927SRod.Evans@Sun.COM 	} else
204*12927SRod.Evans@Sun.COM 		(void) fprintf(stderr, "psi: no event registered for "
205*12927SRod.Evans@Sun.COM 		    "preinit\n");
206*12927SRod.Evans@Sun.COM 
207*12927SRod.Evans@Sun.COM 	if (rd_event_addr(procp->pp_rap, RD_POSTINIT, &rd_notify) == RD_OK) {
208*12927SRod.Evans@Sun.COM 		if (set_breakpoint(procp, rd_notify.u.bptaddr,
209*12927SRod.Evans@Sun.COM 		    FLG_BP_RDPOSTINIT) != RET_OK)
210*12927SRod.Evans@Sun.COM 			(void) fprintf(stderr,
211*12927SRod.Evans@Sun.COM 			    "psi: failed to set BP for postinit at: 0x%lx\n",
212*12927SRod.Evans@Sun.COM 			    rd_notify.u.bptaddr);
213*12927SRod.Evans@Sun.COM 	} else
214*12927SRod.Evans@Sun.COM 		(void) fprintf(stderr, "psi: no event registered for "
215*12927SRod.Evans@Sun.COM 		    "postinit\n");
216*12927SRod.Evans@Sun.COM 
217*12927SRod.Evans@Sun.COM 	if (rd_event_addr(procp->pp_rap, RD_DLACTIVITY, &rd_notify) == RD_OK) {
218*12927SRod.Evans@Sun.COM 		if (set_breakpoint(procp, rd_notify.u.bptaddr,
219*12927SRod.Evans@Sun.COM 		    FLG_BP_RDDLACT) != RET_OK)
220*12927SRod.Evans@Sun.COM 			(void) fprintf(stderr,
221*12927SRod.Evans@Sun.COM 			    "psi: failed to set BP for dlact at: 0x%lx\n",
222*12927SRod.Evans@Sun.COM 			    rd_notify.u.bptaddr);
223*12927SRod.Evans@Sun.COM 	} else
224*12927SRod.Evans@Sun.COM 		(void) fprintf(stderr, "psi: no event registered for dlact\n");
225*12927SRod.Evans@Sun.COM 
226*12927SRod.Evans@Sun.COM 	return (RET_OK);
227*12927SRod.Evans@Sun.COM }
228*12927SRod.Evans@Sun.COM 
229*12927SRod.Evans@Sun.COM retc_t
ps_close(struct ps_prochandle * ph)230*12927SRod.Evans@Sun.COM ps_close(struct ps_prochandle *ph)
231*12927SRod.Evans@Sun.COM {
232*12927SRod.Evans@Sun.COM 	(void) delete_all_breakpoints(ph);
233*12927SRod.Evans@Sun.COM 
234*12927SRod.Evans@Sun.COM 	if (ph->pp_auxvp)
235*12927SRod.Evans@Sun.COM 		free(ph->pp_auxvp);
236*12927SRod.Evans@Sun.COM 	free_linkmaps(ph);
237*12927SRod.Evans@Sun.COM 	return (RET_OK);
238*12927SRod.Evans@Sun.COM }
239*12927SRod.Evans@Sun.COM 
240*12927SRod.Evans@Sun.COM ps_err_e
ps_pauxv(struct ps_prochandle * ph,const auxv_t ** auxvp)241*12927SRod.Evans@Sun.COM ps_pauxv(struct ps_prochandle *ph, const auxv_t **auxvp)
242*12927SRod.Evans@Sun.COM {
243*12927SRod.Evans@Sun.COM 	*auxvp = ph->pp_auxvp;
244*12927SRod.Evans@Sun.COM 	return (PS_OK);
245*12927SRod.Evans@Sun.COM }
246*12927SRod.Evans@Sun.COM 
247*12927SRod.Evans@Sun.COM ps_err_e
ps_pdmodel(struct ps_prochandle * ph,int * dm)248*12927SRod.Evans@Sun.COM ps_pdmodel(struct ps_prochandle *ph, int *dm)
249*12927SRod.Evans@Sun.COM {
250*12927SRod.Evans@Sun.COM 	pstatus_t	pstatus;
251*12927SRod.Evans@Sun.COM 
252*12927SRod.Evans@Sun.COM 	if (pread(ph->pp_statusfd, &pstatus, sizeof (pstatus), 0) == -1)
253*12927SRod.Evans@Sun.COM 		return (PS_ERR);
254*12927SRod.Evans@Sun.COM 
255*12927SRod.Evans@Sun.COM 	*dm = (int)pstatus.pr_dmodel;
256*12927SRod.Evans@Sun.COM 	return (PS_OK);
257*12927SRod.Evans@Sun.COM }
258*12927SRod.Evans@Sun.COM 
259*12927SRod.Evans@Sun.COM ps_err_e
ps_pread(struct ps_prochandle * ph,psaddr_t addr,void * buf,size_t size)260*12927SRod.Evans@Sun.COM ps_pread(struct ps_prochandle *ph, psaddr_t addr, void *buf, size_t size)
261*12927SRod.Evans@Sun.COM {
262*12927SRod.Evans@Sun.COM 	if (pread(ph->pp_asfd, buf, size, (off_t)addr) != size)
263*12927SRod.Evans@Sun.COM 		return (PS_ERR);
264*12927SRod.Evans@Sun.COM 
265*12927SRod.Evans@Sun.COM 	return (PS_OK);
266*12927SRod.Evans@Sun.COM }
267*12927SRod.Evans@Sun.COM 
268*12927SRod.Evans@Sun.COM ps_err_e
ps_pwrite(struct ps_prochandle * ph,psaddr_t addr,const void * buf,size_t size)269*12927SRod.Evans@Sun.COM ps_pwrite(struct ps_prochandle *ph, psaddr_t addr, const void *buf, size_t size)
270*12927SRod.Evans@Sun.COM {
271*12927SRod.Evans@Sun.COM 	if (pwrite(ph->pp_asfd, buf, size, (off_t)addr) != size)
272*12927SRod.Evans@Sun.COM 		return (PS_ERR);
273*12927SRod.Evans@Sun.COM 
274*12927SRod.Evans@Sun.COM 	return (PS_OK);
275*12927SRod.Evans@Sun.COM }
276*12927SRod.Evans@Sun.COM 
277*12927SRod.Evans@Sun.COM ps_err_e
ps_pglobal_sym(struct ps_prochandle * ph,const char * object_name,const char * sym_name,ps_sym_t * symp)278*12927SRod.Evans@Sun.COM ps_pglobal_sym(struct ps_prochandle *ph, const char *object_name,
279*12927SRod.Evans@Sun.COM     const char *sym_name, ps_sym_t *symp)
280*12927SRod.Evans@Sun.COM {
281*12927SRod.Evans@Sun.COM 	map_info_t	*mip;
282*12927SRod.Evans@Sun.COM 	GElf_Sym	gsym;
283*12927SRod.Evans@Sun.COM 
284*12927SRod.Evans@Sun.COM 	if ((mip = str_to_map(ph, object_name)) == NULL)
285*12927SRod.Evans@Sun.COM 		return (PS_ERR);
286*12927SRod.Evans@Sun.COM 
287*12927SRod.Evans@Sun.COM 	if (str_map_sym(sym_name, mip, &gsym, NULL) == RET_FAILED)
288*12927SRod.Evans@Sun.COM 		return (PS_ERR);
289*12927SRod.Evans@Sun.COM 
290*12927SRod.Evans@Sun.COM #if	defined(_LP64)
291*12927SRod.Evans@Sun.COM 	*symp = gsym;
292*12927SRod.Evans@Sun.COM #else
293*12927SRod.Evans@Sun.COM 	gelf_sym_to_elf32(&gsym, (Elf32_Sym *)symp);
294*12927SRod.Evans@Sun.COM #endif
295*12927SRod.Evans@Sun.COM 
296*12927SRod.Evans@Sun.COM 	return (PS_OK);
297*12927SRod.Evans@Sun.COM }
298*12927SRod.Evans@Sun.COM 
299*12927SRod.Evans@Sun.COM ps_err_e
ps_pglobal_lookup(struct ps_prochandle * ph,const char * object_name,const char * sym_name,ulong_t * sym_addr)300*12927SRod.Evans@Sun.COM ps_pglobal_lookup(struct ps_prochandle *ph, const char *object_name,
301*12927SRod.Evans@Sun.COM     const char *sym_name, ulong_t *sym_addr)
302*12927SRod.Evans@Sun.COM {
303*12927SRod.Evans@Sun.COM 	GElf_Sym	sym;
304*12927SRod.Evans@Sun.COM 	map_info_t	*mip;
305*12927SRod.Evans@Sun.COM 
306*12927SRod.Evans@Sun.COM 	if ((mip = str_to_map(ph, object_name)) == NULL)
307*12927SRod.Evans@Sun.COM 		return (PS_ERR);
308*12927SRod.Evans@Sun.COM 
309*12927SRod.Evans@Sun.COM 	if (str_map_sym(sym_name, mip, &sym, NULL) == RET_FAILED)
310*12927SRod.Evans@Sun.COM 		return (PS_ERR);
311*12927SRod.Evans@Sun.COM 
312*12927SRod.Evans@Sun.COM 	*sym_addr = sym.st_value;
313*12927SRod.Evans@Sun.COM 
314*12927SRod.Evans@Sun.COM 	return (PS_OK);
315*12927SRod.Evans@Sun.COM }
316*12927SRod.Evans@Sun.COM 
317*12927SRod.Evans@Sun.COM ps_err_e
ps_lgetregs(struct ps_prochandle * ph,lwpid_t lid,prgregset_t gregset)318*12927SRod.Evans@Sun.COM ps_lgetregs(struct ps_prochandle *ph, lwpid_t lid, prgregset_t gregset)
319*12927SRod.Evans@Sun.COM {
320*12927SRod.Evans@Sun.COM 	char		procname[MAXPATHLEN];
321*12927SRod.Evans@Sun.COM 	int		lwpfd;
322*12927SRod.Evans@Sun.COM 	lwpstatus_t	lwpstatus;
323*12927SRod.Evans@Sun.COM 
324*12927SRod.Evans@Sun.COM 	(void) snprintf(procname, MAXPATHLEN - 1,
325*12927SRod.Evans@Sun.COM 	    "/proc/%d/lwp/%d/lwpstatus", EC_SWORD(ph->pp_pid), EC_SWORD(lid));
326*12927SRod.Evans@Sun.COM 
327*12927SRod.Evans@Sun.COM 	if ((lwpfd = open(procname, O_RDONLY)) == -1)
328*12927SRod.Evans@Sun.COM 		return (PS_ERR);
329*12927SRod.Evans@Sun.COM 
330*12927SRod.Evans@Sun.COM 	if (read(lwpfd, &lwpstatus, sizeof (lwpstatus)) == -1)
331*12927SRod.Evans@Sun.COM 		return (PS_ERR);
332*12927SRod.Evans@Sun.COM 
333*12927SRod.Evans@Sun.COM 	gregset = lwpstatus.pr_reg;
334*12927SRod.Evans@Sun.COM 
335*12927SRod.Evans@Sun.COM 	(void) close(lwpfd);
336*12927SRod.Evans@Sun.COM 	return (PS_OK);
337*12927SRod.Evans@Sun.COM }
338*12927SRod.Evans@Sun.COM 
339*12927SRod.Evans@Sun.COM void
ps_plog(const char * fmt,...)340*12927SRod.Evans@Sun.COM ps_plog(const char *fmt, ...)
341*12927SRod.Evans@Sun.COM {
342*12927SRod.Evans@Sun.COM 	va_list		args;
343*12927SRod.Evans@Sun.COM 	static FILE	*log_fp = NULL;
344*12927SRod.Evans@Sun.COM 
345*12927SRod.Evans@Sun.COM 	if (log_fp == NULL) {
346*12927SRod.Evans@Sun.COM 		char		log_fname[256];
347*12927SRod.Evans@Sun.COM 		(void) sprintf(log_fname, "/tmp/tdlog.%d", EC_SWORD(getpid()));
348*12927SRod.Evans@Sun.COM 		if ((log_fp = fopen(log_fname, "w")) == NULL) {
349*12927SRod.Evans@Sun.COM 			/*
350*12927SRod.Evans@Sun.COM 			 * Unable to open log file - default to stderr.
351*12927SRod.Evans@Sun.COM 			 */
352*12927SRod.Evans@Sun.COM 			(void) fprintf(stderr, "unable to open %s, logging "
353*12927SRod.Evans@Sun.COM 			    "redirected to stderr", log_fname);
354*12927SRod.Evans@Sun.COM 			log_fp = stderr;
355*12927SRod.Evans@Sun.COM 		}
356*12927SRod.Evans@Sun.COM 	}
357*12927SRod.Evans@Sun.COM 
358*12927SRod.Evans@Sun.COM 	va_start(args, fmt);
359*12927SRod.Evans@Sun.COM 	(void) vfprintf(log_fp, fmt, args);
360*12927SRod.Evans@Sun.COM 	va_end(args);
361*12927SRod.Evans@Sun.COM 	(void) fputc('\n', log_fp);
362*12927SRod.Evans@Sun.COM 	(void) fflush(log_fp);
363*12927SRod.Evans@Sun.COM }
364*12927SRod.Evans@Sun.COM 
365*12927SRod.Evans@Sun.COM /* ARGSUSED0 */
366*12927SRod.Evans@Sun.COM ps_err_e
ps_pbrandname(struct ps_prochandle * P,char * buf,size_t len)367*12927SRod.Evans@Sun.COM ps_pbrandname(struct ps_prochandle *P, char *buf, size_t len)
368*12927SRod.Evans@Sun.COM {
369*12927SRod.Evans@Sun.COM 	return (PS_ERR);
370*12927SRod.Evans@Sun.COM }
371