kernels which have CONFIG_HAVE_ARCH_PREL32_RELOCATIONS will now store module symbol values relative to themselves since linux kernel's commit 7290d580957 ("module: use relative references for __ksymtab entries") Do the lookup one way or another depending on the kernel's kernel_symbol struct, the case without the ARCH_PREL32_RELOCATIONS is the same as the old behaviour --- Hi! This is a follow-up on the bz I opened yesterday[1] I'll let you commit your part of the tasks_struct pids, with both patches I can start crash normally and could check that address of symbols within a module look correct when compared to /proc/kallsyms, so I guess this isn't too bad. I also tried with an older kernel without problem. [1] https://bugzilla.redhat.com/show_bug.cgi?id=1623127 defs.h | 1 + symbols.c | 98 +++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 68 insertions(+), 31 deletions(-) diff --git a/defs.h b/defs.h index 8687ff1..166ee48 100644 --- a/defs.h +++ b/defs.h @@ -2036,6 +2036,7 @@ struct offset_table { /* stash of commonly-used offsets */ long memcg_cache_params___root_caches_node; long memcg_cache_params_children; long memcg_cache_params_children_node; + long kernel_symbol_value; }; struct size_table { /* stash of commonly-used sizes */ diff --git a/symbols.c b/symbols.c index 2e6713a..7e73bad 100644 --- a/symbols.c +++ b/symbols.c @@ -1595,12 +1595,40 @@ store_module_symbols_v1(ulong total, int mods_installed) st->flags |= INSMOD_BUILTIN; } -struct kernel_symbol -{ - unsigned long value; - const char *name; +union kernel_symbol { + struct kernel_symbol_v1 { + unsigned long value; + const char *name; + } v1; + /* kernel 4.19 introduced relative symbol positionning */ + struct kernel_symbol_v2 { + int value_offset; + int name_offset; + } v2; }; +static ulong +modsym_name(ulong syms, union kernel_symbol *modsym, int i) +{ + if (VALID_MEMBER(kernel_symbol_value)) + return (ulong)modsym->v1.name; + + return syms + i * sizeof(struct kernel_symbol_v2) + + offsetof(struct kernel_symbol_v2, name_offset) + + modsym->v2.name_offset; +} + +static ulong +modsym_value(ulong syms, union kernel_symbol *modsym, int i) +{ + if (VALID_MEMBER(kernel_symbol_value)) + return (ulong)modsym->v1.value; + + return syms + i * sizeof(struct kernel_symbol_v2) + + offsetof(struct kernel_symbol_v2, value_offset) + + modsym->v2.value_offset; +} + void store_module_symbols_v2(ulong total, int mods_installed) { @@ -1614,7 +1642,8 @@ store_module_symbols_v2(ulong total, int mods_installed) long strbuflen; ulong size; int mcnt, lm_mcnt; - struct kernel_symbol *modsym; + union kernel_symbol *modsym; + size_t kernel_symbol_size; struct load_module *lm; char buf1[BUFSIZE]; char buf2[BUFSIZE]; @@ -1639,6 +1668,13 @@ store_module_symbols_v2(ulong total, int mods_installed) "re-initialization of module symbols not implemented yet!\n"); } + MEMBER_OFFSET_INIT(kernel_symbol_value, "kernel_symbol", "value"); + if (VALID_MEMBER(kernel_symbol_value)) { + kernel_symbol_size = sizeof(struct kernel_symbol_v1); + } else { + kernel_symbol_size = sizeof(struct kernel_symbol_v2); + } + if ((st->ext_module_symtable = (struct syment *) calloc(total, sizeof(struct syment))) == NULL) error(FATAL, "v2 module syment space malloc (%ld symbols): %s\n", @@ -1750,20 +1786,20 @@ store_module_symbols_v2(ulong total, int mods_installed) } if (nsyms) { - modsymbuf = GETBUF(sizeof(struct kernel_symbol)*nsyms); + modsymbuf = GETBUF(kernel_symbol_size*nsyms); readmem((ulong)syms, KVADDR, modsymbuf, - nsyms * sizeof(struct kernel_symbol), + nsyms * kernel_symbol_size, "module symbols", FAULT_ON_ERROR); } for (i = first = last = 0; i < nsyms; i++) { - modsym = (struct kernel_symbol *) - (modsymbuf + (i * sizeof(struct kernel_symbol))); + modsym = (union kernel_symbol *) + (modsymbuf + (i * kernel_symbol_size)); if (!first - || first > (ulong)modsym->name) - first = (ulong)modsym->name; - if ((ulong)modsym->name > last) - last = (ulong)modsym->name; + || first > modsym_name(syms, modsym, i)) + first = modsym_name(syms, modsym, i); + if (modsym_name(syms, modsym, i) > last) + last = modsym_name(syms, modsym, i); } if (last > first) { @@ -1787,21 +1823,21 @@ store_module_symbols_v2(ulong total, int mods_installed) for (i = 0; i < nsyms; i++) { - modsym = (struct kernel_symbol *) - (modsymbuf + (i * sizeof(struct kernel_symbol))); + modsym = (union kernel_symbol *) + (modsymbuf + (i * kernel_symbol_size)); BZERO(buf1, BUFSIZE); if (strbuf) strcpy(buf1, - &strbuf[(ulong)modsym->name - first]); + &strbuf[modsym_name(syms, modsym, i) - first]); else - read_string((ulong)modsym->name, buf1, + read_string(modsym_name(syms, modsym, i), buf1, BUFSIZE-1); if (strlen(buf1)) { st->ext_module_symtable[mcnt].value = - modsym->value; + modsym_value(syms, modsym, i); st->ext_module_symtable[mcnt].type = '?'; st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL; strip_module_symbol_end(buf1); @@ -1823,21 +1859,21 @@ store_module_symbols_v2(ulong total, int mods_installed) FREEBUF(strbuf); if (ngplsyms) { - modsymbuf = GETBUF(sizeof(struct kernel_symbol) * + modsymbuf = GETBUF(kernel_symbol_size * ngplsyms); readmem((ulong)gpl_syms, KVADDR, modsymbuf, - ngplsyms * sizeof(struct kernel_symbol), + ngplsyms * kernel_symbol_size, "module gpl symbols", FAULT_ON_ERROR); } for (i = first = last = 0; i < ngplsyms; i++) { - modsym = (struct kernel_symbol *) - (modsymbuf + (i * sizeof(struct kernel_symbol))); + modsym = (union kernel_symbol *) + (modsymbuf + (i * kernel_symbol_size)); if (!first - || first > (ulong)modsym->name) - first = (ulong)modsym->name; - if ((ulong)modsym->name > last) - last = (ulong)modsym->name; + || first > modsym_name(gpl_syms, modsym, i)) + first = modsym_name(gpl_syms, modsym, i); + if (modsym_name(gpl_syms, modsym, i) > last) + last = modsym_name(gpl_syms, modsym, i); } if (last > first) { @@ -1860,21 +1896,21 @@ store_module_symbols_v2(ulong total, int mods_installed) for (i = 0; i < ngplsyms; i++) { - modsym = (struct kernel_symbol *) - (modsymbuf + (i * sizeof(struct kernel_symbol))); + modsym = (union kernel_symbol *) + (modsymbuf + (i * kernel_symbol_size)); BZERO(buf1, BUFSIZE); if (strbuf) strcpy(buf1, - &strbuf[(ulong)modsym->name - first]); + &strbuf[modsym_name(gpl_syms, modsym, i) - first]); else - read_string((ulong)modsym->name, buf1, + read_string(modsym_name(gpl_syms, modsym, i), buf1, BUFSIZE-1); if (strlen(buf1)) { st->ext_module_symtable[mcnt].value = - modsym->value; + modsym_value(gpl_syms, modsym, i); st->ext_module_symtable[mcnt].type = '?'; st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL; strip_module_symbol_end(buf1); -- 2.17.1 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility