home *** CD-ROM | disk | FTP | other *** search
- head 1.5;
- access;
- symbols
- version39-41:1.4;
- locks;
- comment @ * @;
-
-
- 1.5
- date 92.08.09.21.01.09; author amiga; state Exp;
- branches;
- next 1.4;
-
- 1.4
- date 92.07.04.19.23.16; author mwild; state Exp;
- branches;
- next 1.3;
-
- 1.3
- date 92.05.22.01.51.07; author mwild; state Exp;
- branches;
- next 1.2;
-
- 1.2
- date 92.05.18.12.24.20; author mwild; state Exp;
- branches;
- next 1.1;
-
- 1.1
- date 92.05.14.19.55.40; author mwild; state Exp;
- branches;
- next ;
-
-
- desc
- @support for any tracing-clients (if configured with TRACE_LIBRARY)
- @
-
-
- 1.5
- log
- @import sysbase
- @
- text
- @/*
- * This file is part of ixemul.library for the Amiga.
- * Copyright (C) 1991, 1992 Markus M. Wild
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id: tracecntl.c,v 1.4 1992/07/04 19:23:16 mwild Exp $
- *
- * $Log: tracecntl.c,v $
- * Revision 1.4 1992/07/04 19:23:16 mwild
- * double the number of passed parameters. Probably still not enough for weird
- * cases, but I can't do much about that...
- *
- * Revision 1.3 1992/05/22 01:51:07 mwild
- * all common double returning functions are _JMP or they won't work
- *
- * Revision 1.2 1992/05/18 12:24:20 mwild
- * new way of getting at the result of a function. Do the call from
- * inside the handler and tell the library call hook to not call the
- * function again (TRACE_ACTION_RTS). Removed trace_exit() handler.
- *
- * Revision 1.1 1992/05/14 19:55:40 mwild
- * Initial revision
- *
- */
-
- #define KERNEL
- #include "ixemul.h"
-
- #include <sys/tracecntl.h>
-
- #ifdef DEBUG
- #define DP(a) kprintf a
- #else
- #define DP(a)
- #endif
-
- #ifdef TRACE_LIBRARY
- struct ExecBase *SysBase;
-
- static struct List packets = {
- (struct Node *) &packets.lh_Tail, 0, (struct Node *) &packets.lh_Head,
- };
-
- static struct SignalSemaphore psem;
- static sem_initialized = 0;
-
- /* for each function traced, the trace_entry() function decides whether
- the trace_exit() function is invoked or not.
- If trace_entry() returns false, trace_exit() is not invoked.
-
- NOTE: having setjmp, vfork and the like invoke trace_exit will *NOT*
- work and will cause crashes!!
-
- Since I consider placing break points just to get the return value
- a bit overkill, I'll take a less optimal solution: I copy 8 args, this
- will do for 99% of all cases, and some nasty printf() style call will
- probably fail if tracing is enabled, so what ;-)) */
-
- int
- trace_entry (int scall, int (*func)(...), void *ret_addr,
- int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8,
- int a9, int aa, int ab, int ac, int ad, int ae, int af)
- {
- struct trace_packet *tp, *ntp;
- struct Task *me = FindTask (0);
- int te_action, handler_active;
- int omask;
-
- /* for safety, don't do anything if running in Forbid() or Disable() */
- if (SysBase->TDNestCnt >= 0 || SysBase->IDNestCnt >= 0)
- return TRACE_ACTION_JMP;
-
- /* have to do this here, or the handler may get into a deadlock
- situation when trying to obtain the semaphore */
- if (u.u_trace_flags)
- return TRACE_ACTION_JMP;
-
- /* get default action value */
- switch (scall)
- {
- case SYS_abort:
- case SYS_exit:
- case SYS_longjmp:
- case SYS_setjmp: /* can return twice ! */
- case SYS_siglongjmp:
- case SYS_sigreturn:
- case SYS_sigsetjmp: /* "" */
- case SYS__exit:
- case SYS__longjmp:
- case SYS__setjmp: /* "" */
- case SYS_vfork: /* "" */
- case SYS_vfork_resume: /* does longjmp-y thing... */
- case SYS_execve:
- case SYS_ix_geta4: /* special, result is in A4, not D0 ;-)) */
- case SYS_ix_check_cpu: /* may not return (but isn't used currently ;-)) */
- case SYS_ix_startup: /* those two call longjmp thru _exit */
- case SYS_ix_exec_entry:
- case SYS_fork:
- case SYS_floor: /* have all functions returning more than */
- case SYS_ceil: /* 4 bytes be called JMP'y */
- case SYS_atof:
- case SYS_frexp:
- case SYS_modf:
- case SYS_ldexp:
- case SYS_atan ... SYS_fabs: /* all the trigo stuff from *transbase.. */
- case SYS_strtod:
- te_action = TRACE_ACTION_JMP;
- break;
-
- default:
- te_action = TRACE_ACTION_JSR;
- break;
- }
-
- /* don't use syscall() here.. */
- omask = sigsetmask (~0);
- if (! sem_initialized)
- {
- sem_initialized = 1;
- InitSemaphore (& psem);
- }
- ObtainSemaphore (& psem);
- handler_active = 0;
- for (tp = (struct trace_packet *) packets.lh_Head;
- ntp = (struct trace_packet *) tp->tp_message.mn_Node.ln_Succ;
- tp = ntp)
- {
- if ((!tp->tp_pid || tp->tp_pid == (pid_t) me) &&
- (!tp->tp_syscall || tp->tp_syscall == scall))
- {
- Remove ((struct Node *) tp);
-
- tp->tp_is_entry = 1;
- tp->tp_argv = &scall;
- tp->tp_errno = u.u_errno;
- /* provide the default for the handler to (possibly) override */
- tp->tp_action = te_action;
- /* wanted to use u.u_sync_mp here, but this leads to some
- deadlock situations when the port is used for packets.. */
- tp->tp_message.mn_ReplyPort = (struct MsgPort *) me;
- SetSignal (0, SIGBREAKF_CTRL_E);
- PutMsg (tp->tp_tracer_port, (struct Message *) tp);
- Wait (SIGBREAKF_CTRL_E);
- /* the last handler wins ;-)) */
- te_action = tp->tp_action;
- handler_active = 1;
-
- /* should be safe.. */
- AddHead (&packets, (struct Node *) tp);
- }
- }
- ReleaseSemaphore (& psem);
- sigsetmask (omask);
-
- if (! handler_active)
- te_action = TRACE_ACTION_JMP;
-
- switch (te_action)
- {
- case TRACE_ACTION_ABORT:
- abort();
-
- default:
- case TRACE_ACTION_JMP:
- return TRACE_ACTION_JMP;
-
- case TRACE_ACTION_JSR:
- {
- int result, error;
-
- /* we now know that there is at least one trace handler
- interested in this result, so do the extra overhead of
- calling with (excess) argument copying */
- result = func (a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af);
- error = errno;
-
- /* replace the function address with the result */
- *(int *)&func = result;
-
- /* and repeat the process of calling the trace handler(s) */
- omask = sigsetmask (~0);
- ObtainSemaphore (& psem);
- for (tp = (struct trace_packet *) packets.lh_Head;
- ntp = (struct trace_packet *) tp->tp_message.mn_Node.ln_Succ;
- tp = ntp)
- {
- if ((!tp->tp_pid || tp->tp_pid == (pid_t) me) &&
- (!tp->tp_syscall || tp->tp_syscall == scall))
- {
- Remove ((struct Node *) tp);
-
- tp->tp_is_entry = 0;
- tp->tp_argv = &scall;
- errno = error;
- tp->tp_errno = u.u_errno;
- tp->tp_message.mn_ReplyPort = (struct MsgPort *) me;
- SetSignal (0, SIGBREAKF_CTRL_E);
- PutMsg (tp->tp_tracer_port, (struct Message *) tp);
- Wait (SIGBREAKF_CTRL_E);
-
- error = errno;
- /* should be safe.. */
- AddHead (&packets, (struct Node *) tp);
- }
- }
- ReleaseSemaphore (& psem);
- sigsetmask (omask);
- errno = error;
- }
- /* fall into */
-
- case TRACE_ACTION_RTS:
- return TRACE_ACTION_RTS;
- }
- }
-
- #endif /* TRACE_LIBRARY */
-
-
- int
- tracecntl (enum trace_cmd cmd, struct trace_packet *tp)
- {
- #ifndef TRACE_LIBRARY
- errno = ENOSYS;
- return -1;
- #else
- switch (cmd)
- {
- case TRACE_INSTALL_HANDLER:
- ix_lock_base ();
- tp->tp_message.mn_Node.ln_Type = NT_MESSAGE;
- tp->tp_message.mn_Length = sizeof (struct trace_packet);
- ObtainSemaphore (& psem);
- AddTail (&packets, (struct Node *) tp);
- ReleaseSemaphore (& psem);
- ix_unlock_base ();
- u.u_trace_flags = 1;
- return errno = 0;
-
- case TRACE_REMOVE_HANDLER:
- ix_lock_base ();
- ObtainSemaphore (& psem);
- Remove ((struct Node *) tp);
- ReleaseSemaphore (& psem);
- ix_unlock_base ();
- u.u_trace_flags = 0;
- return errno = 0;
-
- default:
- errno = EINVAL;
- return -1;
- }
- #endif
- }
- @
-
-
- 1.4
- log
- @double the number of passed parameters. Probably still not enough for weird
- cases, but I can't do much about that...
- @
- text
- @d19 1
- a19 1
- * $Id: tracecntl.c,v 1.3 1992/05/22 01:51:07 mwild Exp $
- d22 4
- d51 1
- a77 1
- struct ExecBase *SysBase = *(void **)4;
- @
-
-
- 1.3
- log
- @all common double returning functions are _JMP or they won't work
- @
- text
- @d19 1
- a19 1
- * $Id: tracecntl.c,v 1.2 1992/05/18 12:24:20 mwild Exp $
- d22 3
- d69 2
- a70 1
- int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8)
- d183 1
- a183 1
- result = func (a1, a2, a3, a4, a5, a6, a7, a8);
- @
-
-
- 1.2
- log
- @new way of getting at the result of a function. Do the call from
- inside the handler and tell the library call hook to not call the
- function again (TRACE_ACTION_RTS). Removed trace_exit() handler.
- @
- text
- @d19 1
- a19 1
- * $Id: tracecntl.c,v 1.1 1992/05/14 19:55:40 mwild Exp $
- d22 5
- d98 1
- d103 9
- @
-
-
- 1.1
- log
- @Initial revision
- @
- text
- @d19 1
- a19 1
- * $Id$
- d21 4
- a24 1
- * $Log$
- d52 6
- a57 1
- work and will cause crashes!! */
- d60 2
- a61 1
- trace_entry (int scall, ...)
- a80 4
- #if 1
- default:
- #endif
-
- d95 2
- a98 1
- #if 0
- a102 1
- #endif
- d145 2
- a146 30
- if (te_action == TRACE_ACTION_ABORT)
- abort ();
- #if 0
- else
- /* there's no reason to invoke the exit handler if there's nobody
- interested in this event */
- return handler_active ? te_action : TRACE_ACTION_JMP;
- #else
- return TRACE_ACTION_JMP;
- #endif
- }
-
- /* we still have the original argument vector on the stack before the
- result. Some handler might be interested in this (sprintf for example) */
- void
- trace_exit (int scall, int result, ...)
- {
- struct trace_packet *tp, *ntp;
- struct ExecBase *SysBase = *(void **)4;
- struct Task *me = FindTask (0);
- int omask;
-
- /* for safety, don't do anything if running in Forbid() or Disable() */
- if (SysBase->TDNestCnt >= 0 || SysBase->IDNestCnt >= 0)
- return TRACE_ACTION_JMP;
-
- /* have to do this here, or the handler may get into a deadlock
- situation when trying to obtain the semaphore */
- if (u.u_trace_flags)
- return TRACE_ACTION_JMP;
- d148 1
- a148 5
- omask = sigsetmask (~0);
- ObtainSemaphore (& psem);
- for (tp = (struct trace_packet *) packets.lh_Head;
- ntp = (struct trace_packet *) tp->tp_message.mn_Node.ln_Succ;
- tp = ntp)
- d150 2
- a151 5
- /* don't trace the trace handler itself... */
- if ((!tp->tp_pid || tp->tp_pid == (pid_t) me) &&
- (!tp->tp_syscall || tp->tp_syscall == scall))
- {
- Remove ((struct Node *) tp);
- d153 48
- a200 8
- tp->tp_is_entry = 0;
- tp->tp_argv = &scall;
- tp->tp_errno = u.u_errno;
- tp->tp_action = 0;
- tp->tp_message.mn_ReplyPort = (struct MsgPort *) me;
- SetSignal (0, SIGBREAKF_CTRL_E);
- PutMsg (tp->tp_tracer_port, (struct Message *) tp);
- Wait (SIGBREAKF_CTRL_E);
- d202 2
- a203 2
- AddHead (&packets, (struct Node *) tp);
- }
- a204 2
- ReleaseSemaphore (& psem);
- sigsetmask (omask);
- @
-