4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
33 #include <sys/types.h>
34 #include <sys/signal.h>
35 #include <sys/fault.h>
36 #include <sys/syscall.h>
40 #include <sys/param.h>
41 #include <sys/machelf.h>
46 static const char *fault_strings
[] = {
48 "illegal instruction",
49 "privileged instruction",
50 "breakpoint instruction",
51 "trace trap (single-step)",
52 "Memory access (e.g., alignment)",
53 "Memory bounds (invalid address)",
56 "Floating-point exception",
57 "Irrecoverable stack faul",
58 "Recoverable page fault (no associated sig)"
61 #define MAXFAULT FLTPAGE
64 set_breakpoint(struct ps_prochandle
*ph
, ulong_t addr
, unsigned flags
)
66 bptlist_t
*new, *cur
, *prev
;
68 for (cur
= ph
->pp_breakpoints
, prev
= NULL
;
69 (cur
&& (cur
->bl_addr
< addr
));
70 prev
= cur
, cur
= cur
->bl_next
)
72 if (cur
&& (cur
->bl_addr
== addr
)) {
74 * already have break point set here.
76 cur
->bl_flags
|= flags
;
80 new = malloc(sizeof (bptlist_t
));
82 new->bl_flags
= flags
;
87 new->bl_next
= ph
->pp_breakpoints
;
88 ph
->pp_breakpoints
= new;
98 find_bp(struct ps_prochandle
*ph
, ulong_t addr
)
102 for (cur
= ph
->pp_breakpoints
;
103 (cur
&& (cur
->bl_addr
!= addr
));
107 if ((cur
== NULL
) || (cur
->bl_addr
!= addr
))
108 return ((bptlist_t
*)-1);
113 delete_bp(struct ps_prochandle
*ph
, ulong_t addr
)
115 bptlist_t
*cur
, *prev
;
117 for (cur
= ph
->pp_breakpoints
, prev
= NULL
;
118 (cur
&& (cur
->bl_addr
< addr
));
119 prev
= cur
, cur
= cur
->bl_next
)
121 if ((cur
== NULL
) || (cur
->bl_addr
!= addr
))
125 ph
->pp_breakpoints
= cur
->bl_next
;
127 prev
->bl_next
= cur
->bl_next
;
134 list_breakpoints(struct ps_prochandle
*ph
)
138 if (ph
->pp_breakpoints
== NULL
) {
139 (void) printf("no active breakpoints.\n");
143 (void) printf("active breakpoints:\n");
144 for (cur
= ph
->pp_breakpoints
; cur
; cur
= cur
->bl_next
) {
145 (void) printf("\t0x%08lx:0x%04x - %s\n", cur
->bl_addr
,
146 cur
->bl_flags
, print_address_ps(ph
, cur
->bl_addr
,
152 set_breaks(struct ps_prochandle
*ph
)
155 bptinstr_t bpt_instr
= BPINSTR
;
157 for (cur
= ph
->pp_breakpoints
; cur
; cur
= cur
->bl_next
) {
158 bptinstr_t old_inst
= 0;
160 if (ps_pread(ph
, cur
->bl_addr
, (char *)&old_inst
,
161 sizeof (bptinstr_t
)) != PS_OK
)
162 perr("sb: error setting breakpoint");
164 cur
->bl_instr
= old_inst
;
166 if (ps_pwrite(ph
, cur
->bl_addr
, (char *)&bpt_instr
,
167 sizeof (bptinstr_t
)) != PS_OK
)
168 perr("sb1: error setting breakpoint\n");
174 clear_breaks(struct ps_prochandle
*ph
)
179 * Restore all the original instructions
181 for (cur
= ph
->pp_breakpoints
; cur
; cur
= cur
->bl_next
)
182 if (ps_pwrite(ph
, cur
->bl_addr
, (char *)&(cur
->bl_instr
),
183 sizeof (bptinstr_t
)) != PS_OK
)
184 perr("cb: error clearing breakpoint");
188 delete_all_breakpoints(struct ps_prochandle
*ph
)
190 bptlist_t
*cur
, *prev
;
192 if (ph
->pp_breakpoints
== NULL
)
195 for (prev
= NULL
, cur
= ph
->pp_breakpoints
;
196 cur
; prev
= cur
, cur
= cur
->bl_next
)
202 ph
->pp_breakpoints
= NULL
;
207 delete_breakpoint(struct ps_prochandle
*ph
, ulong_t addr
, unsigned flags
)
211 if (((bpt
= find_bp(ph
, addr
)) == (bptlist_t
*)-1) ||
212 ((bpt
->bl_flags
& flags
) == 0))
215 bpt
->bl_flags
&= ~flags
;
219 return (delete_bp(ph
, addr
));
223 handle_sp_break(struct ps_prochandle
*ph
)
227 if (rd_event_getmsg(ph
->pp_rap
, &emt
) != RD_OK
) {
228 (void) fprintf(stderr
, "hsb: failed rd_event_getmsg()\n");
232 if (emt
.type
== RD_DLACTIVITY
) {
233 if (emt
.u
.state
== RD_CONSISTENT
)
234 ph
->pp_flags
|= FLG_PP_LMAPS
;
236 ph
->pp_flags
&= ~FLG_PP_LMAPS
;
237 if ((rdb_flags
& RDB_FL_EVENTS
) == 0)
240 (void) printf("dlactivity: state changed to: ");
241 switch (emt
.u
.state
) {
243 (void) printf("RD_CONSISTENT\n");
246 (void) printf("RD_ADD\n");
249 (void) printf("RD_DELETE\n");
252 (void) printf("unknown: 0x%x\n", emt
.u
.state
);
257 if ((rdb_flags
& RDB_FL_EVENTS
) == 0)
260 if (emt
.type
== RD_PREINIT
) {
261 (void) printf("preinit reached\n");
265 if (emt
.type
== RD_POSTINIT
)
266 (void) printf("postinit reached\n");
270 continue_to_break(struct ps_prochandle
*ph
)
274 struct iovec piov
[5];
275 long oper1
, oper2
, oper3
, pflags
= 0;
279 * We step by the first instruction incase their was
280 * a break-point there.
282 (void) step_n(ph
, 1, FLG_SN_NONE
);
285 praddset(&faults
, FLTBPT
);
286 praddset(&faults
, FLTILL
);
287 praddset(&faults
, FLTPRIV
);
288 praddset(&faults
, FLTACCESS
);
289 praddset(&faults
, FLTBOUNDS
);
290 praddset(&faults
, FLTIZDIV
);
291 praddset(&faults
, FLTSTACK
);
292 praddset(&faults
, FLTTRACE
);
295 /* LINTED CONSTANT */
299 piov
[0].iov_base
= (caddr_t
)(&oper1
);
300 piov
[0].iov_len
= sizeof (oper1
);
302 piov
[1].iov_base
= (caddr_t
)(&faults
);
303 piov
[1].iov_len
= sizeof (faults
);
306 piov
[2].iov_base
= (caddr_t
)(&oper2
);
307 piov
[2].iov_len
= sizeof (oper2
);
309 piov
[3].iov_base
= (caddr_t
)(&pflags
);
310 piov
[3].iov_len
= sizeof (pflags
);
313 piov
[4].iov_base
= (caddr_t
)(&oper3
);
314 piov
[4].iov_len
= sizeof (oper3
);
316 if (writev(ph
->pp_ctlfd
, piov
, 5) == -1) {
317 if (errno
== ENOENT
) {
318 ph
->pp_flags
&= ~FLG_PP_PACT
;
321 (void) printf("process terminated.\n");
324 perr("ctb: PCWSTOP");
327 if (pread(ph
->pp_statusfd
, &pstatus
, sizeof (pstatus
), 0) == -1)
328 perr("ctb: reading status");
331 if ((pstatus
.pr_lwp
.pr_why
!= PR_FAULTED
) ||
332 (pstatus
.pr_lwp
.pr_what
!= FLTBPT
)) {
335 if ((pstatus
.pr_lwp
.pr_what
<= MAXFAULT
) &&
336 (pstatus
.pr_lwp
.pr_why
== PR_FAULTED
))
337 fltmsg
= fault_strings
[pstatus
.pr_lwp
.pr_what
];
339 fltmsg
= "<unknown error>";
341 (void) fprintf(stderr
, "ctb: bad stop - stopped "
342 "on why: 0x%x what: %s(0x%x)\n",
343 pstatus
.pr_lwp
.pr_why
, fltmsg
,
344 pstatus
.pr_lwp
.pr_what
);
349 if (writev(ph
->pp_ctlfd
, piov
, 1) == -1)
350 perr("ctb: PCCFAULT");
352 if ((bpt
= find_bp(ph
, pstatus
.pr_lwp
.pr_reg
[R_PC
])) ==
354 (void) fprintf(stderr
,
355 "stopped at unregistered breakpoint! "
357 EC_WORD(pstatus
.pr_lwp
.pr_reg
[R_PC
]));
363 * If this was a BP at which we should stop
365 if (bpt
->bl_flags
& MASK_BP_STOP
)
368 (void) step_n(ph
, 1, FLG_SN_NONE
);
371 if (bpt
->bl_flags
& FLG_BP_USERDEF
)
372 (void) printf("break point reached at addr: 0x%x\n",
373 EC_WORD(pstatus
.pr_lwp
.pr_reg
[R_PC
]));
375 if (bpt
->bl_flags
& MASK_BP_SPECIAL
)
378 if (ph
->pp_flags
& FLG_PP_LMAPS
) {
379 if (get_linkmaps(ph
) != PS_OK
)
380 (void) fprintf(stderr
, "problem loading linkmaps\n");
383 return (bpt
->bl_flags
);
387 is_plt(struct ps_prochandle
*ph
, ulong_t pc
)
392 if ((mip
= addr_to_map(ph
, pc
)) == (map_info_t
*)0)
395 pltbase
= mip
->mi_pltbase
;
396 if ((mip
->mi_flags
& FLG_MI_EXEC
) == 0)
397 pltbase
+= mip
->mi_addr
;
399 if ((pc
>= pltbase
) && (pc
<= (pltbase
+ mip
->mi_pltsize
)))
406 step_n(struct ps_prochandle
*ph
, size_t count
, sn_flags_e flgs
)
413 struct iovec piov
[2];
415 if (pread(ph
->pp_statusfd
, &pstatus
, sizeof (pstatus
), 0) == -1)
416 perr("stn: reading status");
418 piov
[0].iov_base
= (caddr_t
)(&oper
);
419 piov
[0].iov_len
= sizeof (oper
);
422 praddset(&faults
, FLTTRACE
);
424 flags
= PRSTEP
| PRCFAULT
;
426 for (i
= 0; i
< count
; i
++) {
428 uintptr_t pc
, pltbase
;
430 pc
= pstatus
.pr_lwp
.pr_reg
[R_PC
];
432 if ((bpt
= find_bp(ph
, pc
)) != (bptlist_t
*)-1) {
433 if (bpt
->bl_flags
& MASK_BP_SPECIAL
)
437 if (flgs
& FLG_SN_VERBOSE
)
441 piov
[1].iov_base
= (caddr_t
)(&faults
);
442 piov
[1].iov_len
= sizeof (faults
);
444 if (writev(ph
->pp_ctlfd
, piov
, 2) == -1)
445 perr("stn: PCSFAULT");
448 piov
[1].iov_base
= (caddr_t
)(&flags
);
449 piov
[1].iov_len
= sizeof (flags
);
450 if (writev(ph
->pp_ctlfd
, piov
, 2) == -1)
451 perr("stn: PCRUN(PRSETP)");
454 if (writev(ph
->pp_ctlfd
, piov
, 1) == -1)
455 perr("stn: PCWSTOP stepping");
457 if (pread(ph
->pp_statusfd
, &pstatus
, sizeof (pstatus
), 0) == -1)
458 perr("stn1: reading status");
459 pc
= pstatus
.pr_lwp
.pr_reg
[R_PC
];
462 if ((pstatus
.pr_lwp
.pr_why
!= PR_FAULTED
) ||
463 (pstatus
.pr_lwp
.pr_what
!= FLTTRACE
)) {
464 (void) fprintf(stderr
, "sn: bad stop - stopped on "
465 "why: 0x%x what: 0x%x\n", pstatus
.pr_lwp
.pr_why
,
466 pstatus
.pr_lwp
.pr_what
);
470 if ((flgs
& FLG_SN_PLTSKIP
) &&
471 ((pltbase
= is_plt(ph
, pc
)) != (ulong_t
)0)) {
473 if (rd_plt_resolution(ph
->pp_rap
, pc
,
474 pstatus
.pr_lwp
.pr_lwpid
, pltbase
, &rp
) != RD_OK
) {
475 (void) fprintf(stderr
,
476 "sn: rd_plt_resolution failed\n");
479 if (rp
.pi_skip_method
== RD_RESOLVE_TARGET_STEP
) {
482 (void) set_breakpoint(ph
, rp
.pi_target
,
484 bpflags
= continue_to_break(ph
);
486 (void) delete_breakpoint(ph
, rp
.pi_target
,
489 if (bpflags
& FLG_BP_PLTRES
)
490 (void) step_n(ph
, rp
.pi_nstep
,
492 } else if (rp
.pi_skip_method
== RD_RESOLVE_STEP
)
493 (void) step_n(ph
, rp
.pi_nstep
, FLG_SN_NONE
);
498 if (writev(ph
->pp_ctlfd
, piov
, 1) == -1)
499 perr("stn: PRCFAULT");
501 if ((flgs
& FLG_SN_VERBOSE
) && (ph
->pp_flags
& FLG_PP_LMAPS
)) {
502 if (get_linkmaps(ph
) != PS_OK
)
503 (void) fprintf(stderr
, "problem loading linkmaps\n");
510 step_to_addr(struct ps_prochandle
*ph
, ulong_t addr
)
516 if (read(ph
->pp_statusfd
, &pstat
, sizeof (pstat
)) == -1)
517 perr("sta: reading status");
519 caddr
= pstat
.pr_lwp
.pr_reg
[R_PC
];
521 while ((caddr
> addr
) || ((caddr
+ 0xff) < addr
)) {
522 (void) step_n(ph
, 1, FLG_SN_NONE
);
523 if (read(ph
->pp_statusfd
, &pstat
, sizeof (pstat
)) == -1)
524 perr("sta1: reading status");
525 caddr
= pstat
.pr_lwp
.pr_reg
[R_PC
];
526 if ((count
% 10000) == 0) {
527 (void) printf("%d: ", count
);
534 (void) printf("address found %d instructions in: pc: 0x%lx addr: "
535 "0x%lx\n", count
, caddr
, addr
);