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