OpenSolaris_b135/lib/efcode/engine/tracing.c

Compare this file to the similar file:
Show the results in this format:

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 1999 by Sun Microsystems, Inc.
 * All rights reserved.
 */

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include <stdio.h>
#include <dlfcn.h>

#include <fcode/private.h>
#include <fcode/log.h>

#ifdef DEBUG

static void (*trace_fn)(fcode_env_t *);

void
set_tracer(fcode_env_t *env, void (*tracer)(fcode_env_t *))
{
	trace_fn = tracer;
}

void
set_level(long lvl)
{
	long debug;

	debug = get_interpreter_debug_level();
	set_interpreter_debug_level(debug | lvl);
}

void
unset_level(long lvl)
{
	long debug;

	debug = get_interpreter_debug_level();
	set_interpreter_debug_level(debug & ~lvl);
}

void
enable_trace(fcode_env_t *env)
{
	set_level(DEBUG_TRACING);
}

void
enable_stack_trace(fcode_env_t *env)
{
	set_level(DEBUG_TRACE_STACK);
}

void
disable_stack_trace(fcode_env_t *env)
{
	unset_level(DEBUG_TRACE_STACK);
}

void
disable_trace(fcode_env_t *env)
{
	unset_level(DEBUG_TRACING);
}

void
call_trace(fcode_env_t *env)
{
	set_level(DEBUG_CALL_METHOD);
}

void
no_call_trace(fcode_env_t *env)
{
	unset_level(DEBUG_CALL_METHOD);
}

void
do_fclib_trace(fcode_env_t *env, void *fn)
{
	void *address;
	Dl_info dlip;
	static char buf[80];

	if (dladdr((void *) fn, &dlip)) {
		int offset;

		address = dlsym(RTLD_DEFAULT, dlip.dli_sname);
		offset = ((char *) fn) - ((char *) address);
		if (offset == 0) {
			log_message(MSG_FC_DEBUG, "%s: tracing %s()\n",
			    dlip.dli_fname, dlip.dli_sname);
		} else {
			log_message(MSG_FC_DEBUG, "%s: tracing %s%s0x%x()\n",
			    dlip.dli_fname, dlip.dli_sname,
			    ((offset < 0) ? "-" : "+"),
			    ((offset < 0) ? -offset : offset));
		}
	} else {
		log_message(MSG_FC_DEBUG, "do_fclib_trace: <Unknown> %p\n", fn);
	}
	if (trace_fn)
		trace_fn(env);
}

void
output_step_message(fcode_env_t *env)
{
	log_message(MSG_INFO, "Step keys: <space>, Continue, Forth, Go,"
	    " Help, Step, Quit\n");
}

void
enable_step(fcode_env_t *env)
{
	output_step_message(env);
	set_level(DEBUG_STEPPING);
}


void
disable_step(fcode_env_t *env)
{
	unset_level(DEBUG_STEPPING);
}

/*
 * Output of state info is done elsewhere
 */
int
do_fclib_step(fcode_env_t *env)
{
	int c;
	fcode_env_t *new_env;

	for (; ; ) {
		c = getchar();
		if (c != '\n') {
			while (getchar() != '\n')
				;
		}
		switch (c) {
		case EOF:
		case 'q':
			unbug(env);
			IP = 0;
			return (1);

		case 'c':
			debug_set_level(env,
			    DEBUG_EXEC_TRACE|DEBUG_EXEC_DUMP_DS);
			break;

		case 'g':
			unbug(env);
			break;

		case 'f':
			unset_level(DEBUG_STEPPING);
			new_env = clone_environment(env, NULL);
			do_interact(new_env);
			destroy_environment(new_env);
			set_level(DEBUG_STEPPING);
			continue;

		case ' ':
		case '\n':
			break;

		case 'd':	/* Unimplemented */
		case 'u':	/* Unimplemented */
		default:
			output_step_message(env);
			continue;
		}
		break;
	}
	return (0);
}

#pragma init(_init)

static void
_init(void)
{
	fcode_env_t *env = initial_env;

	ASSERT(env);
	NOTICE;


	FORTH(0,	"stack-trace",		enable_stack_trace);
	FORTH(0,	"no-stack-trace",	disable_stack_trace);
	FORTH(0,	"trace-on",		enable_trace);
	FORTH(0,	"trace-off",		disable_trace);
	FORTH(0,	"call-trace",		call_trace);
	FORTH(0,	"no-call-trace",	no_call_trace);
	FORTH(0,	"step-on",		enable_step);
	FORTH(0,	"step-off",		disable_step);
}

#endif