xref: /onnv-gate/usr/src/cmd/sgs/librtld_db/demo/common/bpt.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 <libelf.h>
40*12927SRod.Evans@Sun.COM #include <sys/param.h>
41*12927SRod.Evans@Sun.COM #include <sys/machelf.h>
42*12927SRod.Evans@Sun.COM #include <stdarg.h>
43*12927SRod.Evans@Sun.COM 
44*12927SRod.Evans@Sun.COM #include "rdb.h"
45*12927SRod.Evans@Sun.COM 
46*12927SRod.Evans@Sun.COM static const char *fault_strings[] = {
47*12927SRod.Evans@Sun.COM 	"<null string>",
48*12927SRod.Evans@Sun.COM 	"illegal instruction",
49*12927SRod.Evans@Sun.COM 	"privileged instruction",
50*12927SRod.Evans@Sun.COM 	"breakpoint instruction",
51*12927SRod.Evans@Sun.COM 	"trace trap (single-step)",
52*12927SRod.Evans@Sun.COM 	"Memory access (e.g., alignment)",
53*12927SRod.Evans@Sun.COM 	"Memory bounds (invalid address)",
54*12927SRod.Evans@Sun.COM 	"Integer overflow",
55*12927SRod.Evans@Sun.COM 	"Integer zero divide"
56*12927SRod.Evans@Sun.COM 	"Floating-point exception",
57*12927SRod.Evans@Sun.COM 	"Irrecoverable stack faul",
58*12927SRod.Evans@Sun.COM 	"Recoverable page fault (no associated sig)"
59*12927SRod.Evans@Sun.COM };
60*12927SRod.Evans@Sun.COM 
61*12927SRod.Evans@Sun.COM #define	MAXFAULT	FLTPAGE
62*12927SRod.Evans@Sun.COM 
63*12927SRod.Evans@Sun.COM retc_t
set_breakpoint(struct ps_prochandle * ph,ulong_t addr,unsigned flags)64*12927SRod.Evans@Sun.COM set_breakpoint(struct ps_prochandle *ph, ulong_t addr, unsigned flags)
65*12927SRod.Evans@Sun.COM {
66*12927SRod.Evans@Sun.COM 	bptlist_t	*new, *cur, *prev;
67*12927SRod.Evans@Sun.COM 
68*12927SRod.Evans@Sun.COM 	for (cur = ph->pp_breakpoints, prev = NULL;
69*12927SRod.Evans@Sun.COM 	    (cur && (cur->bl_addr < addr));
70*12927SRod.Evans@Sun.COM 	    prev = cur, cur = cur->bl_next)
71*12927SRod.Evans@Sun.COM 		;
72*12927SRod.Evans@Sun.COM 	if (cur && (cur->bl_addr == addr)) {
73*12927SRod.Evans@Sun.COM 		/*
74*12927SRod.Evans@Sun.COM 		 * already have break point set here.
75*12927SRod.Evans@Sun.COM 		 */
76*12927SRod.Evans@Sun.COM 		cur->bl_flags |= flags;
77*12927SRod.Evans@Sun.COM 		return (RET_OK);
78*12927SRod.Evans@Sun.COM 	}
79*12927SRod.Evans@Sun.COM 
80*12927SRod.Evans@Sun.COM 	new = malloc(sizeof (bptlist_t));
81*12927SRod.Evans@Sun.COM 	new->bl_addr = addr;
82*12927SRod.Evans@Sun.COM 	new->bl_flags = flags;
83*12927SRod.Evans@Sun.COM 	if (prev == NULL) {
84*12927SRod.Evans@Sun.COM 		/*
85*12927SRod.Evans@Sun.COM 		 * insert at head
86*12927SRod.Evans@Sun.COM 		 */
87*12927SRod.Evans@Sun.COM 		new->bl_next = ph->pp_breakpoints;
88*12927SRod.Evans@Sun.COM 		ph->pp_breakpoints = new;
89*12927SRod.Evans@Sun.COM 		return (RET_OK);
90*12927SRod.Evans@Sun.COM 	}
91*12927SRod.Evans@Sun.COM 
92*12927SRod.Evans@Sun.COM 	prev->bl_next = new;
93*12927SRod.Evans@Sun.COM 	new->bl_next = cur;
94*12927SRod.Evans@Sun.COM 	return (RET_OK);
95*12927SRod.Evans@Sun.COM }
96*12927SRod.Evans@Sun.COM 
97*12927SRod.Evans@Sun.COM static bptlist_t *
find_bp(struct ps_prochandle * ph,ulong_t addr)98*12927SRod.Evans@Sun.COM find_bp(struct ps_prochandle *ph, ulong_t addr)
99*12927SRod.Evans@Sun.COM {
100*12927SRod.Evans@Sun.COM 	bptlist_t	*cur;
101*12927SRod.Evans@Sun.COM 
102*12927SRod.Evans@Sun.COM 	for (cur = ph->pp_breakpoints;
103*12927SRod.Evans@Sun.COM 	    (cur && (cur->bl_addr != addr));
104*12927SRod.Evans@Sun.COM 	    cur = cur->bl_next)
105*12927SRod.Evans@Sun.COM 		;
106*12927SRod.Evans@Sun.COM 
107*12927SRod.Evans@Sun.COM 	if ((cur == NULL) || (cur->bl_addr != addr))
108*12927SRod.Evans@Sun.COM 		return ((bptlist_t *)-1);
109*12927SRod.Evans@Sun.COM 	return (cur);
110*12927SRod.Evans@Sun.COM }
111*12927SRod.Evans@Sun.COM 
112*12927SRod.Evans@Sun.COM static retc_t
delete_bp(struct ps_prochandle * ph,ulong_t addr)113*12927SRod.Evans@Sun.COM delete_bp(struct ps_prochandle *ph, ulong_t addr)
114*12927SRod.Evans@Sun.COM {
115*12927SRod.Evans@Sun.COM 	bptlist_t	*cur, *prev;
116*12927SRod.Evans@Sun.COM 
117*12927SRod.Evans@Sun.COM 	for (cur = ph->pp_breakpoints, prev = NULL;
118*12927SRod.Evans@Sun.COM 	    (cur && (cur->bl_addr < addr));
119*12927SRod.Evans@Sun.COM 	    prev = cur, cur = cur->bl_next)
120*12927SRod.Evans@Sun.COM 		;
121*12927SRod.Evans@Sun.COM 	if ((cur == NULL) || (cur->bl_addr != addr))
122*12927SRod.Evans@Sun.COM 		return (RET_FAILED);
123*12927SRod.Evans@Sun.COM 
124*12927SRod.Evans@Sun.COM 	if (prev == NULL)
125*12927SRod.Evans@Sun.COM 		ph->pp_breakpoints = cur->bl_next;
126*12927SRod.Evans@Sun.COM 	else
127*12927SRod.Evans@Sun.COM 		prev->bl_next = cur->bl_next;
128*12927SRod.Evans@Sun.COM 
129*12927SRod.Evans@Sun.COM 	free(cur);
130*12927SRod.Evans@Sun.COM 	return (RET_OK);
131*12927SRod.Evans@Sun.COM }
132*12927SRod.Evans@Sun.COM 
133*12927SRod.Evans@Sun.COM void
list_breakpoints(struct ps_prochandle * ph)134*12927SRod.Evans@Sun.COM list_breakpoints(struct ps_prochandle *ph)
135*12927SRod.Evans@Sun.COM {
136*12927SRod.Evans@Sun.COM 	bptlist_t	*cur;
137*12927SRod.Evans@Sun.COM 
138*12927SRod.Evans@Sun.COM 	if (ph->pp_breakpoints == NULL) {
139*12927SRod.Evans@Sun.COM 		(void) printf("no active breakpoints.\n");
140*12927SRod.Evans@Sun.COM 		return;
141*12927SRod.Evans@Sun.COM 	}
142*12927SRod.Evans@Sun.COM 
143*12927SRod.Evans@Sun.COM 	(void) printf("active breakpoints:\n");
144*12927SRod.Evans@Sun.COM 	for (cur = ph->pp_breakpoints; cur; cur = cur->bl_next) {
145*12927SRod.Evans@Sun.COM 		(void) printf("\t0x%08lx:0x%04x - %s\n", cur->bl_addr,
146*12927SRod.Evans@Sun.COM 		    cur->bl_flags, print_address_ps(ph, cur->bl_addr,
147*12927SRod.Evans@Sun.COM 		    FLG_PAP_SONAME));
148*12927SRod.Evans@Sun.COM 	}
149*12927SRod.Evans@Sun.COM }
150*12927SRod.Evans@Sun.COM 
151*12927SRod.Evans@Sun.COM static void
set_breaks(struct ps_prochandle * ph)152*12927SRod.Evans@Sun.COM set_breaks(struct ps_prochandle *ph)
153*12927SRod.Evans@Sun.COM {
154*12927SRod.Evans@Sun.COM 	bptlist_t	*cur;
155*12927SRod.Evans@Sun.COM 	bptinstr_t	bpt_instr = BPINSTR;
156*12927SRod.Evans@Sun.COM 
157*12927SRod.Evans@Sun.COM 	for (cur = ph->pp_breakpoints; cur; cur = cur->bl_next) {
158*12927SRod.Evans@Sun.COM 		bptinstr_t	old_inst = 0;
159*12927SRod.Evans@Sun.COM 
160*12927SRod.Evans@Sun.COM 		if (ps_pread(ph, cur->bl_addr, (char *)&old_inst,
161*12927SRod.Evans@Sun.COM 		    sizeof (bptinstr_t)) != PS_OK)
162*12927SRod.Evans@Sun.COM 			perr("sb: error setting breakpoint");
163*12927SRod.Evans@Sun.COM 
164*12927SRod.Evans@Sun.COM 		cur->bl_instr = old_inst;
165*12927SRod.Evans@Sun.COM 
166*12927SRod.Evans@Sun.COM 		if (ps_pwrite(ph, cur->bl_addr, (char *)&bpt_instr,
167*12927SRod.Evans@Sun.COM 		    sizeof (bptinstr_t)) != PS_OK)
168*12927SRod.Evans@Sun.COM 			perr("sb1: error setting breakpoint\n");
169*12927SRod.Evans@Sun.COM 	}
170*12927SRod.Evans@Sun.COM 
171*12927SRod.Evans@Sun.COM }
172*12927SRod.Evans@Sun.COM 
173*12927SRod.Evans@Sun.COM static void
clear_breaks(struct ps_prochandle * ph)174*12927SRod.Evans@Sun.COM clear_breaks(struct ps_prochandle *ph)
175*12927SRod.Evans@Sun.COM {
176*12927SRod.Evans@Sun.COM 	bptlist_t	*cur;
177*12927SRod.Evans@Sun.COM 
178*12927SRod.Evans@Sun.COM 	/*
179*12927SRod.Evans@Sun.COM 	 * Restore all the original instructions
180*12927SRod.Evans@Sun.COM 	 */
181*12927SRod.Evans@Sun.COM 	for (cur = ph->pp_breakpoints; cur; cur = cur->bl_next)
182*12927SRod.Evans@Sun.COM 		if (ps_pwrite(ph, cur->bl_addr, (char *)&(cur->bl_instr),
183*12927SRod.Evans@Sun.COM 		    sizeof (bptinstr_t)) != PS_OK)
184*12927SRod.Evans@Sun.COM 			perr("cb: error clearing breakpoint");
185*12927SRod.Evans@Sun.COM }
186*12927SRod.Evans@Sun.COM 
187*12927SRod.Evans@Sun.COM retc_t
delete_all_breakpoints(struct ps_prochandle * ph)188*12927SRod.Evans@Sun.COM delete_all_breakpoints(struct ps_prochandle *ph)
189*12927SRod.Evans@Sun.COM {
190*12927SRod.Evans@Sun.COM 	bptlist_t	*cur, *prev;
191*12927SRod.Evans@Sun.COM 
192*12927SRod.Evans@Sun.COM 	if (ph->pp_breakpoints == NULL)
193*12927SRod.Evans@Sun.COM 		return (RET_OK);
194*12927SRod.Evans@Sun.COM 
195*12927SRod.Evans@Sun.COM 	for (prev = NULL, cur = ph->pp_breakpoints;
196*12927SRod.Evans@Sun.COM 	    cur; prev = cur, cur = cur->bl_next)
197*12927SRod.Evans@Sun.COM 		if (prev)
198*12927SRod.Evans@Sun.COM 			free(prev);
199*12927SRod.Evans@Sun.COM 	if (prev)
200*12927SRod.Evans@Sun.COM 		free(prev);
201*12927SRod.Evans@Sun.COM 
202*12927SRod.Evans@Sun.COM 	ph->pp_breakpoints = NULL;
203*12927SRod.Evans@Sun.COM 	return (RET_OK);
204*12927SRod.Evans@Sun.COM }
205*12927SRod.Evans@Sun.COM 
206*12927SRod.Evans@Sun.COM retc_t
delete_breakpoint(struct ps_prochandle * ph,ulong_t addr,unsigned flags)207*12927SRod.Evans@Sun.COM delete_breakpoint(struct ps_prochandle *ph, ulong_t addr, unsigned flags)
208*12927SRod.Evans@Sun.COM {
209*12927SRod.Evans@Sun.COM 	bptlist_t	*bpt;
210*12927SRod.Evans@Sun.COM 
211*12927SRod.Evans@Sun.COM 	if (((bpt = find_bp(ph, addr)) == (bptlist_t *)-1) ||
212*12927SRod.Evans@Sun.COM 	    ((bpt->bl_flags & flags) == 0))
213*12927SRod.Evans@Sun.COM 		return (RET_FAILED);
214*12927SRod.Evans@Sun.COM 
215*12927SRod.Evans@Sun.COM 	bpt->bl_flags &= ~flags;
216*12927SRod.Evans@Sun.COM 	if (bpt->bl_flags)
217*12927SRod.Evans@Sun.COM 		return (RET_OK);
218*12927SRod.Evans@Sun.COM 
219*12927SRod.Evans@Sun.COM 	return (delete_bp(ph, addr));
220*12927SRod.Evans@Sun.COM }
221*12927SRod.Evans@Sun.COM 
222*12927SRod.Evans@Sun.COM static void
handle_sp_break(struct ps_prochandle * ph)223*12927SRod.Evans@Sun.COM handle_sp_break(struct ps_prochandle *ph)
224*12927SRod.Evans@Sun.COM {
225*12927SRod.Evans@Sun.COM 	rd_event_msg_t	emt;
226*12927SRod.Evans@Sun.COM 
227*12927SRod.Evans@Sun.COM 	if (rd_event_getmsg(ph->pp_rap, &emt) != RD_OK) {
228*12927SRod.Evans@Sun.COM 		(void) fprintf(stderr, "hsb: failed rd_event_getmsg()\n");
229*12927SRod.Evans@Sun.COM 		return;
230*12927SRod.Evans@Sun.COM 	}
231*12927SRod.Evans@Sun.COM 
232*12927SRod.Evans@Sun.COM 	if (emt.type == RD_DLACTIVITY) {
233*12927SRod.Evans@Sun.COM 		if (emt.u.state == RD_CONSISTENT)
234*12927SRod.Evans@Sun.COM 			ph->pp_flags |= FLG_PP_LMAPS;
235*12927SRod.Evans@Sun.COM 		else
236*12927SRod.Evans@Sun.COM 			ph->pp_flags &= ~FLG_PP_LMAPS;
237*12927SRod.Evans@Sun.COM 		if ((rdb_flags & RDB_FL_EVENTS) == 0)
238*12927SRod.Evans@Sun.COM 			return;
239*12927SRod.Evans@Sun.COM 
240*12927SRod.Evans@Sun.COM 		(void) printf("dlactivity: state changed to: ");
241*12927SRod.Evans@Sun.COM 		switch (emt.u.state) {
242*12927SRod.Evans@Sun.COM 		case RD_CONSISTENT:
243*12927SRod.Evans@Sun.COM 			(void) printf("RD_CONSISTENT\n");
244*12927SRod.Evans@Sun.COM 			break;
245*12927SRod.Evans@Sun.COM 		case RD_ADD:
246*12927SRod.Evans@Sun.COM 			(void) printf("RD_ADD\n");
247*12927SRod.Evans@Sun.COM 			break;
248*12927SRod.Evans@Sun.COM 		case RD_DELETE:
249*12927SRod.Evans@Sun.COM 			(void) printf("RD_DELETE\n");
250*12927SRod.Evans@Sun.COM 			break;
251*12927SRod.Evans@Sun.COM 		default:
252*12927SRod.Evans@Sun.COM 			(void) printf("unknown: 0x%x\n", emt.u.state);
253*12927SRod.Evans@Sun.COM 		}
254*12927SRod.Evans@Sun.COM 		return;
255*12927SRod.Evans@Sun.COM 	}
256*12927SRod.Evans@Sun.COM 
257*12927SRod.Evans@Sun.COM 	if ((rdb_flags & RDB_FL_EVENTS) == 0)
258*12927SRod.Evans@Sun.COM 		return;
259*12927SRod.Evans@Sun.COM 
260*12927SRod.Evans@Sun.COM 	if (emt.type == RD_PREINIT) {
261*12927SRod.Evans@Sun.COM 		(void) printf("preinit reached\n");
262*12927SRod.Evans@Sun.COM 		return;
263*12927SRod.Evans@Sun.COM 	}
264*12927SRod.Evans@Sun.COM 
265*12927SRod.Evans@Sun.COM 	if (emt.type == RD_POSTINIT)
266*12927SRod.Evans@Sun.COM 		(void) printf("postinit reached\n");
267*12927SRod.Evans@Sun.COM }
268*12927SRod.Evans@Sun.COM 
269*12927SRod.Evans@Sun.COM unsigned
continue_to_break(struct ps_prochandle * ph)270*12927SRod.Evans@Sun.COM continue_to_break(struct ps_prochandle *ph)
271*12927SRod.Evans@Sun.COM {
272*12927SRod.Evans@Sun.COM 	bptlist_t	*bpt;
273*12927SRod.Evans@Sun.COM 	pstatus_t	pstatus;
274*12927SRod.Evans@Sun.COM 	struct iovec	piov[5];
275*12927SRod.Evans@Sun.COM 	long		oper1, oper2, oper3, pflags = 0;
276*12927SRod.Evans@Sun.COM 	fltset_t	faults;
277*12927SRod.Evans@Sun.COM 
278*12927SRod.Evans@Sun.COM 	/*
279*12927SRod.Evans@Sun.COM 	 * We step by the first instruction incase their was
280*12927SRod.Evans@Sun.COM 	 * a break-point there.
281*12927SRod.Evans@Sun.COM 	 */
282*12927SRod.Evans@Sun.COM 	(void) step_n(ph, 1, FLG_SN_NONE);
283*12927SRod.Evans@Sun.COM 
284*12927SRod.Evans@Sun.COM 	premptyset(&faults);
285*12927SRod.Evans@Sun.COM 	praddset(&faults, FLTBPT);
286*12927SRod.Evans@Sun.COM 	praddset(&faults, FLTILL);
287*12927SRod.Evans@Sun.COM 	praddset(&faults, FLTPRIV);
288*12927SRod.Evans@Sun.COM 	praddset(&faults, FLTACCESS);
289*12927SRod.Evans@Sun.COM 	praddset(&faults, FLTBOUNDS);
290*12927SRod.Evans@Sun.COM 	praddset(&faults, FLTIZDIV);
291*12927SRod.Evans@Sun.COM 	praddset(&faults, FLTSTACK);
292*12927SRod.Evans@Sun.COM 	praddset(&faults, FLTTRACE);
293*12927SRod.Evans@Sun.COM 
294*12927SRod.Evans@Sun.COM 
295*12927SRod.Evans@Sun.COM 	/* LINTED CONSTANT */
296*12927SRod.Evans@Sun.COM 	while (1) {
297*12927SRod.Evans@Sun.COM 		set_breaks(ph);
298*12927SRod.Evans@Sun.COM 		oper1 = PCSFAULT;
299*12927SRod.Evans@Sun.COM 		piov[0].iov_base = (caddr_t)(&oper1);
300*12927SRod.Evans@Sun.COM 		piov[0].iov_len = sizeof (oper1);
301*12927SRod.Evans@Sun.COM 
302*12927SRod.Evans@Sun.COM 		piov[1].iov_base = (caddr_t)(&faults);
303*12927SRod.Evans@Sun.COM 		piov[1].iov_len = sizeof (faults);
304*12927SRod.Evans@Sun.COM 
305*12927SRod.Evans@Sun.COM 		oper2 = PCRUN;
306*12927SRod.Evans@Sun.COM 		piov[2].iov_base = (caddr_t)(&oper2);
307*12927SRod.Evans@Sun.COM 		piov[2].iov_len = sizeof (oper2);
308*12927SRod.Evans@Sun.COM 		pflags = PRCFAULT;
309*12927SRod.Evans@Sun.COM 		piov[3].iov_base = (caddr_t)(&pflags);
310*12927SRod.Evans@Sun.COM 		piov[3].iov_len = sizeof (pflags);
311*12927SRod.Evans@Sun.COM 
312*12927SRod.Evans@Sun.COM 		oper3 = PCWSTOP;
313*12927SRod.Evans@Sun.COM 		piov[4].iov_base = (caddr_t)(&oper3);
314*12927SRod.Evans@Sun.COM 		piov[4].iov_len = sizeof (oper3);
315*12927SRod.Evans@Sun.COM 
316*12927SRod.Evans@Sun.COM 		if (writev(ph->pp_ctlfd, piov, 5) == -1) {
317*12927SRod.Evans@Sun.COM 			if (errno == ENOENT) {
318*12927SRod.Evans@Sun.COM 				ph->pp_flags &= ~FLG_PP_PACT;
319*12927SRod.Evans@Sun.COM 
320*12927SRod.Evans@Sun.COM 				(void) ps_close(ph);
321*12927SRod.Evans@Sun.COM 				(void) printf("process terminated.\n");
322*12927SRod.Evans@Sun.COM 				return (0);
323*12927SRod.Evans@Sun.COM 			}
324*12927SRod.Evans@Sun.COM 			perr("ctb: PCWSTOP");
325*12927SRod.Evans@Sun.COM 		}
326*12927SRod.Evans@Sun.COM 
327*12927SRod.Evans@Sun.COM 		if (pread(ph->pp_statusfd, &pstatus, sizeof (pstatus), 0) == -1)
328*12927SRod.Evans@Sun.COM 			perr("ctb: reading status");
329*12927SRod.Evans@Sun.COM 
330*12927SRod.Evans@Sun.COM 
331*12927SRod.Evans@Sun.COM 		if ((pstatus.pr_lwp.pr_why != PR_FAULTED) ||
332*12927SRod.Evans@Sun.COM 		    (pstatus.pr_lwp.pr_what != FLTBPT)) {
333*12927SRod.Evans@Sun.COM 			const char	*fltmsg;
334*12927SRod.Evans@Sun.COM 
335*12927SRod.Evans@Sun.COM 			if ((pstatus.pr_lwp.pr_what <= MAXFAULT) &&
336*12927SRod.Evans@Sun.COM 			    (pstatus.pr_lwp.pr_why == PR_FAULTED))
337*12927SRod.Evans@Sun.COM 				fltmsg = fault_strings[pstatus.pr_lwp.pr_what];
338*12927SRod.Evans@Sun.COM 			else
339*12927SRod.Evans@Sun.COM 				fltmsg = "<unknown error>";
340*12927SRod.Evans@Sun.COM 
341*12927SRod.Evans@Sun.COM 			(void) fprintf(stderr, "ctb: bad stop - stopped "
342*12927SRod.Evans@Sun.COM 			    "on why: 0x%x what: %s(0x%x)\n",
343*12927SRod.Evans@Sun.COM 			    pstatus.pr_lwp.pr_why, fltmsg,
344*12927SRod.Evans@Sun.COM 			    pstatus.pr_lwp.pr_what);
345*12927SRod.Evans@Sun.COM 			return (0);
346*12927SRod.Evans@Sun.COM 		}
347*12927SRod.Evans@Sun.COM 
348*12927SRod.Evans@Sun.COM 		oper1 = PCCFAULT;
349*12927SRod.Evans@Sun.COM 		if (writev(ph->pp_ctlfd, piov, 1) == -1)
350*12927SRod.Evans@Sun.COM 			perr("ctb: PCCFAULT");
351*12927SRod.Evans@Sun.COM 
352*12927SRod.Evans@Sun.COM 		if ((bpt = find_bp(ph, pstatus.pr_lwp.pr_reg[R_PC])) ==
353*12927SRod.Evans@Sun.COM 		    (bptlist_t *)-1) {
354*12927SRod.Evans@Sun.COM 			(void) fprintf(stderr,
355*12927SRod.Evans@Sun.COM 			    "stopped at unregistered breakpoint! "
356*12927SRod.Evans@Sun.COM 			    "addr: 0x%x\n",
357*12927SRod.Evans@Sun.COM 			    EC_WORD(pstatus.pr_lwp.pr_reg[R_PC]));
358*12927SRod.Evans@Sun.COM 			break;
359*12927SRod.Evans@Sun.COM 		}
360*12927SRod.Evans@Sun.COM 		clear_breaks(ph);
361*12927SRod.Evans@Sun.COM 
362*12927SRod.Evans@Sun.COM 		/*
363*12927SRod.Evans@Sun.COM 		 * If this was a BP at which we should stop
364*12927SRod.Evans@Sun.COM 		 */
365*12927SRod.Evans@Sun.COM 		if (bpt->bl_flags & MASK_BP_STOP)
366*12927SRod.Evans@Sun.COM 			break;
367*12927SRod.Evans@Sun.COM 
368*12927SRod.Evans@Sun.COM 		(void) step_n(ph, 1, FLG_SN_NONE);
369*12927SRod.Evans@Sun.COM 	}
370*12927SRod.Evans@Sun.COM 
371*12927SRod.Evans@Sun.COM 	if (bpt->bl_flags & FLG_BP_USERDEF)
372*12927SRod.Evans@Sun.COM 		(void) printf("break point reached at addr: 0x%x\n",
373*12927SRod.Evans@Sun.COM 		    EC_WORD(pstatus.pr_lwp.pr_reg[R_PC]));
374*12927SRod.Evans@Sun.COM 
375*12927SRod.Evans@Sun.COM 	if (bpt->bl_flags & MASK_BP_SPECIAL)
376*12927SRod.Evans@Sun.COM 		handle_sp_break(ph);
377*12927SRod.Evans@Sun.COM 
378*12927SRod.Evans@Sun.COM 	if (ph->pp_flags & FLG_PP_LMAPS) {
379*12927SRod.Evans@Sun.COM 		if (get_linkmaps(ph) != PS_OK)
380*12927SRod.Evans@Sun.COM 			(void) fprintf(stderr, "problem loading linkmaps\n");
381*12927SRod.Evans@Sun.COM 	}
382*12927SRod.Evans@Sun.COM 
383*12927SRod.Evans@Sun.COM 	return (bpt->bl_flags);
384*12927SRod.Evans@Sun.COM }
385*12927SRod.Evans@Sun.COM 
386*12927SRod.Evans@Sun.COM ulong_t
is_plt(struct ps_prochandle * ph,ulong_t pc)387*12927SRod.Evans@Sun.COM is_plt(struct ps_prochandle *ph, ulong_t pc)
388*12927SRod.Evans@Sun.COM {
389*12927SRod.Evans@Sun.COM 	map_info_t	*mip;
390*12927SRod.Evans@Sun.COM 	ulong_t		pltbase;
391*12927SRod.Evans@Sun.COM 
392*12927SRod.Evans@Sun.COM 	if ((mip = addr_to_map(ph, pc)) == (map_info_t *)0)
393*12927SRod.Evans@Sun.COM 		return ((ulong_t)0);
394*12927SRod.Evans@Sun.COM 
395*12927SRod.Evans@Sun.COM 	pltbase = mip->mi_pltbase;
396*12927SRod.Evans@Sun.COM 	if ((mip->mi_flags & FLG_MI_EXEC) == 0)
397*12927SRod.Evans@Sun.COM 		pltbase += mip->mi_addr;
398*12927SRod.Evans@Sun.COM 
399*12927SRod.Evans@Sun.COM 	if ((pc >= pltbase) && (pc <= (pltbase + mip->mi_pltsize)))
400*12927SRod.Evans@Sun.COM 		return (pltbase);
401*12927SRod.Evans@Sun.COM 
402*12927SRod.Evans@Sun.COM 	return ((ulong_t)0);
403*12927SRod.Evans@Sun.COM }
404*12927SRod.Evans@Sun.COM 
405*12927SRod.Evans@Sun.COM retc_t
step_n(struct ps_prochandle * ph,size_t count,sn_flags_e flgs)406*12927SRod.Evans@Sun.COM step_n(struct ps_prochandle *ph, size_t count, sn_flags_e flgs)
407*12927SRod.Evans@Sun.COM {
408*12927SRod.Evans@Sun.COM 	pstatus_t	pstatus;
409*12927SRod.Evans@Sun.COM 	fltset_t	faults;
410*12927SRod.Evans@Sun.COM 	int		i;
411*12927SRod.Evans@Sun.COM 	long		oper;
412*12927SRod.Evans@Sun.COM 	long		flags;
413*12927SRod.Evans@Sun.COM 	struct iovec	piov[2];
414*12927SRod.Evans@Sun.COM 
415*12927SRod.Evans@Sun.COM 	if (pread(ph->pp_statusfd, &pstatus, sizeof (pstatus), 0) == -1)
416*12927SRod.Evans@Sun.COM 		perr("stn: reading status");
417*12927SRod.Evans@Sun.COM 
418*12927SRod.Evans@Sun.COM 	piov[0].iov_base = (caddr_t)(&oper);
419*12927SRod.Evans@Sun.COM 	piov[0].iov_len = sizeof (oper);
420*12927SRod.Evans@Sun.COM 
421*12927SRod.Evans@Sun.COM 	premptyset(&faults);
422*12927SRod.Evans@Sun.COM 	praddset(&faults, FLTTRACE);
423*12927SRod.Evans@Sun.COM 
424*12927SRod.Evans@Sun.COM 	flags = PRSTEP | PRCFAULT;
425*12927SRod.Evans@Sun.COM 
426*12927SRod.Evans@Sun.COM 	for (i = 0; i < count; i++) {
427*12927SRod.Evans@Sun.COM 		bptlist_t	*bpt;
428*12927SRod.Evans@Sun.COM 		uintptr_t	pc, pltbase;
429*12927SRod.Evans@Sun.COM 
430*12927SRod.Evans@Sun.COM 		pc = pstatus.pr_lwp.pr_reg[R_PC];
431*12927SRod.Evans@Sun.COM 
432*12927SRod.Evans@Sun.COM 		if ((bpt = find_bp(ph, pc)) != (bptlist_t *)-1) {
433*12927SRod.Evans@Sun.COM 			if (bpt->bl_flags & MASK_BP_SPECIAL)
434*12927SRod.Evans@Sun.COM 				handle_sp_break(ph);
435*12927SRod.Evans@Sun.COM 		}
436*12927SRod.Evans@Sun.COM 
437*12927SRod.Evans@Sun.COM 		if (flgs & FLG_SN_VERBOSE)
438*12927SRod.Evans@Sun.COM 			disasm(ph, 1);
439*12927SRod.Evans@Sun.COM 
440*12927SRod.Evans@Sun.COM 		oper = PCSFAULT;
441*12927SRod.Evans@Sun.COM 		piov[1].iov_base = (caddr_t)(&faults);
442*12927SRod.Evans@Sun.COM 		piov[1].iov_len = sizeof (faults);
443*12927SRod.Evans@Sun.COM 
444*12927SRod.Evans@Sun.COM 		if (writev(ph->pp_ctlfd, piov, 2) == -1)
445*12927SRod.Evans@Sun.COM 			perr("stn: PCSFAULT");
446*12927SRod.Evans@Sun.COM 
447*12927SRod.Evans@Sun.COM 		oper = PCRUN;
448*12927SRod.Evans@Sun.COM 		piov[1].iov_base = (caddr_t)(&flags);
449*12927SRod.Evans@Sun.COM 		piov[1].iov_len = sizeof (flags);
450*12927SRod.Evans@Sun.COM 		if (writev(ph->pp_ctlfd, piov, 2) == -1)
451*12927SRod.Evans@Sun.COM 			perr("stn: PCRUN(PRSETP)");
452*12927SRod.Evans@Sun.COM 
453*12927SRod.Evans@Sun.COM 		oper = PCWSTOP;
454*12927SRod.Evans@Sun.COM 		if (writev(ph->pp_ctlfd, piov, 1) == -1)
455*12927SRod.Evans@Sun.COM 			perr("stn: PCWSTOP stepping");
456*12927SRod.Evans@Sun.COM 
457*12927SRod.Evans@Sun.COM 		if (pread(ph->pp_statusfd, &pstatus, sizeof (pstatus), 0) == -1)
458*12927SRod.Evans@Sun.COM 			perr("stn1: reading status");
459*12927SRod.Evans@Sun.COM 		pc = pstatus.pr_lwp.pr_reg[R_PC];
460*12927SRod.Evans@Sun.COM 
461*12927SRod.Evans@Sun.COM 
462*12927SRod.Evans@Sun.COM 		if ((pstatus.pr_lwp.pr_why != PR_FAULTED) ||
463*12927SRod.Evans@Sun.COM 		    (pstatus.pr_lwp.pr_what != FLTTRACE)) {
464*12927SRod.Evans@Sun.COM 			(void) fprintf(stderr, "sn: bad stop - stopped on "
465*12927SRod.Evans@Sun.COM 			    "why: 0x%x what: 0x%x\n", pstatus.pr_lwp.pr_why,
466*12927SRod.Evans@Sun.COM 			    pstatus.pr_lwp.pr_what);
467*12927SRod.Evans@Sun.COM 			return (RET_FAILED);
468*12927SRod.Evans@Sun.COM 		}
469*12927SRod.Evans@Sun.COM 
470*12927SRod.Evans@Sun.COM 		if ((flgs & FLG_SN_PLTSKIP) &&
471*12927SRod.Evans@Sun.COM 		    ((pltbase = is_plt(ph, pc)) != (ulong_t)0)) {
472*12927SRod.Evans@Sun.COM 			rd_plt_info_t	rp;
473*12927SRod.Evans@Sun.COM 			if (rd_plt_resolution(ph->pp_rap, pc,
474*12927SRod.Evans@Sun.COM 			    pstatus.pr_lwp.pr_lwpid, pltbase, &rp) != RD_OK) {
475*12927SRod.Evans@Sun.COM 				(void) fprintf(stderr,
476*12927SRod.Evans@Sun.COM 				    "sn: rd_plt_resolution failed\n");
477*12927SRod.Evans@Sun.COM 				return (RET_FAILED);
478*12927SRod.Evans@Sun.COM 			}
479*12927SRod.Evans@Sun.COM 			if (rp.pi_skip_method == RD_RESOLVE_TARGET_STEP) {
480*12927SRod.Evans@Sun.COM 				unsigned	bpflags;
481*12927SRod.Evans@Sun.COM 
482*12927SRod.Evans@Sun.COM 				(void) set_breakpoint(ph, rp.pi_target,
483*12927SRod.Evans@Sun.COM 				    FLG_BP_PLTRES);
484*12927SRod.Evans@Sun.COM 				bpflags = continue_to_break(ph);
485*12927SRod.Evans@Sun.COM 
486*12927SRod.Evans@Sun.COM 				(void) delete_breakpoint(ph, rp.pi_target,
487*12927SRod.Evans@Sun.COM 				    FLG_BP_PLTRES);
488*12927SRod.Evans@Sun.COM 
489*12927SRod.Evans@Sun.COM 				if (bpflags & FLG_BP_PLTRES)
490*12927SRod.Evans@Sun.COM 					(void) step_n(ph, rp.pi_nstep,
491*12927SRod.Evans@Sun.COM 					    FLG_SN_NONE);
492*12927SRod.Evans@Sun.COM 			} else if (rp.pi_skip_method == RD_RESOLVE_STEP)
493*12927SRod.Evans@Sun.COM 				(void) step_n(ph, rp.pi_nstep, FLG_SN_NONE);
494*12927SRod.Evans@Sun.COM 		}
495*12927SRod.Evans@Sun.COM 	}
496*12927SRod.Evans@Sun.COM 
497*12927SRod.Evans@Sun.COM 	oper = PRCFAULT;
498*12927SRod.Evans@Sun.COM 	if (writev(ph->pp_ctlfd, piov, 1) == -1)
499*12927SRod.Evans@Sun.COM 		perr("stn: PRCFAULT");
500*12927SRod.Evans@Sun.COM 
501*12927SRod.Evans@Sun.COM 	if ((flgs & FLG_SN_VERBOSE) && (ph->pp_flags & FLG_PP_LMAPS)) {
502*12927SRod.Evans@Sun.COM 		if (get_linkmaps(ph) != PS_OK)
503*12927SRod.Evans@Sun.COM 			(void) fprintf(stderr, "problem loading linkmaps\n");
504*12927SRod.Evans@Sun.COM 	}
505*12927SRod.Evans@Sun.COM 
506*12927SRod.Evans@Sun.COM 	return (RET_OK);
507*12927SRod.Evans@Sun.COM }
508*12927SRod.Evans@Sun.COM 
509*12927SRod.Evans@Sun.COM void
step_to_addr(struct ps_prochandle * ph,ulong_t addr)510*12927SRod.Evans@Sun.COM step_to_addr(struct ps_prochandle *ph, ulong_t addr)
511*12927SRod.Evans@Sun.COM {
512*12927SRod.Evans@Sun.COM 	pstatus_t	pstat;
513*12927SRod.Evans@Sun.COM 	int		count = 0;
514*12927SRod.Evans@Sun.COM 	ulong_t		caddr;
515*12927SRod.Evans@Sun.COM 
516*12927SRod.Evans@Sun.COM 	if (read(ph->pp_statusfd, &pstat, sizeof (pstat)) == -1)
517*12927SRod.Evans@Sun.COM 		perr("sta: reading status");
518*12927SRod.Evans@Sun.COM 
519*12927SRod.Evans@Sun.COM 	caddr = pstat.pr_lwp.pr_reg[R_PC];
520*12927SRod.Evans@Sun.COM 
521*12927SRod.Evans@Sun.COM 	while ((caddr > addr) || ((caddr + 0xff) < addr)) {
522*12927SRod.Evans@Sun.COM 		(void) step_n(ph, 1, FLG_SN_NONE);
523*12927SRod.Evans@Sun.COM 		if (read(ph->pp_statusfd, &pstat, sizeof (pstat)) == -1)
524*12927SRod.Evans@Sun.COM 			perr("sta1: reading status");
525*12927SRod.Evans@Sun.COM 		caddr = pstat.pr_lwp.pr_reg[R_PC];
526*12927SRod.Evans@Sun.COM 		if ((count % 10000) == 0) {
527*12927SRod.Evans@Sun.COM 			(void) printf("%d: ", count);
528*12927SRod.Evans@Sun.COM 			disasm(ph, 1);
529*12927SRod.Evans@Sun.COM 		}
530*12927SRod.Evans@Sun.COM 
531*12927SRod.Evans@Sun.COM 		count++;
532*12927SRod.Evans@Sun.COM 	}
533*12927SRod.Evans@Sun.COM 
534*12927SRod.Evans@Sun.COM 	(void) printf("address found %d instructions in: pc: 0x%lx addr: "
535*12927SRod.Evans@Sun.COM 	    "0x%lx\n", count, caddr, addr);
536*12927SRod.Evans@Sun.COM }
537