1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright (c) 1999 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <stdio.h>
30 #include <dlfcn.h>
31
32 #include <fcode/private.h>
33 #include <fcode/log.h>
34
35 #ifdef DEBUG
36
37 static void (*trace_fn)(fcode_env_t *);
38
39 void
set_tracer(fcode_env_t * env,void (* tracer)(fcode_env_t *))40 set_tracer(fcode_env_t *env, void (*tracer)(fcode_env_t *))
41 {
42 trace_fn = tracer;
43 }
44
45 void
set_level(long lvl)46 set_level(long lvl)
47 {
48 long debug;
49
50 debug = get_interpreter_debug_level();
51 set_interpreter_debug_level(debug | lvl);
52 }
53
54 void
unset_level(long lvl)55 unset_level(long lvl)
56 {
57 long debug;
58
59 debug = get_interpreter_debug_level();
60 set_interpreter_debug_level(debug & ~lvl);
61 }
62
63 void
enable_trace(fcode_env_t * env)64 enable_trace(fcode_env_t *env)
65 {
66 set_level(DEBUG_TRACING);
67 }
68
69 void
enable_stack_trace(fcode_env_t * env)70 enable_stack_trace(fcode_env_t *env)
71 {
72 set_level(DEBUG_TRACE_STACK);
73 }
74
75 void
disable_stack_trace(fcode_env_t * env)76 disable_stack_trace(fcode_env_t *env)
77 {
78 unset_level(DEBUG_TRACE_STACK);
79 }
80
81 void
disable_trace(fcode_env_t * env)82 disable_trace(fcode_env_t *env)
83 {
84 unset_level(DEBUG_TRACING);
85 }
86
87 void
call_trace(fcode_env_t * env)88 call_trace(fcode_env_t *env)
89 {
90 set_level(DEBUG_CALL_METHOD);
91 }
92
93 void
no_call_trace(fcode_env_t * env)94 no_call_trace(fcode_env_t *env)
95 {
96 unset_level(DEBUG_CALL_METHOD);
97 }
98
99 void
do_fclib_trace(fcode_env_t * env,void * fn)100 do_fclib_trace(fcode_env_t *env, void *fn)
101 {
102 void *address;
103 Dl_info dlip;
104 static char buf[80];
105
106 if (dladdr((void *) fn, &dlip)) {
107 int offset;
108
109 address = dlsym(RTLD_DEFAULT, dlip.dli_sname);
110 offset = ((char *) fn) - ((char *) address);
111 if (offset == 0) {
112 log_message(MSG_FC_DEBUG, "%s: tracing %s()\n",
113 dlip.dli_fname, dlip.dli_sname);
114 } else {
115 log_message(MSG_FC_DEBUG, "%s: tracing %s%s0x%x()\n",
116 dlip.dli_fname, dlip.dli_sname,
117 ((offset < 0) ? "-" : "+"),
118 ((offset < 0) ? -offset : offset));
119 }
120 } else {
121 log_message(MSG_FC_DEBUG, "do_fclib_trace: <Unknown> %p\n", fn);
122 }
123 if (trace_fn)
124 trace_fn(env);
125 }
126
127 void
output_step_message(fcode_env_t * env)128 output_step_message(fcode_env_t *env)
129 {
130 log_message(MSG_INFO, "Step keys: <space>, Continue, Forth, Go,"
131 " Help, Step, Quit\n");
132 }
133
134 void
enable_step(fcode_env_t * env)135 enable_step(fcode_env_t *env)
136 {
137 output_step_message(env);
138 set_level(DEBUG_STEPPING);
139 }
140
141
142 void
disable_step(fcode_env_t * env)143 disable_step(fcode_env_t *env)
144 {
145 unset_level(DEBUG_STEPPING);
146 }
147
148 /*
149 * Output of state info is done elsewhere
150 */
151 int
do_fclib_step(fcode_env_t * env)152 do_fclib_step(fcode_env_t *env)
153 {
154 int c;
155 fcode_env_t *new_env;
156
157 for (; ; ) {
158 c = getchar();
159 if (c != '\n') {
160 while (getchar() != '\n')
161 ;
162 }
163 switch (c) {
164 case EOF:
165 case 'q':
166 unbug(env);
167 IP = 0;
168 return (1);
169
170 case 'c':
171 debug_set_level(env,
172 DEBUG_EXEC_TRACE|DEBUG_EXEC_DUMP_DS);
173 break;
174
175 case 'g':
176 unbug(env);
177 break;
178
179 case 'f':
180 unset_level(DEBUG_STEPPING);
181 new_env = clone_environment(env, NULL);
182 do_interact(new_env);
183 destroy_environment(new_env);
184 set_level(DEBUG_STEPPING);
185 continue;
186
187 case ' ':
188 case '\n':
189 break;
190
191 case 'd': /* Unimplemented */
192 case 'u': /* Unimplemented */
193 default:
194 output_step_message(env);
195 continue;
196 }
197 break;
198 }
199 return (0);
200 }
201
202 #pragma init(_init)
203
204 static void
_init(void)205 _init(void)
206 {
207 fcode_env_t *env = initial_env;
208
209 ASSERT(env);
210 NOTICE;
211
212
213 FORTH(0, "stack-trace", enable_stack_trace);
214 FORTH(0, "no-stack-trace", disable_stack_trace);
215 FORTH(0, "trace-on", enable_trace);
216 FORTH(0, "trace-off", disable_trace);
217 FORTH(0, "call-trace", call_trace);
218 FORTH(0, "no-call-trace", no_call_trace);
219 FORTH(0, "step-on", enable_step);
220 FORTH(0, "step-off", disable_step);
221 }
222
223 #endif
224