Support "mod -s|-S" with introducing lm->load_sym{table,end} but many functions like "mod -d|-D" are still not supported. Signed-off-by: Kazuhito Hagio <k-hagio-ab@xxxxxxx> --- defs.h | 9 +- gdb-10.2.patch | 16 +++ symbols.c | 350 ++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 340 insertions(+), 35 deletions(-) diff --git a/defs.h b/defs.h index 95e44e8cb87c..b2478b6741ec 100644 --- a/defs.h +++ b/defs.h @@ -2925,6 +2925,7 @@ struct mod_section_data { ulong size; int priority; int flags; + ulong addr; }; /* This is unlikely to change, so imported from kernel for now. */ @@ -2982,8 +2983,12 @@ struct load_module { /* For 6.4 module_memory */ struct module_memory mem[MOD_MEM_NUM_TYPES]; - struct syment *symtable[MOD_MEM_NUM_TYPES]; - struct syment *symend[MOD_MEM_NUM_TYPES]; + struct syment **symtable; + struct syment **symend; + struct syment *ext_symtable[MOD_MEM_NUM_TYPES]; + struct syment *ext_symend[MOD_MEM_NUM_TYPES]; + struct syment *load_symtable[MOD_MEM_NUM_TYPES]; + struct syment *load_symend[MOD_MEM_NUM_TYPES]; int address_order[MOD_MEM_NUM_TYPES]; int nr_mems; }; diff --git a/gdb-10.2.patch b/gdb-10.2.patch index 835aae9859be..b3f6d8b086eb 100644 --- a/gdb-10.2.patch +++ b/gdb-10.2.patch @@ -3120,3 +3120,19 @@ exit 0 return result; } +--- gdb-10.2/gdb/symtab.c.orig ++++ gdb-10.2/gdb/symtab.c +@@ -7515,8 +7515,11 @@ gdb_add_symbol_file(struct gnu_request * + 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); ++ if (lm->mod_section_data[i].addr) ++ sprintf(buf, " -s %s 0x%lx", secname, lm->mod_section_data[i].addr); ++ else ++ sprintf(buf, " -s %s 0x%lx", secname, ++ lm->mod_section_data[i].offset + lm->mod_base); + strcat(req->buf, buf); + } + } diff --git a/symbols.c b/symbols.c index ef00ce0b79ca..8343081f51f7 100644 --- a/symbols.c +++ b/symbols.c @@ -50,6 +50,8 @@ static void store_section_data(struct load_module *, bfd *, asection *); 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 calculate_load_order_v3(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; @@ -2288,20 +2290,22 @@ store_module_symbols_v3(ulong total, int mods_installed) for (sp = st->ext_module_symtable; sp < st->ext_module_symend; sp++) { if (STREQ(sp->name, buf1)) { - lm->symtable[i] = sp; + lm->ext_symtable[i] = sp; break; } } for ( ; sp < st->ext_module_symend; sp++) { if (STREQ(sp->name, buf2)) { - lm->symend[i] = sp; + lm->ext_symend[i] = sp; break; } } - if (lm->symtable[i] && lm->symend[i]) - mod_symtable_hash_install_range(lm->symtable[i], lm->symend[i]); + if (lm->ext_symtable[i] && lm->ext_symend[i]) + mod_symtable_hash_install_range(lm->ext_symtable[i], lm->ext_symend[i]); } + lm->symtable = lm->ext_symtable; + lm->symend = lm->ext_symend; } st->flags |= MODULE_SYMS; @@ -4090,15 +4094,27 @@ dump_symbol_table(void) for (j = 0; j < lm->nr_mems; j++) fprintf(fp, " %d", lm->address_order[j]); fprintf(fp, "\n"); + fprintf(fp, " symtable: %lx\n", (ulong)lm->symtable); + fprintf(fp, " ext_symtable: %lx\n", (ulong)lm->ext_symtable); + for (j = MOD_TEXT; j < MOD_MEM_NUM_TYPES; j++) { + fprintf(fp, " ext_symtable[%d]: %lx - %lx\n", + j, (ulong)lm->ext_symtable[j], (ulong)lm->ext_symend[j]); + } + fprintf(fp, " load_symtable: %lx\n", (ulong)lm->load_symtable); + for (j = MOD_TEXT; j < MOD_MEM_NUM_TYPES; j++) { + fprintf(fp, " load_symtable[%d]: %lx - %lx\n", + j, (ulong)lm->load_symtable[j], (ulong)lm->load_symend[j]); + } } for (s = 0; s < lm->mod_sections; s++) { fprintf(fp, - " %12s prio: %x flags: %05x offset: %-8lx size: %lx\n", + " %20s prio: %x flags: %08x offset: %-8lx addr: %-16lx size: %lx\n", lm->mod_section_data[s].name, lm->mod_section_data[s].priority, lm->mod_section_data[s].flags, lm->mod_section_data[s].offset, + lm->mod_section_data[s].addr, lm->mod_section_data[s].size); } @@ -12122,6 +12138,7 @@ store_section_data(struct load_module *lm, bfd *bfd, asection *section) } lm->mod_section_data[i].size = bfd_section_size(section); lm->mod_section_data[i].offset = 0; + lm->mod_section_data[i].addr = 0; if (strlen(name) < MAX_MOD_SEC_NAME) strcpy(lm->mod_section_data[i].name, name); else @@ -12367,6 +12384,133 @@ calculate_load_order_v2(struct load_module *lm, bfd *bfd, int dynamic, } } +/* Linux 6.4 and later */ +static void +calculate_load_order_v3(struct load_module *lm, bfd *bfd, int dynamic, + void *minisyms, long symcount, unsigned int size) +{ + struct syment *s1, *s2; + ulong sec_start; + bfd_byte *from, *fromend; + asymbol *store; + asymbol *sym; + symbol_info syminfo; + char *secname; + int i, j; + + if ((store = bfd_make_empty_symbol(bfd)) == NULL) + error(FATAL, "bfd_make_empty_symbol() failed\n"); + + for (j = MOD_TEXT; j < MOD_MEM_NUM_TYPES; j++) { + + s1 = lm->symtable[j]; + s2 = lm->symend[j]; + while (s1 < s2) { + + 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 (s1->value >= lm->mod_section_data[i].addr + && s1->value < lm->mod_section_data[i].addr + + 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_section_name(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; + } + + if (lm->mod_section_data[i].flags & SEC_FOUND) { + s1++; + continue; + } + + /* Update the offset information for the section */ + sec_start = s1->value - syminfo.value; + //lm->mod_section_data[i].offset = sec_start - lm->mem[j].base; + /* keep the address instead of offset */ + lm->mod_section_data[i].addr = sec_start; + lm->mod_section_data[i].flags |= SEC_FOUND; + + if (CRASHDEBUG(2)) { + fprintf(fp, "update sec offset sym %s @ %lx val %lx section %s\n", + s1->name, s1->value, (ulong)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, ".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 @@ -12561,6 +12705,7 @@ add_symbol_file(struct load_module *lm) req = &request; BZERO(req, sizeof(struct gnu_request)); + /* TODO: ugh, module section data structures changed? */ if ((lm->mod_flags & MOD_KALLSYMS) && add_symbol_file_kallsyms(lm, req)) return TRUE; @@ -12572,8 +12717,11 @@ add_symbol_file(struct load_module *lm) (!STREQ(secname, ".text") && !STREQ(secname, ".data.percpu") && !STREQ(secname, ".data..percpu"))) { - sprintf(buf, " -s %s 0x%lx", secname, - lm->mod_section_data[i].offset + lm->mod_base); + if (MODULE_MEMORY()) + sprintf(buf, " -s %s 0x%lx", secname, lm->mod_section_data[i].addr); + else + sprintf(buf, " -s %s 0x%lx", secname, + lm->mod_section_data[i].offset + lm->mod_base); len += strlen(buf); } } @@ -12914,24 +13062,43 @@ static struct syment * kallsyms_module_symbol(struct load_module *lm, symbol_info *syminfo) { struct syment *sp, *spx; - int cnt; + int i, cnt; if (!(lm->mod_flags & MOD_KALLSYMS)) return NULL; sp = NULL; cnt = 0; - for (spx = lm->mod_ext_symtable; spx <= lm->mod_ext_symend; spx++) { - if (!STREQ(spx->name, syminfo->name)) - continue; - if (spx->cnt) { - cnt++; - continue; - } + if (MODULE_MEMORY()) { + for (i = MOD_TEXT; i < MOD_MEM_NUM_TYPES; i++) { + if (!lm->ext_symtable[i]) + continue; + for (spx = lm->ext_symtable[i]; spx <= lm->ext_symend[i]; spx++) { + if (!STREQ(spx->name, syminfo->name)) + continue; + if (spx->cnt) { + cnt++; + continue; + } - spx->cnt++; - sp = spx; - break; + spx->cnt++; + sp = spx; + break; + } + } + } else { + for (spx = lm->mod_ext_symtable; spx <= lm->mod_ext_symend; spx++) { + if (!STREQ(spx->name, syminfo->name)) + continue; + if (spx->cnt) { + cnt++; + continue; + } + + spx->cnt++; + sp = spx; + break; + } } if (CRASHDEBUG(2)) { @@ -12968,7 +13135,7 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms, char *nameptr, *secname; long index; long symalloc; - int found; + int found = FALSE; if ((store = bfd_make_empty_symbol(bfd)) == NULL) error(FATAL, "bfd_make_empty_symbol() failed\n"); @@ -13025,8 +13192,17 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms, lm->mod_rodata_start = lm->mod_bss_start = 0; lm->mod_load_symcnt = 0; lm->mod_sections = 0; - for (spx = lm->mod_ext_symtable; spx <= lm->mod_ext_symend; spx++) - spx->cnt = 0; + if (MODULE_MEMORY()) { + for (i = MOD_TEXT; i < MOD_MEM_NUM_TYPES; i++) { + if (!lm->ext_symtable[i]) + continue; + for (spx = lm->ext_symtable[i]; spx <= lm->ext_symend[i]; spx++) + spx->cnt = 0; + } + } else { + for (spx = lm->mod_ext_symtable; spx <= lm->mod_ext_symend; spx++) + spx->cnt = 0; + } sp = lm->mod_load_symtable; if (!(lm->mod_section_data = (struct mod_section_data *) @@ -13037,7 +13213,17 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms, bfd_map_over_sections(bfd, section_header_info, MODULE_SECTIONS); - if (kt->flags & KMOD_V1) + /* for debug + for (i = 0; i < lm->mod_sections; i++) { + struct mod_section_data *m = &lm->mod_section_data[i]; + fprintf(fp, "%d: name %s offset %ld size %ld flags %x\n", + i, m->name, m->offset, m->size, m->flags); + } + */ + + if (MODULE_MEMORY()) + calculate_load_order_v3(lm, bfd, dynamic, minisyms, symcount, size); + else if (kt->flags & KMOD_V1) calculate_load_order_v1(lm, bfd); else calculate_load_order_v2(lm, bfd, dynamic, minisyms, @@ -13146,7 +13332,10 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms, syminfo.value += lm->mod_percpu; found = TRUE; } else { - syminfo.value += lm->mod_section_data[i].offset + lm->mod_base; + if (MODULE_MEMORY()) + syminfo.value += lm->mod_section_data[i].addr; + else + syminfo.value += lm->mod_section_data[i].offset + lm->mod_base; found = TRUE; } } @@ -13181,6 +13370,51 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms, * syminfo data types accepted above, plus the two pseudo symbols. * Note that the new syment name pointers haven't been resolved yet. */ + if (MODULE_MEMORY()) { + for (i = MOD_TEXT; i < MOD_MEM_NUM_TYPES; i++) { + if (!lm->ext_symtable[i]) + continue; + for (spx = lm->ext_symtable[i]; spx <= lm->ext_symend[i]; spx++) { + found = FALSE; + for (sp = lm->mod_load_symtable; sp < lm->mod_load_symend; sp++) { + index = (long)sp->name; + nameptr = &lm->mod_load_namespace.address[index]; + if (STREQ(spx->name, nameptr)) { + found = TRUE; + if (spx->value == sp->value) { + if (CRASHDEBUG(2)) + fprintf(fp, "%s: %s matches!\n", + lm->mod_name, nameptr); + } else { + if (CRASHDEBUG(2)) + fprintf(fp, + "[%s] %s: %lx != extern'd value: %lx\n", + lm->mod_name, + nameptr, sp->value, + spx->value); + } + break; + } + } + if (!found) { + if (CRASHDEBUG(2)) + fprintf(fp, "append ext %s (%lx)\n", spx->name, spx->value); + /* append it here... */ + namespace_ctl(NAMESPACE_INSTALL, + &lm->mod_load_namespace, + lm->mod_load_symend, spx->name); + + lm->mod_load_symend->value = spx->value; + lm->mod_load_symend->type = spx->type; + lm->mod_load_symend->flags |= MODULE_SYMBOL; + lm->mod_load_symend++; + lm->mod_load_symcnt++; + } + } + } + goto append_section_symbols; + } + for (spx = lm->mod_ext_symtable; spx <= lm->mod_ext_symend; spx++) { found = FALSE; for (sp = lm->mod_load_symtable; @@ -13223,6 +13457,7 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms, } } +append_section_symbols: /* * Append helpful pseudo symbols about found out sections. * Use 'S' as its type which is never seen in existing symbols. @@ -13232,8 +13467,11 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms, if (!(lm->mod_section_data[i].flags & SEC_FOUND)) continue; /* Section start */ - lm->mod_load_symend->value = lm->mod_base + - lm->mod_section_data[i].offset; + if (MODULE_MEMORY()) + lm->mod_load_symend->value = lm->mod_section_data[i].addr; + else + lm->mod_load_symend->value = lm->mod_base + + lm->mod_section_data[i].offset; lm->mod_load_symend->type = 'S'; lm->mod_load_symend->flags |= MODULE_SYMBOL; sprintf(name, "_MODULE_SECTION_START [%s]", @@ -13244,9 +13482,12 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms, lm->mod_load_symcnt++; /* Section end */ - lm->mod_load_symend->value = lm->mod_base + - lm->mod_section_data[i].offset + - lm->mod_section_data[i].size; + if (MODULE_MEMORY()) + lm->mod_load_symend->value = lm->mod_section_data[i].addr; + else + lm->mod_load_symend->value = lm->mod_base + + lm->mod_section_data[i].offset; + lm->mod_load_symend->value += lm->mod_section_data[i].size; lm->mod_load_symend->type = 'S'; lm->mod_load_symend->flags |= MODULE_SYMBOL; sprintf(name, "_MODULE_SECTION_END [%s]", @@ -13263,16 +13504,59 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms, qsort(lm->mod_load_symtable, lm->mod_load_symcnt, sizeof(struct syment), compare_syms); + /* keep load symtable addresses to lm->load_symtable[] */ + /* TODO: make more efficient */ + for (sp = lm->mod_load_symtable; sp < lm->mod_load_symend; sp++) { + char buf1[BUFSIZE], buf2[BUFSIZE]; + + if (CRASHDEBUG(1)) + fprintf(fp, "DEBUG: value %16lx name %s\n", sp->value, sp->name); + if (!MODULE_PSEUDO_SYMBOL(sp)) + continue; + + for (i = MOD_TEXT; i < MOD_MEM_NUM_TYPES; i++) { + if (!lm->mem[i].base) + continue; + + sprintf(buf1, "%s%s", module_start_tags[i], lm->mod_name); + sprintf(buf2, "%s%s", module_end_tags[i], lm->mod_name); + + if (STREQ(sp->name, buf1)) { + lm->load_symtable[i] = sp; + break; + } else if (STREQ(sp->name, buf2)) { + lm->load_symend[i] = sp; + break; + } + } + } + + /* TODO: add check for 6.4 and later */ lm->mod_load_symend--; - if (!MODULE_END(lm->mod_load_symend) && + if (!MODULE_MEMORY() && !MODULE_END(lm->mod_load_symend) && !IN_MODULE_PERCPU(lm->mod_load_symend->value, lm)) error(INFO, "%s: last symbol: %s is not _MODULE_END_%s?\n", lm->mod_name, lm->mod_load_symend->name, lm->mod_name); - mod_symtable_hash_remove_range(lm->mod_symtable, lm->mod_symend); - lm->mod_symtable = lm->mod_load_symtable; - lm->mod_symend = lm->mod_load_symend; - mod_symtable_hash_install_range(lm->mod_symtable, lm->mod_symend); + if (MODULE_MEMORY()) { + for (i = MOD_TEXT; i < MOD_MEM_NUM_TYPES; i++) { + if (!lm->symtable[i]) + continue; + mod_symtable_hash_remove_range(lm->symtable[i], lm->symend[i]); + } + lm->symtable = lm->load_symtable; + lm->symend = lm->load_symend; + for (i = MOD_TEXT; i < MOD_MEM_NUM_TYPES; i++) { + if (!lm->symtable[i]) + continue; + mod_symtable_hash_install_range(lm->symtable[i], lm->symend[i]); + } + } else { + mod_symtable_hash_remove_range(lm->mod_symtable, lm->mod_symend); + lm->mod_symtable = lm->mod_load_symtable; + lm->mod_symend = lm->mod_load_symend; + mod_symtable_hash_install_range(lm->mod_symtable, lm->mod_symend); + } lm->mod_flags &= ~MOD_EXT_SYMS; lm->mod_flags |= MOD_LOAD_SYMS; -- 2.31.1 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://listman.redhat.com/mailman/listinfo/crash-utility Contribution Guidelines: https://github.com/crash-utility/crash/wiki