From 9cbc15b7e72b2f108b886f89778ae606c7b6a526 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 22 Feb 2013 13:37:36 +0100 Subject: [PATCH] Eliminate MAX_QUALS, make qualifier array dynamic MAX_QUALS was 2048, even though most arches used less than 500 entries in it. MAX_QUALS had to be maintained by hand to be higher than syscall count. It also limited the highest possible fd to track. This change makes qual_flagsN[] arrays start sized to the required minimum (number of syscalls) and grow dynamically if user requested -e read=BIGNUM. As a precaution, BIGNUM should be < 2^15, but this limit can be raised with no cost for normal strace invocations. qual_flags is now a define to qual_vec[current_personality]. As a bonus, this patch aliases sysent, errnoent, signalent, ioctlent names in one-personality arches to their corresponding 0 arrays, removing one indirection level. text data bss dec hex filename 244471 700 12928 258099 3f033 strace.t7/strace 244627 680 10860 256167 3e8a7 strace.t8/strace Signed-off-by: Denys Vlasenko --- defs.h | 30 +++++---- syscall.c | 186 ++++++++++++++++++++++++++++++------------------------ 2 files changed, 120 insertions(+), 96 deletions(-) diff --git a/defs.h b/defs.h index 980dd3af..3212418c 100644 --- a/defs.h +++ b/defs.h @@ -91,13 +91,6 @@ extern char *stpcpy(char *dst, const char *src); #endif /* Configuration section */ -#ifndef MAX_QUALS -# if defined(MIPS) -# define MAX_QUALS 7000 /* maximum number of syscalls, signals, etc. */ -# else -# define MAX_QUALS 2048 /* maximum number of syscalls, signals, etc. */ -# endif -#endif #ifndef DEFAULT_STRLEN /* default maximum # of bytes printed in `printstr', change with -s switch */ # define DEFAULT_STRLEN 32 @@ -524,7 +517,6 @@ typedef enum { CFLAG_BOTH } cflag_t; extern cflag_t cflag; -extern qualbits_t *qual_flags; extern bool debug_flag; extern bool Tflag; extern bool qflag; @@ -745,14 +737,28 @@ extern unsigned current_wordsize; # define widen_to_long(v) ((long)(v)) #endif +extern const struct_sysent sysent0[]; +extern const char *const errnoent0[]; +extern const char *const signalent0[]; +extern const struct_ioctlent ioctlent0[]; +extern qualbits_t *qual_vec[SUPPORTED_PERSONALITIES]; +#define qual_flags (qual_vec[current_personality]) +#if SUPPORTED_PERSONALITIES > 1 extern const struct_sysent *sysent; -extern unsigned nsyscalls; extern const char *const *errnoent; -extern unsigned nerrnos; -extern const struct_ioctlent *ioctlent; -extern unsigned nioctlents; extern const char *const *signalent; +extern const struct_ioctlent *ioctlent; +#else +# define sysent sysent0 +# define errnoent errnoent0 +# define signalent signalent0 +# define ioctlent ioctlent0 +#endif +extern unsigned nsyscalls; +extern unsigned nerrnos; extern unsigned nsignals; +extern unsigned nioctlents; +extern unsigned num_quals; /* * If you need non-NULL sysent[scno].sys_func and sysent[scno].sys_name diff --git a/syscall.c b/syscall.c index b92ddc0e..ef14a0af 100644 --- a/syscall.c +++ b/syscall.c @@ -118,7 +118,7 @@ #define NF SYSCALL_NEVER_FAILS #define MA MAX_ARGS -static const struct_sysent sysent0[] = { +const struct_sysent sysent0[] = { #include "syscallent.h" }; @@ -153,20 +153,19 @@ static const struct_sysent sysent2[] = { * in "/usr/include". */ -static const char *const errnoent0[] = { +const char *const errnoent0[] = { #include "errnoent.h" }; -static const char *const signalent0[] = { +const char *const signalent0[] = { #include "signalent.h" }; -static const struct_ioctlent ioctlent0[] = { +const struct_ioctlent ioctlent0[] = { #include "ioctlent.h" }; enum { nsyscalls0 = ARRAY_SIZE(sysent0) }; enum { nerrnos0 = ARRAY_SIZE(errnoent0) }; enum { nsignals0 = ARRAY_SIZE(signalent0) }; enum { nioctlents0 = ARRAY_SIZE(ioctlent0) }; -qualbits_t qual_flags0[MAX_QUALS]; #if SUPPORTED_PERSONALITIES > 1 static const char *const errnoent1[] = { @@ -182,7 +181,6 @@ enum { nsyscalls1 = ARRAY_SIZE(sysent1) }; enum { nerrnos1 = ARRAY_SIZE(errnoent1) }; enum { nsignals1 = ARRAY_SIZE(signalent1) }; enum { nioctlents1 = ARRAY_SIZE(ioctlent1) }; -qualbits_t qual_flags1[MAX_QUALS]; #endif #if SUPPORTED_PERSONALITIES > 2 @@ -199,18 +197,60 @@ enum { nsyscalls2 = ARRAY_SIZE(sysent2) }; enum { nerrnos2 = ARRAY_SIZE(errnoent2) }; enum { nsignals2 = ARRAY_SIZE(signalent2) }; enum { nioctlents2 = ARRAY_SIZE(ioctlent2) }; -qualbits_t qual_flags2[MAX_QUALS]; #endif +#if SUPPORTED_PERSONALITIES > 1 const struct_sysent *sysent = sysent0; const char *const *errnoent = errnoent0; const char *const *signalent = signalent0; const struct_ioctlent *ioctlent = ioctlent0; +#endif unsigned nsyscalls = nsyscalls0; unsigned nerrnos = nerrnos0; unsigned nsignals = nsignals0; unsigned nioctlents = nioctlents0; -qualbits_t *qual_flags = qual_flags0; + +unsigned num_quals; +qualbits_t *qual_vec[SUPPORTED_PERSONALITIES]; + +static const unsigned nsyscall_vec[SUPPORTED_PERSONALITIES] = { + nsyscalls0, +#if SUPPORTED_PERSONALITIES > 1 + nsyscalls1, +#endif +#if SUPPORTED_PERSONALITIES > 2 + nsyscalls2, +#endif +}; +static const struct_sysent *const sysent_vec[SUPPORTED_PERSONALITIES] = { + sysent0, +#if SUPPORTED_PERSONALITIES > 1 + sysent1, +#endif +#if SUPPORTED_PERSONALITIES > 2 + sysent2, +#endif +}; + +enum { + MAX_NSYSCALLS1 = (nsyscalls0 +#if SUPPORTED_PERSONALITIES > 1 + > nsyscalls1 ? nsyscalls0 : nsyscalls1 +#endif + ), + MAX_NSYSCALLS2 = (MAX_NSYSCALLS1 +#if SUPPORTED_PERSONALITIES > 2 + > nsyscalls2 ? MAX_NSYSCALLS1 : nsyscalls2 +#endif + ), + MAX_NSYSCALLS = MAX_NSYSCALLS2, + /* We are ready for arches with up to 255 signals, + * even though the largest known signo is on MIPS and it is 128. + * The number of existing syscalls on all arches is + * larger that 255 anyway, so it is just a pedantic matter. + */ + MIN_QUALS = MAX_NSYSCALLS > 255 ? MAX_NSYSCALLS : 255 +}; #if SUPPORTED_PERSONALITIES > 1 unsigned current_personality; @@ -229,42 +269,36 @@ static const int personality_wordsize[SUPPORTED_PERSONALITIES] = { void set_personality(int personality) { + nsyscalls = nsyscall_vec[personality]; + sysent = sysent_vec[personality]; + switch (personality) { case 0: errnoent = errnoent0; nerrnos = nerrnos0; - sysent = sysent0; - nsyscalls = nsyscalls0; ioctlent = ioctlent0; nioctlents = nioctlents0; signalent = signalent0; nsignals = nsignals0; - qual_flags = qual_flags0; break; case 1: errnoent = errnoent1; nerrnos = nerrnos1; - sysent = sysent1; - nsyscalls = nsyscalls1; ioctlent = ioctlent1; nioctlents = nioctlents1; signalent = signalent1; nsignals = nsignals1; - qual_flags = qual_flags1; break; # if SUPPORTED_PERSONALITIES > 2 case 2: errnoent = errnoent2; nerrnos = nerrnos2; - sysent = sysent2; - nsyscalls = nsyscalls2; ioctlent = ioctlent2; nioctlents = nioctlents2; signalent = signalent2; nsignals = nsignals2; - qual_flags = qual_flags2; break; # endif } @@ -348,72 +382,63 @@ static const struct qual_options { { 0, NULL, NULL, NULL }, }; +static void +reallocate_qual(int n) +{ + unsigned p; + qualbits_t *qp; + for (p = 0; p < SUPPORTED_PERSONALITIES; p++) { + qp = qual_vec[p] = realloc(qual_vec[p], n * sizeof(qualbits_t)); + if (!qp) + die_out_of_memory(); + memset(&qp[num_quals], 0, (n - num_quals) * sizeof(qualbits_t)); + } + num_quals = n; +} + static void qualify_one(int n, int bitflag, int not, int pers) { - if (pers == 0 || pers < 0) { - if (not) - qual_flags0[n] &= ~bitflag; - else - qual_flags0[n] |= bitflag; - } + unsigned p; -#if SUPPORTED_PERSONALITIES > 1 - if (pers == 1 || pers < 0) { - if (not) - qual_flags1[n] &= ~bitflag; - else - qual_flags1[n] |= bitflag; - } -#endif + if (num_quals <= n) + reallocate_qual(n + 1); -#if SUPPORTED_PERSONALITIES > 2 - if (pers == 2 || pers < 0) { - if (not) - qual_flags2[n] &= ~bitflag; - else - qual_flags2[n] |= bitflag; + for (p = 0; p < SUPPORTED_PERSONALITIES; p++) { + if (pers == p || pers < 0) { + if (not) + qual_vec[p][n] &= ~bitflag; + else + qual_vec[p][n] |= bitflag; + } } -#endif } static int qual_syscall(const char *s, int bitflag, int not) { - int i; + unsigned p; + unsigned i; int rc = -1; if (*s >= '0' && *s <= '9') { - int i = string_to_uint(s); - if (i < 0 || i >= MAX_QUALS) + i = string_to_uint(s); + if (i > MAX_NSYSCALLS) return -1; qualify_one(i, bitflag, not, -1); return 0; } - for (i = 0; i < nsyscalls0; i++) - if (sysent0[i].sys_name && - strcmp(s, sysent0[i].sys_name) == 0) { - qualify_one(i, bitflag, not, 0); - rc = 0; - } - -#if SUPPORTED_PERSONALITIES > 1 - for (i = 0; i < nsyscalls1; i++) - if (sysent1[i].sys_name && - strcmp(s, sysent1[i].sys_name) == 0) { - qualify_one(i, bitflag, not, 1); - rc = 0; - } -#endif -#if SUPPORTED_PERSONALITIES > 2 - for (i = 0; i < nsyscalls2; i++) - if (sysent2[i].sys_name && - strcmp(s, sysent2[i].sys_name) == 0) { - qualify_one(i, bitflag, not, 2); - rc = 0; + for (p = 0; p < SUPPORTED_PERSONALITIES; p++) { + for (i = 0; i < nsyscall_vec[p]; i++) { + if (sysent_vec[p][i].sys_name + && strcmp(s, sysent_vec[p][i].sys_name) == 0 + ) { + qualify_one(i, bitflag, not, 0); + rc = 0; + } } -#endif + } return rc; } @@ -425,7 +450,7 @@ qual_signal(const char *s, int bitflag, int not) if (*s >= '0' && *s <= '9') { int signo = string_to_uint(s); - if (signo < 0 || signo >= MAX_QUALS) + if (signo < 0 || signo > 255) return -1; qualify_one(signo, bitflag, not, -1); return 0; @@ -446,7 +471,7 @@ qual_desc(const char *s, int bitflag, int not) { if (*s >= '0' && *s <= '9') { int desc = string_to_uint(s); - if (desc < 0 || desc >= MAX_QUALS) + if (desc < 0 || desc > 0x7fff) /* paranoia */ return -1; qualify_one(desc, bitflag, not, -1); return 0; @@ -483,6 +508,9 @@ qualify(const char *s) const char *p; int i, n; + if (num_quals == 0) + reallocate_qual(MIN_QUALS); + opt = &qual_options[0]; for (i = 0; (p = qual_options[i].option_name); i++) { n = strlen(p); @@ -502,12 +530,12 @@ qualify(const char *s) s = "all"; } if (strcmp(s, "all") == 0) { - for (i = 0; i < MAX_QUALS; i++) { + for (i = 0; i < num_quals; i++) { qualify_one(i, opt->bitflag, not, -1); } return; } - for (i = 0; i < MAX_QUALS; i++) { + for (i = 0; i < num_quals; i++) { qualify_one(i, opt->bitflag, !not, -1); } copy = strdup(s); @@ -515,22 +543,12 @@ qualify(const char *s) die_out_of_memory(); for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) { if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) { - for (i = 0; i < nsyscalls0; i++) - if (sysent0[i].sys_flags & n) - qualify_one(i, opt->bitflag, not, 0); - -#if SUPPORTED_PERSONALITIES > 1 - for (i = 0; i < nsyscalls1; i++) - if (sysent1[i].sys_flags & n) - qualify_one(i, opt->bitflag, not, 1); -#endif - -#if SUPPORTED_PERSONALITIES > 2 - for (i = 0; i < nsyscalls2; i++) - if (sysent2[i].sys_flags & n) - qualify_one(i, opt->bitflag, not, 2); -#endif - + unsigned pers; + for (pers = 0; pers < SUPPORTED_PERSONALITIES; pers++) { + for (i = 0; i < nsyscall_vec[pers]; i++) + if (sysent_vec[pers][i].sys_flags & n) + qualify_one(i, opt->bitflag, not, 0); + } continue; } if (opt->qualify(p, opt->bitflag, not)) { @@ -2336,7 +2354,7 @@ dumpio(struct tcb *tcp) if (syserror(tcp)) return; - if ((unsigned long) tcp->u_arg[0] >= MAX_QUALS) + if ((unsigned long) tcp->u_arg[0] >= num_quals) return; func = tcp->s_ent->sys_func; if (func == printargs) -- 2.40.0