diff -aur -x Makefile crash-4.0-3.16/defs.h crash-4.0-3.16-sym/defs.h --- crash-4.0-3.16/defs.h 2006-12-21 11:54:11 -08:00 +++ crash-4.0-3.16-sym/defs.h 2006-12-22 12:20:36 -08:00 @@ -1759,6 +1759,7 @@ ulong dwarf_eh_frame_size; }; +/* flags for st */ #define KERNEL_SYMS (0x1) #define MODULE_SYMS (0x2) #define LOAD_MODULE_SYMS (0x4) @@ -1770,6 +1771,13 @@ #define FORCE_DEBUGINFO (0x80) #define CRC_MATCHES (0x100) #define ADD_SYMBOL_FILE (0x200) +#define FORCE_V2_MOD_SYM (0x400) +#ifndef V2_MOD_SYM_WORKS +#define USE_V2_MOD_SYM() (st->flags & FORCE_V2_MOD_SYM) +#else +#define USE_V2_MOD_SYM() (1) +#endif + #endif /* !GDB_COMMON */ @@ -1784,6 +1792,8 @@ #define MOD_REMOTE (0x4) #define MOD_KALLSYMS (0x8) #define MOD_INITRD (0x10) + +#define SEC_FOUND (0x10000) struct mod_section_data { #if defined(GDB_6_1) diff -aur -x Makefile crash-4.0-3.16/gdb-6.1/gdb/symtab.c crash-4.0-3.16-sym/gdb-6.1/gdb/symtab.c --- crash-4.0-3.16/gdb-6.1/gdb/symtab.c 2006-12-21 11:54:11 -08:00 +++ crash-4.0-3.16-sym/gdb-6.1/gdb/symtab.c 2006-12-27 16:39:22 -08:00 @@ -4524,13 +4524,42 @@ struct expression *expr; struct cleanup *old_chain; + int allsect = 0, i; + char *secname; + + gdb_current_load_module = lm = (struct load_module *)req->addr; 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); + for (i = 0 ; i < lm->mod_sections; i++) { + if (STREQ(lm->mod_section_data[i].name, ".text") && + SEC_FOUND & lm->mod_section_data[i].flags) + allsect = 1; + } + + if (!allsect) { + 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); + } else { + char buf[80]; + sprintf(req->buf, "add-symbol-file %s 0x%lx", lm->mod_namelist, + lm->mod_text_start); + for (i = 0; i < lm->mod_sections; i++) { + secname = lm->mod_section_data[i].name; + if (lm->mod_section_data[i].flags & SEC_FOUND && + !STREQ(secname, ".text")) { + sprintf(buf, " -s %s 0x%lx", secname, + lm->mod_section_data[i].offset + lm->mod_base); + strcat(req->buf, buf); + } + } + } execute_command(req->buf, FALSE); diff -aur -x Makefile crash-4.0-3.16/help.c crash-4.0-3.16-sym/help.c --- crash-4.0-3.16/help.c 2006-12-21 11:54:11 -08:00 +++ crash-4.0-3.16-sym/help.c 2006-12-27 16:31:48 -08:00 @@ -3375,7 +3375,7 @@ char *help_mod[] = { "mod", "module information and loading of symbols and debugging data", -"[ -s module [objfile] | -d module | -S [directory] | -D | -r ] ", +"[ -s module [objfile] | -d module | -S [directory] | -D | -r | -l ] ", " With no arguments, this command displays basic information of the currently", " installed modules, consisting of the module address, name, size, the", " object file name (if known), and whether the module was compiled with", @@ -3423,6 +3423,7 @@ " If a directory argument is appended, then the search", " will be restricted to that directory.", " -D Deletes the symbolic and debugging data of all modules.", +" -l Force load of module symbols with new mechanism", " -r Reinitialize module data. All currently-loaded symbolic", " and debugging data will be deleted, and the installed", " module list will be updated (live system only).", diff -aur -x Makefile crash-4.0-3.16/kernel.c crash-4.0-3.16-sym/kernel.c --- crash-4.0-3.16/kernel.c 2006-12-21 11:54:11 -08:00 +++ crash-4.0-3.16-sym/kernel.c 2006-12-22 12:00:13 -08:00 @@ -2307,7 +2307,7 @@ address = 0; flag = LIST_MODULE_HDR; - while ((c = getopt(argcnt, args, "rd:Ds:St:")) != EOF) { + while ((c = getopt(argcnt, args, "rd:Ds:St:l")) != EOF) { switch(c) { case 'r': @@ -2338,6 +2338,15 @@ modref = optarg; else cmd_usage(pc->curcmd, SYNOPSIS); + break; + + /* + * kmod version 2 symbols do not always load correctly. + * It appears to work on x86, and x86_64, but problems + * have been seen on s390x. So have it off by default. + */ + case 'l': + st->flags |= FORCE_V2_MOD_SYM; break; case 't': diff -aur -x Makefile crash-4.0-3.16/symbols.c crash-4.0-3.16-sym/symbols.c --- crash-4.0-3.16/symbols.c 2006-12-21 11:54:11 -08:00 +++ crash-4.0-3.16-sym/symbols.c 2006-12-27 17:01:47 -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; @@ -7049,8 +7051,9 @@ i = lm->mod_sections; lm->mod_section_data[i].section = section; lm->mod_section_data[i].priority = prio; - lm->mod_section_data[i].flags = section->flags; + lm->mod_section_data[i].flags = section->flags & ~SEC_FOUND; 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,131 @@ } /* + * 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) { + break; + } + } + + /* Matched one of the sections. Skip symbol. */ + if (i < lm->mod_sections) { + if (CRASHDEBUG(2)) { + fprintf(fp, "skip %lx %s %s\n", s1->value, s1->name, + lm->mod_section_data[i].name); + } + 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 (CRASHDEBUG(3)) { + fprintf(fp,"matching sym %s %lx against bfd %s %lx\n", + s1->name, (long) s1->value, syminfo.name, + (long) syminfo.value); + } + 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 %s not found for symbol %s\n", + secname, 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; + s1++; + } +} + +/* * 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 +7402,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 +7416,10 @@ strcpy(lm->mod_namelist, namelist); else strncpy(lm->mod_namelist, namelist, MAX_MOD_NAMELIST-1); - goto add_symbols; + if (!USE_V2_MOD_SYM()) { + goto add_symbols; + } + } if ((mbfd = bfd_openr(namelist, NULL)) == NULL) @@ -7308,6 +7439,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,8 +7450,8 @@ 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); @@ -7473,7 +7608,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; @@ -7486,104 +7626,112 @@ bfd_get_symbol_info(bfd, sym, &syminfo); secname = (char *)bfd_get_section_name(bfd, sym->section); + found = 0; - switch (syminfo.type) - { - case 'b': - case 'B': - if (CRASHDEBUG(2)) - fprintf(fp, "%08lx (%c) [%s] %s\n", - (ulong)syminfo.value, - syminfo.type, secname, syminfo.name); + if (kt->flags & KMOD_V1) { + switch (syminfo.type) + { + case 'b': + case 'B': + if (CRASHDEBUG(2)) + fprintf(fp, "%08lx (%c) [%s] %s\n", + (ulong)syminfo.value, + syminfo.type, secname, syminfo.name); - syminfo.value += lm->mod_bss_start; - strcpy(name, syminfo.name); - strip_module_symbol_end(name); + if (!lm->mod_bss_start) + break; - if (machdep->verify_symbol(name, syminfo.value, - syminfo.type)) { - sp->value = syminfo.value; - sp->type = syminfo.type; - - namespace_ctl(NAMESPACE_INSTALL, - &lm->mod_load_namespace, sp, name); + syminfo.value += lm->mod_bss_start; + found = 1; + break; - if (CRASHDEBUG(1)) - fprintf(fp, "%08lx %s\n", sp->value, - name); + case 'd': + case 'D': + if (CRASHDEBUG(2)) + fprintf(fp, "%08lx (%c) [%s] %s\n", + (ulong)syminfo.value, + syminfo.type, secname, syminfo.name); + + if (STREQ(secname, ".rodata")) { + if (!lm->mod_rodata_start) + break; + syminfo.value += lm->mod_rodata_start; + } else { + if (!lm->mod_data_start) + break; + syminfo.value += lm->mod_data_start; + } + found = 1; + break; - sp++; - lm->mod_load_symcnt++; - } - break; + case 't': + case 'T': + if (CRASHDEBUG(2)) + fprintf(fp, "%08lx (%c) [%s] %s\n", + (ulong)syminfo.value, + syminfo.type, secname, syminfo.name); - case 'd': - case 'D': - if (CRASHDEBUG(2)) - fprintf(fp, "%08lx (%c) [%s] %s\n", - (ulong)syminfo.value, - syminfo.type, secname, syminfo.name); + if (! lm->mod_text_start) { + break; + } - if (STREQ(secname, ".rodata")) - syminfo.value += lm->mod_rodata_start; - else - syminfo.value += lm->mod_data_start; + if ((st->flags & INSMOD_BUILTIN) && + (STREQ(name, "init_module") || + STREQ(name, "cleanup_module"))) + break; + + syminfo.value += lm->mod_text_start; + found = 1; + break; + + default: + break; + } + + } else { + /* Match the section it came in. */ + for (i = 0; i < lm->mod_sections; i++) { + if (STREQ(lm->mod_section_data[i].name, secname) + && (lm->mod_section_data[i].flags & SEC_FOUND)) { + break; + } + } + if (i < lm->mod_sections) { + if (CRASHDEBUG(2)) + fprintf(fp, "%08lx (%c) [%s] %s\n", + (ulong)syminfo.value, + syminfo.type, secname, syminfo.name); + + if ((st->flags & INSMOD_BUILTIN) && + (STREQ(name, "init_module") || + STREQ(name, "cleanup_module"))) { + found = 0; + } else { + syminfo.value += lm->mod_section_data[i].offset + lm->mod_base; + found = 1; + } + } + } + if (found) { strcpy(name, syminfo.name); strip_module_symbol_end(name); - if (machdep->verify_symbol(name, syminfo.value, - syminfo.type)) { + if (machdep->verify_symbol(name, syminfo.value, + syminfo.type)) { sp->value = syminfo.value; - sp->type = syminfo.type; + sp->type = syminfo.type; namespace_ctl(NAMESPACE_INSTALL, - &lm->mod_load_namespace, sp, name); + &lm->mod_load_namespace, sp, name); if (CRASHDEBUG(1)) - fprintf(fp, "%08lx %s\n", sp->value, + fprintf(fp, "installing %c %08lx %s\n", syminfo.type, sp->value, name); sp++; lm->mod_load_symcnt++; } - break; - - case 't': - case 'T': - if (CRASHDEBUG(2)) - fprintf(fp, "%08lx (%c) [%s] %s\n", - (ulong)syminfo.value, - syminfo.type, secname, syminfo.name); - - syminfo.value += lm->mod_text_start; - strcpy(name, syminfo.name); - strip_module_symbol_end(name); - - if ((st->flags & INSMOD_BUILTIN) && - (STREQ(name, "init_module") || - STREQ(name, "cleanup_module"))) - break; - - if (machdep->verify_symbol(name, syminfo.value, - syminfo.type)) { - sp->value = syminfo.value; - sp->type = syminfo.type; - namespace_ctl(NAMESPACE_INSTALL, - &lm->mod_load_namespace, sp, name); - - if (CRASHDEBUG(1)) - fprintf(fp, "%08lx %s\n", sp->value, - name); - - sp++; - lm->mod_load_symcnt++; - } - - break; - - default: - break; - } + } } lm->mod_load_symend = &lm->mod_load_symtable[lm->mod_load_symcnt];