The array applet_nameofs consumes two bytes per applet. It encodes nofork/noexec flags suid flags the offset of the applet name in the applet_name string
Change the applet_table build tool to store the flags in two separate arrays (applet_flags and applet_suid) and remove the applet_nameofs array. The name offsets are no longer stored. This requires changes to the macros APPLET_IS_NOFORK, APPLET_IS_NOEXEC and APPLET_SUID. The APPLET_NAME macro is replaced by a function, get_applet_name, which uses a linear search though the applet_name string to find the applet name given its number. As an optimisation get_applet_name stores the last applet number/name combination looked up. There are three cases where get_applet_name is used: 1) In install_links applets are processed in numerical order. Every time get_applet_name is called it is to search for the applet number following the stored value; 2) In find_applet_by_name a binary search is performed for the required name. With the default configuration this usually results in eight calls to get_applet_name. Sometimes the stored value reduces the linear search, though not always; 3) In run_applet_no_and_exit and run_nofork_applet the applet number passed to get_applet_name was obtained by an earlier call to find_applet_by_name. The stored value is exactly the one required so no linear search is needed. function old new delta applet_suid - 91 +91 get_applet_name - 60 +60 static.last_applet_name - 8 +8 static.last_applet_no - 4 +4 run_applet_no_and_exit 480 481 +1 applet_name_compare 31 24 -7 run_applet_and_exit 755 742 -13 .rodata 155866 155229 -637 applet_nameofs 728 - -728 ------------------------------------------------------------------------------ (add/remove: 4/1 grow/shrink: 1/3 up/down: 164/-1385) Total: -1221 bytes text data bss dec hex filename 823821 4078 9088 836987 cc57b busybox_old 823225 4086 9096 836407 cc337 busybox_unstripped Signed-off-by: Ron Yorston <[email protected]> --- applets/applet_tables.c | 37 ++++++++++++++++++++++++++++--------- include/busybox.h | 15 +++++---------- include/libbb.h | 1 + libbb/appletlib.c | 29 ++++++++++++++++++++++++++--- libbb/vfork_daemon_rexec.c | 2 +- 5 files changed, 61 insertions(+), 23 deletions(-) diff --git a/applets/applet_tables.c b/applets/applet_tables.c index 92bf1e4..b7f156b 100644 --- a/applets/applet_tables.c +++ b/applets/applet_tables.c @@ -119,20 +119,39 @@ int main(int argc, char **argv) printf("};\n"); printf("#endif\n\n"); - printf("const uint16_t applet_nameofs[] ALIGN2 = {\n"); - for (i = 0; i < NUM_APPLETS; i++) { - printf("0x%04x,\n", - offset[i] #if ENABLE_FEATURE_PREFER_APPLETS - + (applets[i].nofork << 12) - + (applets[i].noexec << 13) + printf("const uint8_t applet_flags[] ALIGN1 = {\n"); + i = 0; + while (i < NUM_APPLETS) { + int v = applets[i].nofork + (applets[i].noexec << 1); + if (++i < NUM_APPLETS) + v |= (applets[i].nofork + (applets[i].noexec << 1)) << 2; + if (++i < NUM_APPLETS) + v |= (applets[i].nofork + (applets[i].noexec << 1)) << 4; + if (++i < NUM_APPLETS) + v |= (applets[i].nofork + (applets[i].noexec << 1)) << 6; + printf("0x%02x,\n", v); + i++; + } + printf("};\n\n"); #endif + #if ENABLE_FEATURE_SUID - + (applets[i].need_suid << 14) /* 2 bits */ -#endif - ); + printf("const uint8_t applet_suid[] ALIGN1 = {\n"); + i = 0; + while (i < NUM_APPLETS) { + int v = applets[i].need_suid; /* 2 bits */ + if (++i < NUM_APPLETS) + v |= applets[i].need_suid << 2; + if (++i < NUM_APPLETS) + v |= applets[i].need_suid << 4; + if (++i < NUM_APPLETS) + v |= applets[i].need_suid << 6; + printf("0x%02x,\n", v); + i++; } printf("};\n\n"); +#endif #if ENABLE_FEATURE_INSTALLER printf("const uint8_t applet_install_loc[] ALIGN1 = {\n"); diff --git a/include/busybox.h b/include/busybox.h index b1e31e5..737627b 100644 --- a/include/busybox.h +++ b/include/busybox.h @@ -15,25 +15,20 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN /* Keep in sync with applets/applet_tables.c! */ extern const char applet_names[] ALIGN1; extern int (*const applet_main[])(int argc, char **argv); -extern const uint16_t applet_nameofs[]; +extern const uint8_t applet_flags[] ALIGN1; +extern const uint8_t applet_suid[] ALIGN1; extern const uint8_t applet_install_loc[] ALIGN1; -#if ENABLE_FEATURE_SUID || ENABLE_FEATURE_PREFER_APPLETS -# define APPLET_NAME(i) (applet_names + (applet_nameofs[i] & 0x0fff)) -#else -# define APPLET_NAME(i) (applet_names + applet_nameofs[i]) -#endif - #if ENABLE_FEATURE_PREFER_APPLETS -# define APPLET_IS_NOFORK(i) (applet_nameofs[i] & (1 << 12)) -# define APPLET_IS_NOEXEC(i) (applet_nameofs[i] & (1 << 13)) +# define APPLET_IS_NOFORK(i) (applet_flags[(i)/4] & (1 << (2 * ((i)%4)))) +# define APPLET_IS_NOEXEC(i) (applet_flags[(i)/4] & (1 << ((2 * ((i)%4))+1))) #else # define APPLET_IS_NOFORK(i) 0 # define APPLET_IS_NOEXEC(i) 0 #endif #if ENABLE_FEATURE_SUID -# define APPLET_SUID(i) ((applet_nameofs[i] >> 14) & 0x3) +# define APPLET_SUID(i) ((applet_suid[(i)/4] >> (2 * ((i)%4)) & 3)) #endif #if ENABLE_FEATURE_INSTALLER diff --git a/include/libbb.h b/include/libbb.h index 8b226c0..692b9f3 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1226,6 +1226,7 @@ const struct hwtype *get_hwntype(int type) FAST_FUNC; #ifndef BUILD_INDIVIDUAL extern int find_applet_by_name(const char *name) FAST_FUNC; +extern const char *get_applet_name(int applet_no) FAST_FUNC; /* Returns only if applet is not found. */ extern void run_applet_and_exit(const char *name, char **argv) FAST_FUNC; extern void run_applet_no_and_exit(int a, char **argv) NORETURN FAST_FUNC; diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 95e589e..d56d1ce 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -139,11 +139,34 @@ void FAST_FUNC bb_show_usage(void) xfunc_die(); } +const char * FAST_FUNC get_applet_name(int applet_no) +{ + int count = applet_no; + const char *p = applet_names; + static int last_applet_no = 0; + static const char *last_applet_name = applet_names; + + if (applet_no >= last_applet_no) { + count = applet_no - last_applet_no; + p = last_applet_name; + } + + while (count--) { + while (*p++) + ; + } + + last_applet_no = applet_no; + last_applet_name = p; + + return p; +} + #if NUM_APPLETS > 8 static int applet_name_compare(const void *name, const void *idx) { int i = (int)(ptrdiff_t)idx - 1; - return strcmp(name, APPLET_NAME(i)); + return strcmp(name, get_applet_name(i)); } #endif int FAST_FUNC find_applet_by_name(const char *name) @@ -593,7 +616,7 @@ static void install_links(const char *busybox, int use_symbolic_links, for (i = 0; i < ARRAY_SIZE(applet_main); i++) { fpc = concat_path_file( custom_install_dir ? custom_install_dir : install_dir[APPLET_INSTALL_LOC(i)], - APPLET_NAME(i)); + get_applet_name(i)); // debug: bb_error_msg("%slinking %s to busybox", // use_symbolic_links ? "sym" : "", fpc); rc = lf(busybox, fpc); @@ -754,7 +777,7 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) /* Reinit some shared global data */ xfunc_error_retval = EXIT_FAILURE; - applet_name = APPLET_NAME(applet_no); + applet_name = get_applet_name(applet_no); /* Special case. POSIX says "test --help" * should be no different from e.g. "test --foo". diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index d6ca7b2..640d216 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -116,7 +116,7 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv) save_nofork_data(&old); - applet_name = APPLET_NAME(applet_no); + applet_name = get_applet_name(applet_no); xfunc_error_retval = EXIT_FAILURE; -- 2.5.5 _______________________________________________ busybox mailing list [email protected] http://lists.busybox.net/mailman/listinfo/busybox
