From: Roland McGrath Date: Wed, 18 Dec 2002 04:16:10 +0000 (+0000) Subject: 2002-12-17 Roland McGrath X-Git-Tag: v4.5.18~937 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ee9d435275fd7abf736992f84b5053ee16ec4fc7;p=strace 2002-12-17 Roland McGrath * 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. --- diff --git a/defs.h b/defs.h index 43036852..c2f8ee6c 100644 --- a/defs.h +++ b/defs.h @@ -45,9 +45,6 @@ #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 */ @@ -90,7 +87,7 @@ # if defined(X86_64) # define LINUX_X86_64 # endif -#endif +#endif #if defined(SVR4) || defined(FREEBSD) #define USE_PROCFS @@ -186,8 +183,8 @@ extern int ptrace(); #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); @@ -216,7 +213,7 @@ 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 @@ -355,13 +352,13 @@ struct xlat { #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; diff --git a/process.c b/process.c index e30fd1cf..06ef7f20 100644 --- a/process.c +++ b/process.c @@ -368,6 +368,40 @@ struct tcb *tcp; 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 @@ -414,13 +448,8 @@ struct tcb *tcp; 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) { @@ -649,14 +678,8 @@ struct tcb *tcp; 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 { @@ -729,12 +752,8 @@ struct tcb *tcp; 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; } diff --git a/strace.c b/strace.c index 9f2a8610..9a4773fb 100644 --- a/strace.c +++ b/strace.c @@ -78,8 +78,8 @@ int acolumn = DEFAULT_ACOLUMN; 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; @@ -105,7 +105,7 @@ static int interrupted; 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 @@ -184,6 +184,13 @@ char *argv[]; 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; @@ -358,7 +365,8 @@ char *argv[]; 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)) @@ -596,7 +604,8 @@ int pid; 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; @@ -930,7 +939,8 @@ int pid; 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) @@ -948,7 +958,7 @@ int pfd; 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) @@ -1167,7 +1177,8 @@ cleanup() 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) @@ -1255,7 +1266,15 @@ rebuild_pollv() 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;