* strace.c (tcbtab): Make this a pointer to pointers, not an array.
(tcbtabsize): New variable.
(main): Initialize them using dynamic allocation.
(alloctcb, main): Use tcbtabsize in place of MAX_PROCS; indirect.
(pid2tcb, cleanup): Likewise.
[USE_PROCFS] (pollv): Make this a pointer, not an array; make static.
(rebuild_pollv): Dynamically allocate the vector.
* defs.h (tcbtab): Update decls.
(MAX_PROCS): Macro removed, no more static limit on this.
* process.c (fork_tcb): New function.
(internal_clone, internal_fork): Use it instead of checking nprocs.
#define MAX_QUALS 2048 /* maximum number of syscalls, signals, etc. */
#endif
#endif
-#ifndef MAX_PROCS
-#define MAX_PROCS 64 /* maximum number of processes tracable */
-#endif
#ifndef DEFAULT_STRLEN
#define DEFAULT_STRLEN 32 /* default maximum # of bytes printed in
`printstr', change with `-s' switch */
# if defined(X86_64)
# define LINUX_X86_64
# endif
-#endif
+#endif
#if defined(SVR4) || defined(FREEBSD)
#define USE_PROCFS
#ifdef X86_64
#undef SUPPORTED_PERSONALITIES
#define SUPPORTED_PERSONALITIES 2
-#endif
-
+#endif
+
#ifdef SVR4
#ifdef HAVE_MP_PROCFS
extern int mp_ioctl (int f, int c, void *a, int s);
#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 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 TRACE_PROCESS 010 /* Trace process-related syscalls. */
#define TRACE_SIGNAL 020 /* Trace signal-related syscalls. */
-extern struct tcb tcbtab[];
+extern struct tcb **tcbtab;
extern int qual_flags[];
extern int debug, followfork, followvfork;
extern int rflag, tflag, dtime, cflag, xflag, qflag;
extern int acolumn;
extern char *outfname;
-extern int nprocs;
+extern unsigned int nprocs, tcbtabsize;
extern int max_strlen;
extern struct tcb *tcp_last;
return 0;
}
+/* TCP is creating a child we want to follow.
+ If there will be space in tcbtab for it, set TCB_FOLLOWFORK and return 0.
+ If not, clear TCB_FOLLOWFORK, print an error, and return 1. */
+static int
+fork_tcb(struct tcb *tcp)
+{
+ if (nprocs == tcbtabsize) {
+ /* Allocate some more TCBs and expand the table.
+ We don't want to relocate the TCBs because our
+ callers have pointers and it would be a pain.
+ So tcbtab is a table of pointers. Since we never
+ free the TCBs, we allocate a single chunk of many. */
+ struct tcb **newtab = (struct tcb **)
+ realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
+ struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
+ sizeof *newtcbs);
+ int i;
+ if (newtab == NULL || newtcbs == NULL) {
+ if (newtab != NULL)
+ free(newtab);
+ tcp->flags &= ~TCB_FOLLOWFORK;
+ fprintf(stderr, "sys_fork: tcb table full\n");
+ return 1;
+ }
+ for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
+ newtab[i] = &newtcbs[i - tcbtabsize];
+ tcbtabsize *= 2;
+ tcbtab = newtab;
+ }
+
+ tcp->flags |= TCB_FOLLOWFORK;
+ return 0;
+}
+
#ifdef USE_PROCFS
int
return 0;
if (!followfork)
return 0;
- if (nprocs == MAX_PROCS) {
- tcp->flags &= ~TCB_FOLLOWFORK;
- fprintf(stderr, "sys_fork: tcb table full\n");
+ if (fork_tcb(tcp))
return 0;
- }
- else
- tcp->flags |= TCB_FOLLOWFORK;
if (syserror(tcp))
return 0;
if ((tcpchild = alloctcb(tcp->u_rval)) == NULL) {
if (entering(tcp)) {
if (!followfork)
return 0;
- if (nprocs == MAX_PROCS) {
- tcp->flags &= ~TCB_FOLLOWFORK;
- fprintf(stderr, "sys_fork: tcb table full\n");
+ if (fork_tcb(tcp))
return 0;
- }
- tcp->flags |= TCB_FOLLOWFORK;
-
-
if (setbpt(tcp) < 0)
return 0;
} else {
if (entering(tcp)) {
if (!followfork || dont_follow)
return 0;
- if (nprocs == MAX_PROCS) {
- tcp->flags &= ~TCB_FOLLOWFORK;
- fprintf(stderr, "sys_fork: tcb table full\n");
+ if (fork_tcb(tcp))
return 0;
- }
- tcp->flags |= TCB_FOLLOWFORK;
if (setbpt(tcp) < 0)
return 0;
}
int max_strlen = DEFAULT_STRLEN;
char *outfname = NULL;
FILE *outf;
-struct tcb tcbtab[MAX_PROCS];
-int nprocs;
+struct tcb **tcbtab;
+unsigned int nprocs, tcbtabsize;
char *progname;
extern char version[];
extern char **environ;
static struct tcb *pfd2tcb P((int pfd));
static void reaper P((int sig));
static void rebuild_pollv P((void));
-struct pollfd pollv[MAX_PROCS];
+static struct pollfd *pollv;
#ifndef HAVE_POLLABLE_PROCFS
static char buf[BUFSIZ];
+ /* Allocate the initial tcbtab. */
+ tcbtabsize = argc; /* Surely enough for all -p args. */
+ tcbtab = (struct tcb **) malloc (tcbtabsize * sizeof tcbtab[0]);
+ tcbtab[0] = (struct tcb *) calloc (tcbtabsize, sizeof *tcbtab[0]);
+ for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
+ tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
+
progname = argv[0];
outf = stderr;
interactive = 1;
else
qflag = 1;
- for (c = 0, tcp = tcbtab; c < MAX_PROCS; c++, tcp++) {
+ for (c = 0; c < tcbtabsize; c++) {
+ tcp = tcbtab[c];
/* Reinitialize the output since it may have changed. */
tcp->outf = outf;
if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
int i;
struct tcb *tcp;
- for (i = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) {
+ for (i = 0; i < tcbtabsize; i++) {
+ tcp = tcbtab[i];
if ((tcp->flags & TCB_INUSE) == 0) {
tcp->pid = pid;
tcp->parent = NULL;
int i;
struct tcb *tcp;
- for (i = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) {
+ for (i = 0; i < tcbtabsize; i++) {
+ tcp = tcbtab[i];
if (pid && tcp->pid != pid)
continue;
if (tcp->flags & TCB_INUSE)
int i;
struct tcb *tcp;
- for (i = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) {
+ for (i = 0, tcp = tcbtab; i < tcbtabsize; i++, tcp++) {
if (tcp->pfd != pfd)
continue;
if (tcp->flags & TCB_INUSE)
int i;
struct tcb *tcp;
- for (i = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) {
+ for (i = 0; i < tcbtabsize; i++) {
+ tcp = tcbtab[i];
if (!(tcp->flags & TCB_INUSE))
continue;
if (debug)
int i, j;
struct tcb *tcp;
- for (i = j = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) {
+ if (pollv != NULL)
+ free (pollv);
+ pollv = (struct poll *) malloc(nprocs * sizeof pollv[0]);
+ if (pollv == NULL) {
+ fprintf(stderr, "strace: out of memory for poll vector\n");
+ exit(1);
+ }
+
+ for (i = j = 0, tcp = tcbtab; i < tcbtabsize; i++, tcp++) {
if (!(tcp->flags & TCB_INUSE))
continue;
pollv[j].fd = tcp->pfd;