setsebool: new applet (Yuichi Nakamura <ynakam@hitachisoft.jp>)
[oweals/busybox.git] / modutils / insmod.c
index 882fcf80f6d67036439c994b562e6cc249cdadb0..6f3b7d0f46383441d086129e19481bc1515cf6b2 100644 (file)
@@ -40,7 +40,7 @@
  *   PowerPC specific code stolen from modutils-2.3.16,
  *   written by Paul Mackerras, Copyright 1996, 1997 Linux International.
  *   I've only tested the code on mpc8xx platforms in big-endian mode.
- *   Did some cleanup and added CONFIG_USE_xxx_ENTRIES...
+ *   Did some cleanup and added USE_xxx_ENTRIES...
  *
  * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001.
  *   based on modutils-2.4.2
  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  */
 
-#include "busybox.h"
+#include "libbb.h"
 #include <libgen.h>
 #include <sys/utsname.h>
 
-#if !defined(CONFIG_FEATURE_2_4_MODULES) && \
-       !defined(CONFIG_FEATURE_2_6_MODULES)
-#define CONFIG_FEATURE_2_4_MODULES
+#if !ENABLE_FEATURE_2_4_MODULES && !ENABLE_FEATURE_2_6_MODULES
+#undef ENABLE_FEATURE_2_4_MODULES
+#define ENABLE_FEATURE_2_4_MODULES 1
 #endif
 
-#if !defined(CONFIG_FEATURE_2_4_MODULES)
+#if !ENABLE_FEATURE_2_4_MODULES
 #define insmod_ng_main insmod_main
 #endif
 
-#if defined(CONFIG_FEATURE_2_6_MODULES)
-extern int insmod_ng_main( int argc, char **argv);
+#if ENABLE_FEATURE_2_6_MODULES
+extern int insmod_ng_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 #endif
 
 
-#if defined(CONFIG_FEATURE_2_4_MODULES)
+#if ENABLE_FEATURE_2_4_MODULES
 
 
-#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
+#if ENABLE_FEATURE_INSMOD_LOADINKMEM
 #define LOADBITS 0
 #else
 #define LOADBITS 1
@@ -100,11 +100,11 @@ extern int insmod_ng_main( int argc, char **argv);
 #define SHT_RELM       SHT_REL
 #define Elf32_RelM     Elf32_Rel
 #define ELFCLASSM      ELFCLASS32
-#define CONFIG_USE_PLT_ENTRIES
-#define CONFIG_PLT_ENTRY_SIZE 8
-#define CONFIG_USE_GOT_ENTRIES
-#define CONFIG_GOT_ENTRY_SIZE 8
-#define CONFIG_USE_SINGLE
+#define USE_PLT_ENTRIES
+#define PLT_ENTRY_SIZE 8
+#define USE_GOT_ENTRIES
+#define GOT_ENTRY_SIZE 8
+#define USE_SINGLE
 #endif
 
 /* blackfin */
@@ -134,7 +134,7 @@ extern int insmod_ng_main( int argc, char **argv);
 #define SHT_RELM       SHT_RELA
 #define Elf32_RelM     Elf32_Rela
 #define ELFCLASSM      ELFCLASS32
-#define CONFIG_USE_SINGLE
+#define USE_SINGLE
 #define SYMBOL_PREFIX  "_"
 #endif
 
@@ -161,9 +161,9 @@ extern int insmod_ng_main( int argc, char **argv);
 #define SHT_RELM       SHT_REL
 #define Elf32_RelM     Elf32_Rel
 #define ELFCLASSM      ELFCLASS32
-#define CONFIG_USE_GOT_ENTRIES
-#define CONFIG_GOT_ENTRY_SIZE 4
-#define CONFIG_USE_SINGLE
+#define USE_GOT_ENTRIES
+#define GOT_ENTRY_SIZE 4
+#define USE_SINGLE
 #endif
 
 /* IA64, aka Itanium */
@@ -180,14 +180,14 @@ extern int insmod_ng_main( int argc, char **argv);
 #define SHT_RELM       SHT_RELA
 #define Elf32_RelM     Elf32_Rela
 #define ELFCLASSM      ELFCLASS32
-#define CONFIG_USE_GOT_ENTRIES
-#define CONFIG_GOT_ENTRY_SIZE 4
-#define CONFIG_USE_SINGLE
+#define USE_GOT_ENTRIES
+#define GOT_ENTRY_SIZE 4
+#define USE_SINGLE
 #endif
 
 /* Microblaze */
 #if defined(__microblaze__)
-#define CONFIG_USE_SINGLE
+#define USE_SINGLE
 #define MATCH_MACHINE(x) (x == EM_XILINX_MICROBLAZE)
 #define SHT_RELM       SHT_RELA
 #define Elf32_RelM     Elf32_Rela
@@ -230,11 +230,11 @@ extern int insmod_ng_main( int argc, char **argv);
 #define SHT_RELM       SHT_RELA
 #define Elf32_RelM     Elf32_Rela
 #define ELFCLASSM      ELFCLASS32
-#define CONFIG_USE_PLT_ENTRIES
-#define CONFIG_PLT_ENTRY_SIZE 16
-#define CONFIG_USE_PLT_LIST
-#define CONFIG_LIST_ARCHTYPE ElfW(Addr)
-#define CONFIG_USE_LIST
+#define USE_PLT_ENTRIES
+#define PLT_ENTRY_SIZE 16
+#define USE_PLT_LIST
+#define LIST_ARCHTYPE ElfW(Addr)
+#define USE_LIST
 #define ARCHDATAM       "__ftr_fixup"
 #endif
 
@@ -244,11 +244,11 @@ extern int insmod_ng_main( int argc, char **argv);
 #define SHT_RELM       SHT_RELA
 #define Elf32_RelM     Elf32_Rela
 #define ELFCLASSM      ELFCLASS32
-#define CONFIG_USE_PLT_ENTRIES
-#define CONFIG_PLT_ENTRY_SIZE 8
-#define CONFIG_USE_GOT_ENTRIES
-#define CONFIG_GOT_ENTRY_SIZE 8
-#define CONFIG_USE_SINGLE
+#define USE_PLT_ENTRIES
+#define PLT_ENTRY_SIZE 8
+#define USE_GOT_ENTRIES
+#define GOT_ENTRY_SIZE 8
+#define USE_SINGLE
 #endif
 
 /* SuperH */
@@ -257,9 +257,9 @@ extern int insmod_ng_main( int argc, char **argv);
 #define SHT_RELM       SHT_RELA
 #define Elf32_RelM     Elf32_Rela
 #define ELFCLASSM      ELFCLASS32
-#define CONFIG_USE_GOT_ENTRIES
-#define CONFIG_GOT_ENTRY_SIZE 4
-#define CONFIG_USE_SINGLE
+#define USE_GOT_ENTRIES
+#define GOT_ENTRY_SIZE 4
+#define USE_SINGLE
 /* the SH changes have only been tested in =little endian= mode */
 /* I'm not sure about big endian, so let's warn: */
 #if defined(__sh__) && BB_BIG_ENDIAN
@@ -280,14 +280,14 @@ extern int insmod_ng_main( int argc, char **argv);
 #endif
 
 /* v850e */
-#if defined (__v850e__)
+#if defined(__v850e__)
 #define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
 #define SHT_RELM       SHT_RELA
 #define Elf32_RelM     Elf32_Rela
 #define ELFCLASSM      ELFCLASS32
-#define CONFIG_USE_PLT_ENTRIES
-#define CONFIG_PLT_ENTRY_SIZE 8
-#define CONFIG_USE_SINGLE
+#define USE_PLT_ENTRIES
+#define PLT_ENTRY_SIZE 8
+#define USE_SINGLE
 #ifndef EM_CYGNUS_V850 /* grumble */
 #define EM_CYGNUS_V850 0x9080
 #endif
@@ -298,9 +298,9 @@ extern int insmod_ng_main( int argc, char **argv);
 #if defined(__x86_64__)
 #define MATCH_MACHINE(x) (x == EM_X86_64)
 #define SHT_RELM       SHT_RELA
-#define CONFIG_USE_GOT_ENTRIES
-#define CONFIG_GOT_ENTRY_SIZE 8
-#define CONFIG_USE_SINGLE
+#define USE_GOT_ENTRIES
+#define GOT_ENTRY_SIZE 8
+#define USE_SINGLE
 #define Elf64_RelM     Elf64_Rela
 #define ELFCLASSM      ELFCLASS64
 #endif
@@ -337,7 +337,6 @@ extern int insmod_ng_main( int argc, char **argv);
 
 
 #ifndef MODUTILS_MODULE_H
-/* Why? static const int MODUTILS_MODULE_H = 1;*/
 
 /*======================================================================*/
 /* For sizeof() which are related to the module platform and not to the
@@ -494,11 +493,9 @@ int delete_module(const char *);
 
 
 #ifndef MODUTILS_OBJ_H
-/* Why? static const int MODUTILS_OBJ_H = 1; */
 
 /* The relocatable object is manipulated using elfin types.  */
 
-#include <stdio.h>
 #include <elf.h>
 #include <endian.h>
 
@@ -600,35 +597,35 @@ static unsigned long obj_elf_hash(const char *);
 
 static unsigned long obj_elf_hash_n(const char *, unsigned long len);
 
-static struct obj_symbol *obj_find_symbol (struct obj_file *f,
+static struct obj_symbol *obj_find_symbol(struct obj_file *f,
                                         const char *name);
 
 static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
                                  struct obj_symbol *sym);
 
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
 static void obj_set_symbol_compare(struct obj_file *f,
                            int (*cmp)(const char *, const char *),
                            unsigned long (*hash)(const char *));
 #endif
 
-static struct obj_section *obj_find_section (struct obj_file *f,
+static struct obj_section *obj_find_section(struct obj_file *f,
                                           const char *name);
 
-static void obj_insert_section_load_order (struct obj_file *f,
+static void obj_insert_section_load_order(struct obj_file *f,
                                    struct obj_section *sec);
 
-static struct obj_section *obj_create_alloced_section (struct obj_file *f,
+static struct obj_section *obj_create_alloced_section(struct obj_file *f,
                                                const char *name,
                                                unsigned long align,
                                                unsigned long size);
 
-static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
+static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
                                                      const char *name,
                                                      unsigned long align,
                                                      unsigned long size);
 
-static void *obj_extend_section (struct obj_section *sec, unsigned long more);
+static void *obj_extend_section(struct obj_section *sec, unsigned long more);
 
 static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
                     const char *string);
@@ -640,32 +637,32 @@ static int obj_check_undefineds(struct obj_file *f);
 
 static void obj_allocate_commons(struct obj_file *f);
 
-static unsigned long obj_load_size (struct obj_file *f);
+static unsigned long obj_load_size(struct obj_file *f);
 
-static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
+static int obj_relocate(struct obj_file *f, ElfW(Addr) base);
 
 static struct obj_file *obj_load(FILE *f, int loadprogbits);
 
-static int obj_create_image (struct obj_file *f, char *image);
+static int obj_create_image(struct obj_file *f, char *image);
 
 /* Architecture specific manipulation routines.  */
 
-static struct obj_file *arch_new_file (void);
+static struct obj_file *arch_new_file(void);
 
-static struct obj_section *arch_new_section (void);
+static struct obj_section *arch_new_section(void);
 
-static struct obj_symbol *arch_new_symbol (void);
+static struct obj_symbol *arch_new_symbol(void);
 
-static enum obj_reloc arch_apply_relocation (struct obj_file *f,
+static enum obj_reloc arch_apply_relocation(struct obj_file *f,
                                      struct obj_section *targsec,
                                      struct obj_section *symsec,
                                      struct obj_symbol *sym,
                                      ElfW(RelM) *rel, ElfW(Addr) value);
 
-static void arch_create_got (struct obj_file *f);
+static void arch_create_got(struct obj_file *f);
 #if ENABLE_FEATURE_CHECK_TAINTED_MODULE
 static int obj_gpl_license(struct obj_file *f, const char **license);
-#endif /* ENABLE_FEATURE_CHECK_TAINTED_MODULE */
+#endif /* FEATURE_CHECK_TAINTED_MODULE */
 #endif /* obj.h */
 //----------------------------------------------------------------------------
 //--------end of modutils obj.h
@@ -681,7 +678,7 @@ static int obj_gpl_license(struct obj_file *f, const char **license);
 
 
 #define _PATH_MODULES  "/lib/modules"
-enum { STRVERSIONLEN = 32 };
+enum { STRVERSIONLEN = 64 };
 
 /*======================================================================*/
 
@@ -709,7 +706,7 @@ enum {
 #define flag_verbose (option_mask32 & OPT_v)
 #define flag_quiet (option_mask32 & OPT_q)
 #define flag_noexport (option_mask32 & OPT_x)
-#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
+#if ENABLE_FEATURE_INSMOD_LOAD_MAP
 #define flag_print_load_map (option_mask32 & OPT_m)
 #else
 #define flag_print_load_map 0
@@ -717,19 +714,19 @@ enum {
 
 /*======================================================================*/
 
-#if defined(CONFIG_USE_LIST)
+#if defined(USE_LIST)
 
 struct arch_list_entry
 {
        struct arch_list_entry *next;
-       CONFIG_LIST_ARCHTYPE addend;
+       LIST_ARCHTYPE addend;
        int offset;
        int inited : 1;
 };
 
 #endif
 
-#if defined(CONFIG_USE_SINGLE)
+#if defined(USE_SINGLE)
 
 struct arch_single_entry
 {
@@ -751,10 +748,10 @@ struct mips_hi16
 
 struct arch_file {
        struct obj_file root;
-#if defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_PLT_ENTRIES)
        struct obj_section *plt;
 #endif
-#if defined(CONFIG_USE_GOT_ENTRIES)
+#if defined(USE_GOT_ENTRIES)
        struct obj_section *got;
 #endif
 #if defined(__mips__)
@@ -764,14 +761,14 @@ struct arch_file {
 
 struct arch_symbol {
        struct obj_symbol root;
-#if defined(CONFIG_USE_PLT_ENTRIES)
-#if defined(CONFIG_USE_PLT_LIST)
+#if defined(USE_PLT_ENTRIES)
+#if defined(USE_PLT_LIST)
        struct arch_list_entry *pltent;
 #else
        struct arch_single_entry pltent;
 #endif
 #endif
-#if defined(CONFIG_USE_GOT_ENTRIES)
+#if defined(USE_GOT_ENTRIES)
        struct arch_single_entry gotent;
 #endif
 };
@@ -801,24 +798,24 @@ static char *m_fullName;
 
 
 static int check_module_name_match(const char *filename, struct stat *statbuf,
-                               void *userdata)
+                               void *userdata, int depth)
 {
        char *fullname = (char *) userdata;
 
        if (fullname[0] == '\0')
-               return (FALSE);
+               return FALSE;
        else {
                char *tmp, *tmp1 = xstrdup(filename);
-               tmp = bb_get_last_path_component(tmp1);
+               tmp = bb_get_last_path_component_nostrip(tmp1);
                if (strcmp(tmp, fullname) == 0) {
                        free(tmp1);
                        /* Stop searching if we find a match */
                        m_filename = xstrdup(filename);
-                       return (FALSE);
+                       return FALSE;
                }
                free(tmp1);
        }
-       return (TRUE);
+       return TRUE;
 }
 
 
@@ -860,18 +857,18 @@ arch_apply_relocation(struct obj_file *f,
        enum obj_reloc ret = obj_reloc_ok;
        ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
        ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
-#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
        struct arch_symbol *isym = (struct arch_symbol *) sym;
 #endif
 #if defined(__arm__) || defined(__i386__) || defined(__mc68000__) || defined(__sh__) || defined(__s390__)
-#if defined(CONFIG_USE_GOT_ENTRIES)
+#if defined(USE_GOT_ENTRIES)
        ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
 #endif
 #endif
-#if defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_PLT_ENTRIES)
        ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
        unsigned long *ip;
-# if defined(CONFIG_USE_PLT_LIST)
+# if defined(USE_PLT_LIST)
        struct arch_list_entry *pe;
 # else
        struct arch_single_entry *pe;
@@ -984,7 +981,7 @@ arch_apply_relocation(struct obj_file *f,
                        *loc += v - got;
                        break;
 
-#elif defined (__microblaze__)
+#elif defined(__microblaze__)
                case R_MICROBLAZE_NONE:
                case R_MICROBLAZE_64_NONE:
                case R_MICROBLAZE_32_SYM_OP_SYM:
@@ -1132,7 +1129,7 @@ arch_apply_relocation(struct obj_file *f,
                                /* We cannot relocate this one now because we don't know the value
                                   of the carry we need to add.  Save the information, and let LO16
                                   do the actual relocation.  */
-                               n = (struct mips_hi16 *) xmalloc(sizeof *n);
+                               n = xmalloc(sizeof *n);
                                n->addr = loc;
                                n->value = v;
                                n->next = ifile->mips_hi16_list;
@@ -1542,7 +1539,7 @@ arch_apply_relocation(struct obj_file *f,
                        }
 # endif /* __SH5__ */
 
-#elif defined (__v850e__)
+#elif defined(__v850e__)
 
                case R_V850_NONE:
                        break;
@@ -1637,13 +1634,13 @@ arch_apply_relocation(struct obj_file *f,
                        ret = obj_reloc_unhandled;
                        break;
 
-#if defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_PLT_ENTRIES)
 
 bb_use_plt:
 
                        /* find the plt entry and initialize it if necessary */
 
-#if defined(CONFIG_USE_PLT_LIST)
+#if defined(USE_PLT_LIST)
                        for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
                                pe = pe->next;
 #else
@@ -1665,7 +1662,7 @@ bb_use_plt:
                                ip[2] = 0x7d6903a6;                           /* mtctr r11 */
                                ip[3] = 0x4e800420;                           /* bctr */
 #endif
-#if defined (__v850e__)
+#if defined(__v850e__)
                                /* We have to trash a register, so we assume that any control
                                   transfer more than 21-bits away must be a function call
                                   (so we can use a call-clobbered register).  */
@@ -1678,15 +1675,15 @@ bb_use_plt:
                        /* relative distance to target */
                        v -= dot;
                        /* if the target is too far away.... */
-#if defined (__arm__) || defined (__powerpc__)
+#if defined(__arm__) || defined(__powerpc__)
                        if ((int)v < -0x02000000 || (int)v >= 0x02000000)
-#elif defined (__v850e__)
+#elif defined(__v850e__)
                                if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
 #endif
                                        /* go via the plt */
                                        v = plt + pe->offset - dot;
 
-#if defined (__v850e__)
+#if defined(__v850e__)
                        if (v & 1)
 #else
                                if (v & 3)
@@ -1703,7 +1700,7 @@ bb_use_plt:
 #if defined(__powerpc__)
                        *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
 #endif
-#if defined (__v850e__)
+#if defined(__v850e__)
                        /* We write two shorts instead of a long because even 32-bit insns
                           only need half-word alignment, but the 32-bit data write needs
                           to be long-word aligned.  */
@@ -1714,9 +1711,9 @@ bb_use_plt:
                                (v & 0xffff);                    /* offs low part */
 #endif
                        break;
-#endif /* CONFIG_USE_PLT_ENTRIES */
+#endif /* USE_PLT_ENTRIES */
 
-#if defined(CONFIG_USE_GOT_ENTRIES)
+#if defined(USE_GOT_ENTRIES)
 bb_use_got:
 
                        /* needs an entry in the .got: set it, once */
@@ -1732,14 +1729,14 @@ bb_use_got:
 #endif
                        break;
 
-#endif /* CONFIG_USE_GOT_ENTRIES */
+#endif /* USE_GOT_ENTRIES */
        }
 
        return ret;
 }
 
 
-#if defined(CONFIG_USE_LIST)
+#if defined(USE_LIST)
 
 static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
                          int offset, int size)
@@ -1766,7 +1763,7 @@ static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
 
 #endif
 
-#if defined(CONFIG_USE_SINGLE)
+#if defined(USE_SINGLE)
 
 static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
                             int offset, int size)
@@ -1782,9 +1779,9 @@ static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
 
 #endif
 
-#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
 
-static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
+static struct obj_section *arch_xsect_init(struct obj_file *f, const char *name,
                                           int offset, int size)
 {
        struct obj_section *myrelsec = obj_find_section(f, name);
@@ -1807,13 +1804,13 @@ static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
 
 static void arch_create_got(struct obj_file *f)
 {
-#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
        struct arch_file *ifile = (struct arch_file *) f;
        int i;
-#if defined(CONFIG_USE_GOT_ENTRIES)
+#if defined(USE_GOT_ENTRIES)
        int got_offset = 0, got_needed = 0, got_allocate;
 #endif
-#if defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_PLT_ENTRIES)
        int plt_offset = 0, plt_needed = 0, plt_allocate;
 #endif
        struct obj_section *relsec, *symsec, *strsec;
@@ -1838,10 +1835,10 @@ static void arch_create_got(struct obj_file *f)
                for (; rel < relend; ++rel) {
                        extsym = &symtab[ELF_R_SYM(rel->r_info)];
 
-#if defined(CONFIG_USE_GOT_ENTRIES)
+#if defined(USE_GOT_ENTRIES)
                        got_allocate = 0;
 #endif
-#if defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_PLT_ENTRIES)
                        plt_allocate = 0;
 #endif
 
@@ -1897,7 +1894,7 @@ static void arch_create_got(struct obj_file *f)
                                got_needed = 1;
                                continue;
 
-#elif defined (__v850e__)
+#elif defined(__v850e__)
                        case R_V850_22_PCREL:
                                plt_needed = 1;
                                break;
@@ -1913,25 +1910,25 @@ static void arch_create_got(struct obj_file *f)
                                name = f->sections[extsym->st_shndx]->name;
                        }
                        intsym = (struct arch_symbol *) obj_find_symbol(f, name);
-#if defined(CONFIG_USE_GOT_ENTRIES)
+#if defined(USE_GOT_ENTRIES)
                        if (got_allocate) {
                                got_offset += arch_single_init(
                                                rel, &intsym->gotent,
-                                               got_offset, CONFIG_GOT_ENTRY_SIZE);
+                                               got_offset, GOT_ENTRY_SIZE);
 
                                got_needed = 1;
                        }
 #endif
-#if defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_PLT_ENTRIES)
                        if (plt_allocate) {
-#if defined(CONFIG_USE_PLT_LIST)
+#if defined(USE_PLT_LIST)
                                plt_offset += arch_list_add(
                                                rel, &intsym->pltent,
-                                               plt_offset, CONFIG_PLT_ENTRY_SIZE);
+                                               plt_offset, PLT_ENTRY_SIZE);
 #else
                                plt_offset += arch_single_init(
                                                rel, &intsym->pltent,
-                                               plt_offset, CONFIG_PLT_ENTRY_SIZE);
+                                               plt_offset, PLT_ENTRY_SIZE);
 #endif
                                plt_needed = 1;
                        }
@@ -1939,21 +1936,21 @@ static void arch_create_got(struct obj_file *f)
                }
        }
 
-#if defined(CONFIG_USE_GOT_ENTRIES)
+#if defined(USE_GOT_ENTRIES)
        if (got_needed) {
                ifile->got = arch_xsect_init(f, ".got", got_offset,
-                               CONFIG_GOT_ENTRY_SIZE);
+                               GOT_ENTRY_SIZE);
        }
 #endif
 
-#if defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_PLT_ENTRIES)
        if (plt_needed) {
                ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
-                               CONFIG_PLT_ENTRY_SIZE);
+                               PLT_ENTRY_SIZE);
        }
 #endif
 
-#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
+#endif /* defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) */
 }
 
 /*======================================================================*/
@@ -1982,7 +1979,7 @@ static unsigned long obj_elf_hash(const char *name)
        return obj_elf_hash_n(name, strlen(name));
 }
 
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
 /* String comparison for non-co-versioned kernel and module.  */
 
 static int ncv_strcmp(const char *a, const char *b)
@@ -2034,7 +2031,7 @@ obj_set_symbol_compare(struct obj_file *f,
        }
 }
 
-#endif                                                 /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+#endif /* FEATURE_INSMOD_VERSION_CHECKING */
 
 static struct obj_symbol *
 obj_add_symbol(struct obj_file *f, const char *name,
@@ -2281,7 +2278,7 @@ add_symbols_from( struct obj_file *f,
        char *name_buf = 0;
        size_t name_alloced_size = 0;
 #endif
-#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
+#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
        int gpl;
 
        gpl = obj_gpl_license(f, NULL) == 0;
@@ -2301,7 +2298,7 @@ add_symbols_from( struct obj_file *f,
                 * their references.
                 */
                if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
-#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
+#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
                        if (gpl)
                                s->name += 8;
                        else
@@ -2315,13 +2312,13 @@ add_symbols_from( struct obj_file *f,
                   kernel exports `C names', but module object files
                   reference `linker names').  */
                size_t extra = sizeof SYMBOL_PREFIX;
-               size_t name_size = strlen (name) + extra;
+               size_t name_size = strlen(name) + extra;
                if (name_size > name_alloced_size) {
                        name_alloced_size = name_size * 2;
-                       name_buf = alloca (name_alloced_size);
+                       name_buf = alloca(name_alloced_size);
                }
-               strcpy (name_buf, SYMBOL_PREFIX);
-               strcpy (name_buf + extra - 1, name);
+               strcpy(name_buf, SYMBOL_PREFIX);
+               strcpy(name_buf + extra - 1, name);
                name = name_buf;
 #endif /* SYMBOL_PREFIX */
 
@@ -2329,8 +2326,8 @@ add_symbols_from( struct obj_file *f,
                if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
 #ifdef SYMBOL_PREFIX
                        /* Put NAME_BUF into more permanent storage.  */
-                       name = xmalloc (name_size);
-                       strcpy (name, name_buf);
+                       name = xmalloc(name_size);
+                       strcpy(name, name_buf);
 #endif
                        sym = obj_add_symbol(f, name, -1,
                                        ELF_ST_INFO(STB_GLOBAL,
@@ -2353,10 +2350,14 @@ static void add_kernel_symbols(struct obj_file *f)
 
        /* Add module symbols first.  */
 
-       for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
+       for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m) {
                if (m->nsyms
-                               && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
-                                       m->nsyms)) m->used = 1, ++nused;
+                && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms, m->nsyms)
+               ) {
+                       m->used = 1;
+                       ++nused;
+               }
+       }
 
        n_ext_modules_used = nused;
 
@@ -2425,9 +2426,9 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv)
                }
 
 #ifdef SYMBOL_PREFIX
-               sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
-               strcpy (sym_name, SYMBOL_PREFIX);
-               strcat (sym_name, key);
+               sym_name = alloca(strlen(key) + sizeof SYMBOL_PREFIX);
+               strcpy(sym_name, SYMBOL_PREFIX);
+               strcat(sym_name, key);
 #else
                sym_name = key;
 #endif
@@ -2542,7 +2543,7 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv)
                                        } else {
                                                /* last string */
                                                str = q;
-                                               q = "";
+                                               q = (char*)"";
                                        }
                                }
 
@@ -2551,7 +2552,7 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv)
                                        obj_string_patch(f, sym->secidx, loc - contents, str);
                                        loc += tgt_sizeof_char_p;
                                } else {
-                                       /* Array of chars (in fact, matrix !) */
+                                       /* Array of chars (in fact, matrix!) */
                                        unsigned long charssize;        /* size of each member */
 
                                        /* Get the size of each member */
@@ -2637,7 +2638,7 @@ end_of_arg:
        return 1;
 }
 
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
 static int new_is_module_checksummed(struct obj_file *f)
 {
        const char *p = get_modinfo_value(f, "using_checksums");
@@ -2673,7 +2674,7 @@ new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
        return a << 16 | b << 8 | c;
 }
 
-#endif   /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+#endif   /* FEATURE_INSMOD_VERSION_CHECKING */
 
 
 /* Fetch the loaded modules, and all currently exported symbols.  */
@@ -2803,7 +2804,7 @@ static int new_create_this_module(struct obj_file *f, const char *m_name)
        return 1;
 }
 
-#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
+#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
 /* add an entry to the __ksymtab section, creating it if necessary */
 static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
 {
@@ -2826,14 +2827,14 @@ static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
        if (!sec)
                return;
        sec->header.sh_flags |= SHF_ALLOC;
-       sec->header.sh_addralign = tgt_sizeof_void_p;   /* Empty section might
-                                                                                                          be byte-aligned */
+       /* Empty section might be byte-aligned */
+       sec->header.sh_addralign = tgt_sizeof_void_p;
        ofs = sec->header.sh_size;
        obj_symbol_patch(f, sec->idx, ofs, sym);
        obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
        obj_extend_section(sec, 2 * tgt_sizeof_char_p);
 }
-#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
+#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
 
 static int new_create_module_ksymtab(struct obj_file *f)
 {
@@ -3408,7 +3409,7 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
                sec->header = section_headers[i];
                sec->idx = i;
 
-               if(sec->header.sh_size) {
+               if (sec->header.sh_size) {
                        switch (sec->header.sh_type) {
                        case SHT_NULL:
                        case SHT_NOTE:
@@ -3552,7 +3553,7 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
        return f;
 }
 
-#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
+#if ENABLE_FEATURE_INSMOD_LOADINKMEM
 /*
  * load the unloaded sections directly into the memory allocated by
  * kernel for the module
@@ -3604,7 +3605,7 @@ static void hide_special_symbols(struct obj_file *f)
 }
 
 
-#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
+#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
 static int obj_gpl_license(struct obj_file *f, const char **license)
 {
        struct obj_section *sec;
@@ -3612,12 +3613,12 @@ static int obj_gpl_license(struct obj_file *f, const char **license)
         * linux/include/linux/module.h.  Checking for leading "GPL" will not
         * work, somebody will use "GPL sucks, this is proprietary".
         */
-       static const char * const gpl_licenses[] = {
+       static const char *const gpl_licenses[] = {
                "GPL",
                "GPL v2",
                "GPL and additional rights",
                "Dual BSD/GPL",
-               "Dual MPL/GPL",
+               "Dual MPL/GPL"
        };
 
        sec = obj_find_section(f, ".modinfo");
@@ -3631,11 +3632,11 @@ static int obj_gpl_license(struct obj_file *f, const char **license)
                                int i;
                                if (license)
                                        *license = value+1;
-                               for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
+                               for (i = 0; i < ARRAY_SIZE(gpl_licenses); ++i) {
                                        if (strcmp(value+1, gpl_licenses[i]) == 0)
-                                               return(0);
+                                               return 0;
                                }
-                               return(2);
+                               return 2;
                        }
                        if (strchr(ptr, '\0'))
                                ptr = strchr(ptr, '\0') + 1;
@@ -3643,7 +3644,7 @@ static int obj_gpl_license(struct obj_file *f, const char **license)
                                ptr = endptr;
                }
        }
-       return(1);
+       return 1;
 }
 
 #define TAINT_FILENAME                  "/proc/sys/kernel/tainted"
@@ -3655,16 +3656,18 @@ static int obj_gpl_license(struct obj_file *f, const char **license)
 static void set_tainted(struct obj_file *f, int fd, char *m_name,
                int kernel_has_tainted, int taint, const char *text1, const char *text2)
 {
+       static smallint printed_info;
+
        char buf[80];
        int oldval;
-       static int first = 1;
+
        if (fd < 0 && !kernel_has_tainted)
                return;         /* New modutils on old kernel */
        printf("Warning: loading %s will taint the kernel: %s%s\n",
                        m_name, text1, text2);
-       if (first) {
+       if (!printed_info) {
                printf("  See %s for information about tainted modules\n", TAINT_URL);
-               first = 0;
+               printed_info = 1;
        }
        if (fd >= 0) {
                read(fd, buf, sizeof(buf)-1);
@@ -3678,7 +3681,8 @@ static void set_tainted(struct obj_file *f, int fd, char *m_name,
 /* Check if loading this module will taint the kernel. */
 static void check_tainted_module(struct obj_file *f, char *m_name)
 {
-       static const char tainted_file[] = TAINT_FILENAME;
+       static const char tainted_file[] ALIGN1 = TAINT_FILENAME;
+
        int fd, kernel_has_tainted;
        const char *ptr;
 
@@ -3719,11 +3723,11 @@ static void check_tainted_module(struct obj_file *f, char *m_name)
        if (fd >= 0)
                close(fd);
 }
-#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
-#define check_tainted_module(x, y) do { } while(0);
-#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
+#else /* FEATURE_CHECK_TAINTED_MODULE */
+#define check_tainted_module(x, y) do { } while (0);
+#endif /* FEATURE_CHECK_TAINTED_MODULE */
 
-#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
+#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
 /* add module source, timestamp, kernel version and a symbol for the
  * start of some sections.  this info is used by ksymoops to do better
  * debugging.
@@ -3731,12 +3735,12 @@ static void check_tainted_module(struct obj_file *f, char *m_name)
 static int
 get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
 {
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
        return new_get_module_version(f, str);
-#else  /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+#else  /* FEATURE_INSMOD_VERSION_CHECKING */
        strncpy(str, "???", sizeof(str));
        return -1;
-#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+#endif /* FEATURE_INSMOD_VERSION_CHECKING */
 }
 
 /* add module source, timestamp, kernel version and a symbol for the
@@ -3747,7 +3751,8 @@ static void
 add_ksymoops_symbols(struct obj_file *f, const char *filename,
                                 const char *m_name)
 {
-       static const char symprefix[] = "__insmod_";
+       static const char symprefix[] ALIGN1 = "__insmod_";
+
        struct obj_section *sec;
        struct obj_symbol *sym;
        char *name, *absolute_filename;
@@ -3765,12 +3770,8 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename,
 
        if (realpath(filename, real)) {
                absolute_filename = xstrdup(real);
-       }
-       else {
-               int save_errno = errno;
-               bb_error_msg("cannot get realpath for %s", filename);
-               errno = save_errno;
-               perror("");
+       } else {
+               bb_perror_msg("cannot get realpath for %s", filename);
                absolute_filename = xstrdup(filename);
        }
 
@@ -3783,7 +3784,8 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename,
         */
        use_ksymtab = obj_find_section(f, "__ksymtab") || flag_noexport;
 
-       if ((sec = obj_find_section(f, ".this"))) {
+       sec = obj_find_section(f, ".this");
+       if (sec) {
                /* tag the module header with the object name, last modified
                 * timestamp and module version.  worst case for module version
                 * is 0xffffff, decimal 16777215.  putting all three fields in
@@ -3833,9 +3835,9 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename,
 #endif /* _NOT_SUPPORTED_ */
        /* tag the desired sections if size is non-zero */
 
-       for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
-               if ((sec = obj_find_section(f, section_names[i])) &&
-                               sec->header.sh_size) {
+       for (i = 0; i < ARRAY_SIZE(section_names); ++i) {
+               sec = obj_find_section(f, section_names[i]);
+               if (sec && sec->header.sh_size) {
                        l = sizeof(symprefix)+          /* "__insmod_" */
                                lm_name+                /* module name */
                                2+                      /* "_S" */
@@ -3854,16 +3856,17 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename,
                }
        }
 }
-#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
+#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
 
-#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
+#if ENABLE_FEATURE_INSMOD_LOAD_MAP
 static void print_load_map(struct obj_file *f)
 {
-       struct obj_symbol *sym;
-       struct obj_symbol **all, **p;
        struct obj_section *sec;
+#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
+       struct obj_symbol **all, **p;
        int i, nsyms, *loaded;
-
+       struct obj_symbol *sym;
+#endif
        /* Report on the section layout.  */
 
        printf("Sections:       Size      %-*s  Align\n",
@@ -3885,7 +3888,7 @@ static void print_load_map(struct obj_file *f)
                                (long)sec->header.sh_addr,
                                a);
        }
-#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
+#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
        /* Quick reference which section indicies are loaded.  */
 
        loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
@@ -3945,11 +3948,12 @@ static void print_load_map(struct obj_file *f)
        }
 #endif
 }
-#else /* !CONFIG_FEATURE_INSMOD_LOAD_MAP */
+#else /* !FEATURE_INSMOD_LOAD_MAP */
 void print_load_map(struct obj_file *f);
 #endif
 
-int insmod_main( int argc, char **argv)
+int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int insmod_main(int argc, char **argv)
 {
        char *opt_o, *arg1;
        int len;
@@ -3962,13 +3966,13 @@ int insmod_main( int argc, char **argv)
        char *m_name = 0;
        int exit_status = EXIT_FAILURE;
        int m_has_modinfo;
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
        struct utsname uts_info;
        char m_strversion[STRVERSIONLEN];
        int m_version, m_crcs;
 #endif
-#ifdef CONFIG_FEATURE_CLEAN_UP
-       FILE *fp = 0;
+#if ENABLE_FEATURE_CLEAN_UP
+       FILE *fp = NULL;
 #else
        FILE *fp;
 #endif
@@ -3976,7 +3980,7 @@ int insmod_main( int argc, char **argv)
        struct utsname myuname;
 
        /* Parse any options */
-       getopt32(argc, argv, OPTION_STR, &opt_o);
+       getopt32(argv, OPTION_STR, &opt_o);
        arg1 = argv[optind];
        if (option_mask32 & OPT_o) { // -o /* name the output module */
                free(m_name);
@@ -3998,7 +4002,7 @@ int insmod_main( int argc, char **argv)
                }
        }
 
-#if defined(CONFIG_FEATURE_2_6_MODULES)
+#if ENABLE_FEATURE_2_6_MODULES
        if (k_version > 4 && len > 3 && tmp[len - 3] == '.'
         && tmp[len - 2] == 'k' && tmp[len - 1] == 'o'
        ) {
@@ -4012,7 +4016,7 @@ int insmod_main( int argc, char **argv)
                }
 
 
-#if defined(CONFIG_FEATURE_2_6_MODULES)
+#if ENABLE_FEATURE_2_6_MODULES
        if (k_version > 4)
                m_fullName = xasprintf("%s.ko", tmp);
        else
@@ -4026,7 +4030,7 @@ int insmod_main( int argc, char **argv)
                tmp1 = 0;       /* flag for free(m_name) before exit() */
        }
 
-       /* Get a filedesc for the module.  Check we we have a complete path */
+       /* Get a filedesc for the module.  Check that we have a complete path */
        if (stat(arg1, &st) < 0 || !S_ISREG(st.st_mode)
         || (fp = fopen(arg1, "r")) == NULL
        ) {
@@ -4047,32 +4051,32 @@ int insmod_main( int argc, char **argv)
                                module_dir = tmdn;
                        else
                                module_dir = real_module_dir;
-                       recursive_action(module_dir, TRUE, FALSE, FALSE,
-                                       check_module_name_match, 0, m_fullName);
+                       recursive_action(module_dir, ACTION_RECURSE,
+                                       check_module_name_match, 0, m_fullName, 0);
                        free(tmdn);
                }
 
                /* Check if we have found anything yet */
-               if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL)) {
+               if (!m_filename || ((fp = fopen(m_filename, "r")) == NULL)) {
                        char module_dir[FILENAME_MAX];
 
                        free(m_filename);
-                       m_filename = 0;
-                       if (realpath (_PATH_MODULES, module_dir) == NULL)
+                       m_filename = NULL;
+                       if (realpath(_PATH_MODULES, module_dir) == NULL)
                                strcpy(module_dir, _PATH_MODULES);
                        /* No module found under /lib/modules/`uname -r`, this
                         * time cast the net a bit wider.  Search /lib/modules/ */
-                       if (!recursive_action(module_dir, TRUE, FALSE, FALSE,
-                                                   check_module_name_match, 0, m_fullName)
+                       if (!recursive_action(module_dir, ACTION_RECURSE,
+                                                   check_module_name_match, 0, m_fullName, 0)
                        ) {
                                if (m_filename == 0
                                 || ((fp = fopen(m_filename, "r")) == NULL)
                                ) {
-                                       bb_error_msg("%s: no module by that name found", m_fullName);
+                                       bb_error_msg("%s: module not found", m_fullName);
                                        goto out;
                                }
                        } else
-                               bb_error_msg_and_die("%s: no module by that name found", m_fullName);
+                               bb_error_msg_and_die("%s: module not found", m_fullName);
                }
        } else
                m_filename = xstrdup(arg1);
@@ -4080,7 +4084,7 @@ int insmod_main( int argc, char **argv)
        if (flag_verbose)
                printf("Using %s\n", m_filename);
 
-#ifdef CONFIG_FEATURE_2_6_MODULES
+#if ENABLE_FEATURE_2_6_MODULES
        if (k_version > 4) {
                argv[optind] = m_filename;
                optind--;
@@ -4097,7 +4101,7 @@ int insmod_main( int argc, char **argv)
        else
                m_has_modinfo = 1;
 
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
        /* Version correspondence?  */
        if (!flag_quiet) {
                if (uname(&uts_info) < 0)
@@ -4112,40 +4116,35 @@ int insmod_main( int argc, char **argv)
                }
 
                if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
-                       if (flag_force_load) {
-                               bb_error_msg("Warning: kernel-module version mismatch\n"
-                                               "\t%s was compiled for kernel version %s\n"
-                                               "\twhile this kernel is version %s",
-                                               m_filename, m_strversion, uts_info.release);
-                       } else {
-                               bb_error_msg("kernel-module version mismatch\n"
-                                               "\t%s was compiled for kernel version %s\n"
-                                               "\twhile this kernel is version %s.",
-                                               m_filename, m_strversion, uts_info.release);
+                       bb_error_msg("%skernel-module version mismatch\n"
+                               "\t%s was compiled for kernel version %s\n"
+                               "\twhile this kernel is version %s",
+                               flag_force_load ? "warning: " : "",
+                               m_filename, m_strversion, uts_info.release);
+                       if (!flag_force_load)
                                goto out;
-                       }
                }
        }
        k_crcs = 0;
-#endif                                                 /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+#endif /* FEATURE_INSMOD_VERSION_CHECKING */
 
        if (!query_module(NULL, 0, NULL, 0, NULL)) {
                if (!new_get_kernel_symbols())
                        goto out;
                k_crcs = new_is_kernel_checksummed();
        } else {
-               bb_error_msg("Not configured to support old kernels");
+               bb_error_msg("not configured to support old kernels");
                goto out;
        }
 
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
        m_crcs = 0;
        if (m_has_modinfo)
                m_crcs = new_is_module_checksummed(f);
 
        if (m_crcs != k_crcs)
                obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
-#endif                                                 /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+#endif /* FEATURE_INSMOD_VERSION_CHECKING */
 
        /* Let the module know about the kernel symbols.  */
        add_kernel_symbols(f);
@@ -4173,9 +4172,9 @@ int insmod_main( int argc, char **argv)
        arch_create_got(f);
        hide_special_symbols(f);
 
-#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
+#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
        add_ksymoops_symbols(f, m_filename, m_name);
-#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
+#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
 
        new_create_module_ksymtab(f);
 
@@ -4218,29 +4217,28 @@ int insmod_main( int argc, char **argv)
                goto out;
        }
 
-       if(flag_print_load_map)
+       if (flag_print_load_map)
                print_load_map(f);
 
        exit_status = EXIT_SUCCESS;
 
 out:
-#ifdef CONFIG_FEATURE_CLEAN_UP
-       if(fp)
+#if ENABLE_FEATURE_CLEAN_UP
+       if (fp)
                fclose(fp);
        free(tmp1);
-       if(!tmp1) {
+       if (!tmp1)
                free(m_name);
-       }
        free(m_filename);
 #endif
-       return(exit_status);
+       return exit_status;
 }
 
 
 #endif
 
 
-#ifdef CONFIG_FEATURE_2_6_MODULES
+#if ENABLE_FEATURE_2_6_MODULES
 
 #include <sys/mman.h>
 #include <asm/unistd.h>
@@ -4263,48 +4261,54 @@ static const char *moderror(int err)
        }
 }
 
-int insmod_ng_main( int argc, char **argv)
+int insmod_ng_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int insmod_ng_main(int argc, char **argv)
 {
-       int i;
-       int fd;
-       long int ret;
-       struct stat st;
-       unsigned long len;
+       long ret;
+       size_t len;
+       int optlen;
        void *map;
-       char *filename, *options = xstrdup("");
+       char *filename, *options;
 
-       filename = argv[1];
-       if (!filename) {
+       filename = *++argv;
+       if (!filename)
                bb_show_usage();
-               return -1;
-       }
 
        /* Rest is options */
-       for (i = 2; i < argc; i++) {
-               options = xrealloc(options, strlen(options) + 2 + strlen(argv[i]) + 2);
+       options = xzalloc(1);
+       optlen = 0;
+       while (*++argv) {
+               options = xrealloc(options, optlen + 2 + strlen(*argv) + 2);
                /* Spaces handled by "" pairs, but no way of escaping quotes */
-               if (strchr(argv[i], ' ')) {
-                       strcat(options, "\"");
-                       strcat(options, argv[i]);
-                       strcat(options, "\"");
-               } else {
-                       strcat(options, argv[i]);
-               }
-               strcat(options, " ");
+               optlen += sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv);
        }
 
+#if 0
+       /* Any special reason why mmap? It isn't performace critical... */
+       int fd;
+       struct stat st;
+       unsigned long len;
        fd = xopen(filename, O_RDONLY);
-
        fstat(fd, &st);
        len = st.st_size;
        map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
        if (map == MAP_FAILED) {
-               bb_perror_msg_and_die("cannot mmap `%s'", filename);
+               bb_perror_msg_and_die("cannot mmap '%s'", filename);
+       }
+
+       /* map == NULL on Blackfin, probably on other MMU-less systems too. Workaround. */
+       if (map == NULL) {
+               map = xmalloc(len);
+               xread(fd, map, len);
        }
+#else
+       len = MAXINT(ssize_t);
+       map = xmalloc_open_read_close(filename, &len);
+#endif
 
        ret = syscall(__NR_init_module, map, len, options);
        if (ret != 0) {
-               bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
+               bb_perror_msg_and_die("cannot insert '%s': %s (%li)",
                                filename, moderror(errno), ret);
        }