Further optimize applet tables; prettify build output
No binary (build failed)
—
(log yok)
| @@ -14,20 +14,20 @@ always:= $(hostprogs-y) | |
| # Generated files need additional love | |
| - | quiet_cmd_gen_usage_compressed = GEN include/usage_compressed.h |
| - | cmd_gen_usage_compressed = $(srctree)/applets/usage_compressed include/usage_compressed.h applets |
| - | |
| HOSTCFLAGS_usage.o = -I$(srctree)/include | |
| - | applets/applets.o: include/usage_compressed.h include/applet_tables.h |
| + | applets/applets.o: include/usage_compressed.h include/applet_tables.h |
| - | applets/usage: .config $(srctree)/applets/usage_compressed |
| + | applets/usage: .config $(srctree)/applets/usage_compressed |
| + | |
| + | quiet_cmd_gen_usage_compressed = GEN include/usage_compressed.h |
| + | cmd_gen_usage_compressed = $(srctree)/applets/usage_compressed include/usage_compressed.h applets |
| include/usage_compressed.h: applets/usage $(srctree)/applets/usage_compressed | |
| $(call cmd,gen_usage_compressed) | |
| - | # Two-stage file creation, to avoid having target file still created |
| - | # in case applet_tables fails |
| + | quiet_cmd_gen_applet_tables = GEN include/applet_tables.h |
| + | cmd_gen_applet_tables = applets/applet_tables include/applet_tables.h |
| + | |
| include/applet_tables.h: applets/applet_tables | |
| - | applets/applet_tables >include/applet_tables.h.tmp |
| - | mv include/applet_tables.h.tmp include/applet_tables.h |
| + | $(call cmd,gen_applet_tables) |
| @@ -50,45 +50,66 @@ int main(int argc, char **argv) | |
| qsort(applets, NUM_APPLETS, sizeof(applets[0]), cmp_name); | |
| - | /* Keep in sync with include/busybox.h! */ |
| - | |
| - | puts("const char applet_names[] ALIGN1 ="); |
| ofs = 0; | |
| - | i = 0; |
| for (i = 0; i < NUM_APPLETS; i++) { | |
| offset[i] = ofs; | |
| ofs += strlen(applets[i].name) + 1; | |
| + | } |
| + | /* We reuse 4 high-order bits of offset array for other purposes, |
| + | * so if they are indeed needed, refuse to proceed */ |
| + | if (ofs > 0xfff) |
| + | return 1; |
| + | if (!argv[1]) |
| + | return 1; |
| + | |
| + | i = open(argv[1], O_WRONLY | O_TRUNC | O_CREAT, 0666); |
| + | if (i < 0) |
| + | return 1; |
| + | dup2(i, 1); |
| + | |
| + | /* Keep in sync with include/busybox.h! */ |
| + | |
| + | puts("/* This is a generated file, don't edit */"); |
| + | |
| + | puts("const char applet_names[] ALIGN1 ="); |
| + | for (i = 0; i < NUM_APPLETS; i++) { |
| printf("\"%s\" \"\\0\"\n", applets[i].name); | |
| } | |
| puts(";"); | |
| - | puts("int (*const applet_mains[])(int argc, char **argv) = {"); |
| + | puts("int (*const applet_main[])(int argc, char **argv) = {"); |
| for (i = 0; i < NUM_APPLETS; i++) { | |
| printf("%s_main,\n", applets[i].main); | |
| } | |
| puts("};"); | |
| - | #if ENABLE_FEATURE_INSTALLER || ENABLE_FEATURE_PREFER_APPLETS |
| - | puts("const uint32_t applet_nameofs[] = {"); |
| - | #else |
| puts("const uint16_t applet_nameofs[] ALIGN2 = {"); | |
| - | #endif |
| for (i = 0; i < NUM_APPLETS; i++) { | |
| - | printf("0x%08x,\n", |
| + | printf("0x%04x,\n", |
| offset[i] | |
| + | #if ENABLE_FEATURE_PREFER_APPLETS |
| + | + (applets[i].nofork << 12) |
| + | + (applets[i].noexec << 13) |
| + | #endif |
| #if ENABLE_FEATURE_SUID | |
| + (applets[i].need_suid << 14) /* 2 bits */ | |
| - | #endif |
| - | #if ENABLE_FEATURE_INSTALLER |
| - | + (applets[i].install_loc << 16) /* 3 bits */ |
| - | #endif |
| - | #if ENABLE_FEATURE_PREFER_APPLETS |
| - | + (applets[i].nofork << 19) |
| - | + (applets[i].noexec << 20) |
| #endif | |
| ); | |
| } | |
| puts("};"); | |
| + | #if ENABLE_FEATURE_INSTALLER |
| + | puts("const uint8_t applet_install_loc[] ALIGN1 = {"); |
| + | i = 0; |
| + | while (i < NUM_APPLETS) { |
| + | int v = applets[i].install_loc; /* 3 bits */ |
| + | if (++i < NUM_APPLETS) |
| + | v |= applets[i].install_loc << 4; /* 3 bits */ |
| + | printf("0x%02x,\n", v); |
| + | i++; |
| + | } |
| + | puts("};"); |
| + | #endif |
| + | |
| return 0; | |
| } | |
| @@ -28,28 +28,31 @@ typedef enum bb_suid_t { | |
| /* Defined in appletlib.c (by including generated applet_tables.h) */ | |
| /* Keep in sync with applets/applet_tables.c! */ | |
| extern const char applet_names[]; | |
| - | extern int (*const applet_mains[])(int argc, char **argv); |
| + | extern int (*const applet_main[])(int argc, char **argv); |
| + | extern const uint16_t applet_nameofs[]; |
| + | extern const uint8_t applet_install_loc[]; |
| - | #if ENABLE_FEATURE_INSTALLER || ENABLE_FEATURE_PREFER_APPLETS |
| - | extern const uint32_t applet_nameofs[]; |
| + | #if ENABLE_FEATURE_SUID || ENABLE_FEATURE_PREFER_APPLETS |
| + | #define APPLET_NAME(i) (applet_names + (applet_nameofs[i] & 0x0fff)) |
| #else | |
| - | extern const uint16_t applet_nameofs[]; |
| + | #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)) |
| #endif | |
| #if ENABLE_FEATURE_SUID | |
| - | #define APPLET_NAME(i) (applet_names + (applet_nameofs[i] & 0x3fff)) |
| #define APPLET_SUID(i) ((applet_nameofs[i] >> 14) & 0x3) | |
| - | #else |
| - | #define APPLET_NAME(i) (applet_names + (applet_nameofs[i] & 0xffff)) |
| #endif | |
| #if ENABLE_FEATURE_INSTALLER | |
| - | #define APPLET_INSTALL_LOC(i) ((applet_nameofs[i] >> 16) & 0x7) |
| - | #endif |
| - | |
| - | #if ENABLE_FEATURE_PREFER_APPLETS |
| - | #define APPLET_IS_NOFORK(i) (applet_nameofs[i] & (1 << 19)) |
| - | #define APPLET_IS_NOEXEC(i) (applet_nameofs[i] & (1 << 20)) |
| + | #define APPLET_INSTALL_LOC(i) ({ \ |
| + | unsigned v = (i); \ |
| + | if (v & 1) v = applet_install_loc[v/2] >> 4; \ |
| + | else v = applet_install_loc[v/2] & 0xf; \ |
| + | v; }) |
| #endif | |
| @@ -101,19 +101,17 @@ void bb_show_usage(void) | |
| } | |
| + | /* NB: any char pointer will work as well, not necessarily applet_names */ |
| static int applet_name_compare(const void *name, const void *v) | |
| { | |
| int i = (const char *)v - applet_names; | |
| return strcmp(name, APPLET_NAME(i)); | |
| } | |
| - | |
| int find_applet_by_name(const char *name) | |
| { | |
| - | const char *p; |
| /* Do a binary search to find the applet entry given the name. */ | |
| - | |
| - | /* NB: any char pointer will work as well, not necessarily applet_names */ |
| - | p = bsearch(name, applet_names, ARRAY_SIZE(applet_mains), 1, applet_name_compare); |
| + | const char *p; |
| + | p = bsearch(name, applet_names, ARRAY_SIZE(applet_main), 1, applet_name_compare); |
| if (!p) | |
| return -1; | |
| return p - applet_names; | |
| @@ -543,10 +541,12 @@ static void install_links(const char *busybox, int use_symbolic_links) | |
| if (use_symbolic_links) | |
| lf = symlink; | |
| - | for (i = 0; i < ARRAY_SIZE(applet_mains); i++) { |
| + | for (i = 0; i < ARRAY_SIZE(applet_main); i++) { |
| fpc = concat_path_file( | |
| install_dir[APPLET_INSTALL_LOC(i)], | |
| APPLET_NAME(i)); | |
| + | // debug: bb_error_msg("%slinking %s to busybox", |
| + | // use_symbolic_links ? "sym" : "", fpc); |
| rc = lf(busybox, fpc); | |
| if (rc != 0 && errno != EEXIST) { | |
| bb_simple_perror_msg(fpc); | |
| @@ -644,7 +644,7 @@ void run_applet_no_and_exit(int applet_no, char **argv) | |
| bb_show_usage(); | |
| if (ENABLE_FEATURE_SUID) | |
| check_suid(applet_no); | |
| - | exit(applet_mains[applet_no](argc, argv)); |
| + | exit(applet_main[applet_no](argc, argv)); |
| } | |
| void run_applet_and_exit(const char *name, char **argv) | |
| @@ -143,7 +143,7 @@ int run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char ** | |
| char *tmp_argv[argc+1]; | |
| memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); | |
| /* Finally we can call NOFORK applet's main() */ | |
| - | rc = applet_mains[applet_no](argc, tmp_argv); |
| + | rc = applet_main[applet_no](argc, tmp_argv); |
| } else { /* xfunc died in NOFORK applet */ | |
| /* in case they meant to return 0... */ | |
| if (rc == -2222) | |