diff --git a/0001-symbols-Implement-install-and-remove-operations-for-.patch b/0001-symbols-Implement-install-and-remove-operations-for-.patch new file mode 100644 index 0000000..b8f8eae --- /dev/null +++ b/0001-symbols-Implement-install-and-remove-operations-for-.patch @@ -0,0 +1,151 @@ +From 2fab8fbc0c4f1c4cbe889de4cead5f7457a19f77 Mon Sep 17 00:00:00 2001 +From: Tao Liu +Date: Sat, 16 Oct 2021 13:21:11 +0800 +Subject: [PATCH 1/9] symbols: Implement install and remove operations for + mod_symname_hash + +Currently the sequence for symbol_search to search a symbol is: 1) kernel +symname hash table, 2) iterate all kernel symbols, 3) iterate all kernel +modules and their symbols. In the worst case, if a non-exist symbol been +searched, all 3 stages will be went through. The time consuming status for +each stage is like: + + stage 1 stage 2 stage 3 + 0.007000(ms) 0.593000(ms) 2.421000(ms) + +stage 3 takes too much time when comparing to stage 1. This patch series +introduces a symname hash table for kernel modules, to improve the +performance of symbol searching. + +Functions symbol_search() and symbol_exists() are fundamental and widely +used by other crash functions, thus the benefit of performance improvement +can get accumulated. For example, "ps -m" and "irq" commands, which call +the functions many times, will become faster with the patch series. + +This patch indroduces mod_symname_hash, and its install/remove operations. +Since symbol_search() has to return the lowest address symbol and +symbol_search_next() returns the next lowest symbol, thus the installation +should be sorted ascendingly. + +In mod_symname_hash_install_range() scenario, spn are already arranged +ascendingly, so for mod_symname_hash_install(): + +Install spn previous to sp: + + If sp is the start of bucket, or + 1) spn->value is smaller than sp->value. + +Install spn next to sp: + + 1) sp->name_hash_next is NULL, or + 2) sp->name_hash_next->value is larger than spn->value + +spn->value is the kernel address of the symbol and will not change. +So we use it mainly to determine the sequence. When spn->value equals +sp->value, they must be symbols within a kernel module. + +Signed-off-by: Tao Liu +--- + defs.h | 1 + + symbols.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 74 insertions(+) + +diff --git a/defs.h b/defs.h +index cbd45e52f9da..bbdca799f72d 100644 +--- a/defs.h ++++ b/defs.h +@@ -2755,6 +2755,7 @@ struct symbol_table_data { + double val_hash_searches; + double val_hash_iterations; + struct syment *symname_hash[SYMNAME_HASH]; ++ struct syment *mod_symname_hash[SYMNAME_HASH]; + struct symbol_namespace kernel_namespace; + struct syment *ext_module_symtable; + struct syment *ext_module_symend; +diff --git a/symbols.c b/symbols.c +index 69dccdb09d5f..ad12d1c22225 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -1157,6 +1157,79 @@ symname_hash_install(struct syment *spn) + } + } + ++/* ++ * Install a single kernel module symbol into the mod_symname_hash. ++ */ ++static void ++mod_symname_hash_install(struct syment *spn) ++{ ++ struct syment *sp; ++ int index; ++ ++ if (!spn) ++ return; ++ ++ index = SYMNAME_HASH_INDEX(spn->name); ++ ++ sp = st->mod_symname_hash[index]; ++ ++ if (!sp || (spn->value < sp->value)) { ++ st->mod_symname_hash[index] = spn; ++ spn->name_hash_next = sp; ++ return; ++ } ++ for (; sp; sp = sp->name_hash_next) { ++ if (!sp->name_hash_next || ++ spn->value < sp->name_hash_next->value) { ++ spn->name_hash_next = sp->name_hash_next; ++ sp->name_hash_next = spn; ++ return; ++ } ++ } ++} ++ ++static void ++mod_symname_hash_remove(struct syment *spn) ++{ ++ struct syment *sp; ++ int index; ++ ++ if (!spn) ++ return; ++ ++ index = SYMNAME_HASH_INDEX(spn->name); ++ ++ if (st->mod_symname_hash[index] == spn) { ++ st->mod_symname_hash[index] = spn->name_hash_next; ++ return; ++ } ++ ++ for (sp = st->mod_symname_hash[index]; sp; sp = sp->name_hash_next) { ++ if (sp->name_hash_next == spn) { ++ sp->name_hash_next = spn->name_hash_next; ++ return; ++ } ++ } ++} ++ ++static void ++mod_symtable_hash_install_range(struct syment *from, struct syment *to) ++{ ++ struct syment *sp; ++ ++ for (sp = from; sp <= to; sp++) ++ mod_symname_hash_install(sp); ++} ++ ++static void ++mod_symtable_hash_remove_range(struct syment *from, struct syment *to) ++{ ++ struct syment *sp; ++ ++ for (sp = from; sp <= to; sp++) ++ mod_symname_hash_remove(sp); ++} ++ + /* + * Static kernel symbol value search + */ +-- +2.30.2 + diff --git a/0002-symbols-Integrate-symbol_search-with-mod_symname_has.patch b/0002-symbols-Integrate-symbol_search-with-mod_symname_has.patch new file mode 100644 index 0000000..807bbf1 --- /dev/null +++ b/0002-symbols-Integrate-symbol_search-with-mod_symname_has.patch @@ -0,0 +1,103 @@ +From 214f9bf3727c3350401b3f4b4389258c24486e06 Mon Sep 17 00:00:00 2001 +From: Tao Liu +Date: Sat, 16 Oct 2021 13:21:12 +0800 +Subject: [PATCH 2/9] symbols: Integrate symbol_search() with mod_symname_hash + search + +This patch introduces mod_symname_hash search to symbol_search(), +to get a better searching performance. + +Signed-off-by: Tao Liu +Reviewed-by: Philipp Rudo +--- + symbols.c | 58 ++++++++++++++++++------------------------------------- + 1 file changed, 19 insertions(+), 39 deletions(-) + +diff --git a/symbols.c b/symbols.c +index ad12d1c22225..c4ad31fe926f 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -4551,6 +4551,17 @@ symbol_query(char *s, char *print_pad, struct syment **spp) + return(cnt); + } + ++static int ++skip_symbols(struct syment *sp, char *s) ++{ ++ int pseudos, skip = FALSE; ++ ++ pseudos = (strstr(s, "_MODULE_START_") || strstr(s, "_MODULE_END_") || ++ strstr(s, "_MODULE_INIT_START_") || strstr(s, "_MODULE_INIT_END_")); ++ if (!pseudos && MODULE_PSEUDO_SYMBOL(sp)) ++ skip = TRUE; ++ return skip; ++} + + /* + * Return the syment of a symbol. +@@ -4558,10 +4569,7 @@ symbol_query(char *s, char *print_pad, struct syment **spp) + struct syment * + symbol_search(char *s) + { +- int i; +- struct syment *sp_hashed, *sp, *sp_end; +- struct load_module *lm; +- int pseudos, search_init; ++ struct syment *sp_hashed, *sp; + + sp_hashed = symname_hash_search(s); + +@@ -4570,43 +4578,15 @@ symbol_search(char *s) + return(sp); + } + +- pseudos = (strstr(s, "_MODULE_START_") || strstr(s, "_MODULE_END_")); +- search_init = FALSE; +- +- for (i = 0; i < st->mods_installed; i++) { +- lm = &st->load_modules[i]; +- if (lm->mod_flags & MOD_INIT) +- search_init = TRUE; +- sp = lm->mod_symtable; +- sp_end = lm->mod_symend; +- +- for ( ; sp <= sp_end; sp++) { +- if (!pseudos && MODULE_PSEUDO_SYMBOL(sp)) +- continue; +- if (STREQ(s, sp->name)) +- return(sp); +- } +- } +- +- if (!search_init) +- return((struct syment *)NULL); +- +- pseudos = (strstr(s, "_MODULE_INIT_START_") || strstr(s, "_MODULE_INIT_END_")); +- +- for (i = 0; i < st->mods_installed; i++) { +- lm = &st->load_modules[i]; +- if (!lm->mod_init_symtable) ++ sp = st->mod_symname_hash[SYMNAME_HASH_INDEX(s)]; ++ while (sp) { ++ if (skip_symbols(sp, s)) { ++ sp = sp->name_hash_next; + continue; +- sp = lm->mod_init_symtable; +- sp_end = lm->mod_init_symend; +- +- for ( ; sp < sp_end; sp++) { +- if (!pseudos && MODULE_PSEUDO_SYMBOL(sp)) +- continue; +- +- if (STREQ(s, sp->name)) +- return(sp); + } ++ if (STREQ(sp->name, s)) ++ return sp; ++ sp = sp->name_hash_next; + } + + return((struct syment *)NULL); +-- +2.30.2 + diff --git a/0003-symbols-Extend-symname_hash_search-with-hash-table-s.patch b/0003-symbols-Extend-symname_hash_search-with-hash-table-s.patch new file mode 100644 index 0000000..e164e93 --- /dev/null +++ b/0003-symbols-Extend-symname_hash_search-with-hash-table-s.patch @@ -0,0 +1,82 @@ +From 340c6ad1a0a7ce76eb5d9397833bfc6a049e2b3b Mon Sep 17 00:00:00 2001 +From: Tao Liu +Date: Sat, 16 Oct 2021 13:21:13 +0800 +Subject: [PATCH 3/9] symbols: Extend symname_hash_search() with hash table + select + +Previously symname_hash_search() can only search symbols from kernel's +symname_hash. This patch add hash table pointer as parameter for +symname_hash_search(). Thus symname_hash_search() can be used both for +symname_hash and mod_symname_hash searching. + +Signed-off-by: Tao Liu +--- + symbols.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/symbols.c b/symbols.c +index c4ad31fe926f..83393f09270d 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -65,7 +65,7 @@ static void symval_hash_init(void); + static struct syment *symval_hash_search(ulong); + static void symname_hash_init(void); + static void symname_hash_install(struct syment *); +-static struct syment *symname_hash_search(char *); ++static struct syment *symname_hash_search(struct syment *[], char *); + static void gnu_qsort(bfd *, void *, long, unsigned int, asymbol *, asymbol *); + static int check_gnu_debuglink(bfd *); + static int separate_debug_file_exists(const char *, unsigned long, int *); +@@ -1234,11 +1234,11 @@ mod_symtable_hash_remove_range(struct syment *from, struct syment *to) + * Static kernel symbol value search + */ + static struct syment * +-symname_hash_search(char *name) ++symname_hash_search(struct syment *table[], char *name) + { + struct syment *sp; + +- sp = st->symname_hash[SYMNAME_HASH_INDEX(name)]; ++ sp = table[SYMNAME_HASH_INDEX(name)]; + + while (sp) { + if (STREQ(sp->name, name)) +@@ -4571,7 +4571,7 @@ symbol_search(char *s) + { + struct syment *sp_hashed, *sp; + +- sp_hashed = symname_hash_search(s); ++ sp_hashed = symname_hash_search(st->symname_hash, s); + + for (sp = sp_hashed ? sp_hashed : st->symtable; sp < st->symend; sp++) { + if (STREQ(s, sp->name)) +@@ -5485,7 +5485,7 @@ symbol_exists(char *symbol) + struct syment *sp, *sp_end; + struct load_module *lm; + +- if ((sp = symname_hash_search(symbol))) ++ if ((sp = symname_hash_search(st->symname_hash, symbol))) + return TRUE; + + for (i = 0; i < st->mods_installed; i++) { +@@ -5564,7 +5564,7 @@ kernel_symbol_exists(char *symbol) + { + struct syment *sp; + +- if ((sp = symname_hash_search(symbol))) ++ if ((sp = symname_hash_search(st->symname_hash, symbol))) + return TRUE; + else + return FALSE; +@@ -5576,7 +5576,7 @@ kernel_symbol_exists(char *symbol) + struct syment * + kernel_symbol_search(char *symbol) + { +- return symname_hash_search(symbol); ++ return symname_hash_search(st->symname_hash, symbol); + } + + /* +-- +2.30.2 + diff --git a/0004-symbols-Intergrate-symbol_exists-with-mod_symname_ha.patch b/0004-symbols-Intergrate-symbol_exists-with-mod_symname_ha.patch new file mode 100644 index 0000000..e6c67d4 --- /dev/null +++ b/0004-symbols-Intergrate-symbol_exists-with-mod_symname_ha.patch @@ -0,0 +1,74 @@ +From f3bee9375ed32b85e7f81a5e46a0040620553ae0 Mon Sep 17 00:00:00 2001 +From: Tao Liu +Date: Sat, 16 Oct 2021 13:21:14 +0800 +Subject: [PATCH 4/9] symbols: Intergrate symbol_exists() with mod_symname_hash + search + +This patch introduces mod_symname_hash search to symbol_exists() +to improve its performance. And code refactoring for +kernel_symbol_exists(). + +Signed-off-by: Tao Liu +Reviewed-by: Philipp Rudo +--- + symbols.c | 35 ++++------------------------------- + 1 file changed, 4 insertions(+), 31 deletions(-) + +diff --git a/symbols.c b/symbols.c +index 83393f09270d..8d3dd95f737b 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -5481,33 +5481,11 @@ value_symbol(ulong value) + int + symbol_exists(char *symbol) + { +- int i; +- struct syment *sp, *sp_end; +- struct load_module *lm; +- +- if ((sp = symname_hash_search(st->symname_hash, symbol))) ++ if (symname_hash_search(st->symname_hash, symbol)) + return TRUE; + +- for (i = 0; i < st->mods_installed; i++) { +- lm = &st->load_modules[i]; +- sp = lm->mod_symtable; +- sp_end = lm->mod_symend; +- +- for ( ; sp < sp_end; sp++) { +- if (STREQ(symbol, sp->name)) +- return(TRUE); +- } +- +- if (lm->mod_init_symtable) { +- sp = lm->mod_init_symtable; +- sp_end = lm->mod_init_symend; +- +- for ( ; sp < sp_end; sp++) { +- if (STREQ(symbol, sp->name)) +- return(TRUE); +- } +- } +- } ++ if (symname_hash_search(st->mod_symname_hash, symbol)) ++ return TRUE; + + return(FALSE); + } +@@ -5562,12 +5540,7 @@ per_cpu_symbol_search(char *symbol) + int + kernel_symbol_exists(char *symbol) + { +- struct syment *sp; +- +- if ((sp = symname_hash_search(st->symname_hash, symbol))) +- return TRUE; +- else +- return FALSE; ++ return !!symname_hash_search(st->symname_hash, symbol); + } + + /* +-- +2.30.2 + diff --git a/0005-symbols-Sync-module-symbols-into-mod_symtable-whenev.patch b/0005-symbols-Sync-module-symbols-into-mod_symtable-whenev.patch new file mode 100644 index 0000000..4f5e351 --- /dev/null +++ b/0005-symbols-Sync-module-symbols-into-mod_symtable-whenev.patch @@ -0,0 +1,92 @@ +From 1e23335dab6bf9f6219a23bf0be4ad9f433f4f43 Mon Sep 17 00:00:00 2001 +From: Tao Liu +Date: Sat, 16 Oct 2021 13:21:15 +0800 +Subject: [PATCH 5/9] symbols: Sync module symbols into mod_symtable whenever + module symbols change + +Signed-off-by: Tao Liu +Reviewed-by: Philipp Rudo +--- + kernel.c | 1 + + symbols.c | 9 +++++++++ + 2 files changed, 10 insertions(+) + +diff --git a/kernel.c b/kernel.c +index 3ead4bbb172e..f10b8b216571 100644 +--- a/kernel.c ++++ b/kernel.c +@@ -4661,6 +4661,7 @@ reinit_modules(void) + st->ext_module_symtable = NULL; + st->load_modules = NULL; + kt->mods_installed = 0; ++ memset(st->mod_symname_hash, 0, sizeof(st->mod_symname_hash)); + + module_init(); + } +diff --git a/symbols.c b/symbols.c +index 8d3dd95f737b..5603a2efd61f 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -1668,6 +1668,7 @@ store_module_symbols_v1(ulong total, int mods_installed) + lm->mod_symend = sp; + } + } ++ mod_symtable_hash_install_range(lm->mod_symtable, lm->mod_symend); + } + + st->flags |= MODULE_SYMS; +@@ -2148,6 +2149,8 @@ store_module_symbols_v2(ulong total, int mods_installed) + lm->mod_init_symend = sp; + } + } ++ mod_symtable_hash_install_range(lm->mod_symtable, lm->mod_symend); ++ mod_symtable_hash_install_range(lm->mod_init_symtable, lm->mod_init_symend); + } + + st->flags |= MODULE_SYMS; +@@ -12478,8 +12481,10 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms, + 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); + + lm->mod_flags &= ~MOD_EXT_SYMS; + lm->mod_flags |= MOD_LOAD_SYMS; +@@ -12509,6 +12514,7 @@ delete_load_module(ulong base_addr) + req->name = lm->mod_namelist; + gdb_interface(req); + } ++ mod_symtable_hash_remove_range(lm->mod_symtable, lm->mod_symend); + if (lm->mod_load_symtable) { + free(lm->mod_load_symtable); + namespace_ctl(NAMESPACE_FREE, +@@ -12518,6 +12524,7 @@ delete_load_module(ulong base_addr) + unlink_module(lm); + lm->mod_symtable = lm->mod_ext_symtable; + lm->mod_symend = lm->mod_ext_symend; ++ mod_symtable_hash_install_range(lm->mod_symtable, lm->mod_symend); + lm->mod_flags &= ~(MOD_LOAD_SYMS|MOD_REMOTE|MOD_NOPATCH); + lm->mod_flags |= MOD_EXT_SYMS; + lm->mod_load_symtable = NULL; +@@ -12546,6 +12553,7 @@ delete_load_module(ulong base_addr) + req->name = lm->mod_namelist; + gdb_interface(req); + } ++ mod_symtable_hash_remove_range(lm->mod_symtable, lm->mod_symend); + if (lm->mod_load_symtable) { + free(lm->mod_load_symtable); + namespace_ctl(NAMESPACE_FREE, +@@ -12555,6 +12563,7 @@ delete_load_module(ulong base_addr) + unlink_module(lm); + lm->mod_symtable = lm->mod_ext_symtable; + lm->mod_symend = lm->mod_ext_symend; ++ mod_symtable_hash_install_range(lm->mod_symtable, lm->mod_symend); + lm->mod_flags &= ~(MOD_LOAD_SYMS|MOD_REMOTE|MOD_NOPATCH); + lm->mod_flags |= MOD_EXT_SYMS; + lm->mod_load_symtable = NULL; +-- +2.30.2 + diff --git a/0006-symbols-Refactor-SYMNAME_HASH_INDEX-macro-to-be-a-fu.patch b/0006-symbols-Refactor-SYMNAME_HASH_INDEX-macro-to-be-a-fu.patch new file mode 100644 index 0000000..ad57abe --- /dev/null +++ b/0006-symbols-Refactor-SYMNAME_HASH_INDEX-macro-to-be-a-fu.patch @@ -0,0 +1,121 @@ +From df0049d12b2ced1b6ff7350ee3c0ca28c3f7cd52 Mon Sep 17 00:00:00 2001 +From: Tao Liu +Date: Sat, 16 Oct 2021 13:21:16 +0800 +Subject: [PATCH 6/9] symbols: Refactor SYMNAME_HASH_INDEX macro to be a + function + +SYMNAME_HASH_INDEX is used as the index of symname hash table. It will +be out of range if SYMNAME_HASH_INDEX is negative. This patch avoids +the risk by changing the marco into a function, and casting and calculating +the numbers as unsigned. + +Suggested-by: Lianbo Jiang +Suggested-by: Philipp Rudo +Signed-off-by: Tao Liu +--- + defs.h | 2 -- + symbols.c | 31 +++++++++++++++++++++++-------- + 2 files changed, 23 insertions(+), 10 deletions(-) + +diff --git a/defs.h b/defs.h +index bbdca799f72d..8b356d5e8959 100644 +--- a/defs.h ++++ b/defs.h +@@ -2728,8 +2728,6 @@ struct downsized { + (((vaddr) >> machdep->pageshift) % SYMVAL_HASH) + + #define SYMNAME_HASH (512) +-#define SYMNAME_HASH_INDEX(name) \ +- ((name[0] ^ (name[strlen(name)-1] * name[strlen(name)/2])) % SYMNAME_HASH) + + #define PATCH_KERNEL_SYMBOLS_START ((char *)(1)) + #define PATCH_KERNEL_SYMBOLS_STOP ((char *)(2)) +diff --git a/symbols.c b/symbols.c +index 5603a2efd61f..67b701454563 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -1127,6 +1127,21 @@ symname_hash_init(void) + st->__per_cpu_end = sp->value; + } + ++static unsigned int ++symname_hash_index(char *name) ++{ ++ unsigned int len, value; ++ unsigned char *array = (unsigned char *)name; ++ ++ len = strlen(name); ++ if (!len) ++ error(FATAL, "The length of the symbol name is zero!\n"); ++ ++ value = array[len - 1] * array[len / 2]; ++ ++ return (array[0] ^ value) % SYMNAME_HASH; ++} ++ + /* + * Install a single static kernel symbol into the symname_hash. + */ +@@ -1134,9 +1149,9 @@ static void + symname_hash_install(struct syment *spn) + { + struct syment *sp; +- int index; ++ unsigned int index; + +- index = SYMNAME_HASH_INDEX(spn->name); ++ index = symname_hash_index(spn->name); + spn->cnt = 1; + + if ((sp = st->symname_hash[index]) == NULL) +@@ -1164,12 +1179,12 @@ static void + mod_symname_hash_install(struct syment *spn) + { + struct syment *sp; +- int index; ++ unsigned int index; + + if (!spn) + return; + +- index = SYMNAME_HASH_INDEX(spn->name); ++ index = symname_hash_index(spn->name); + + sp = st->mod_symname_hash[index]; + +@@ -1192,12 +1207,12 @@ static void + mod_symname_hash_remove(struct syment *spn) + { + struct syment *sp; +- int index; ++ unsigned int index; + + if (!spn) + return; + +- index = SYMNAME_HASH_INDEX(spn->name); ++ index = symname_hash_index(spn->name); + + if (st->mod_symname_hash[index] == spn) { + st->mod_symname_hash[index] = spn->name_hash_next; +@@ -1238,7 +1253,7 @@ symname_hash_search(struct syment *table[], char *name) + { + struct syment *sp; + +- sp = table[SYMNAME_HASH_INDEX(name)]; ++ sp = table[symname_hash_index(name)]; + + while (sp) { + if (STREQ(sp->name, name)) +@@ -4581,7 +4596,7 @@ symbol_search(char *s) + return(sp); + } + +- sp = st->mod_symname_hash[SYMNAME_HASH_INDEX(s)]; ++ sp = st->mod_symname_hash[symname_hash_index(s)]; + while (sp) { + if (skip_symbols(sp, s)) { + sp = sp->name_hash_next; +-- +2.30.2 + diff --git a/0007-symbols-Add-mod_symname_hash-table-dump-to-help-s.patch b/0007-symbols-Add-mod_symname_hash-table-dump-to-help-s.patch new file mode 100644 index 0000000..87d6c27 --- /dev/null +++ b/0007-symbols-Add-mod_symname_hash-table-dump-to-help-s.patch @@ -0,0 +1,99 @@ +From 5c04a6f3f923af7c50f0d853477044802b3fa6ec Mon Sep 17 00:00:00 2001 +From: Tao Liu +Date: Sat, 16 Oct 2021 13:21:17 +0800 +Subject: [PATCH 7/9] symbols: Add mod_symname_hash table dump to help -s + +Previously, help -s only print out the dump status of symname_hash +table. Since we have mod_symname_hash table introduced, let's print +out mod_symname_hash in help -s as well. + +Signed-off-by: Tao Liu +--- + symbols.c | 57 ++++++++++++++++++++++++++++++++++--------------------- + 1 file changed, 35 insertions(+), 22 deletions(-) + +diff --git a/symbols.c b/symbols.c +index 67b701454563..73baa953217a 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -3219,13 +3219,40 @@ kallsyms_module_function_size(struct syment *sp, struct load_module *lm, ulong * + return FALSE; + } + ++static void ++dump_symname_hash_table(struct syment *table[]) ++{ ++ int i, cnt, tot; ++ struct syment *sp; ++ ++ fprintf(fp, " "); ++ for (i = tot = 0; i < SYMNAME_HASH; i++) { ++ fprintf(fp, "[%3d]: ", i); ++ if ((sp = table[i]) == NULL) ++ fprintf(fp, "%3d ", 0); ++ else { ++ cnt = 1; ++ while (sp->name_hash_next) { ++ cnt++; ++ sp = sp->name_hash_next; ++ } ++ fprintf(fp, "%3d ", cnt); ++ tot += cnt; ++ } ++ if (i && (((i+1) % 6) == 0)) ++ fprintf(fp, "\n "); ++ } ++ if (SYMNAME_HASH % 6) ++ fprintf(fp, "\n"); ++} ++ + /* + * "help -s" output + */ + void + dump_symbol_table(void) + { +- int i, s, cnt, tot; ++ int i, s, cnt; + struct load_module *lm; + struct syment *sp; + struct downsized *ds; +@@ -3355,28 +3382,14 @@ dump_symbol_table(void) + + fprintf(fp, " symname_hash[%d]: %lx\n", SYMNAME_HASH, + (ulong)&st->symname_hash[0]); ++ if (CRASHDEBUG(1)) ++ dump_symname_hash_table(st->symname_hash); ++ ++ fprintf(fp, "mod_symname_hash[%d]: %lx\n", SYMNAME_HASH, ++ (ulong)&st->mod_symname_hash[0]); ++ if (CRASHDEBUG(1)) ++ dump_symname_hash_table(st->mod_symname_hash); + +- if (CRASHDEBUG(1)) { +- fprintf(fp, " "); +- for (i = tot = 0; i < SYMNAME_HASH; i++) { +- fprintf(fp, "[%3d]: ", i); +- if ((sp = st->symname_hash[i]) == NULL) +- fprintf(fp, "%3d ", 0); +- else { +- cnt = 1; +- while (sp->name_hash_next) { +- cnt++; +- sp = sp->name_hash_next; +- } +- fprintf(fp, "%3d ", cnt); +- tot += cnt; +- } +- if (i && (((i+1) % 6) == 0)) +- fprintf(fp, "\n "); +- } +- if (SYMNAME_HASH % 6) +- fprintf(fp, "\n"); +- } + fprintf(fp, " symbol_namespace: "); + fprintf(fp, "address: %lx ", (ulong)st->kernel_namespace.address); + fprintf(fp, "index: %ld ", st->kernel_namespace.index); +-- +2.30.2 + diff --git a/0008-arm64-Use-VA_BITS-for-page_offset-calculation.patch b/0008-arm64-Use-VA_BITS-for-page_offset-calculation.patch new file mode 100644 index 0000000..b987041 --- /dev/null +++ b/0008-arm64-Use-VA_BITS-for-page_offset-calculation.patch @@ -0,0 +1,66 @@ +From c180a63f2cb370da6097ad97eb07333c07aa988b Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Mon, 25 Oct 2021 16:53:26 +0900 +Subject: [PATCH 8/9] arm64: Use VA_BITS for page_offset calculation + +Commit 167d37e347fe ("arm64: assign page_offset with VA_BITS kernel +configuration value") changed the page_offset calculation from +using VA_BITS_ACTUAL to CONFIG_ARM64_VA_BITS. This caused an error +for ramdumps without vmcoreinfo like this: + + crash: vmlinux and /var/tmp/ramdump_elf_XUtCMT do not match! + +Set the vmcoreinfo value to VA_BITS if available, and use VA_BITS +for page_offset calculation instead. + +Also remove ARM64_FLIP_PAGE_OFFSET_ACTUAL because it's not used +actually. + +Reported-by: Ankur Bansal +Signed-off-by: Kazuhito Hagio +--- + arm64.c | 5 ++++- + defs.h | 4 +--- + 2 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/arm64.c b/arm64.c +index 7069312671cf..3dcbcc642fda 100644 +--- a/arm64.c ++++ b/arm64.c +@@ -404,7 +404,7 @@ arm64_init(int when) + fprintf(fp, "CONFIG_ARM64_VA_BITS: %ld\n", ms->CONFIG_ARM64_VA_BITS); + fprintf(fp, " VA_BITS_ACTUAL: %ld\n", ms->VA_BITS_ACTUAL); + fprintf(fp, "(calculated) VA_BITS: %ld\n", ms->VA_BITS); +- fprintf(fp, " PAGE_OFFSET: %lx\n", ARM64_FLIP_PAGE_OFFSET_ACTUAL); ++ fprintf(fp, " PAGE_OFFSET: %lx\n", ARM64_FLIP_PAGE_OFFSET); + fprintf(fp, " VA_START: %lx\n", ms->VA_START); + fprintf(fp, " modules: %lx - %lx\n", ms->modules_vaddr, ms->modules_end); + fprintf(fp, " vmalloc: %lx - %lx\n", ms->vmalloc_start_addr, ms->vmalloc_end); +@@ -4031,6 +4031,9 @@ arm64_calc_VA_BITS(void) + error(FATAL, "cannot determine VA_BITS_ACTUAL\n"); + } + ++ if (machdep->machspec->CONFIG_ARM64_VA_BITS) ++ machdep->machspec->VA_BITS = machdep->machspec->CONFIG_ARM64_VA_BITS; ++ + /* + * The mm flip commit is introduced before 52-bits VA, which is before the + * commit to export NUMBER(TCR_EL1_T1SZ) +diff --git a/defs.h b/defs.h +index 8b356d5e8959..971005596506 100644 +--- a/defs.h ++++ b/defs.h +@@ -3238,9 +3238,7 @@ typedef signed int s32; + #define ARM64_PAGE_OFFSET ((0xffffffffffffffffUL) \ + << (machdep->machspec->VA_BITS - 1)) + /* kernels >= v5.4 the kernel VA space is flipped */ +-#define ARM64_FLIP_PAGE_OFFSET (-(1UL) << machdep->machspec->CONFIG_ARM64_VA_BITS) +-#define ARM64_FLIP_PAGE_OFFSET_ACTUAL ((0xffffffffffffffffUL) \ +- - ((1UL) << machdep->machspec->VA_BITS_ACTUAL) + 1) ++#define ARM64_FLIP_PAGE_OFFSET (-(1UL) << machdep->machspec->VA_BITS) + + #define ARM64_USERSPACE_TOP ((1UL) << machdep->machspec->VA_BITS) + #define ARM64_USERSPACE_TOP_ACTUAL ((1UL) << machdep->machspec->VA_BITS_ACTUAL) +-- +2.30.2 + diff --git a/0009-Handle-task_struct-cpu-member-changes-for-kernels-5..patch b/0009-Handle-task_struct-cpu-member-changes-for-kernels-5..patch new file mode 100644 index 0000000..2d08984 --- /dev/null +++ b/0009-Handle-task_struct-cpu-member-changes-for-kernels-5..patch @@ -0,0 +1,57 @@ +From 68870c83d299603c07785e3530e33c13045c87ef Mon Sep 17 00:00:00 2001 +From: Alexander Egorenkov +Date: Wed, 13 Oct 2021 10:56:39 +0200 +Subject: [PATCH 9/9] Handle task_struct cpu member changes for kernels >= + 5.16-rc1 + +Kernel commit bcf9033e5449bdcaa9bed46467a7141a8049dadb +("sched: move CPU field back into thread_info if THREAD_INFO_IN_TASK=y") +moved the member cpu of task_struct back into thread_info. +Without the patch, crash fails with the following error message +during session initialization: + + crash: invalid structure member offset: task_struct_cpu + FILE: task.c LINE: 2904 FUNCTION: add_context() + +Signed-off-by: Alexander Egorenkov +Signed-off-by: Kazuhito Hagio +--- + task.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/task.c b/task.c +index 672b41697e75..bb6a5da8ad33 100644 +--- a/task.c ++++ b/task.c +@@ -278,8 +278,10 @@ task_init(void) + } else if (VALID_MEMBER(task_struct_stack)) + MEMBER_OFFSET_INIT(task_struct_thread_info, "task_struct", "stack"); + ++ MEMBER_OFFSET_INIT(task_struct_cpu, "task_struct", "cpu"); ++ + if (VALID_MEMBER(task_struct_thread_info)) { +- if (tt->flags & THREAD_INFO_IN_TASK) { ++ if (tt->flags & THREAD_INFO_IN_TASK && VALID_MEMBER(task_struct_cpu)) { + MEMBER_OFFSET_INIT(thread_info_flags, "thread_info", "flags"); + /* (unnecessary) reminders */ + ASSIGN_OFFSET(thread_info_task) = INVALID_OFFSET; +@@ -315,7 +317,6 @@ task_init(void) + MEMBER_OFFSET_INIT(task_struct_has_cpu, "task_struct", "has_cpu"); + MEMBER_OFFSET_INIT(task_struct_cpus_runnable, + "task_struct", "cpus_runnable"); +- MEMBER_OFFSET_INIT(task_struct_cpu, "task_struct", "cpu"); + MEMBER_OFFSET_INIT(task_struct_active_mm, "task_struct", "active_mm"); + MEMBER_OFFSET_INIT(task_struct_next_run, "task_struct", "next_run"); + MEMBER_OFFSET_INIT(task_struct_flags, "task_struct", "flags"); +@@ -2900,7 +2901,7 @@ add_context(ulong task, char *tp) + else + tc->thread_info = ULONG(tp + OFFSET(task_struct_thread_info)); + fill_thread_info(tc->thread_info); +- if (tt->flags & THREAD_INFO_IN_TASK) ++ if (tt->flags & THREAD_INFO_IN_TASK && VALID_MEMBER(task_struct_cpu)) + processor_addr = (int *) (tp + OFFSET(task_struct_cpu)); + else + processor_addr = (int *) (tt->thread_info + +-- +2.30.2 + diff --git a/crash.spec b/crash.spec index f8348d7..e3af485 100644 --- a/crash.spec +++ b/crash.spec @@ -4,7 +4,7 @@ Summary: Kernel analysis utility for live systems, netdump, diskdump, kdump, LKCD or mcore dumpfiles Name: crash Version: 7.3.0 -Release: 4%{?dist} +Release: 5%{?dist} License: GPLv3 Source0: https://github.com/crash-utility/crash/archive/crash-%{version}.tar.gz Source1: http://ftp.gnu.org/gnu/gdb/gdb-10.2.tar.gz @@ -61,6 +61,15 @@ Patch40: 0024-Set-gdb-max-value-size-to-be-unlimited.patch Patch41: 0025-Fix-tab-completion-issues.patch Patch42: 0026-Remove-text-value-cache-code.patch Patch43: 0027-.gitignore-add-gdb-10.2-directory.patch +Patch44: 0001-symbols-Implement-install-and-remove-operations-for-.patch +Patch45: 0002-symbols-Integrate-symbol_search-with-mod_symname_has.patch +Patch46: 0003-symbols-Extend-symname_hash_search-with-hash-table-s.patch +Patch47: 0004-symbols-Intergrate-symbol_exists-with-mod_symname_ha.patch +Patch48: 0005-symbols-Sync-module-symbols-into-mod_symtable-whenev.patch +Patch49: 0006-symbols-Refactor-SYMNAME_HASH_INDEX-macro-to-be-a-fu.patch +Patch50: 0007-symbols-Add-mod_symname_hash-table-dump-to-help-s.patch +Patch51: 0008-arm64-Use-VA_BITS-for-page_offset-calculation.patch +Patch52: 0009-Handle-task_struct-cpu-member-changes-for-kernels-5..patch %description The core analysis suite is a self-contained tool that can be used to @@ -124,6 +133,15 @@ offered by Mission Critical Linux, or the LKCD kernel patch. %patch41 -p1 %patch42 -p1 %patch43 -p1 +%patch44 -p1 +%patch45 -p1 +%patch46 -p1 +%patch47 -p1 +%patch48 -p1 +%patch49 -p1 +%patch50 -p1 +%patch51 -p1 +%patch52 -p1 %build # This package has an internal copy of GDB which has broken configure code for @@ -157,6 +175,9 @@ cp -p defs.h %{buildroot}%{_includedir}/crash %{_includedir}/* %changelog +* Sat Nov 06 2021 Lianbo Jiang - 7.3.0-5 +- Update to the latest upstream: commit <68870c83d299> + * Tue Oct 12 2021 Lianbo Jiang - 7.3.0-4 - Update to gdb-10.2