Patch from Artem Egorkine to support the -m option
authorEric Andersen <andersen@codepoet.org>
Thu, 23 Jan 2003 04:57:35 +0000 (04:57 -0000)
committerEric Andersen <andersen@codepoet.org>
Thu, 23 Jan 2003 04:57:35 +0000 (04:57 -0000)
include/usage.h
modutils/Config.in
modutils/insmod.c

index e5aad2f4f1c9f57fabe39773d83ee3e8b5b10124..beb32fdc9097aaa101b6843a8576559c7d72582b 100644 (file)
 "      ::shutdown:/bin/umount -a -r\n" \
 "      ::shutdown:/sbin/swapoff -a\n"
 
+#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
+  #define USAGE_INSMOD_MAP(a) a
+#else
+  #define USAGE_INSMOD_MAP(a)
+#endif
 #define insmod_trivial_usage \
        "[OPTION]... MODULE [symbol=value]..."
 #define insmod_full_usage \
        "\t-k\tMake module autoclean-able.\n" \
        "\t-v\tverbose output\n"  \
        "\t-L\tLock to prevent simultaneous loads of a module\n" \
-       "\t-x\tdo not export externs"
+       USAGE_INSMOD_MAP("\t-m\tOutput load map to stdout") \
+       "\t-x\tdo not export externs\n"
 
 #define ip_trivial_usage \
        "[ OPTIONS ] { address | link | route | tunnel } { COMMAND | help }"
index 98aef003229c97ac358de741f48ce08aa07a890d..c634e393872b5feddbca0c2b2f504758c1749684 100644 (file)
@@ -58,6 +58,27 @@ config CONFIG_FEATURE_INSMOD_LOADINKMEM
        help
          Please submit a patch to add help text for this item.
 
+config CONFIG_FEATURE_INSMOD_LOAD_MAP
+       bool "  Enable load map (-m) option" 
+       default n
+       depends on CONFIG_INSMOD
+       help
+         Enabling this, one would be able to get a load map
+         output on stdout. This makes kernel module debugging
+         easier.
+         If you don't plan to debug kernel modules, you
+         don't need this option.
+
+config CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
+       bool "  Symbols in load map"
+       default y
+       depends on CONFIG_FEATURE_INSMOD_LOAD_MAP
+       help
+         Without this option, -m will only output section
+         load map.
+         With this option, -m will also output symbols
+         load map.
+
 config CONFIG_LSMOD
        bool "lsmod"
        default n
index db9e1997e52d56206af401b51a7e3938f4401561..af12f36a6ffd101bfe1c6d72b4631e3c2aad4f54 100644 (file)
 #ifndef MODUTILS_MODULE_H
 static const int MODUTILS_MODULE_H = 1;
 
-#ident "$Id: insmod.c,v 1.93 2003/01/23 04:48:34 andersen Exp $"
+#ident "$Id: insmod.c,v 1.94 2003/01/23 04:57:35 andersen Exp $"
 
 /* This file contains the structures used by the 2.0 and 2.1 kernels.
    We do not use the kernel headers directly because we do not wish
@@ -455,7 +455,7 @@ int delete_module(const char *);
 #ifndef MODUTILS_OBJ_H
 static const int MODUTILS_OBJ_H = 1;
 
-#ident "$Id: insmod.c,v 1.93 2003/01/23 04:48:34 andersen Exp $"
+#ident "$Id: insmod.c,v 1.94 2003/01/23 04:57:35 andersen Exp $"
 
 /* The relocatable object is manipulated using elfin types.  */
 
@@ -3706,6 +3706,98 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename,
 }
 #endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
 
+#ifdef CONFIG_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;
+       int i, nsyms, *loaded;
+
+       /* Report on the section layout.  */
+
+       printf("Sections:       Size      %-*s  Align\n",
+                       (int) (2 * sizeof(void *)), "Address");
+
+       for (sec = f->load_order; sec; sec = sec->load_next) {
+               int a;
+               unsigned long tmp;
+
+               for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
+                       tmp >>= 1;
+               if (a == -1)
+                       a = 0;
+
+               printf("%-15s %08lx  %0*lx  2**%d\n",
+                               sec->name,
+                               (long)sec->header.sh_size,
+                               (int) (2 * sizeof(void *)),
+                               (long)sec->header.sh_addr,
+                               a);
+       }
+#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
+       /* Quick reference which section indicies are loaded.  */
+
+       loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
+       while (--i >= 0)
+               loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
+
+       /* Collect the symbols we'll be listing.  */
+
+       for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
+               for (sym = f->symtab[i]; sym; sym = sym->next)
+                       if (sym->secidx <= SHN_HIRESERVE
+                                       && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
+                               ++nsyms;
+
+       all = alloca(nsyms * sizeof(struct obj_symbol *));
+
+       for (i = 0, p = all; i < HASH_BUCKETS; ++i)
+               for (sym = f->symtab[i]; sym; sym = sym->next)
+                       if (sym->secidx <= SHN_HIRESERVE
+                                       && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
+                               *p++ = sym;
+
+       /* And list them.  */
+       printf("\nSymbols:\n");
+       for (p = all; p < all + nsyms; ++p) {
+               char type = '?';
+               unsigned long value;
+
+               sym = *p;
+               if (sym->secidx == SHN_ABS) {
+                       type = 'A';
+                       value = sym->value;
+               } else if (sym->secidx == SHN_UNDEF) {
+                       type = 'U';
+                       value = 0;
+               } else {
+                       sec = f->sections[sym->secidx];
+
+                       if (sec->header.sh_type == SHT_NOBITS)
+                               type = 'B';
+                       else if (sec->header.sh_flags & SHF_ALLOC) {
+                               if (sec->header.sh_flags & SHF_EXECINSTR)
+                                       type = 'T';
+                               else if (sec->header.sh_flags & SHF_WRITE)
+                                       type = 'D';
+                               else
+                                       type = 'R';
+                       }
+                       value = sym->value + sec->header.sh_addr;
+               }
+
+               if (ELFW(ST_BIND) (sym->info) == STB_LOCAL)
+                       type = tolower(type);
+
+               printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
+                               type, sym->name);
+       }
+#endif
+}
+
+#endif
+
 extern int insmod_main( int argc, char **argv)
 {
        int opt;
@@ -3731,9 +3823,16 @@ extern int insmod_main( int argc, char **argv)
 #else
        FILE *fp;
 #endif
+#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
+       int flag_print_load_map = 0;
+#endif
 
        /* Parse any options */
+#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
+       while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0) {
+#else
        while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0) {
+#endif
                switch (opt) {
                        case 'f':                       /* force loading */
                                flag_force_load = 1;
@@ -3766,6 +3865,11 @@ extern int insmod_main( int argc, char **argv)
                                 * that.  So be careful and plan your life around not
                                 * loading the same module 50 times concurrently. */
                                break;
+#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
+                       case 'm':                       /* print module load map */
+                               flag_print_load_map = 1;
+                               break;
+#endif
                        default:
                                show_usage();
                }
@@ -4005,6 +4109,11 @@ extern int insmod_main( int argc, char **argv)
                goto out;
        }
 
+#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
+       if(flag_print_load_map)
+               print_load_map(f);
+#endif
+
        exit_status = EXIT_SUCCESS;
 
 out: