xref: /illumos-gate/usr/src/cmd/sgs/demo_rdb/common/ps.c (revision d9328cd4)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
59039eeafSab  * Common Development and Distribution License (the "License").
69039eeafSab  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
2120c1c355SRod Evans 
227c478bd9Sstevel@tonic-gate /*
2320c1c355SRod Evans  * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <stdio.h>
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include <unistd.h>
297c478bd9Sstevel@tonic-gate #include <sys/uio.h>
307c478bd9Sstevel@tonic-gate #include <fcntl.h>
317c478bd9Sstevel@tonic-gate #include <string.h>
327c478bd9Sstevel@tonic-gate #include <errno.h>
337c478bd9Sstevel@tonic-gate #include <sys/types.h>
347c478bd9Sstevel@tonic-gate #include <sys/signal.h>
357c478bd9Sstevel@tonic-gate #include <sys/fault.h>
367c478bd9Sstevel@tonic-gate #include <sys/syscall.h>
377c478bd9Sstevel@tonic-gate #include <procfs.h>
387c478bd9Sstevel@tonic-gate #include <sys/auxv.h>
397c478bd9Sstevel@tonic-gate #include <sys/stat.h>
407c478bd9Sstevel@tonic-gate #include <sys/mman.h>
417c478bd9Sstevel@tonic-gate #include <libelf.h>
427c478bd9Sstevel@tonic-gate #include <sys/param.h>
4320c1c355SRod Evans #include <sys/machelf.h>
447c478bd9Sstevel@tonic-gate #include <stdarg.h>
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate #include <proc_service.h>
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate #include "rdb.h"
497c478bd9Sstevel@tonic-gate #include "disasm.h"
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate #if	!defined(_LP64)
527c478bd9Sstevel@tonic-gate static void
gelf_sym_to_elf32(GElf_Sym * src,Elf32_Sym * dst)539039eeafSab gelf_sym_to_elf32(GElf_Sym *src, Elf32_Sym *dst)
547c478bd9Sstevel@tonic-gate {
557c478bd9Sstevel@tonic-gate 	dst->st_name	= src->st_name;
5620c1c355SRod Evans 	dst->st_value	= src->st_value;
5720c1c355SRod Evans 	dst->st_size	= src->st_size;
587c478bd9Sstevel@tonic-gate 	dst->st_info	= ELF32_ST_INFO(GELF_ST_BIND(src->st_info),
5920c1c355SRod Evans 	    GELF_ST_TYPE(src->st_info));
607c478bd9Sstevel@tonic-gate 	dst->st_other	= src->st_other;
617c478bd9Sstevel@tonic-gate 	dst->st_shndx	= src->st_shndx;
627c478bd9Sstevel@tonic-gate }
637c478bd9Sstevel@tonic-gate #endif
647c478bd9Sstevel@tonic-gate 
6520c1c355SRod Evans #define	PROCSIZE	20
6620c1c355SRod Evans 
677c478bd9Sstevel@tonic-gate static void
get_ldbase(struct ps_prochandle * procp)689039eeafSab get_ldbase(struct ps_prochandle *procp)
697c478bd9Sstevel@tonic-gate {
707c478bd9Sstevel@tonic-gate 	int		pauxvfd;
7120c1c355SRod Evans 	char		pname[PROCSIZE];
727c478bd9Sstevel@tonic-gate 	struct stat	stbuf;
739039eeafSab 	void		*auxvptr, *auxvtail;
749039eeafSab 	auxv_t		*auxvp;
757c478bd9Sstevel@tonic-gate 	uint_t		entsize;
767c478bd9Sstevel@tonic-gate 
7720c1c355SRod Evans 	(void) snprintf(pname, PROCSIZE, "/proc/%d/auxv",
7820c1c355SRod Evans 	    EC_SWORD(procp->pp_pid));
797c478bd9Sstevel@tonic-gate 	if ((pauxvfd = open(pname, O_RDONLY)) == -1)
807c478bd9Sstevel@tonic-gate 		perr("open auxv");
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate 	if (fstat(pauxvfd, &stbuf) == -1)
837c478bd9Sstevel@tonic-gate 		perr("stat auxv");
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 	auxvptr = malloc(stbuf.st_size);
867c478bd9Sstevel@tonic-gate 	if (read(pauxvfd, auxvptr, stbuf.st_size) == -1)
877c478bd9Sstevel@tonic-gate 		perr("gldb: reading auxv");
887c478bd9Sstevel@tonic-gate 
8920c1c355SRod Evans 	(void) close(pauxvfd);
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate 	procp->pp_auxvp = auxvptr;
927c478bd9Sstevel@tonic-gate 	auxvtail = (void *)((uintptr_t)auxvptr + stbuf.st_size);
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate #if defined(_LP64)
957c478bd9Sstevel@tonic-gate 	if (procp->pp_dmodel == PR_MODEL_ILP32)
967c478bd9Sstevel@tonic-gate 		entsize = sizeof (auxv32_t);
977c478bd9Sstevel@tonic-gate 	else
987c478bd9Sstevel@tonic-gate #endif
997c478bd9Sstevel@tonic-gate 		entsize = sizeof (auxv_t);
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 	while (auxvptr < auxvtail) {
1027c478bd9Sstevel@tonic-gate 		auxvp = auxvptr;
1037c478bd9Sstevel@tonic-gate 		if (auxvp->a_type == AT_BASE) {
1047c478bd9Sstevel@tonic-gate #if defined(_LP64)
1057c478bd9Sstevel@tonic-gate 			if (procp->pp_dmodel == PR_MODEL_ILP32)
1067c478bd9Sstevel@tonic-gate 				procp->pp_ldsobase =
1077c478bd9Sstevel@tonic-gate 				    ((uintptr_t)((auxv32_t *)auxvp)->
1087c478bd9Sstevel@tonic-gate 				    a_un.a_val);
1097c478bd9Sstevel@tonic-gate 			else
1107c478bd9Sstevel@tonic-gate #endif
1117c478bd9Sstevel@tonic-gate 				procp->pp_ldsobase =  auxvp->a_un.a_val;
1127c478bd9Sstevel@tonic-gate 		} else if (auxvp->a_type == AT_PHDR) {
1137c478bd9Sstevel@tonic-gate #if defined(_LP64)
1147c478bd9Sstevel@tonic-gate 			if (procp->pp_dmodel == PR_MODEL_ILP32)
1157c478bd9Sstevel@tonic-gate 				procp->pp_execphdr =
1167c478bd9Sstevel@tonic-gate 				    ((uintptr_t)((auxv32_t *)auxvp)->
1177c478bd9Sstevel@tonic-gate 				    a_un.a_val);
1187c478bd9Sstevel@tonic-gate 			else
1197c478bd9Sstevel@tonic-gate #endif
1207c478bd9Sstevel@tonic-gate 				procp->pp_execphdr =  auxvp->a_un.a_val;
1217c478bd9Sstevel@tonic-gate 		}
1227c478bd9Sstevel@tonic-gate 		auxvptr = (void *)((uintptr_t)auxvptr + entsize);
1237c478bd9Sstevel@tonic-gate 	}
1247c478bd9Sstevel@tonic-gate }
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate retc_t
ps_init(int pctlfd,int pstatusfd,pid_t pid,struct ps_prochandle * procp)1279039eeafSab ps_init(int pctlfd, int pstatusfd, pid_t pid, struct ps_prochandle *procp)
1287c478bd9Sstevel@tonic-gate {
1297c478bd9Sstevel@tonic-gate 	rd_notify_t	rd_notify;
13020c1c355SRod Evans 	char		procname[PROCSIZE];
13120c1c355SRod Evans 	long		oper, pflags;
1327c478bd9Sstevel@tonic-gate 	struct iovec	piov[2];
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	procp->pp_pid = pid;
1357c478bd9Sstevel@tonic-gate 	procp->pp_ctlfd = pctlfd;
1367c478bd9Sstevel@tonic-gate 	procp->pp_statusfd = pstatusfd;
1377c478bd9Sstevel@tonic-gate 
13820c1c355SRod Evans 	(void) snprintf(procname, PROCSIZE, "/proc/%d/map",
13920c1c355SRod Evans 	    EC_SWORD(procp->pp_pid));
1407c478bd9Sstevel@tonic-gate 	if ((procp->pp_mapfd = open(procname, O_RDONLY)) == -1)
1417c478bd9Sstevel@tonic-gate 		perr("psi: open of /proc/dpid/map failed");
1427c478bd9Sstevel@tonic-gate 
14320c1c355SRod Evans 	(void) snprintf(procname, PROCSIZE, "/proc/%d/as",
14420c1c355SRod Evans 	    EC_SWORD(procp->pp_pid));
1457c478bd9Sstevel@tonic-gate 	if ((procp->pp_asfd = open(procname, O_RDWR)) == -1)
1467c478bd9Sstevel@tonic-gate 		perr("psi: open of /proc/dpid/as failed");
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	if (ps_pdmodel(procp, &procp->pp_dmodel) != PS_OK)
1497c478bd9Sstevel@tonic-gate 		perr("psi: data model");
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate #if	!defined(_LP64)
1527c478bd9Sstevel@tonic-gate 	if (procp->pp_dmodel == PR_MODEL_LP64)
1537c478bd9Sstevel@tonic-gate 		perr("psi:  run 64-bit rdb to debug a 64-bit process");
1547c478bd9Sstevel@tonic-gate #endif
1557c478bd9Sstevel@tonic-gate 	get_ldbase(procp);
1567c478bd9Sstevel@tonic-gate 
15720c1c355SRod Evans 	(void) load_map(procp, (caddr_t)procp->pp_ldsobase,
15820c1c355SRod Evans 	    &(procp->pp_ldsomap));
1597c478bd9Sstevel@tonic-gate 	procp->pp_ldsomap.mi_addr += procp->pp_ldsobase;
1607c478bd9Sstevel@tonic-gate 	procp->pp_ldsomap.mi_end += procp->pp_ldsobase;
1617c478bd9Sstevel@tonic-gate 	procp->pp_ldsomap.mi_name = "<procfs: interp>";
1627c478bd9Sstevel@tonic-gate 
16320c1c355SRod Evans 	(void) load_map(procp, (caddr_t)procp->pp_execphdr,
16420c1c355SRod Evans 	    &(procp->pp_execmap));
1657c478bd9Sstevel@tonic-gate 	procp->pp_execmap.mi_name = "<procfs: exec>";
1667c478bd9Sstevel@tonic-gate 
16720c1c355SRod Evans 	procp->pp_breakpoints = NULL;
1687c478bd9Sstevel@tonic-gate 	procp->pp_flags = FLG_PP_PACT | FLG_PP_PLTSKIP;
16920c1c355SRod Evans 	procp->pp_lmaplist.ml_head = NULL;
17020c1c355SRod Evans 	procp->pp_lmaplist.ml_tail = NULL;
17120c1c355SRod Evans 	if ((procp->pp_rap = rd_new(procp)) == NULL) {
17220c1c355SRod Evans 		(void) fprintf(stderr, "rdb: rtld_db: rd_new() call failed\n");
1737c478bd9Sstevel@tonic-gate 		exit(1);
1747c478bd9Sstevel@tonic-gate 	}
17520c1c355SRod Evans 	(void) rd_event_enable(procp->pp_rap, 1);
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	/*
1787c478bd9Sstevel@tonic-gate 	 * For those architectures that increment the PC on
1797c478bd9Sstevel@tonic-gate 	 * a breakpoint fault we enable the PR_BPTADJ adjustments.
1807c478bd9Sstevel@tonic-gate 	 */
1817c478bd9Sstevel@tonic-gate 	oper = PCSET;
1827c478bd9Sstevel@tonic-gate 	pflags = PR_BPTADJ;
1837c478bd9Sstevel@tonic-gate 	piov[0].iov_base = (caddr_t)(&oper);
1847c478bd9Sstevel@tonic-gate 	piov[0].iov_len = sizeof (oper);
1857c478bd9Sstevel@tonic-gate 	piov[1].iov_base = (caddr_t)(&pflags);
1867c478bd9Sstevel@tonic-gate 	piov[1].iov_len = sizeof (pflags);
1877c478bd9Sstevel@tonic-gate 	if (writev(procp->pp_ctlfd, piov, 2) == -1)
1887c478bd9Sstevel@tonic-gate 		perr("psinit: PCSET(PR_BTPADJ)");
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 	/*
1917c478bd9Sstevel@tonic-gate 	 * Set breakpoints for special handshakes between librtld_db.so
1927c478bd9Sstevel@tonic-gate 	 * and the debugger.  These include:
1937c478bd9Sstevel@tonic-gate 	 *	PREINIT		- before .init processing.
1947c478bd9Sstevel@tonic-gate 	 *	POSTINIT	- after .init processing
1957c478bd9Sstevel@tonic-gate 	 *	DLACTIVITY	- link_maps status has changed
1967c478bd9Sstevel@tonic-gate 	 */
1977c478bd9Sstevel@tonic-gate 	if (rd_event_addr(procp->pp_rap, RD_PREINIT, &rd_notify) == RD_OK) {
1987c478bd9Sstevel@tonic-gate 		if (set_breakpoint(procp, rd_notify.u.bptaddr,
1997c478bd9Sstevel@tonic-gate 		    FLG_BP_RDPREINIT) != RET_OK)
20020c1c355SRod Evans 			(void) fprintf(stderr,
20120c1c355SRod Evans 			    "psi: failed to set BP for preinit at: 0x%lx\n",
20220c1c355SRod Evans 			    rd_notify.u.bptaddr);
2037c478bd9Sstevel@tonic-gate 	} else
20420c1c355SRod Evans 		(void) fprintf(stderr, "psi: no event registered for "
20520c1c355SRod Evans 		    "preinit\n");
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	if (rd_event_addr(procp->pp_rap, RD_POSTINIT, &rd_notify) == RD_OK) {
2087c478bd9Sstevel@tonic-gate 		if (set_breakpoint(procp, rd_notify.u.bptaddr,
2097c478bd9Sstevel@tonic-gate 		    FLG_BP_RDPOSTINIT) != RET_OK)
21020c1c355SRod Evans 			(void) fprintf(stderr,
2117c478bd9Sstevel@tonic-gate 			    "psi: failed to set BP for postinit at: 0x%lx\n",
2127c478bd9Sstevel@tonic-gate 			    rd_notify.u.bptaddr);
2137c478bd9Sstevel@tonic-gate 	} else
21420c1c355SRod Evans 		(void) fprintf(stderr, "psi: no event registered for "
21520c1c355SRod Evans 		    "postinit\n");
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	if (rd_event_addr(procp->pp_rap, RD_DLACTIVITY, &rd_notify) == RD_OK) {
2187c478bd9Sstevel@tonic-gate 		if (set_breakpoint(procp, rd_notify.u.bptaddr,
2197c478bd9Sstevel@tonic-gate 		    FLG_BP_RDDLACT) != RET_OK)
22020c1c355SRod Evans 			(void) fprintf(stderr,
22120c1c355SRod Evans 			    "psi: failed to set BP for dlact at: 0x%lx\n",
22220c1c355SRod Evans 			    rd_notify.u.bptaddr);
2237c478bd9Sstevel@tonic-gate 	} else
22420c1c355SRod Evans 		(void) fprintf(stderr, "psi: no event registered for dlact\n");
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	return (RET_OK);
2277c478bd9Sstevel@tonic-gate }
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate retc_t
ps_close(struct ps_prochandle * ph)2309039eeafSab ps_close(struct ps_prochandle *ph)
2317c478bd9Sstevel@tonic-gate {
23220c1c355SRod Evans 	(void) delete_all_breakpoints(ph);
23320c1c355SRod Evans 
2347c478bd9Sstevel@tonic-gate 	if (ph->pp_auxvp)
2357c478bd9Sstevel@tonic-gate 		free(ph->pp_auxvp);
2367c478bd9Sstevel@tonic-gate 	free_linkmaps(ph);
2377c478bd9Sstevel@tonic-gate 	return (RET_OK);
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate ps_err_e
ps_pauxv(struct ps_prochandle * ph,const auxv_t ** auxvp)2419039eeafSab ps_pauxv(struct ps_prochandle *ph, const auxv_t **auxvp)
2427c478bd9Sstevel@tonic-gate {
2437c478bd9Sstevel@tonic-gate 	*auxvp = ph->pp_auxvp;
2447c478bd9Sstevel@tonic-gate 	return (PS_OK);
2457c478bd9Sstevel@tonic-gate }
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate ps_err_e
ps_pdmodel(struct ps_prochandle * ph,int * dm)2489039eeafSab ps_pdmodel(struct ps_prochandle *ph, int *dm)
2497c478bd9Sstevel@tonic-gate {
2507c478bd9Sstevel@tonic-gate 	pstatus_t	pstatus;
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	if (pread(ph->pp_statusfd, &pstatus, sizeof (pstatus), 0) == -1)
2537c478bd9Sstevel@tonic-gate 		return (PS_ERR);
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	*dm = (int)pstatus.pr_dmodel;
2567c478bd9Sstevel@tonic-gate 	return (PS_OK);
2577c478bd9Sstevel@tonic-gate }
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate ps_err_e
ps_pread(struct ps_prochandle * ph,psaddr_t addr,void * buf,size_t size)2609039eeafSab ps_pread(struct ps_prochandle *ph, psaddr_t addr, void *buf, size_t size)
2617c478bd9Sstevel@tonic-gate {
2627c478bd9Sstevel@tonic-gate 	if (pread(ph->pp_asfd, buf, size, (off_t)addr) != size)
2637c478bd9Sstevel@tonic-gate 		return (PS_ERR);
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	return (PS_OK);
2667c478bd9Sstevel@tonic-gate }
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate ps_err_e
ps_pwrite(struct ps_prochandle * ph,psaddr_t addr,const void * buf,size_t size)2699039eeafSab ps_pwrite(struct ps_prochandle *ph, psaddr_t addr, const void *buf, size_t size)
2707c478bd9Sstevel@tonic-gate {
2717c478bd9Sstevel@tonic-gate 	if (pwrite(ph->pp_asfd, buf, size, (off_t)addr) != size)
2727c478bd9Sstevel@tonic-gate 		return (PS_ERR);
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	return (PS_OK);
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate ps_err_e
ps_pglobal_sym(struct ps_prochandle * ph,const char * object_name,const char * sym_name,ps_sym_t * symp)2789039eeafSab ps_pglobal_sym(struct ps_prochandle *ph, const char *object_name,
2799039eeafSab     const char *sym_name, ps_sym_t *symp)
2807c478bd9Sstevel@tonic-gate {
2819039eeafSab 	map_info_t	*mip;
2827c478bd9Sstevel@tonic-gate 	GElf_Sym	gsym;
2837c478bd9Sstevel@tonic-gate 
28420c1c355SRod Evans 	if ((mip = str_to_map(ph, object_name)) == NULL)
2857c478bd9Sstevel@tonic-gate 		return (PS_ERR);
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 	if (str_map_sym(sym_name, mip, &gsym, NULL) == RET_FAILED)
2887c478bd9Sstevel@tonic-gate 		return (PS_ERR);
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate #if	defined(_LP64)
2917c478bd9Sstevel@tonic-gate 	*symp = gsym;
2927c478bd9Sstevel@tonic-gate #else
2937c478bd9Sstevel@tonic-gate 	gelf_sym_to_elf32(&gsym, (Elf32_Sym *)symp);
2947c478bd9Sstevel@tonic-gate #endif
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	return (PS_OK);
2977c478bd9Sstevel@tonic-gate }
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate ps_err_e
ps_pglobal_lookup(struct ps_prochandle * ph,const char * object_name,const char * sym_name,ulong_t * sym_addr)3009039eeafSab ps_pglobal_lookup(struct ps_prochandle *ph, const char *object_name,
3019039eeafSab     const char *sym_name, ulong_t *sym_addr)
3027c478bd9Sstevel@tonic-gate {
3037c478bd9Sstevel@tonic-gate 	GElf_Sym	sym;
3049039eeafSab 	map_info_t	*mip;
3057c478bd9Sstevel@tonic-gate 
30620c1c355SRod Evans 	if ((mip = str_to_map(ph, object_name)) == NULL)
3077c478bd9Sstevel@tonic-gate 		return (PS_ERR);
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	if (str_map_sym(sym_name, mip, &sym, NULL) == RET_FAILED)
3107c478bd9Sstevel@tonic-gate 		return (PS_ERR);
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	*sym_addr = sym.st_value;
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	return (PS_OK);
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate ps_err_e
ps_lgetregs(struct ps_prochandle * ph,lwpid_t lid,prgregset_t gregset)3189039eeafSab ps_lgetregs(struct ps_prochandle *ph, lwpid_t lid, prgregset_t gregset)
3197c478bd9Sstevel@tonic-gate {
3207c478bd9Sstevel@tonic-gate 	char		procname[MAXPATHLEN];
3217c478bd9Sstevel@tonic-gate 	int		lwpfd;
3227c478bd9Sstevel@tonic-gate 	lwpstatus_t	lwpstatus;
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	(void) snprintf(procname, MAXPATHLEN - 1,
32520c1c355SRod Evans 	    "/proc/%d/lwp/%d/lwpstatus", EC_SWORD(ph->pp_pid), EC_SWORD(lid));
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 	if ((lwpfd = open(procname, O_RDONLY)) == -1)
3287c478bd9Sstevel@tonic-gate 		return (PS_ERR);
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	if (read(lwpfd, &lwpstatus, sizeof (lwpstatus)) == -1)
3317c478bd9Sstevel@tonic-gate 		return (PS_ERR);
3327c478bd9Sstevel@tonic-gate 
33367b1ef3cSRichard Lowe 	(void) memcpy(gregset, lwpstatus.pr_reg, sizeof (*gregset));
3347c478bd9Sstevel@tonic-gate 
33520c1c355SRod Evans 	(void) close(lwpfd);
3367c478bd9Sstevel@tonic-gate 	return (PS_OK);
3377c478bd9Sstevel@tonic-gate }
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate void
ps_plog(const char * fmt,...)3409039eeafSab ps_plog(const char *fmt, ...)
3417c478bd9Sstevel@tonic-gate {
3427c478bd9Sstevel@tonic-gate 	va_list		args;
34320c1c355SRod Evans 	static FILE	*log_fp = NULL;
3447c478bd9Sstevel@tonic-gate 
34520c1c355SRod Evans 	if (log_fp == NULL) {
3467c478bd9Sstevel@tonic-gate 		char		log_fname[256];
34720c1c355SRod Evans 		(void) sprintf(log_fname, "/tmp/tdlog.%d", EC_SWORD(getpid()));
34820c1c355SRod Evans 		if ((log_fp = fopen(log_fname, "w")) == NULL) {
3497c478bd9Sstevel@tonic-gate 			/*
35020c1c355SRod Evans 			 * Unable to open log file - default to stderr.
3517c478bd9Sstevel@tonic-gate 			 */
35220c1c355SRod Evans 			(void) fprintf(stderr, "unable to open %s, logging "
35320c1c355SRod Evans 			    "redirected to stderr", log_fname);
3547c478bd9Sstevel@tonic-gate 			log_fp = stderr;
3557c478bd9Sstevel@tonic-gate 		}
3567c478bd9Sstevel@tonic-gate 	}
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 	va_start(args, fmt);
35920c1c355SRod Evans 	(void) vfprintf(log_fp, fmt, args);
3607c478bd9Sstevel@tonic-gate 	va_end(args);
36120c1c355SRod Evans 	(void) fputc('\n', log_fp);
36220c1c355SRod Evans 	(void) fflush(log_fp);
3637c478bd9Sstevel@tonic-gate }
3649039eeafSab 
36520c1c355SRod Evans /* ARGSUSED0 */
3669039eeafSab ps_err_e
ps_pbrandname(struct ps_prochandle * P,char * buf,size_t len)3679039eeafSab ps_pbrandname(struct ps_prochandle *P, char *buf, size_t len)
3689039eeafSab {
3699039eeafSab 	return (PS_ERR);
3709039eeafSab }
371