diff -x Makefile -ur crash-4.0-3.14/defs.h crash-4.0-3.14-sym/defs.h
--- crash-4.0-3.14/defs.h	2006-12-01 12:39:42 -08:00
+++ crash-4.0-3.14-sym/defs.h	2006-12-04 11:02:44 -08:00
@@ -1784,6 +1784,8 @@
 #define MOD_KALLSYMS    (0x8)
 #define MOD_INITRD     (0x10)
 
+#define SEC_FOUND       (0x10000)
+
 struct mod_section_data {
 #if defined(GDB_6_1)
         struct bfd_section *section;
diff -x Makefile -ur crash-4.0-3.14/gdb-6.1/gdb/symtab.c crash-4.0-3.14-sym/gdb-6.1/gdb/symtab.c
--- crash-4.0-3.14/gdb-6.1/gdb/symtab.c	2006-12-01 12:39:42 -08:00
+++ crash-4.0-3.14-sym/gdb-6.1/gdb/symtab.c	2006-12-04 11:02:44 -08:00
@@ -4529,8 +4529,12 @@
 	req->name = lm->mod_namelist;
 	gdb_delete_symbol_file(req);
 
-        sprintf(req->buf, "add-symbol-file %s 0x%lx", lm->mod_namelist, 
-		lm->mod_text_start);
+        sprintf(req->buf, "add-symbol-file %s 0x%lx "
+		"-s .data 0x%lx "
+		"-s .bss 0x%lx "
+		"-s .rodata 0x%lx", lm->mod_namelist, 
+		lm->mod_text_start, lm->mod_data_start, lm->mod_bss_start,
+		lm->mod_rodata_start);
 
        	execute_command(req->buf, FALSE);
 
diff -x Makefile -ur crash-4.0-3.14/kernel.c crash-4.0-3.14-sym/kernel.c
--- crash-4.0-3.14/kernel.c	2006-12-01 12:39:42 -08:00
+++ crash-4.0-3.14-sym/kernel.c	2006-12-04 11:02:44 -08:00
@@ -2660,16 +2660,20 @@
 		strcpy(file, filename);
 #ifdef MODULES_IN_CWD
        else {
-                sprintf(file, "%s.o", modref);
-                if (access(file, R_OK) == 0) {
-                        retbuf = GETBUF(strlen(file)+1);
-                        strcpy(retbuf, file);
-                        if (CRASHDEBUG(1))
-                            	fprintf(fp, 
-				    "find_module_objfile: [%s] file in cwd\n",
-                                	retbuf);
-                        return retbuf;
-                }
+		char *fileext[] = { "o", "ko"};
+		int i;
+		for (i = 0; i < 2; i++) {
+			sprintf(file, "%s.%s", modref, fileext[i]);
+			if (access(file, R_OK) == 0) {
+				retbuf = GETBUF(strlen(file)+1);
+				strcpy(retbuf, file);
+				if (CRASHDEBUG(1))
+					fprintf(fp, 
+					    "find_module_objfile: [%s] file in cwd\n",
+						retbuf);
+				return retbuf;
+			}
+		}
 	}
 #else
 	else 
diff -x Makefile -ur crash-4.0-3.14/symbols.c crash-4.0-3.14-sym/symbols.c
--- crash-4.0-3.14/symbols.c	2006-12-01 12:39:42 -08:00
+++ crash-4.0-3.14-sym/symbols.c	2006-12-04 11:10:28 -08:00
@@ -36,7 +36,9 @@
 static int load_module_index(struct syment *);
 static void section_header_info(bfd *, asection *, void *);
 static void store_section_data(struct load_module *, bfd *, asection *);
-static void calculate_load_order(struct load_module *, bfd *);
+static void calculate_load_order_v1(struct load_module *, bfd *);
+static void calculate_load_order_v2(struct load_module *, bfd *, int,
+        void *, long, unsigned int);
 static void check_insmod_builtin(struct load_module *, int, ulong *);
 static int is_insmod_builtin(struct load_module *, struct syment *);
 struct load_module;
@@ -7051,6 +7053,7 @@
 	lm->mod_section_data[i].priority = prio;
 	lm->mod_section_data[i].flags = section->flags;
 	lm->mod_section_data[i].size = bfd_section_size(bfd, section);
+	lm->mod_section_data[i].offset = 0;
 	if (strlen(name) < MAX_MOD_SEC_NAME)
 		strcpy(lm->mod_section_data[i].name, name);
 	else
@@ -7102,7 +7105,7 @@
  */
 
 static void
-calculate_load_order(struct load_module *lm, bfd *bfd)
+calculate_load_order_v1(struct load_module *lm, bfd *bfd)
 {
 	int i;
 	asection *section;
@@ -7162,6 +7165,116 @@
 }
 
 /*
+ * Later versions of kmod no longer get the help from insmod,
+ * and while the heuristics might work, it's relatively
+ * straightforward to just try to match the sections in the object file
+ * with exported symbols.
+ *
+ * This works well if kallsyms is set, but may not work so well in other
+ * instances.
+ */
+static void
+calculate_load_order_v2(struct load_module *lm, bfd *bfd, int dynamic,
+	void *minisyms, long symcount, unsigned int size)
+{
+	struct syment *s1, *s2;
+	ulong sec_start, sec_end;
+	bfd_byte *from, *fromend;
+	asymbol *store;
+	asymbol *sym;
+	symbol_info syminfo;
+	char *secname;
+	int i;
+
+	s1 = lm->mod_symtable;
+	s2 = lm->mod_symend;
+	while (s1 < s2) {
+            ulong sym_offset = s1->value - lm->mod_base;
+	    if (MODULE_PSEUDO_SYMBOL(s1)) {
+		    s1++;
+		    continue;
+	    }
+
+            /* Skip over symbols whose sections have been identified. */
+            for (i = 0; i < lm->mod_sections; i++) {
+                    if ((lm->mod_section_data[i].flags & SEC_FOUND) == 0)
+                            continue;
+                    if (sym_offset >= lm->mod_section_data[i].offset
+                        && sym_offset < lm->mod_section_data[i].offset
+                            + lm->mod_section_data[i].size) {
+                            s1++;
+                            continue;
+                    }
+            }
+
+	    /* Find the symbol in the object file. */
+	    from = (bfd_byte *) minisyms;
+	    fromend = from + symcount * size;
+	    secname = NULL;
+	    for (; from < fromend; from += size) {
+		    if ((sym = bfd_minisymbol_to_symbol(bfd, dynamic, from,
+			    store)) == NULL)
+			    error(FATAL,
+				    "bfd_minisymbol_to_symbol() failed\n");
+
+		    bfd_get_symbol_info(bfd, sym, &syminfo);
+		    if (strcmp(syminfo.name, s1->name) == 0) {
+			    secname = (char *)bfd_get_section_name(bfd, sym->section);
+			    break;
+		    }
+
+	    }
+	    if (secname == NULL) {
+                    if (CRASHDEBUG(1)) {
+                        fprintf(fp, "symbol %s not found in module\n", s1->name);
+                    }
+		    s1++;
+		    continue;
+	    }
+
+	    /* Match the section it came in. */
+	    for (i = 0; i < lm->mod_sections; i++) {
+		    if (STREQ(lm->mod_section_data[i].name, secname)) {
+			    break;
+		    }
+	    }
+
+	    if (i == lm->mod_sections) {
+		    fprintf(fp, "?? Section not found for symbol %s\n",
+			s1->name);
+		    s1++;
+		    continue;
+	    }
+
+            /* Update the offset information for the section */
+	    sec_start = s1->value - syminfo.value;
+	    sec_end = sec_start + lm->mod_section_data[i].size;
+	    lm->mod_section_data[i].offset = sec_start - lm->mod_base;
+            lm->mod_section_data[i].flags |= SEC_FOUND;
+
+	    if (CRASHDEBUG(1)) {
+		    fprintf(fp, "update sec offset sym %s @ %lx  val %lx  section %s\n",
+			    s1->name, s1->value, syminfo.value, secname);
+	    }
+
+	    if (strcmp(secname, ".text") == 0)
+		    lm->mod_text_start = sec_start;
+
+	    if (strcmp(secname, ".bss") == 0)
+		    lm->mod_bss_start = sec_start;
+
+	    if (strcmp(secname, ".data") == 0)
+		    lm->mod_data_start = sec_start;
+
+	    if (strcmp(secname, ".data") == 0)
+		    lm->mod_data_start = sec_start;
+
+	    if (strcmp(secname, ".rodata") == 0)
+		    lm->mod_rodata_start = sec_start;
+	}
+}
+
+/*
  *  Later versons of insmod store basic address information of each
  *  module in a format that looks like the following example of the
  *  nfsd module:
@@ -7274,8 +7387,8 @@
 	}
 
 	if (CRASHDEBUG(1))
-		fprintf(fp, "load_module_symbols: %s %s %lx\n",
-			modref, namelist, base_addr);
+		fprintf(fp, "load_module_symbols: %s %s %lx %lx\n",
+			modref, namelist, base_addr, kt->flags);
 
 	switch (kt->flags & (KMOD_V1|KMOD_V2))
 	{
@@ -7288,7 +7401,6 @@
                 	strcpy(lm->mod_namelist, namelist);
         	else
                 	strncpy(lm->mod_namelist, namelist, MAX_MOD_NAMELIST-1);
-		goto add_symbols;
 	}
 
   	if ((mbfd = bfd_openr(namelist, NULL)) == NULL) 
@@ -7308,6 +7420,10 @@
 	else if (symcount == 0)
 		error(FATAL, "no symbols in object file: %s\n", namelist);
 
+        if (CRASHDEBUG(1)) {
+                fprintf(fp, "%ld symbols found in obj file %s\n", symcount,
+                    namelist);
+        }
         sort_x = bfd_make_empty_symbol(mbfd);
         sort_y = bfd_make_empty_symbol(mbfd);
         if (sort_x == NULL || sort_y == NULL)
@@ -7315,14 +7431,13 @@
 
 	gnu_qsort(mbfd, minisyms, symcount, size, sort_x, sort_y);
 
-	store_load_module_symbols(mbfd, FALSE, minisyms, symcount, 
-		size, base_addr, namelist); 
+        store_load_module_symbols(mbfd, FALSE, minisyms, symcount, 
+                size, base_addr, namelist); 
 
 	free(minisyms);
 
 	bfd_close(mbfd);
 
-add_symbols:
 	result = add_symbol_file(st->current);
 
 	if (CRASHDEBUG(1))
@@ -7473,7 +7588,12 @@
 
         bfd_map_over_sections(bfd, section_header_info, MODULE_SECTIONS);
 
-	calculate_load_order(lm, bfd);
+	if (kt->flags & KMOD_V1)
+		calculate_load_order_v1(lm, bfd);
+	else
+		calculate_load_order_v2(lm, bfd, dynamic, minisyms,
+			symcount, size);
+
 
         from = (bfd_byte *) minisyms;
         fromend = from + symcount * size;
