test: stop using lots of bss.
authorDenis Vlasenko <vda.linux@googlemail.com>
Fri, 30 Nov 2007 07:29:05 +0000 (07:29 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Fri, 30 Nov 2007 07:29:05 +0000 (07:29 -0000)
function                                             old     new   delta
test_main                                            425     456     +31
t_lex                                                 69      73      +4
syntax                                               100     104      +4
ptr_to_statics                                         8      12      +4
t_wp_op                                                4       -      -4
t_wp                                                   4       -      -4
ngroups                                                4       -      -4
group_array                                            4       -      -4
binop                                                590     585      -5
oexpr                                                104      97      -7
aexpr                                                101      94      -7
nexpr                                                831     820     -11
leaving                                              156       -    -156
------------------------------------------------------------------------------
(add/remove: 0/5 grow/shrink: 4/4 up/down: 43/-202)          Total: -159 bytes
   text    data     bss     dec     hex filename
 775098     929    9084  785111   bfad7 busybox_old
 775107     933    8908  784948   bfa34 busybox_unstripped

coreutils/test.c
include/applets.h
libbb/lineedit.c

index 0b94100c1f83291d471e6d78a1a474f381dcdc46..a30a5087dcbba67733a117e4877d04d815409a42 100644 (file)
 #include "libbb.h"
 #include <setjmp.h>
 
-/* This is a NOEXEC applet. Be very careful! */
+/* This is a NOFORK applet. Be very careful! */
+
+/* test_main() is called from shells, and we need to be extra careful here.
+ * This is true regardless of PREFER_APPLETS and STANDALONE_SHELL
+ * state. */
 
 
 /* test(1) accepts the following grammar:
@@ -85,12 +89,12 @@ enum token {
        RPAREN,
        OPERAND
 };
-#define is_int_op(a) (((unsigned char)((a) - INTEQ)) <= 5)
-#define is_str_op(a) (((unsigned char)((a) - STREZ)) <= 5)
-#define is_file_op(a) (((unsigned char)((a) - FILNT)) <= 2)
+#define is_int_op(a)      (((unsigned char)((a) - INTEQ)) <= 5)
+#define is_str_op(a)      (((unsigned char)((a) - STREZ)) <= 5)
+#define is_file_op(a)     (((unsigned char)((a) - FILNT)) <= 2)
 #define is_file_access(a) (((unsigned char)((a) - FILRD)) <= 2)
-#define is_file_type(a) (((unsigned char)((a) - FILREG)) <= 5)
-#define is_file_bit(a) (((unsigned char)((a) - FILSUID)) <= 2)
+#define is_file_type(a)   (((unsigned char)((a) - FILREG)) <= 5)
+#define is_file_bit(a)    (((unsigned char)((a) - FILSUID)) <= 2)
 enum token_types {
        UNOP,
        BINOP,
@@ -153,13 +157,33 @@ typedef int64_t arith_t;
 typedef int arith_t;
 #endif
 
-/* Cannot eliminate these static data (do the G trick)
- * because of test_main usage from other applets */
-static char **t_wp;
-static const struct t_op *t_wp_op;
-static gid_t *group_array;
-static int ngroups;
-static jmp_buf leaving;
+
+/* We try to minimize both static and stack usage. */
+struct statics {
+       char **t_wp;
+       const struct t_op *t_wp_op;
+       gid_t *group_array;
+       int ngroups;
+       jmp_buf leaving;
+};
+
+/* Make it reside in writable memory, yet make compiler understand
+ * that it is not going to change. */
+static struct statics *const ptr_to_statics __attribute__ ((section (".data")));
+
+#define S (*ptr_to_statics)
+#define t_wp            (S.t_wp         )
+#define t_wp_op         (S.t_wp_op      )
+#define group_array     (S.group_array  )
+#define ngroups         (S.ngroups      )
+#define leaving         (S.leaving      )
+
+#define INIT_S() do { \
+       (*(struct statics**)&ptr_to_statics) = xzalloc(sizeof(S)); \
+} while (0)
+#define DEINIT_S() do { \
+       free(ptr_to_statics); \
+} while (0)
 
 static arith_t primary(enum token n);
 
@@ -550,9 +574,13 @@ int test_main(int argc, char **argv)
                argv[argc] = NULL;
        }
 
+       /* We must do DEINIT_S() prior to returning */
+       INIT_S();
+
        res = setjmp(leaving);
-       if (res)
-               return res;
+       if (res) {
+               goto ret;
+       }
 
        /* resetting ngroups is probably unnecessary.  it will
         * force a new call to getgroups(), which prevents using
@@ -565,24 +593,30 @@ int test_main(int argc, char **argv)
        ngroups = 0;
 
        /* Implement special cases from POSIX.2, section 4.62.4 */
-       if (argc == 1)
-               return 1;
-       if (argc == 2)
-               return *argv[1] == '\0';
-//assert(argc);
+       if (argc == 1) {
+               res = 1;
+               goto ret;
+       }
+       if (argc == 2) {
+               res = (*argv[1] == '\0');
+               goto ret;
+       }
+
        /* remember if we saw argc==4 which wants *no* '!' test */
        _off = argc - 4;
-       if (_off ?
-               (LONE_CHAR(argv[1], '!'))
-               : (argv[1][0] != '!' || argv[1][1] != '\0'))
-       {
-               if (argc == 3)
-                       return *argv[2] != '\0';
+       if (_off ? (LONE_CHAR(argv[1], '!'))
+                : (argv[1][0] != '!' || argv[1][1] != '\0')
+       ) {
+               if (argc == 3) {
+                       res = (*argv[2] != '\0');
+                       goto ret;
+               }
 
                t_lex(argv[2 + _off]);
                if (t_wp_op && t_wp_op->op_type == BINOP) {
                        t_wp = &argv[1 + _off];
-                       return binop() == _off;
+                       res = (binop() == _off);
+                       goto ret;
                }
        }
        t_wp = &argv[1];
@@ -590,7 +624,9 @@ int test_main(int argc, char **argv)
 
        if (*t_wp != NULL && *++t_wp != NULL) {
                bb_error_msg("%s: unknown operand", *t_wp);
-               return 2;
+               res = 2;
        }
+ ret:
+       DEINIT_S();
        return res;
 }
index f35a1d80be577bb4186c636c09268ff49e5d71e1..c6331cb05c06847084c6e54e1ba027610a8f813d 100644 (file)
@@ -73,7 +73,7 @@ s     - suid type:
 #endif
 
 
-USE_TEST(APPLET_NOEXEC([, test, _BB_DIR_USR_BIN, _BB_SUID_NEVER, test))
+USE_TEST(APPLET_NOFORK([, test, _BB_DIR_USR_BIN, _BB_SUID_NEVER, test))
 USE_TEST(APPLET_NOUSAGE([[, test, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
 USE_ADDGROUP(APPLET(addgroup, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_ADDUSER(APPLET(adduser, _BB_DIR_BIN, _BB_SUID_NEVER))
index 4d33834cea696fa4afe2980d870caf009fb403b8..07db6358dec2bf293a2656c1418b575790f0fb1f 100644 (file)
@@ -121,6 +121,8 @@ struct statics {
 #endif
 };
 
+/* Make it reside in writable memory, yet make compiler understand
+ * that it is not going to change. */
 static struct statics *const ptr_to_statics __attribute__ ((section (".data")));
 
 #define S (*ptr_to_statics)