xref: /titanic_51/usr/src/lib/efcode/engine/tracing.c (revision 342440ec94087b8c751c580ab9ed6c693d31d418)
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
40 set_tracer(fcode_env_t *env, void (*tracer)(fcode_env_t *))
41 {
42 	trace_fn = tracer;
43 }
44 
45 void
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
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
64 enable_trace(fcode_env_t *env)
65 {
66 	set_level(DEBUG_TRACING);
67 }
68 
69 void
70 enable_stack_trace(fcode_env_t *env)
71 {
72 	set_level(DEBUG_TRACE_STACK);
73 }
74 
75 void
76 disable_stack_trace(fcode_env_t *env)
77 {
78 	unset_level(DEBUG_TRACE_STACK);
79 }
80 
81 void
82 disable_trace(fcode_env_t *env)
83 {
84 	unset_level(DEBUG_TRACING);
85 }
86 
87 void
88 call_trace(fcode_env_t *env)
89 {
90 	set_level(DEBUG_CALL_METHOD);
91 }
92 
93 void
94 no_call_trace(fcode_env_t *env)
95 {
96 	unset_level(DEBUG_CALL_METHOD);
97 }
98 
99 void
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
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
135 enable_step(fcode_env_t *env)
136 {
137 	output_step_message(env);
138 	set_level(DEBUG_STEPPING);
139 }
140 
141 
142 void
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
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
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