diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-11-02 23:31:10 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-11-02 23:31:10 +0000 |
commit | b68979aefa0efb519e6af02deba082e6b4180043 (patch) | |
tree | b16d64f31b629e54c70d30abbd98f3b4f46d7cd4 /modutils/insmod.c | |
parent | 9d1afdb571e0ba3053616d74edc99a68325ef5e9 (diff) | |
download | busybox-w32-b68979aefa0efb519e6af02deba082e6b4180043.tar.gz busybox-w32-b68979aefa0efb519e6af02deba082e6b4180043.tar.bz2 busybox-w32-b68979aefa0efb519e6af02deba082e6b4180043.zip |
insmod: code shrink, stop exporting insmod_ng_main.
function old new delta
add_ksymoops_symbols - 421 +421
static.section_names 20 40 +20
lsmod_main 425 424 -1
set_tainted 153 150 -3
main_opts 4 - -4
obj_symbol_patch 47 42 -5
obj_string_patch 144 139 -5
already_loaded 144 138 -6
check_dep 348 341 -7
append_option 75 68 -7
obj_allocate_commons 515 501 -14
new_process_module_arguments 1039 1018 -21
arch_new_symbol 31 9 -22
check_module_name_match 85 61 -24
obj_create_alloced_section 164 136 -28
include_conf 930 902 -28
modprobe_main 1643 1535 -108
obj_load 924 777 -147
insmod_ng_main 245 - -245
insmod_main 4122 3794 -328
------------------------------------------------------------------------------
(add/remove: 1/2 grow/shrink: 1/16 up/down: 441/-1003) Total: -562 bytes
text data bss dec hex filename
776020 974 9420 786414 bffee busybox_old
775384 974 9420 785778 bfd72 busybox_unstripped
Diffstat (limited to 'modutils/insmod.c')
-rw-r--r-- | modutils/insmod.c | 411 |
1 files changed, 172 insertions, 239 deletions
diff --git a/modutils/insmod.c b/modutils/insmod.c index 6f3b7d0f4..df75abbfa 100644 --- a/modutils/insmod.c +++ b/modutils/insmod.c | |||
@@ -67,25 +67,21 @@ | |||
67 | #define ENABLE_FEATURE_2_4_MODULES 1 | 67 | #define ENABLE_FEATURE_2_4_MODULES 1 |
68 | #endif | 68 | #endif |
69 | 69 | ||
70 | #if !ENABLE_FEATURE_2_4_MODULES | 70 | /* |
71 | #define insmod_ng_main insmod_main | 71 | * Big piece of 2.4-specific code |
72 | #endif | 72 | */ |
73 | #if ENABLE_FEATURE_2_4_MODULES | ||
73 | 74 | ||
74 | #if ENABLE_FEATURE_2_6_MODULES | 75 | #if ENABLE_FEATURE_2_6_MODULES |
75 | extern int insmod_ng_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 76 | static int insmod_ng_main(int argc, char **argv); |
76 | #endif | 77 | #endif |
77 | 78 | ||
78 | |||
79 | #if ENABLE_FEATURE_2_4_MODULES | ||
80 | |||
81 | |||
82 | #if ENABLE_FEATURE_INSMOD_LOADINKMEM | 79 | #if ENABLE_FEATURE_INSMOD_LOADINKMEM |
83 | #define LOADBITS 0 | 80 | #define LOADBITS 0 |
84 | #else | 81 | #else |
85 | #define LOADBITS 1 | 82 | #define LOADBITS 1 |
86 | #endif | 83 | #endif |
87 | 84 | ||
88 | |||
89 | /* Alpha */ | 85 | /* Alpha */ |
90 | #if defined(__alpha__) | 86 | #if defined(__alpha__) |
91 | #define MATCH_MACHINE(x) (x == EM_ALPHA) | 87 | #define MATCH_MACHINE(x) (x == EM_ALPHA) |
@@ -627,13 +623,13 @@ static struct obj_section *obj_create_alloced_section_first(struct obj_file *f, | |||
627 | 623 | ||
628 | static void *obj_extend_section(struct obj_section *sec, unsigned long more); | 624 | static void *obj_extend_section(struct obj_section *sec, unsigned long more); |
629 | 625 | ||
630 | static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, | 626 | static void obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, |
631 | const char *string); | 627 | const char *string); |
632 | 628 | ||
633 | static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, | 629 | static void obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, |
634 | struct obj_symbol *sym); | 630 | struct obj_symbol *sym); |
635 | 631 | ||
636 | static int obj_check_undefineds(struct obj_file *f); | 632 | static void obj_check_undefineds(struct obj_file *f); |
637 | 633 | ||
638 | static void obj_allocate_commons(struct obj_file *f); | 634 | static void obj_allocate_commons(struct obj_file *f); |
639 | 635 | ||
@@ -788,7 +784,6 @@ static size_t nksyms; | |||
788 | static struct external_module *ext_modules; | 784 | static struct external_module *ext_modules; |
789 | static int n_ext_modules; | 785 | static int n_ext_modules; |
790 | static int n_ext_modules_used; | 786 | static int n_ext_modules_used; |
791 | extern int delete_module(const char *); | ||
792 | 787 | ||
793 | static char *m_filename; | 788 | static char *m_filename; |
794 | static char *m_fullName; | 789 | static char *m_fullName; |
@@ -801,19 +796,16 @@ static int check_module_name_match(const char *filename, struct stat *statbuf, | |||
801 | void *userdata, int depth) | 796 | void *userdata, int depth) |
802 | { | 797 | { |
803 | char *fullname = (char *) userdata; | 798 | char *fullname = (char *) userdata; |
799 | char *tmp; | ||
804 | 800 | ||
805 | if (fullname[0] == '\0') | 801 | if (fullname[0] == '\0') |
806 | return FALSE; | 802 | return FALSE; |
807 | else { | 803 | |
808 | char *tmp, *tmp1 = xstrdup(filename); | 804 | tmp = bb_get_last_path_component_nostrip(filename); |
809 | tmp = bb_get_last_path_component_nostrip(tmp1); | 805 | if (strcmp(tmp, fullname) == 0) { |
810 | if (strcmp(tmp, fullname) == 0) { | 806 | /* Stop searching if we find a match */ |
811 | free(tmp1); | 807 | m_filename = xstrdup(filename); |
812 | /* Stop searching if we find a match */ | 808 | return FALSE; |
813 | m_filename = xstrdup(filename); | ||
814 | return FALSE; | ||
815 | } | ||
816 | free(tmp1); | ||
817 | } | 809 | } |
818 | return TRUE; | 810 | return TRUE; |
819 | } | 811 | } |
@@ -824,25 +816,19 @@ static int check_module_name_match(const char *filename, struct stat *statbuf, | |||
824 | static struct obj_file *arch_new_file(void) | 816 | static struct obj_file *arch_new_file(void) |
825 | { | 817 | { |
826 | struct arch_file *f; | 818 | struct arch_file *f; |
827 | f = xmalloc(sizeof(*f)); | 819 | f = xzalloc(sizeof(*f)); |
828 | 820 | return &f->root; /* it's a first member */ | |
829 | memset(f, 0, sizeof(*f)); | ||
830 | |||
831 | return &f->root; | ||
832 | } | 821 | } |
833 | 822 | ||
834 | static struct obj_section *arch_new_section(void) | 823 | static struct obj_section *arch_new_section(void) |
835 | { | 824 | { |
836 | return xmalloc(sizeof(struct obj_section)); | 825 | return xzalloc(sizeof(struct obj_section)); |
837 | } | 826 | } |
838 | 827 | ||
839 | static struct obj_symbol *arch_new_symbol(void) | 828 | static struct obj_symbol *arch_new_symbol(void) |
840 | { | 829 | { |
841 | struct arch_symbol *sym; | 830 | struct arch_symbol *sym; |
842 | sym = xmalloc(sizeof(*sym)); | 831 | sym = xzalloc(sizeof(*sym)); |
843 | |||
844 | memset(sym, 0, sizeof(*sym)); | ||
845 | |||
846 | return &sym->root; | 832 | return &sym->root; |
847 | } | 833 | } |
848 | 834 | ||
@@ -2210,7 +2196,6 @@ static struct obj_section *obj_create_alloced_section(struct obj_file *f, | |||
2210 | f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec)); | 2196 | f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec)); |
2211 | f->sections[newidx] = sec = arch_new_section(); | 2197 | f->sections[newidx] = sec = arch_new_section(); |
2212 | 2198 | ||
2213 | memset(sec, 0, sizeof(*sec)); | ||
2214 | sec->header.sh_type = SHT_PROGBITS; | 2199 | sec->header.sh_type = SHT_PROGBITS; |
2215 | sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; | 2200 | sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; |
2216 | sec->header.sh_size = size; | 2201 | sec->header.sh_size = size; |
@@ -2236,7 +2221,6 @@ static struct obj_section *obj_create_alloced_section_first(struct obj_file *f, | |||
2236 | f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec)); | 2221 | f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec)); |
2237 | f->sections[newidx] = sec = arch_new_section(); | 2222 | f->sections[newidx] = sec = arch_new_section(); |
2238 | 2223 | ||
2239 | memset(sec, 0, sizeof(*sec)); | ||
2240 | sec->header.sh_type = SHT_PROGBITS; | 2224 | sec->header.sh_type = SHT_PROGBITS; |
2241 | sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; | 2225 | sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; |
2242 | sec->header.sh_size = size; | 2226 | sec->header.sh_size = size; |
@@ -2398,7 +2382,7 @@ static char *get_modinfo_value(struct obj_file *f, const char *key) | |||
2398 | /*======================================================================*/ | 2382 | /*======================================================================*/ |
2399 | /* Functions relating to module loading after 2.1.18. */ | 2383 | /* Functions relating to module loading after 2.1.18. */ |
2400 | 2384 | ||
2401 | static int | 2385 | static void |
2402 | new_process_module_arguments(struct obj_file *f, int argc, char **argv) | 2386 | new_process_module_arguments(struct obj_file *f, int argc, char **argv) |
2403 | { | 2387 | { |
2404 | while (argc > 0) { | 2388 | while (argc > 0) { |
@@ -2408,7 +2392,8 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) | |||
2408 | int min, max, n; | 2392 | int min, max, n; |
2409 | 2393 | ||
2410 | p = *argv; | 2394 | p = *argv; |
2411 | if ((q = strchr(p, '=')) == NULL) { | 2395 | q = strchr(p, '='); |
2396 | if (q == NULL) { | ||
2412 | argc--; | 2397 | argc--; |
2413 | continue; | 2398 | continue; |
2414 | } | 2399 | } |
@@ -2421,8 +2406,7 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) | |||
2421 | p = get_modinfo_value(f, key); | 2406 | p = get_modinfo_value(f, key); |
2422 | key += 5; | 2407 | key += 5; |
2423 | if (p == NULL) { | 2408 | if (p == NULL) { |
2424 | bb_error_msg("invalid parameter %s", key); | 2409 | bb_error_msg_and_die("invalid parameter %s", key); |
2425 | return 0; | ||
2426 | } | 2410 | } |
2427 | 2411 | ||
2428 | #ifdef SYMBOL_PREFIX | 2412 | #ifdef SYMBOL_PREFIX |
@@ -2436,8 +2420,7 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) | |||
2436 | 2420 | ||
2437 | /* Also check that the parameter was not resolved from the kernel. */ | 2421 | /* Also check that the parameter was not resolved from the kernel. */ |
2438 | if (sym == NULL || sym->secidx > SHN_HIRESERVE) { | 2422 | if (sym == NULL || sym->secidx > SHN_HIRESERVE) { |
2439 | bb_error_msg("symbol for parameter %s not found", key); | 2423 | bb_error_msg_and_die("symbol for parameter %s not found", key); |
2440 | return 0; | ||
2441 | } | 2424 | } |
2442 | 2425 | ||
2443 | if (isdigit(*p)) { | 2426 | if (isdigit(*p)) { |
@@ -2463,11 +2446,10 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) | |||
2463 | 2446 | ||
2464 | str = alloca(strlen(q)); | 2447 | str = alloca(strlen(q)); |
2465 | for (r = str, q++; *q != '"'; ++q, ++r) { | 2448 | for (r = str, q++; *q != '"'; ++q, ++r) { |
2466 | if (*q == '\0') { | 2449 | if (*q == '\0') |
2467 | bb_error_msg("improperly terminated string argument for %s", | 2450 | bb_error_msg_and_die("improperly terminated string argument for %s", |
2468 | key); | 2451 | key); |
2469 | return 0; | 2452 | if (*q == '\\') |
2470 | } else if (*q == '\\') | ||
2471 | switch (*++q) { | 2453 | switch (*++q) { |
2472 | case 'a': | 2454 | case 'a': |
2473 | *r = '\a'; | 2455 | *r = '\a'; |
@@ -2513,8 +2495,9 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) | |||
2513 | default: | 2495 | default: |
2514 | *r = *q; | 2496 | *r = *q; |
2515 | break; | 2497 | break; |
2516 | } else | 2498 | } |
2517 | *r = *q; | 2499 | else |
2500 | *r = *q; | ||
2518 | } | 2501 | } |
2519 | *r = '\0'; | 2502 | *r = '\0'; |
2520 | ++q; | 2503 | ++q; |
@@ -2558,17 +2541,15 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) | |||
2558 | /* Get the size of each member */ | 2541 | /* Get the size of each member */ |
2559 | /* Probably we should do that outside the loop ? */ | 2542 | /* Probably we should do that outside the loop ? */ |
2560 | if (!isdigit(*(p + 1))) { | 2543 | if (!isdigit(*(p + 1))) { |
2561 | bb_error_msg("parameter type 'c' for %s must be followed by" | 2544 | bb_error_msg_and_die("parameter type 'c' for %s must be followed by" |
2562 | " the maximum size", key); | 2545 | " the maximum size", key); |
2563 | return 0; | ||
2564 | } | 2546 | } |
2565 | charssize = strtoul(p + 1, (char **) NULL, 10); | 2547 | charssize = strtoul(p + 1, (char **) NULL, 10); |
2566 | 2548 | ||
2567 | /* Check length */ | 2549 | /* Check length */ |
2568 | if (strlen(str) >= charssize) { | 2550 | if (strlen(str) >= charssize) { |
2569 | bb_error_msg("string too long for %s (max %ld)", key, | 2551 | bb_error_msg_and_die("string too long for %s (max %ld)", key, |
2570 | charssize - 1); | 2552 | charssize - 1); |
2571 | return 0; | ||
2572 | } | 2553 | } |
2573 | 2554 | ||
2574 | /* Copy to location */ | 2555 | /* Copy to location */ |
@@ -2595,12 +2576,10 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) | |||
2595 | break; | 2576 | break; |
2596 | 2577 | ||
2597 | default: | 2578 | default: |
2598 | bb_error_msg("unknown parameter type '%c' for %s", *p, key); | 2579 | bb_error_msg_and_die("unknown parameter type '%c' for %s", *p, key); |
2599 | return 0; | ||
2600 | } | 2580 | } |
2601 | } | 2581 | } |
2602 | 2582 | retry_end_of_value: | |
2603 | retry_end_of_value: | ||
2604 | switch (*q) { | 2583 | switch (*q) { |
2605 | case '\0': | 2584 | case '\0': |
2606 | goto end_of_arg; | 2585 | goto end_of_arg; |
@@ -2614,28 +2593,23 @@ retry_end_of_value: | |||
2614 | 2593 | ||
2615 | case ',': | 2594 | case ',': |
2616 | if (++n > max) { | 2595 | if (++n > max) { |
2617 | bb_error_msg("too many values for %s (max %d)", key, max); | 2596 | bb_error_msg_and_die("too many values for %s (max %d)", key, max); |
2618 | return 0; | ||
2619 | } | 2597 | } |
2620 | ++q; | 2598 | ++q; |
2621 | break; | 2599 | break; |
2622 | 2600 | ||
2623 | default: | 2601 | default: |
2624 | bb_error_msg("invalid argument syntax for %s", key); | 2602 | bb_error_msg_and_die("invalid argument syntax for %s", key); |
2625 | return 0; | ||
2626 | } | 2603 | } |
2627 | } | 2604 | } |
2628 | 2605 | end_of_arg: | |
2629 | end_of_arg: | ||
2630 | if (n < min) { | 2606 | if (n < min) { |
2631 | bb_error_msg("too few values for %s (min %d)", key, min); | 2607 | bb_error_msg_and_die("too few values for %s (min %d)", key, min); |
2632 | return 0; | ||
2633 | } | 2608 | } |
2634 | 2609 | ||
2635 | argc--, argv++; | 2610 | argc--; |
2611 | argv++; | ||
2636 | } | 2612 | } |
2637 | |||
2638 | return 1; | ||
2639 | } | 2613 | } |
2640 | 2614 | ||
2641 | #if ENABLE_FEATURE_INSMOD_VERSION_CHECKING | 2615 | #if ENABLE_FEATURE_INSMOD_VERSION_CHECKING |
@@ -2644,8 +2618,7 @@ static int new_is_module_checksummed(struct obj_file *f) | |||
2644 | const char *p = get_modinfo_value(f, "using_checksums"); | 2618 | const char *p = get_modinfo_value(f, "using_checksums"); |
2645 | if (p) | 2619 | if (p) |
2646 | return xatoi(p); | 2620 | return xatoi(p); |
2647 | else | 2621 | return 0; |
2648 | return 0; | ||
2649 | } | 2622 | } |
2650 | 2623 | ||
2651 | /* Get the module's kernel version in the canonical integer form. */ | 2624 | /* Get the module's kernel version in the canonical integer form. */ |
@@ -2679,7 +2652,7 @@ new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN]) | |||
2679 | 2652 | ||
2680 | /* Fetch the loaded modules, and all currently exported symbols. */ | 2653 | /* Fetch the loaded modules, and all currently exported symbols. */ |
2681 | 2654 | ||
2682 | static int new_get_kernel_symbols(void) | 2655 | static void new_get_kernel_symbols(void) |
2683 | { | 2656 | { |
2684 | char *module_names, *mn; | 2657 | char *module_names, *mn; |
2685 | struct external_module *modules, *m; | 2658 | struct external_module *modules, *m; |
@@ -2688,15 +2661,17 @@ static int new_get_kernel_symbols(void) | |||
2688 | 2661 | ||
2689 | /* Collect the loaded modules. */ | 2662 | /* Collect the loaded modules. */ |
2690 | 2663 | ||
2691 | module_names = xmalloc(bufsize = 256); | 2664 | bufsize = 256; |
2692 | retry_modules_load: | 2665 | module_names = xmalloc(bufsize); |
2666 | |||
2667 | retry_modules_load: | ||
2693 | if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) { | 2668 | if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) { |
2694 | if (errno == ENOSPC && bufsize < ret) { | 2669 | if (errno == ENOSPC && bufsize < ret) { |
2695 | module_names = xrealloc(module_names, bufsize = ret); | 2670 | bufsize = ret; |
2671 | module_names = xrealloc(module_names, bufsize); | ||
2696 | goto retry_modules_load; | 2672 | goto retry_modules_load; |
2697 | } | 2673 | } |
2698 | bb_perror_msg("QM_MODULES"); | 2674 | bb_perror_msg_and_die("QM_MODULES"); |
2699 | return 0; | ||
2700 | } | 2675 | } |
2701 | 2676 | ||
2702 | n_ext_modules = nmod = ret; | 2677 | n_ext_modules = nmod = ret; |
@@ -2715,23 +2690,23 @@ retry_modules_load: | |||
2715 | /* The module was removed out from underneath us. */ | 2690 | /* The module was removed out from underneath us. */ |
2716 | continue; | 2691 | continue; |
2717 | } | 2692 | } |
2718 | bb_perror_msg("query_module: QM_INFO: %s", mn); | 2693 | bb_perror_msg_and_die("query_module: QM_INFO: %s", mn); |
2719 | return 0; | ||
2720 | } | 2694 | } |
2721 | 2695 | ||
2722 | syms = xmalloc(bufsize = 1024); | 2696 | bufsize = 1024; |
2723 | retry_mod_sym_load: | 2697 | syms = xmalloc(bufsize); |
2698 | retry_mod_sym_load: | ||
2724 | if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) { | 2699 | if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) { |
2725 | switch (errno) { | 2700 | switch (errno) { |
2726 | case ENOSPC: | 2701 | case ENOSPC: |
2727 | syms = xrealloc(syms, bufsize = ret); | 2702 | bufsize = ret; |
2703 | syms = xrealloc(syms, bufsize); | ||
2728 | goto retry_mod_sym_load; | 2704 | goto retry_mod_sym_load; |
2729 | case ENOENT: | 2705 | case ENOENT: |
2730 | /* The module was removed out from underneath us. */ | 2706 | /* The module was removed out from underneath us. */ |
2731 | continue; | 2707 | continue; |
2732 | default: | 2708 | default: |
2733 | bb_perror_msg("query_module: QM_SYMBOLS: %s", mn); | 2709 | bb_perror_msg_and_die("query_module: QM_SYMBOLS: %s", mn); |
2734 | return 0; | ||
2735 | } | 2710 | } |
2736 | } | 2711 | } |
2737 | nsyms = ret; | 2712 | nsyms = ret; |
@@ -2750,14 +2725,13 @@ retry_mod_sym_load: | |||
2750 | /* Collect the kernel's symbols. */ | 2725 | /* Collect the kernel's symbols. */ |
2751 | 2726 | ||
2752 | syms = xmalloc(bufsize = 16 * 1024); | 2727 | syms = xmalloc(bufsize = 16 * 1024); |
2753 | retry_kern_sym_load: | 2728 | retry_kern_sym_load: |
2754 | if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) { | 2729 | if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) { |
2755 | if (errno == ENOSPC && bufsize < ret) { | 2730 | if (errno == ENOSPC && bufsize < ret) { |
2756 | syms = xrealloc(syms, bufsize = ret); | 2731 | syms = xrealloc(syms, bufsize = ret); |
2757 | goto retry_kern_sym_load; | 2732 | goto retry_kern_sym_load; |
2758 | } | 2733 | } |
2759 | bb_perror_msg("kernel: QM_SYMBOLS"); | 2734 | bb_perror_msg_and_die("kernel: QM_SYMBOLS"); |
2760 | return 0; | ||
2761 | } | 2735 | } |
2762 | nksyms = nsyms = ret; | 2736 | nksyms = nsyms = ret; |
2763 | ksyms = syms; | 2737 | ksyms = syms; |
@@ -2765,7 +2739,6 @@ retry_kern_sym_load: | |||
2765 | for (j = 0, s = syms; j < nsyms; ++j, ++s) { | 2739 | for (j = 0, s = syms; j < nsyms; ++j, ++s) { |
2766 | s->name += (unsigned long) syms; | 2740 | s->name += (unsigned long) syms; |
2767 | } | 2741 | } |
2768 | return 1; | ||
2769 | } | 2742 | } |
2770 | 2743 | ||
2771 | 2744 | ||
@@ -2786,7 +2759,7 @@ static int new_is_kernel_checksummed(void) | |||
2786 | } | 2759 | } |
2787 | 2760 | ||
2788 | 2761 | ||
2789 | static int new_create_this_module(struct obj_file *f, const char *m_name) | 2762 | static void new_create_this_module(struct obj_file *f, const char *m_name) |
2790 | { | 2763 | { |
2791 | struct obj_section *sec; | 2764 | struct obj_section *sec; |
2792 | 2765 | ||
@@ -2800,8 +2773,6 @@ static int new_create_this_module(struct obj_file *f, const char *m_name) | |||
2800 | 2773 | ||
2801 | obj_string_patch(f, sec->idx, offsetof(struct new_module, name), | 2774 | obj_string_patch(f, sec->idx, offsetof(struct new_module, name), |
2802 | m_name); | 2775 | m_name); |
2803 | |||
2804 | return 1; | ||
2805 | } | 2776 | } |
2806 | 2777 | ||
2807 | #if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS | 2778 | #if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS |
@@ -2985,7 +2956,7 @@ new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size) | |||
2985 | 2956 | ||
2986 | /*======================================================================*/ | 2957 | /*======================================================================*/ |
2987 | 2958 | ||
2988 | static int | 2959 | static void |
2989 | obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, | 2960 | obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, |
2990 | const char *string) | 2961 | const char *string) |
2991 | { | 2962 | { |
@@ -3010,11 +2981,9 @@ obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, | |||
3010 | loc = obj_extend_section(strsec, len); | 2981 | loc = obj_extend_section(strsec, len); |
3011 | } | 2982 | } |
3012 | memcpy(loc, string, len); | 2983 | memcpy(loc, string, len); |
3013 | |||
3014 | return 1; | ||
3015 | } | 2984 | } |
3016 | 2985 | ||
3017 | static int | 2986 | static void |
3018 | obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, | 2987 | obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, |
3019 | struct obj_symbol *sym) | 2988 | struct obj_symbol *sym) |
3020 | { | 2989 | { |
@@ -3026,14 +2995,11 @@ obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, | |||
3026 | p->reloc_offset = offset; | 2995 | p->reloc_offset = offset; |
3027 | p->sym = sym; | 2996 | p->sym = sym; |
3028 | f->symbol_patches = p; | 2997 | f->symbol_patches = p; |
3029 | |||
3030 | return 1; | ||
3031 | } | 2998 | } |
3032 | 2999 | ||
3033 | static int obj_check_undefineds(struct obj_file *f) | 3000 | static void obj_check_undefineds(struct obj_file *f) |
3034 | { | 3001 | { |
3035 | unsigned long i; | 3002 | unsigned i; |
3036 | int ret = 1; | ||
3037 | 3003 | ||
3038 | for (i = 0; i < HASH_BUCKETS; ++i) { | 3004 | for (i = 0; i < HASH_BUCKETS; ++i) { |
3039 | struct obj_symbol *sym; | 3005 | struct obj_symbol *sym; |
@@ -3043,15 +3009,11 @@ static int obj_check_undefineds(struct obj_file *f) | |||
3043 | sym->secidx = SHN_ABS; | 3009 | sym->secidx = SHN_ABS; |
3044 | sym->value = 0; | 3010 | sym->value = 0; |
3045 | } else { | 3011 | } else { |
3046 | if (!flag_quiet) { | 3012 | if (!flag_quiet) |
3047 | bb_error_msg("unresolved symbol %s", sym->name); | 3013 | bb_error_msg_and_die("unresolved symbol %s", sym->name); |
3048 | } | ||
3049 | ret = 0; | ||
3050 | } | 3014 | } |
3051 | } | 3015 | } |
3052 | } | 3016 | } |
3053 | |||
3054 | return ret; | ||
3055 | } | 3017 | } |
3056 | 3018 | ||
3057 | static void obj_allocate_commons(struct obj_file *f) | 3019 | static void obj_allocate_commons(struct obj_file *f) |
@@ -3114,7 +3076,6 @@ static void obj_allocate_commons(struct obj_file *f) | |||
3114 | f->sections[i] = sec = arch_new_section(); | 3076 | f->sections[i] = sec = arch_new_section(); |
3115 | f->header.e_shnum = i + 1; | 3077 | f->header.e_shnum = i + 1; |
3116 | 3078 | ||
3117 | memset(sec, 0, sizeof(*sec)); | ||
3118 | sec->header.sh_type = SHT_PROGBITS; | 3079 | sec->header.sh_type = SHT_PROGBITS; |
3119 | sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; | 3080 | sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; |
3120 | sec->name = ".bss"; | 3081 | sec->name = ".bss"; |
@@ -3347,44 +3308,38 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) | |||
3347 | /* Read the file header. */ | 3308 | /* Read the file header. */ |
3348 | 3309 | ||
3349 | f = arch_new_file(); | 3310 | f = arch_new_file(); |
3350 | memset(f, 0, sizeof(*f)); | ||
3351 | f->symbol_cmp = strcmp; | 3311 | f->symbol_cmp = strcmp; |
3352 | f->symbol_hash = obj_elf_hash; | 3312 | f->symbol_hash = obj_elf_hash; |
3353 | f->load_order_search_start = &f->load_order; | 3313 | f->load_order_search_start = &f->load_order; |
3354 | 3314 | ||
3355 | fseek(fp, 0, SEEK_SET); | 3315 | fseek(fp, 0, SEEK_SET); |
3356 | if (fread(&f->header, sizeof(f->header), 1, fp) != 1) { | 3316 | if (fread(&f->header, sizeof(f->header), 1, fp) != 1) { |
3357 | bb_perror_msg("error reading ELF header"); | 3317 | bb_perror_msg_and_die("error reading ELF header"); |
3358 | return NULL; | ||
3359 | } | 3318 | } |
3360 | 3319 | ||
3361 | if (f->header.e_ident[EI_MAG0] != ELFMAG0 | 3320 | if (f->header.e_ident[EI_MAG0] != ELFMAG0 |
3362 | || f->header.e_ident[EI_MAG1] != ELFMAG1 | 3321 | || f->header.e_ident[EI_MAG1] != ELFMAG1 |
3363 | || f->header.e_ident[EI_MAG2] != ELFMAG2 | 3322 | || f->header.e_ident[EI_MAG2] != ELFMAG2 |
3364 | || f->header.e_ident[EI_MAG3] != ELFMAG3) { | 3323 | || f->header.e_ident[EI_MAG3] != ELFMAG3) { |
3365 | bb_error_msg("not an ELF file"); | 3324 | bb_error_msg_and_die("not an ELF file"); |
3366 | return NULL; | ||
3367 | } | 3325 | } |
3368 | if (f->header.e_ident[EI_CLASS] != ELFCLASSM | 3326 | if (f->header.e_ident[EI_CLASS] != ELFCLASSM |
3369 | || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN | 3327 | || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN |
3370 | ? ELFDATA2MSB : ELFDATA2LSB) | 3328 | ? ELFDATA2MSB : ELFDATA2LSB) |
3371 | || f->header.e_ident[EI_VERSION] != EV_CURRENT | 3329 | || f->header.e_ident[EI_VERSION] != EV_CURRENT |
3372 | || !MATCH_MACHINE(f->header.e_machine)) { | 3330 | || !MATCH_MACHINE(f->header.e_machine)) { |
3373 | bb_error_msg("ELF file not for this architecture"); | 3331 | bb_error_msg_and_die("ELF file not for this architecture"); |
3374 | return NULL; | ||
3375 | } | 3332 | } |
3376 | if (f->header.e_type != ET_REL) { | 3333 | if (f->header.e_type != ET_REL) { |
3377 | bb_error_msg("ELF file not a relocatable object"); | 3334 | bb_error_msg_and_die("ELF file not a relocatable object"); |
3378 | return NULL; | ||
3379 | } | 3335 | } |
3380 | 3336 | ||
3381 | /* Read the section headers. */ | 3337 | /* Read the section headers. */ |
3382 | 3338 | ||
3383 | if (f->header.e_shentsize != sizeof(ElfW(Shdr))) { | 3339 | if (f->header.e_shentsize != sizeof(ElfW(Shdr))) { |
3384 | bb_error_msg("section header size mismatch: %lu != %lu", | 3340 | bb_error_msg_and_die("section header size mismatch: %lu != %lu", |
3385 | (unsigned long) f->header.e_shentsize, | 3341 | (unsigned long) f->header.e_shentsize, |
3386 | (unsigned long) sizeof(ElfW(Shdr))); | 3342 | (unsigned long) sizeof(ElfW(Shdr))); |
3387 | return NULL; | ||
3388 | } | 3343 | } |
3389 | 3344 | ||
3390 | shnum = f->header.e_shnum; | 3345 | shnum = f->header.e_shnum; |
@@ -3394,8 +3349,7 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) | |||
3394 | section_headers = alloca(sizeof(ElfW(Shdr)) * shnum); | 3349 | section_headers = alloca(sizeof(ElfW(Shdr)) * shnum); |
3395 | fseek(fp, f->header.e_shoff, SEEK_SET); | 3350 | fseek(fp, f->header.e_shoff, SEEK_SET); |
3396 | if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) { | 3351 | if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) { |
3397 | bb_perror_msg("error reading ELF section headers"); | 3352 | bb_perror_msg_and_die("error reading ELF section headers"); |
3398 | return NULL; | ||
3399 | } | 3353 | } |
3400 | 3354 | ||
3401 | /* Read the section data. */ | 3355 | /* Read the section data. */ |
@@ -3404,7 +3358,6 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) | |||
3404 | struct obj_section *sec; | 3358 | struct obj_section *sec; |
3405 | 3359 | ||
3406 | f->sections[i] = sec = arch_new_section(); | 3360 | f->sections[i] = sec = arch_new_section(); |
3407 | memset(sec, 0, sizeof(*sec)); | ||
3408 | 3361 | ||
3409 | sec->header = section_headers[i]; | 3362 | sec->header = section_headers[i]; |
3410 | sec->idx = i; | 3363 | sec->idx = i; |
@@ -3431,8 +3384,7 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) | |||
3431 | sec->contents = xmalloc(sec->header.sh_size); | 3384 | sec->contents = xmalloc(sec->header.sh_size); |
3432 | fseek(fp, sec->header.sh_offset, SEEK_SET); | 3385 | fseek(fp, sec->header.sh_offset, SEEK_SET); |
3433 | if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) { | 3386 | if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) { |
3434 | bb_perror_msg("error reading ELF section data"); | 3387 | bb_perror_msg_and_die("error reading ELF section data"); |
3435 | return NULL; | ||
3436 | } | 3388 | } |
3437 | } else { | 3389 | } else { |
3438 | sec->contents = NULL; | 3390 | sec->contents = NULL; |
@@ -3441,14 +3393,11 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) | |||
3441 | 3393 | ||
3442 | #if SHT_RELM == SHT_REL | 3394 | #if SHT_RELM == SHT_REL |
3443 | case SHT_RELA: | 3395 | case SHT_RELA: |
3444 | bb_error_msg("RELA relocations not supported on this architecture"); | 3396 | bb_error_msg_and_die("RELA relocations not supported on this architecture"); |
3445 | return NULL; | ||
3446 | #else | 3397 | #else |
3447 | case SHT_REL: | 3398 | case SHT_REL: |
3448 | bb_error_msg("REL relocations not supported on this architecture"); | 3399 | bb_error_msg_and_die("REL relocations not supported on this architecture"); |
3449 | return NULL; | ||
3450 | #endif | 3400 | #endif |
3451 | |||
3452 | default: | 3401 | default: |
3453 | if (sec->header.sh_type >= SHT_LOPROC) { | 3402 | if (sec->header.sh_type >= SHT_LOPROC) { |
3454 | /* Assume processor specific section types are debug | 3403 | /* Assume processor specific section types are debug |
@@ -3458,9 +3407,8 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) | |||
3458 | break; | 3407 | break; |
3459 | } | 3408 | } |
3460 | 3409 | ||
3461 | bb_error_msg("can't handle sections of type %ld", | 3410 | bb_error_msg_and_die("can't handle sections of type %ld", |
3462 | (long) sec->header.sh_type); | 3411 | (long) sec->header.sh_type); |
3463 | return NULL; | ||
3464 | } | 3412 | } |
3465 | } | 3413 | } |
3466 | } | 3414 | } |
@@ -3494,10 +3442,9 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) | |||
3494 | ElfW(Sym) * sym; | 3442 | ElfW(Sym) * sym; |
3495 | 3443 | ||
3496 | if (sec->header.sh_entsize != sizeof(ElfW(Sym))) { | 3444 | if (sec->header.sh_entsize != sizeof(ElfW(Sym))) { |
3497 | bb_error_msg("symbol size mismatch: %lu != %lu", | 3445 | bb_error_msg_and_die("symbol size mismatch: %lu != %lu", |
3498 | (unsigned long) sec->header.sh_entsize, | 3446 | (unsigned long) sec->header.sh_entsize, |
3499 | (unsigned long) sizeof(ElfW(Sym))); | 3447 | (unsigned long) sizeof(ElfW(Sym))); |
3500 | return NULL; | ||
3501 | } | 3448 | } |
3502 | 3449 | ||
3503 | nsym = sec->header.sh_size / sizeof(ElfW(Sym)); | 3450 | nsym = sec->header.sh_size / sizeof(ElfW(Sym)); |
@@ -3528,7 +3475,6 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) | |||
3528 | */ | 3475 | */ |
3529 | val |= sym->st_other & 4; | 3476 | val |= sym->st_other & 4; |
3530 | #endif | 3477 | #endif |
3531 | |||
3532 | obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx, | 3478 | obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx, |
3533 | val, sym->st_size); | 3479 | val, sym->st_size); |
3534 | } | 3480 | } |
@@ -3537,10 +3483,9 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) | |||
3537 | 3483 | ||
3538 | case SHT_RELM: | 3484 | case SHT_RELM: |
3539 | if (sec->header.sh_entsize != sizeof(ElfW(RelM))) { | 3485 | if (sec->header.sh_entsize != sizeof(ElfW(RelM))) { |
3540 | bb_error_msg("relocation entry size mismatch: %lu != %lu", | 3486 | bb_error_msg_and_die("relocation entry size mismatch: %lu != %lu", |
3541 | (unsigned long) sec->header.sh_entsize, | 3487 | (unsigned long) sec->header.sh_entsize, |
3542 | (unsigned long) sizeof(ElfW(RelM))); | 3488 | (unsigned long) sizeof(ElfW(RelM))); |
3543 | return NULL; | ||
3544 | } | 3489 | } |
3545 | break; | 3490 | break; |
3546 | /* XXX Relocation code from modutils-2.3.19 is not here. | 3491 | /* XXX Relocation code from modutils-2.3.19 is not here. |
@@ -3638,8 +3583,9 @@ static int obj_gpl_license(struct obj_file *f, const char **license) | |||
3638 | } | 3583 | } |
3639 | return 2; | 3584 | return 2; |
3640 | } | 3585 | } |
3641 | if (strchr(ptr, '\0')) | 3586 | ptr = strchr(ptr, '\0'); |
3642 | ptr = strchr(ptr, '\0') + 1; | 3587 | if (ptr) |
3588 | ptr++; | ||
3643 | else | 3589 | else |
3644 | ptr = endptr; | 3590 | ptr = endptr; |
3645 | } | 3591 | } |
@@ -3648,12 +3594,12 @@ static int obj_gpl_license(struct obj_file *f, const char **license) | |||
3648 | } | 3594 | } |
3649 | 3595 | ||
3650 | #define TAINT_FILENAME "/proc/sys/kernel/tainted" | 3596 | #define TAINT_FILENAME "/proc/sys/kernel/tainted" |
3651 | #define TAINT_PROPRIETORY_MODULE (1<<0) | 3597 | #define TAINT_PROPRIETORY_MODULE (1 << 0) |
3652 | #define TAINT_FORCED_MODULE (1<<1) | 3598 | #define TAINT_FORCED_MODULE (1 << 1) |
3653 | #define TAINT_UNSAFE_SMP (1<<2) | 3599 | #define TAINT_UNSAFE_SMP (1 << 2) |
3654 | #define TAINT_URL "http://www.tux.org/lkml/#export-tainted" | 3600 | #define TAINT_URL "http://www.tux.org/lkml/#export-tainted" |
3655 | 3601 | ||
3656 | static void set_tainted(struct obj_file *f, int fd, char *m_name, | 3602 | static void set_tainted(int fd, char *m_name, |
3657 | int kernel_has_tainted, int taint, const char *text1, const char *text2) | 3603 | int kernel_has_tainted, int taint, const char *text1, const char *text2) |
3658 | { | 3604 | { |
3659 | static smallint printed_info; | 3605 | static smallint printed_info; |
@@ -3703,22 +3649,22 @@ static void check_tainted_module(struct obj_file *f, char *m_name) | |||
3703 | case 0: | 3649 | case 0: |
3704 | break; | 3650 | break; |
3705 | case 1: | 3651 | case 1: |
3706 | set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", ""); | 3652 | set_tainted(fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", ""); |
3707 | break; | 3653 | break; |
3708 | case 2: | 3654 | case 2: |
3709 | /* The module has a non-GPL license so we pretend that the | 3655 | /* The module has a non-GPL license so we pretend that the |
3710 | * kernel always has a taint flag to get a warning even on | 3656 | * kernel always has a taint flag to get a warning even on |
3711 | * kernels without the proc flag. | 3657 | * kernels without the proc flag. |
3712 | */ | 3658 | */ |
3713 | set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr); | 3659 | set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr); |
3714 | break; | 3660 | break; |
3715 | default: | 3661 | default: |
3716 | set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", ""); | 3662 | set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", ""); |
3717 | break; | 3663 | break; |
3718 | } | 3664 | } |
3719 | 3665 | ||
3720 | if (flag_force_load) | 3666 | if (flag_force_load) |
3721 | set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", ""); | 3667 | set_tainted(fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", ""); |
3722 | 3668 | ||
3723 | if (fd >= 0) | 3669 | if (fd >= 0) |
3724 | close(fd); | 3670 | close(fd); |
@@ -3752,15 +3698,7 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename, | |||
3752 | const char *m_name) | 3698 | const char *m_name) |
3753 | { | 3699 | { |
3754 | static const char symprefix[] ALIGN1 = "__insmod_"; | 3700 | static const char symprefix[] ALIGN1 = "__insmod_"; |
3755 | 3701 | static const char section_names[][8] = { | |
3756 | struct obj_section *sec; | ||
3757 | struct obj_symbol *sym; | ||
3758 | char *name, *absolute_filename; | ||
3759 | char str[STRVERSIONLEN], real[PATH_MAX]; | ||
3760 | int i, l, lm_name, lfilename, use_ksymtab, version; | ||
3761 | struct stat statbuf; | ||
3762 | |||
3763 | static const char *section_names[] = { | ||
3764 | ".text", | 3702 | ".text", |
3765 | ".rodata", | 3703 | ".rodata", |
3766 | ".data", | 3704 | ".data", |
@@ -3768,12 +3706,18 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename, | |||
3768 | ".sbss" | 3706 | ".sbss" |
3769 | }; | 3707 | }; |
3770 | 3708 | ||
3771 | if (realpath(filename, real)) { | 3709 | struct obj_section *sec; |
3772 | absolute_filename = xstrdup(real); | 3710 | struct obj_symbol *sym; |
3773 | } else { | 3711 | char *name, *absolute_filename; |
3774 | bb_perror_msg("cannot get realpath for %s", filename); | 3712 | char str[STRVERSIONLEN]; |
3713 | int i, l, lm_name, lfilename, use_ksymtab, version; | ||
3714 | struct stat statbuf; | ||
3715 | |||
3716 | /* WARNING: was using realpath, but replaced by readlink to stop using | ||
3717 | * lots of stack. But here it seems to be able to cause problems? */ | ||
3718 | absolute_filename = xmalloc_readlink(filename); | ||
3719 | if (!absolute_filename) | ||
3775 | absolute_filename = xstrdup(filename); | 3720 | absolute_filename = xstrdup(filename); |
3776 | } | ||
3777 | 3721 | ||
3778 | lm_name = strlen(m_name); | 3722 | lm_name = strlen(m_name); |
3779 | lfilename = strlen(absolute_filename); | 3723 | lfilename = strlen(absolute_filename); |
@@ -3791,22 +3735,22 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename, | |||
3791 | * is 0xffffff, decimal 16777215. putting all three fields in | 3735 | * is 0xffffff, decimal 16777215. putting all three fields in |
3792 | * one symbol is less readable but saves kernel space. | 3736 | * one symbol is less readable but saves kernel space. |
3793 | */ | 3737 | */ |
3794 | l = sizeof(symprefix)+ /* "__insmod_" */ | 3738 | l = sizeof(symprefix) + /* "__insmod_" */ |
3795 | lm_name+ /* module name */ | 3739 | lm_name + /* module name */ |
3796 | 2+ /* "_O" */ | 3740 | 2 + /* "_O" */ |
3797 | lfilename+ /* object filename */ | 3741 | lfilename + /* object filename */ |
3798 | 2+ /* "_M" */ | 3742 | 2 + /* "_M" */ |
3799 | 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */ | 3743 | 2 * sizeof(statbuf.st_mtime) + /* mtime in hex */ |
3800 | 2+ /* "_V" */ | 3744 | 2 + /* "_V" */ |
3801 | 8+ /* version in dec */ | 3745 | 8 + /* version in dec */ |
3802 | 1; /* nul */ | 3746 | 1; /* nul */ |
3803 | name = xmalloc(l); | 3747 | name = xmalloc(l); |
3804 | if (stat(absolute_filename, &statbuf) != 0) | 3748 | if (stat(absolute_filename, &statbuf) != 0) |
3805 | statbuf.st_mtime = 0; | 3749 | statbuf.st_mtime = 0; |
3806 | version = get_module_version(f, str); /* -1 if not found */ | 3750 | version = get_module_version(f, str); /* -1 if not found */ |
3807 | snprintf(name, l, "%s%s_O%s_M%0*lX_V%d", | 3751 | snprintf(name, l, "%s%s_O%s_M%0*lX_V%d", |
3808 | symprefix, m_name, absolute_filename, | 3752 | symprefix, m_name, absolute_filename, |
3809 | (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime, | 3753 | (int)(2 * sizeof(statbuf.st_mtime)), statbuf.st_mtime, |
3810 | version); | 3754 | version); |
3811 | sym = obj_add_symbol(f, name, -1, | 3755 | sym = obj_add_symbol(f, name, -1, |
3812 | ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE), | 3756 | ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE), |
@@ -3819,11 +3763,11 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename, | |||
3819 | /* record where the persistent data is going, same address as previous symbol */ | 3763 | /* record where the persistent data is going, same address as previous symbol */ |
3820 | 3764 | ||
3821 | if (f->persist) { | 3765 | if (f->persist) { |
3822 | l = sizeof(symprefix)+ /* "__insmod_" */ | 3766 | l = sizeof(symprefix) + /* "__insmod_" */ |
3823 | lm_name+ /* module name */ | 3767 | lm_name + /* module name */ |
3824 | 2+ /* "_P" */ | 3768 | 2 + /* "_P" */ |
3825 | strlen(f->persist)+ /* data store */ | 3769 | strlen(f->persist) + /* data store */ |
3826 | 1; /* nul */ | 3770 | 1; /* nul */ |
3827 | name = xmalloc(l); | 3771 | name = xmalloc(l); |
3828 | snprintf(name, l, "%s%s_P%s", | 3772 | snprintf(name, l, "%s%s_P%s", |
3829 | symprefix, m_name, f->persist); | 3773 | symprefix, m_name, f->persist); |
@@ -3838,13 +3782,13 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename, | |||
3838 | for (i = 0; i < ARRAY_SIZE(section_names); ++i) { | 3782 | for (i = 0; i < ARRAY_SIZE(section_names); ++i) { |
3839 | sec = obj_find_section(f, section_names[i]); | 3783 | sec = obj_find_section(f, section_names[i]); |
3840 | if (sec && sec->header.sh_size) { | 3784 | if (sec && sec->header.sh_size) { |
3841 | l = sizeof(symprefix)+ /* "__insmod_" */ | 3785 | l = sizeof(symprefix) + /* "__insmod_" */ |
3842 | lm_name+ /* module name */ | 3786 | lm_name + /* module name */ |
3843 | 2+ /* "_S" */ | 3787 | 2 + /* "_S" */ |
3844 | strlen(sec->name)+ /* section name */ | 3788 | strlen(sec->name) + /* section name */ |
3845 | 2+ /* "_L" */ | 3789 | 2 + /* "_L" */ |
3846 | 8+ /* length in dec */ | 3790 | 8 + /* length in dec */ |
3847 | 1; /* nul */ | 3791 | 1; /* nul */ |
3848 | name = xmalloc(l); | 3792 | name = xmalloc(l); |
3849 | snprintf(name, l, "%s%s_S%s_L%ld", | 3793 | snprintf(name, l, "%s%s_S%s_L%ld", |
3850 | symprefix, m_name, sec->name, | 3794 | symprefix, m_name, sec->name, |
@@ -3891,9 +3835,10 @@ static void print_load_map(struct obj_file *f) | |||
3891 | #if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL | 3835 | #if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL |
3892 | /* Quick reference which section indicies are loaded. */ | 3836 | /* Quick reference which section indicies are loaded. */ |
3893 | 3837 | ||
3894 | loaded = alloca(sizeof(int) * (i = f->header.e_shnum)); | 3838 | i = f->header.e_shnum; |
3839 | loaded = alloca(sizeof(int) * i); | ||
3895 | while (--i >= 0) | 3840 | while (--i >= 0) |
3896 | loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0; | 3841 | loaded[i] = ((f->sections[i]->header.sh_flags & SHF_ALLOC) != 0); |
3897 | 3842 | ||
3898 | /* Collect the symbols we'll be listing. */ | 3843 | /* Collect the symbols we'll be listing. */ |
3899 | 3844 | ||
@@ -3963,7 +3908,7 @@ int insmod_main(int argc, char **argv) | |||
3963 | ElfW(Addr) m_addr; | 3908 | ElfW(Addr) m_addr; |
3964 | struct obj_file *f; | 3909 | struct obj_file *f; |
3965 | struct stat st; | 3910 | struct stat st; |
3966 | char *m_name = 0; | 3911 | char *m_name = NULL; |
3967 | int exit_status = EXIT_FAILURE; | 3912 | int exit_status = EXIT_FAILURE; |
3968 | int m_has_modinfo; | 3913 | int m_has_modinfo; |
3969 | #if ENABLE_FEATURE_INSMOD_VERSION_CHECKING | 3914 | #if ENABLE_FEATURE_INSMOD_VERSION_CHECKING |
@@ -4027,7 +3972,7 @@ int insmod_main(int argc, char **argv) | |||
4027 | m_name = tmp; | 3972 | m_name = tmp; |
4028 | } else { | 3973 | } else { |
4029 | free(tmp1); | 3974 | free(tmp1); |
4030 | tmp1 = 0; /* flag for free(m_name) before exit() */ | 3975 | tmp1 = NULL; /* flag for free(m_name) before exit() */ |
4031 | } | 3976 | } |
4032 | 3977 | ||
4033 | /* Get a filedesc for the module. Check that we have a complete path */ | 3978 | /* Get a filedesc for the module. Check that we have a complete path */ |
@@ -4039,7 +3984,6 @@ int insmod_main(int argc, char **argv) | |||
4039 | if (k_version) { /* uname succeedd */ | 3984 | if (k_version) { /* uname succeedd */ |
4040 | char *module_dir; | 3985 | char *module_dir; |
4041 | char *tmdn; | 3986 | char *tmdn; |
4042 | char real_module_dir[FILENAME_MAX]; | ||
4043 | 3987 | ||
4044 | tmdn = concat_path_file(_PATH_MODULES, myuname.release); | 3988 | tmdn = concat_path_file(_PATH_MODULES, myuname.release); |
4045 | /* Jump through hoops in case /lib/modules/`uname -r` | 3989 | /* Jump through hoops in case /lib/modules/`uname -r` |
@@ -4047,36 +3991,37 @@ int insmod_main(int argc, char **argv) | |||
4047 | * follow symlinks, but we do want to follow the | 3991 | * follow symlinks, but we do want to follow the |
4048 | * /lib/modules/`uname -r` dir, So resolve it ourselves | 3992 | * /lib/modules/`uname -r` dir, So resolve it ourselves |
4049 | * if it is a link... */ | 3993 | * if it is a link... */ |
4050 | if (realpath(tmdn, real_module_dir) == NULL) | 3994 | module_dir = xmalloc_readlink(tmdn); |
4051 | module_dir = tmdn; | 3995 | if (!module_dir) |
4052 | else | 3996 | module_dir = xstrdup(tmdn); |
4053 | module_dir = real_module_dir; | ||
4054 | recursive_action(module_dir, ACTION_RECURSE, | 3997 | recursive_action(module_dir, ACTION_RECURSE, |
4055 | check_module_name_match, 0, m_fullName, 0); | 3998 | check_module_name_match, NULL, m_fullName, 0); |
3999 | free(module_dir); | ||
4056 | free(tmdn); | 4000 | free(tmdn); |
4057 | } | 4001 | } |
4058 | 4002 | ||
4059 | /* Check if we have found anything yet */ | 4003 | /* Check if we have found anything yet */ |
4060 | if (!m_filename || ((fp = fopen(m_filename, "r")) == NULL)) { | 4004 | if (!m_filename || ((fp = fopen(m_filename, "r")) == NULL)) { |
4061 | char module_dir[FILENAME_MAX]; | 4005 | int r; |
4006 | char *module_dir; | ||
4062 | 4007 | ||
4063 | free(m_filename); | 4008 | free(m_filename); |
4064 | m_filename = NULL; | 4009 | m_filename = NULL; |
4065 | if (realpath(_PATH_MODULES, module_dir) == NULL) | 4010 | module_dir = xmalloc_readlink(_PATH_MODULES); |
4066 | strcpy(module_dir, _PATH_MODULES); | 4011 | if (!module_dir) |
4012 | module_dir = xstrdup(_PATH_MODULES); | ||
4067 | /* No module found under /lib/modules/`uname -r`, this | 4013 | /* No module found under /lib/modules/`uname -r`, this |
4068 | * time cast the net a bit wider. Search /lib/modules/ */ | 4014 | * time cast the net a bit wider. Search /lib/modules/ */ |
4069 | if (!recursive_action(module_dir, ACTION_RECURSE, | 4015 | r = recursive_action(module_dir, ACTION_RECURSE, |
4070 | check_module_name_match, 0, m_fullName, 0) | 4016 | check_module_name_match, NULL, m_fullName, 0); |
4017 | if (r) | ||
4018 | bb_error_msg_and_die("%s: module not found", m_fullName); | ||
4019 | free(module_dir); | ||
4020 | if (m_filename == NULL | ||
4021 | || ((fp = fopen(m_filename, "r")) == NULL) | ||
4071 | ) { | 4022 | ) { |
4072 | if (m_filename == 0 | ||
4073 | || ((fp = fopen(m_filename, "r")) == NULL) | ||
4074 | ) { | ||
4075 | bb_error_msg("%s: module not found", m_fullName); | ||
4076 | goto out; | ||
4077 | } | ||
4078 | } else | ||
4079 | bb_error_msg_and_die("%s: module not found", m_fullName); | 4023 | bb_error_msg_and_die("%s: module not found", m_fullName); |
4024 | } | ||
4080 | } | 4025 | } |
4081 | } else | 4026 | } else |
4082 | m_filename = xstrdup(arg1); | 4027 | m_filename = xstrdup(arg1); |
@@ -4093,8 +4038,6 @@ int insmod_main(int argc, char **argv) | |||
4093 | #endif | 4038 | #endif |
4094 | 4039 | ||
4095 | f = obj_load(fp, LOADBITS); | 4040 | f = obj_load(fp, LOADBITS); |
4096 | if (f == NULL) | ||
4097 | bb_perror_msg_and_die("cannot load the module"); | ||
4098 | 4041 | ||
4099 | if (get_modinfo_value(f, "kernel_version") == NULL) | 4042 | if (get_modinfo_value(f, "kernel_version") == NULL) |
4100 | m_has_modinfo = 0; | 4043 | m_has_modinfo = 0; |
@@ -4109,9 +4052,8 @@ int insmod_main(int argc, char **argv) | |||
4109 | if (m_has_modinfo) { | 4052 | if (m_has_modinfo) { |
4110 | m_version = new_get_module_version(f, m_strversion); | 4053 | m_version = new_get_module_version(f, m_strversion); |
4111 | if (m_version == -1) { | 4054 | if (m_version == -1) { |
4112 | bb_error_msg("cannot find the kernel version the module was " | 4055 | bb_error_msg_and_die("cannot find the kernel version the module was " |
4113 | "compiled for"); | 4056 | "compiled for"); |
4114 | goto out; | ||
4115 | } | 4057 | } |
4116 | } | 4058 | } |
4117 | 4059 | ||
@@ -4128,14 +4070,10 @@ int insmod_main(int argc, char **argv) | |||
4128 | k_crcs = 0; | 4070 | k_crcs = 0; |
4129 | #endif /* FEATURE_INSMOD_VERSION_CHECKING */ | 4071 | #endif /* FEATURE_INSMOD_VERSION_CHECKING */ |
4130 | 4072 | ||
4131 | if (!query_module(NULL, 0, NULL, 0, NULL)) { | 4073 | if (query_module(NULL, 0, NULL, 0, NULL)) |
4132 | if (!new_get_kernel_symbols()) | 4074 | bb_error_msg_and_die("not configured to support old kernels"); |
4133 | goto out; | 4075 | new_get_kernel_symbols(); |
4134 | k_crcs = new_is_kernel_checksummed(); | 4076 | k_crcs = new_is_kernel_checksummed(); |
4135 | } else { | ||
4136 | bb_error_msg("not configured to support old kernels"); | ||
4137 | goto out; | ||
4138 | } | ||
4139 | 4077 | ||
4140 | #if ENABLE_FEATURE_INSMOD_VERSION_CHECKING | 4078 | #if ENABLE_FEATURE_INSMOD_VERSION_CHECKING |
4141 | m_crcs = 0; | 4079 | m_crcs = 0; |
@@ -4151,22 +4089,15 @@ int insmod_main(int argc, char **argv) | |||
4151 | 4089 | ||
4152 | /* Allocate common symbols, symbol tables, and string tables. */ | 4090 | /* Allocate common symbols, symbol tables, and string tables. */ |
4153 | 4091 | ||
4154 | if (!new_create_this_module(f, m_name)) { | 4092 | new_create_this_module(f, m_name); |
4155 | goto out; | 4093 | obj_check_undefineds(f); |
4156 | } | ||
4157 | |||
4158 | if (!obj_check_undefineds(f)) { | ||
4159 | goto out; | ||
4160 | } | ||
4161 | obj_allocate_commons(f); | 4094 | obj_allocate_commons(f); |
4162 | check_tainted_module(f, m_name); | 4095 | check_tainted_module(f, m_name); |
4163 | 4096 | ||
4164 | /* done with the module name, on to the optional var=value arguments */ | 4097 | /* done with the module name, on to the optional var=value arguments */ |
4165 | ++optind; | 4098 | ++optind; |
4166 | if (optind < argc) { | 4099 | if (optind < argc) { |
4167 | if (!new_process_module_arguments(f, argc - optind, argv + optind)) { | 4100 | new_process_module_arguments(f, argc - optind, argv + optind); |
4168 | goto out; | ||
4169 | } | ||
4170 | } | 4101 | } |
4171 | 4102 | ||
4172 | arch_create_got(f); | 4103 | arch_create_got(f); |
@@ -4181,22 +4112,18 @@ int insmod_main(int argc, char **argv) | |||
4181 | /* Find current size of the module */ | 4112 | /* Find current size of the module */ |
4182 | m_size = obj_load_size(f); | 4113 | m_size = obj_load_size(f); |
4183 | 4114 | ||
4184 | |||
4185 | m_addr = create_module(m_name, m_size); | 4115 | m_addr = create_module(m_name, m_size); |
4186 | if (m_addr == -1) switch (errno) { | 4116 | if (m_addr == -1) switch (errno) { |
4187 | case EEXIST: | 4117 | case EEXIST: |
4188 | bb_error_msg("a module named %s already exists", m_name); | 4118 | bb_error_msg_and_die("a module named %s already exists", m_name); |
4189 | goto out; | ||
4190 | case ENOMEM: | 4119 | case ENOMEM: |
4191 | bb_error_msg("can't allocate kernel memory for module; needed %lu bytes", | 4120 | bb_error_msg_and_die("can't allocate kernel memory for module; needed %lu bytes", |
4192 | m_size); | 4121 | m_size); |
4193 | goto out; | ||
4194 | default: | 4122 | default: |
4195 | bb_perror_msg("create_module: %s", m_name); | 4123 | bb_perror_msg_and_die("create_module: %s", m_name); |
4196 | goto out; | ||
4197 | } | 4124 | } |
4198 | 4125 | ||
4199 | #if !LOADBITS | 4126 | #if !LOADBITS |
4200 | /* | 4127 | /* |
4201 | * the PROGBITS section was not loaded by the obj_load | 4128 | * the PROGBITS section was not loaded by the obj_load |
4202 | * now we can load them directly into the kernel memory | 4129 | * now we can load them directly into the kernel memory |
@@ -4222,7 +4149,7 @@ int insmod_main(int argc, char **argv) | |||
4222 | 4149 | ||
4223 | exit_status = EXIT_SUCCESS; | 4150 | exit_status = EXIT_SUCCESS; |
4224 | 4151 | ||
4225 | out: | 4152 | out: |
4226 | #if ENABLE_FEATURE_CLEAN_UP | 4153 | #if ENABLE_FEATURE_CLEAN_UP |
4227 | if (fp) | 4154 | if (fp) |
4228 | fclose(fp); | 4155 | fclose(fp); |
@@ -4234,8 +4161,10 @@ out: | |||
4234 | return exit_status; | 4161 | return exit_status; |
4235 | } | 4162 | } |
4236 | 4163 | ||
4237 | 4164 | #endif /* ENABLE_FEATURE_2_4_MODULES */ | |
4238 | #endif | 4165 | /* |
4166 | * End of big piece of 2.4-specific code | ||
4167 | */ | ||
4239 | 4168 | ||
4240 | 4169 | ||
4241 | #if ENABLE_FEATURE_2_6_MODULES | 4170 | #if ENABLE_FEATURE_2_6_MODULES |
@@ -4249,20 +4178,24 @@ static const char *moderror(int err) | |||
4249 | { | 4178 | { |
4250 | switch (err) { | 4179 | switch (err) { |
4251 | case ENOEXEC: | 4180 | case ENOEXEC: |
4252 | return "Invalid module format"; | 4181 | return "invalid module format"; |
4253 | case ENOENT: | 4182 | case ENOENT: |
4254 | return "Unknown symbol in module"; | 4183 | return "unknown symbol in module"; |
4255 | case ESRCH: | 4184 | case ESRCH: |
4256 | return "Module has wrong symbol version"; | 4185 | return "module has wrong symbol version"; |
4257 | case EINVAL: | 4186 | case EINVAL: |
4258 | return "Invalid parameters"; | 4187 | return "invalid parameters"; |
4259 | default: | 4188 | default: |
4260 | return strerror(err); | 4189 | return strerror(err); |
4261 | } | 4190 | } |
4262 | } | 4191 | } |
4263 | 4192 | ||
4264 | int insmod_ng_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 4193 | #if !ENABLE_FEATURE_2_4_MODULES |
4265 | int insmod_ng_main(int argc, char **argv) | 4194 | int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
4195 | int insmod_main(int argc, char **argv) | ||
4196 | #else | ||
4197 | static int insmod_ng_main(int argc, char **argv) | ||
4198 | #endif | ||
4266 | { | 4199 | { |
4267 | long ret; | 4200 | long ret; |
4268 | size_t len; | 4201 | size_t len; |