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
37static void (*trace_fn)(fcode_env_t *);
38
39void
40set_tracer(fcode_env_t *env, void (*tracer)(fcode_env_t *))
41{
42	trace_fn = tracer;
43}
44
45void
46set_level(long lvl)
47{
48	long debug;
49
50	debug = get_interpreter_debug_level();
51	set_interpreter_debug_level(debug | lvl);
52}
53
54void
55unset_level(long lvl)
56{
57	long debug;
58
59	debug = get_interpreter_debug_level();
60	set_interpreter_debug_level(debug & ~lvl);
61}
62
63void
64enable_trace(fcode_env_t *env)
65{
66	set_level(DEBUG_TRACING);
67}
68
69void
70enable_stack_trace(fcode_env_t *env)
71{
72	set_level(DEBUG_TRACE_STACK);
73}
74
75void
76disable_stack_trace(fcode_env_t *env)
77{
78	unset_level(DEBUG_TRACE_STACK);
79}
80
81void
82disable_trace(fcode_env_t *env)
83{
84	unset_level(DEBUG_TRACING);
85}
86
87void
88call_trace(fcode_env_t *env)
89{
90	set_level(DEBUG_CALL_METHOD);
91}
92
93void
94no_call_trace(fcode_env_t *env)
95{
96	unset_level(DEBUG_CALL_METHOD);
97}
98
99void
100do_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
127void
128output_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
134void
135enable_step(fcode_env_t *env)
136{
137	output_step_message(env);
138	set_level(DEBUG_STEPPING);
139}
140
141
142void
143disable_step(fcode_env_t *env)
144{
145	unset_level(DEBUG_STEPPING);
146}
147
148/*
149 * Output of state info is done elsewhere
150 */
151int
152do_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
204static 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