* $Id$
*/
+#ifdef linux
+#include <features.h>
+#endif
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* configuration section */
#ifndef MAX_QUALS
-#define MAX_QUALS 1024 /* maximum number of syscalls, signals, etc. */
+#if defined(linux) && defined(MIPS)
+#define MAX_QUALS 4999 /* maximum number of syscalls, signals, etc. */
+#else
+#define MAX_QUALS 2048 /* maximum number of syscalls, signals, etc. */
+#endif
#endif
#ifndef MAX_PROCS
-#define MAX_PROCS 32 /* maximum number of processes tracable */
+#define MAX_PROCS 64 /* maximum number of processes tracable */
#endif
#ifndef DEFAULT_STRLEN
#define DEFAULT_STRLEN 32 /* default maximum # of bytes printed in
#include <stdio.h>
#include <ctype.h>
#include <string.h>
+#include <time.h>
#include <sys/time.h>
#include <errno.h>
#include <stddef.h>
#endif /* STDC_HEADERS */
-#if defined(LINUX) && defined(SPARC)
-#define LINUXSPARC
-#endif /* LINUX && SPARC */
+#if defined(LINUX)
+# if defined(SPARC)
+# define LINUXSPARC
+# endif
+# if defined(ALPHA)
+# define LINUX_64BIT
+# endif
+#endif
+
+#if defined(SVR4) || defined(FREEBSD)
+#define USE_PROCFS
+#else
+#undef USE_PROCFS
+#endif
-#ifdef SVR4
+#ifdef FREEBSD
+#ifndef I386
+#error "FreeBSD support is only for i386 arch right now."
+#endif
+#include <machine/psl.h>
+#include <machine/reg.h>
+#include <sys/syscall.h>
+#endif
+
+#ifdef USE_PROCFS
#include <sys/procfs.h>
-#else /* !SVR4 */
+#ifdef HAVE_MP_PROCFS
+#include <sys/uio.h>
+#endif
+#ifdef FREEBSD
+#include <sys/pioctl.h>
+#endif /* FREEBSD */
+#else /* !USE_PROCFS */
#if defined(LINUXSPARC) && defined(__GLIBC__)
#include <sys/ptrace.h>
#else
#endif /* !SVR4 */
#ifdef LINUX
-#if !defined(LINUXSPARC) || !defined(__GLIBC__)
+#if !defined(__GLIBC__)
#define PTRACE_PEEKUSER PTRACE_PEEKUSR
#define PTRACE_POKEUSER PTRACE_POKEUSR
#endif
#ifdef ALPHA
-#define REG_R0 0
-#define REG_A0 16
-#define REG_A3 19
-#define REG_FP 30
-#define REG_PC 64
+# define REG_R0 0
+# define REG_A0 16
+# define REG_A3 19
+# define REG_FP 30
+# define REG_PC 64
#endif /* ALPHA */
+#ifdef MIPS
+# define REG_V0 2
+# define REG_A0 4
+# define REG_A3 7
+# define REG_SP 29
+# define REG_EPC 64
+#endif /* MIPS */
#endif /* LINUX */
#define SUPPORTED_PERSONALITIES 1
#include <linux/a.out.h>
#include <asm/psr.h>
#undef SUPPORTED_PERSONALITIES
-#define SUPPORTED_PERSONALITIES 3
+#define SUPPORTED_PERSONALITIES 2
#endif /* LINUXSPARC */
+
+#ifdef SVR4
+#ifdef HAVE_MP_PROCFS
+extern int mp_ioctl (int f, int c, void *a, int s);
+#define IOCTL(f,c,a) mp_ioctl (f, c, a, sizeof *a)
+#define IOCTL_STATUS(t) \
+ pread (t->pfd_stat, &t->status, sizeof t->status, 0)
+#define IOCTL_WSTOP(t) \
+ (IOCTL (t->pfd, PCWSTOP, (char *)NULL) < 0 ? -1 : \
+ IOCTL_STATUS (t))
+#define PR_WHY pr_lwp.pr_why
+#define PR_WHAT pr_lwp.pr_what
+#define PR_REG pr_lwp.pr_context.uc_mcontext.gregs
+#define PR_FLAGS pr_lwp.pr_flags
+#define PR_SYSCALL pr_lwp.pr_syscall
+#define PIOCSTIP PCSTOP
+#define PIOCSET PCSET
+#define PIOCRESET PCRESET
+#define PIOCSTRACE PCSTRACE
+#define PIOCSFAULT PCSFAULT
+#define PIOCWSTOP PCWSTOP
+#define PIOCSTOP PCSTOP
+#define PIOCSENTRY PCSENTRY
+#define PIOCSEXIT PCSEXIT
+#define PIOCRUN PCRUN
+#else
+#define IOCTL ioctl
+#define IOCTL_STATUS(t) ioctl (t->pfd, PIOCSTATUS, &t->status)
+#define IOCTL_WSTOP(t) ioctl (t->pfd, PIOCWSTOP, &t->status)
+#define PR_WHY pr_why
+#define PR_WHAT pr_what
+#define PR_REG pr_reg
+#define PR_FLAGS pr_flags
+#define PR_SYSCALL pr_syscall
+#endif
+#endif
+#ifdef FREEBSD
+#define IOCTL ioctl
+#define IOCTL_STATUS(t) ioctl (t->pfd, PIOCSTATUS, &t->status)
+#define IOCTL_WSTOP(t) ioctl (t->pfd, PIOCWAIT, &t->status)
+#define PIOCRUN PIOCCONT
+#define PIOCWSTOP PIOCWAIT
+#define PR_WHY why
+#define PR_WHAT val
+#define PR_FLAGS state
+/* from /usr/src/sys/miscfs/procfs/procfs_vnops.c,
+ status.state = 0 for running, 1 for stopped */
+#define PR_ASLEEP 1
+#define PR_SYSENTRY S_SCE
+#define PR_SYSEXIT S_SCX
+#define PR_SIGNALLED S_SIG
+#define PR_FAULTED S_CORE
+#endif
+
/* Trace Control Block */
struct tcb {
short flags; /* See below for TCB_ values */
long u_arg[MAX_ARGS]; /* System call arguments */
int u_error; /* Error code */
long u_rval; /* (first) return value */
+#ifdef HAVE_LONG_LONG
+ long long u_lrval; /* long long return value */
+#endif
FILE *outf; /* Output file for this process */
- char *auxstr; /* Auxiliary info from syscall (see RVAL_STR) */
+ const char *auxstr; /* Auxiliary info from syscall (see RVAL_STR) */
struct timeval stime; /* System time usage as of last process wait */
struct timeval dtime; /* Delta for system time usage */
struct timeval etime; /* Syscall entry time */
long inst[2]; /* Instructions on above */
int pfd; /* proc file descriptor */
#ifdef SVR4
+#ifdef HAVE_MP_PROCFS
+ int pfd_stat;
+ int pfd_as;
+ pstatus_t status;
+#else
prstatus_t status; /* procfs status structure */
#endif
+#endif
+#ifdef FREEBSD
+ struct procfs_status status;
+ int pfd_reg;
+ int pfd_status;
+#endif
};
/* TCB flags */
#define RVAL_HEX 001 /* hex format */
#define RVAL_OCTAL 002 /* octal format */
#define RVAL_UDECIMAL 003 /* unsigned decimal format */
+#define RVAL_LDECIMAL 004 /* long decimal format */
+#define RVAL_LHEX 005 /* long hex format */
+#define RVAL_LOCTAL 006 /* long octal format */
+#define RVAL_LUDECIMAL 007 /* long unsigned decimal format */
#define RVAL_MASK 007 /* mask for these values */
#define RVAL_STR 010 /* Print `auxstr' field after return val */
extern void set_overhead P((int));
extern void qualify P((char *));
extern void newoutf P((struct tcb *));
+extern int get_scno P((struct tcb *));
extern int trace_syscall P((struct tcb *));
extern void printxval P((struct xlat *, int, char *));
extern int printargs P((struct tcb *));
extern void printpath P((struct tcb *, long));
extern void printpathn P((struct tcb *, long, int));
extern void printtv P((struct tcb *, long));
-extern void printsock P((struct tcb *, long));
+extern void printsock P((struct tcb *, long, int));
extern void printrusage P((struct tcb *, long));
extern int clearbpt P((struct tcb *));
extern int setbpt P((struct tcb *));
extern int sigishandled P((struct tcb *, int));
extern void printcall P((struct tcb *));
+extern char *signame P((int));
extern void printsignal P((int));
extern void printleader P((struct tcb *));
extern void printtrailer P((struct tcb *));
extern void tabto P((int));
extern void call_summary P((FILE *));
extern void fake_execve P((struct tcb *, char *, char *[], char *[]));
+extern void printtv32 P((struct tcb*, long));
+#ifdef LINUX
+extern int internal_clone P((struct tcb *));
+#endif
extern int internal_fork P((struct tcb *));
extern int internal_exec P((struct tcb *));
extern int internal_wait P((struct tcb *));
#if !(defined(LINUX) && !defined(SPARC))
extern long getrval2 P((struct tcb *));
#endif
-#ifdef SVR4
+#ifdef USE_PROCFS
extern int proc_open P((struct tcb *tcp, int attaching));
#endif
extern char *signalent2[];
extern int nsignals2;
#endif /* SUPPORTED_PERSONALITIES >= 3 */
+
+#if FREEBSD
+/* ARRGH! off_t args are aligned on 64 bit boundaries! */
+#define ALIGN64(tcp,arg) \
+do { \
+ if (arg % 2) \
+ memmove (&tcp->u_arg[arg], &tcp->u_arg[arg + 1], \
+ (tcp->u_nargs - arg - 1) * sizeof tcp->u_arg[0]); \
+} while (0)
+#else
+#define ALIGN64(tcp,arg) do { } while (0)
+#endif
+
+#if HAVE_LONG_LONG
+
+/* _l refers to the lower numbered u_arg,
+ * _h refers to the higher numbered u_arg
+ */
+
+#if 1
+/* This should work, assuming we can do non-aligned 64 bit fetches.
+ * if not we'll have to figure out how which of the other versions to use.
+ */
+
+#define LONG_LONG(_l,_h) (*(long long *) &(_l))
+
+#else
+
+#if _LITTLE_ENDIAN
+#define LONG_LONG(_l,_h) \
+ ((long long)((unsigned long long)(_l) | ((unsigned long long)(_h)<<32)))
+#else
+#define LONG_LONG(_l,_h) \
+ ((long long)((unsigned long long)(_h) | ((unsigned long long)(_l)<<32)))
+#endif
+#endif
+#endif