<div dir="ltr"><div dir="ltr">On Tue, Jun 20, 2023 at 9:36 AM lijiang <<a href="mailto:lijiang@redhat.com">lijiang@redhat.com</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr">On Wed, Jun 14, 2023 at 4:06 PM HAGIO KAZUHITO(萩尾 一仁) <<a href="mailto:k-hagio-ab@nec.com" target="_blank">k-hagio-ab@nec.com</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Support module memory layout change on Linux 6.4 by kernel commit<br>
ac3b43283923 ("module: replace module_layout with module_memory") [1].<br>
Without the patch, crash cannot even start a session with an error<br>
message like this:<br>
<br>
  crash: invalid structure member offset: module_core_size<br>
         FILE: kernel.c  LINE: 3787  FUNCTION: module_init()<br>
<br>
[1] <a href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ac3b43283923" rel="noreferrer" target="_blank">https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ac3b43283923</a><br>
<br>
Signed-off-by: Kazuhito Hagio <<a href="mailto:k-hagio-ab@nec.com" target="_blank">k-hagio-ab@nec.com</a>><br>
---<br>
RFC -> v1<br>
- Applied a lot of Lianbo's comments and discussions<br>
- Rewrote {next,prev}_symbol() and splitted functions to skip regions<br>
  that have only pseudo symbols<br>
- Squashed the patchset into one patch, after all<br>
  (Please let me know if there are changes that should be splitted.)<br>
<br>
 defs.h         |   46 +-<br>
 gdb-10.2.patch |   16 +<br>
 kernel.c       |   54 +-<br>
 memory.c       |   36 +-<br>
 symbols.c      | 1588 ++++++++++++++++++++++++++++++++++++++++++++----<br>
 5 files changed, 1607 insertions(+), 133 deletions(-)<br>
<br></blockquote><div><br></div><div>Good job, Kazu.</div><div><br></div><div>The other changes look good, and I don't see any regression issues on my side. But I still have two comments below:</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
diff --git a/defs.h b/defs.h<br>
index bfda0c48d37b..96ea7630123f 100644<br>
--- a/defs.h<br>
+++ b/defs.h<br>
@@ -675,6 +675,7 @@ struct new_utsname {<br>
 #define IRQ_DESC_TREE_RADIX        (0x40ULL)<br>
 #define IRQ_DESC_TREE_XARRAY       (0x80ULL)<br>
 #define KMOD_PAX                  (0x100ULL)<br>
+#define KMOD_MEMORY               (0x200ULL)<br>
<br>
 #define XEN()       (kt->flags & ARCH_XEN)<br>
 #define OPENVZ()    (kt->flags & ARCH_OPENVZ)<br>
@@ -682,6 +683,7 @@ struct new_utsname {<br>
 #define PVOPS_XEN() (kt->flags & ARCH_PVOPS_XEN)<br>
<br>
 #define PAX_MODULE_SPLIT() (kt->flags2 & KMOD_PAX)<br>
+#define MODULE_MEMORY()    (kt->flags2 & KMOD_MEMORY)<br>
<br>
 #define XEN_MACHINE_TO_MFN(m)    ((ulonglong)(m) >> PAGESHIFT())<br>
 #define XEN_PFN_TO_PSEUDO(p)     ((ulonglong)(p) << PAGESHIFT())<br>
@@ -2220,6 +2222,9 @@ struct offset_table {                    /* stash of commonly-used offsets */<br>
        long kset_kobj;<br>
        long subsys_private_subsys;<br>
        long vmap_area_purge_list;<br>
+       long module_mem;<br>
+       long module_memory_base;<br>
+       long module_memory_size;<br>
 };<br>
<br>
 struct size_table {         /* stash of commonly-used sizes */<br>
@@ -2393,6 +2398,7 @@ struct size_table {         /* stash of commonly-used sizes */<br>
        long percpu_counter;<br>
        long maple_tree;<br>
        long maple_node;<br>
+       long module_memory;<br>
 };<br>
<br>
 struct array_table {<br>
@@ -2925,6 +2931,23 @@ struct mod_section_data {<br>
         ulong size;<br>
         int priority;<br>
         int flags;<br>
+       ulong addr;<br>
+};<br>
+<br>
+/* Emulate enum mod_mem_type in include/linux/module.h */<br>
+#define MOD_TEXT               (0)<br>
+#define MOD_DATA               (1)<br>
+#define MOD_RODATA             (2)<br>
+#define MOD_RO_AFTER_INIT      (3)<br>
+#define MOD_INIT_TEXT          (4)<br>
+#define MOD_INIT_DATA          (5)<br>
+#define MOD_INIT_RODATA                (6)<br>
+#define MOD_MEM_NUM_TYPES      (7)<br>
+#define MOD_INVALID            (-1)<br>
+<br>
+struct module_memory {<br>
+       ulong base;<br>
+       uint size;<br>
 };<br>
<br>
 struct load_module {<br>
@@ -2960,19 +2983,29 @@ struct load_module {<br>
        ulong mod_percpu;<br>
        ulong mod_percpu_size;<br>
        struct objfile *loaded_objfile;<br>
-};<br>
<br>
-#define IN_MODULE(A,L) \<br>
- (((ulong)(A) >= (L)->mod_base) && ((ulong)(A) < ((L)->mod_base+(L)->mod_size)))<br>
-<br>
-#define IN_MODULE_INIT(A,L) \<br>
- (((ulong)(A) >= (L)->mod_init_module_ptr) && ((ulong)(A) < ((L)->mod_init_module_ptr+(L)->mod_init_size)))<br>
+       /* For 6.4 module_memory */<br>
+       struct module_memory mem[MOD_MEM_NUM_TYPES];<br>
+       struct syment **symtable;<br>
+       struct syment **symend;<br>
+       struct syment *ext_symtable[MOD_MEM_NUM_TYPES];<br>
+       struct syment *ext_symend[MOD_MEM_NUM_TYPES];<br>
+       struct syment *load_symtable[MOD_MEM_NUM_TYPES];<br>
+       struct syment *load_symend[MOD_MEM_NUM_TYPES];<br>
+};<br>
<br>
+#define IN_MODULE(A,L)         (in_module_range(A, L, MOD_TEXT, MOD_RO_AFTER_INIT) != MOD_INVALID)<br>
+#define IN_MODULE_INIT(A,L)    (in_module_range(A, L, MOD_INIT_TEXT, MOD_INIT_RODATA) != MOD_INVALID)<br>
+#define IN_MODULE_TEXT(A,L)    (in_module_range(A, L, MOD_TEXT, MOD_TEXT) == MOD_TEXT || \<br>
+                               in_module_range(A, L, MOD_INIT_TEXT, MOD_INIT_TEXT) == MOD_INIT_TEXT)<br>
 #define IN_MODULE_PERCPU(A,L) \<br>
  (((ulong)(A) >= (L)->mod_percpu) && ((ulong)(A) < ((L)->mod_percpu+(L)->mod_percpu_size)))<br>
<br>
 #define MODULE_PERCPU_SYMS_LOADED(L) ((L)->mod_percpu && (L)->mod_percpu_size)<br>
<br>
+#define for_each_mod_mem_type(type) \<br>
+       for (int (type) = MOD_TEXT; (type) < MOD_MEM_NUM_TYPES; (type)++)<br>
+<br>
 #ifndef GDB_COMMON<br>
<br>
 #define KVADDR             (0x1)<br>
@@ -5591,6 +5624,7 @@ void dump_struct_member(char *, ulong, unsigned);<br>
 void dump_union(char *, ulong, unsigned);<br>
 void store_module_symbols_v1(ulong, int);<br>
 void store_module_symbols_v2(ulong, int);<br>
+void store_module_symbols_6_4(ulong, int);<br>
 int is_datatype_command(void);<br>
 int is_typedef(char *);<br>
 int arg_to_datatype(char *, struct datatype_member *, ulong);<br>
diff --git a/gdb-10.2.patch b/gdb-10.2.patch<br>
index 835aae9859be..b3f6d8b086eb 100644<br>
--- a/gdb-10.2.patch<br>
+++ b/gdb-10.2.patch<br>
@@ -3120,3 +3120,19 @@ exit 0<br>
    return result;<br>
  }<br>
<br>
+--- gdb-10.2/gdb/symtab.c.orig<br>
++++ gdb-10.2/gdb/symtab.c<br>
+@@ -7515,8 +7515,11 @@ gdb_add_symbol_file(struct gnu_request *<br>
+                             secname = lm->mod_section_data[i].name;<br>
+                             if ((lm->mod_section_data[i].flags & SEC_FOUND) &&<br>
+                                 !STREQ(secname, ".text")) {<br>
+-                                    sprintf(buf, " -s %s 0x%lx", secname,<br>
+-                                        lm->mod_section_data[i].offset + lm->mod_base);<br>
++                                    if (lm->mod_section_data[i].addr)<br>
++                                        sprintf(buf, " -s %s 0x%lx", secname, lm->mod_section_data[i].addr);<br>
++                                    else<br>
++                                        sprintf(buf, " -s %s 0x%lx", secname,<br>
++                                            lm->mod_section_data[i].offset + lm->mod_base);<br>
+                                     strcat(req->buf, buf);<br>
+                             }<br>
+                     }<br></blockquote></div></div></blockquote><div> </div><div>BTW: I can still get the following warnings:</div><div>...</div>  CXX    symtab.o<br>symtab.c: In function ‘void gdb_command_funnel_1(gnu_request*)’:<br>symtab.c:7519:64: warning: ‘%lx’ directive writing between 1 and 16 bytes into a region of size between 10 and 73 [-Wformat-overflow=]<br> 7519 |                                         sprintf(buf, " -s %s 0x%lx", secname, lm->mod_section_data[i].addr);<br>      |                                                                ^~~<br>symtab.c:7519:54: note: directive argument in the range [1, 18446744073709551615]<br> 7519 |                                         sprintf(buf, " -s %s 0x%lx", secname, lm->mod_section_data[i].addr);<br>      |                                                      ^~~~~~~~~~~~~~<br><div><br></div><div>Thanks.</div><div>Lianbo</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
diff --git a/kernel.c b/kernel.c<br>
index 6e98f5f6f6b1..a4d20f5b122e 100644<br>
--- a/kernel.c<br>
+++ b/kernel.c<br>
@@ -3571,7 +3571,21 @@ module_init(void)<br>
                MEMBER_OFFSET_INIT(module_num_gpl_syms, "module", <br>
                        "num_gpl_syms");<br>
<br>
-               if (MEMBER_EXISTS("module", "module_core")) {<br>
+               if (MEMBER_EXISTS("module", "mem")) {   /* 6.4 and later */<br>
+                       kt->flags2 |= KMOD_MEMORY;      /* MODULE_MEMORY() can be used. */<br>
+<br>
+                       MEMBER_OFFSET_INIT(module_mem, "module", "mem");<br>
+                       MEMBER_OFFSET_INIT(module_memory_base, "module_memory", "base");<br>
+                       MEMBER_OFFSET_INIT(module_memory_size, "module_memory", "size");<br>
+                       STRUCT_SIZE_INIT(module_memory, "module_memory");<br>
+<br>
+                       if (CRASHDEBUG(1))<br>
+                               error(INFO, "struct module_memory detected.\n");<br>
+<br>
+                       if (get_array_length("module.mem", NULL, 0) != MOD_MEM_NUM_TYPES)<br>
+                               error(WARNING, "module memory types have changed!\n");<br>
+<br>
+               } else if (MEMBER_EXISTS("module", "module_core")) {<br>
                        MEMBER_OFFSET_INIT(module_core_size, "module",<br>
                                           "core_size");<br>
                        MEMBER_OFFSET_INIT(module_init_size, "module",<br>
@@ -3757,6 +3771,8 @@ module_init(void)<br>
                total += nsyms;<br>
                total += 2;  /* store the module's start/ending addresses */<br>
                total += 2;  /* and the init start/ending addresses */<br>
+               if (MODULE_MEMORY()) /* 7 regions at most -> 14, so needs +10 */<br>
+                       total += 10;<br>
<br>
                /*<br>
                 *  If the module has kallsyms, set up to grab them as well.<br>
@@ -3784,7 +3800,11 @@ module_init(void)<br>
                case KALLSYMS_V2:<br>
                        if (THIS_KERNEL_VERSION >= LINUX(2,6,27)) {<br>
                                numksyms = UINT(modbuf + OFFSET(module_num_symtab));<br>
-                               size = UINT(modbuf + MODULE_OFFSET2(module_core_size, rx));<br>
+                               if (MODULE_MEMORY())<br>
+                                       /* check mem[MOD_TEXT].size only */<br>
+                                       size = UINT(modbuf + OFFSET(module_mem) + OFFSET(module_memory_size));<br>
+                               else<br>
+                                       size = UINT(modbuf + MODULE_OFFSET2(module_core_size, rx));<br>
                        } else {<br>
                                numksyms = ULONG(modbuf + OFFSET(module_num_symtab));<br>
                                size = ULONG(modbuf + MODULE_OFFSET2(module_core_size, rx));<br>
@@ -3822,7 +3842,10 @@ module_init(void)<br>
                store_module_symbols_v1(total, kt->mods_installed);<br>
                break;<br>
        case KMOD_V2:<br>
-               store_module_symbols_v2(total, kt->mods_installed);<br>
+               if (MODULE_MEMORY())<br>
+                       store_module_symbols_6_4(total, kt->mods_installed);<br>
+               else<br>
+                       store_module_symbols_v2(total, kt->mods_installed);<br>
                break;<br>
        }<br>
<br>
@@ -3893,8 +3916,13 @@ verify_modules(void)<br>
                                mod_base = mod;<br>
                                break;<br>
                        case KMOD_V2:<br>
-                               mod_base = ULONG(modbuf + <br>
-                                       MODULE_OFFSET2(module_module_core, rx));<br>
+                               if (MODULE_MEMORY())<br>
+                                       /* mem[MOD_TEXT].base */<br>
+                                       mod_base = ULONG(modbuf + OFFSET(module_mem) +<br>
+                                                       OFFSET(module_memory_base));<br>
+                               else<br>
+                                       mod_base = ULONG(modbuf +<br>
+                                               MODULE_OFFSET2(module_module_core, rx));<br>
                                break;<br>
                        }<br>
<br>
@@ -3916,7 +3944,17 @@ verify_modules(void)<br>
                                case KMOD_V2:<br>
                                        module_name = modbuf + <br>
                                                OFFSET(module_name);<br>
-                                       if (THIS_KERNEL_VERSION >= LINUX(2,6,27))<br>
+                                       if (MODULE_MEMORY()) {<br>
+                                               mod_size = 0;<br>
+                                               for_each_mod_mem_type(t) {<br>
+                                                       if (t == MOD_INIT_TEXT)<br>
+                                                               break;<br>
+<br>
+                                                       mod_size += UINT(modbuf + OFFSET(module_mem) +<br>
+                                                                       SIZE(module_memory) * t +<br>
+                                                                       OFFSET(module_memory_size));<br>
+                                               }<br>
+                                       } else if (THIS_KERNEL_VERSION >= LINUX(2,6,27))<br>
                                                mod_size = UINT(modbuf +<br>
                                                        MODULE_OFFSET2(module_core_size, rx));<br>
                                        else<br>
@@ -4536,7 +4574,7 @@ do_module_cmd(ulong flag, char *modref, ulong address,<br>
                                "MODULE"),<br>
                                mkstring(buf2, maxnamelen, LJUST, "NAME"),<br>
                                mkstring(buf4, VADDR_PRLEN, CENTER|LJUST,<br>
-                               "BASE"),<br>
+                               MODULE_MEMORY() ? "TEXT_BASE" : "BASE"),<br>
                                mkstring(buf3, maxsizelen, RJUST, "SIZE"));<br>
                }<br>
<br>
@@ -6144,6 +6182,8 @@ dump_kernel_table(int verbose)<br>
                fprintf(fp, "%sIRQ_DESC_TREE_XARRAY", others++ ? "|" : "");<br>
        if (kt->flags2 & KMOD_PAX)<br>
                fprintf(fp, "%sKMOD_PAX", others++ ? "|" : "");<br>
+       if (kt->flags2 & KMOD_MEMORY)<br>
+               fprintf(fp, "%sKMOD_MEMORY", others++ ? "|" : "");<br>
        fprintf(fp, ")\n");<br>
<br>
         fprintf(fp, "         stext: %lx\n", kt->stext);<br>
diff --git a/memory.c b/memory.c<br>
index ea3005a5c01f..f282aee59952 100644<br>
--- a/memory.c<br>
+++ b/memory.c<br>
@@ -15713,9 +15713,43 @@ static int<br>
 next_module_vaddr(ulong vaddr, ulong *nextvaddr)<br>
 {<br>
        int i;<br>
-       ulong start, end;<br>
+       ulong start, end, min = (ulong)-1;<br>
        struct load_module *lm;<br>
<br>
+       if (!MODULE_MEMORY())<br>
+               goto old_module;<br>
+<br>
+       for (i = 0; i < st->mods_installed; i++) {<br>
+               lm = &st->load_modules[i];<br>
+<br>
+               for_each_mod_mem_type(t) {<br>
+                       if (!lm->mem[t].size)<br>
+                               continue;<br>
+<br>
+                       start = lm->mem[t].base;<br>
+                       end = start + lm->mem[t].size;<br>
+<br>
+                       if (vaddr >= end)<br>
+                               continue;<br>
+<br>
+                       if (vaddr < start) {<br>
+                               if (start < min) /* replace candidate */<br>
+                                       min = start;<br>
+                               continue;<br>
+                       }<br>
+<br>
+                       *nextvaddr = vaddr;<br>
+                       return TRUE;<br>
+               }<br>
+       }<br>
+<br>
+       if (min != (ulong)-1) {<br>
+               *nextvaddr = min;<br>
+               return TRUE;<br>
+       }<br>
+       return FALSE;<br>
+<br>
+old_module:<br>
        for (i = 0; i < st->mods_installed; i++) {<br>
                lm = &st->load_modules[i];<br>
                start = lm->mod_base;<br>
diff --git a/symbols.c b/symbols.c<br>
index 7b1d59203b90..41a50ced8abd 100644<br>
--- a/symbols.c<br>
+++ b/symbols.c<br>
@@ -48,8 +48,8 @@ static int load_module_index(struct syment *);<br>
 static void section_header_info(bfd *, asection *, void *);<br>
 static void store_section_data(struct load_module *, bfd *, asection *);<br>
 static void calculate_load_order_v1(struct load_module *, bfd *);<br>
-static void calculate_load_order_v2(struct load_module *, bfd *, int,<br>
-        void *, long, unsigned int);<br>
+static void calculate_load_order_v2(struct load_module *, bfd *, int, void *, long, unsigned int);<br>
+static void calculate_load_order_6_4(struct load_module *, bfd *, int, void *, long, unsigned int);<br>
 static void check_insmod_builtin(struct load_module *, int, ulong *);<br>
 static int is_insmod_builtin(struct load_module *, struct syment *);<br>
 struct load_module;<br>
@@ -104,6 +104,42 @@ static unsigned char is_right_brace(const char *);<br>
 static struct struct_elem *find_node(struct struct_elem *, char *);<br>
 static void dump_node(struct struct_elem *, char *, unsigned char, unsigned char);<br>
<br>
+static int module_mem_type(ulong, struct load_module *);<br>
+static ulong module_mem_end(ulong, struct load_module *);<br>
+static int in_module_range(ulong, struct load_module *, int, int);<br>
+struct syment *value_search_module_6_4(ulong, ulong *);<br>
+struct syment *next_symbol_by_symname(char *);<br>
+struct syment *prev_symbol_by_symname(char *);<br>
+struct syment *next_module_symbol_by_value(ulong);<br>
+struct syment *prev_module_symbol_by_value(ulong);<br>
+struct syment *next_module_symbol_by_syment(struct syment *);<br>
+struct syment *prev_module_symbol_by_syment(struct syment *);<br>
+<br></blockquote><div><br></div><div>The above functions are only used in the symbols.c, It should be good to add a 'static' keyword to them.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+struct module_tag {<br>
+       char *start;<br>
+       char *end;<br>
+       char *start_str;<br>
+       char *end_str;<br>
+};<br>
+<br>
+#define MODULE_TAG(type, suffix)       ("_MODULE_" #type "_" #suffix "_")<br>
+#define MODULE_STR(type, suffix)       ( "MODULE " #type " " #suffix)<br>
+#define MODULE_TAGS(type)              {               \<br>
+       .start          = MODULE_TAG(type, START),      \<br>
+       .end            = MODULE_TAG(type, END),        \<br>
+       .start_str      = MODULE_STR(type, START),      \<br>
+       .end_str        = MODULE_STR(type, END)         \<br>
+}<br>
+<br>
+static const struct module_tag module_tag[] = {<br>
+       MODULE_TAGS(TEXT),<br>
+       MODULE_TAGS(DATA),<br>
+       MODULE_TAGS(RODATA),<br>
+       MODULE_TAGS(RO_AFTER_INIT),<br>
+       MODULE_TAGS(INIT_TEXT),<br>
+       MODULE_TAGS(INIT_DATA),<br>
+       MODULE_TAGS(INIT_RODATA),<br>
+};<br>
<br>
 /*<br>
  *  structure/union printing stuff<br>
@@ -1268,10 +1304,7 @@ symname_hash_search(struct syment *table[], char *name)<br>
  *  Output for sym -[lL] command.<br>
  */<br>
<br>
-#define MODULE_PSEUDO_SYMBOL(sp) \<br>
-    ((STRNEQ((sp)->name, "_MODULE_START_") || STRNEQ((sp)->name, "_MODULE_END_")) || \<br>
-    (STRNEQ((sp)->name, "_MODULE_INIT_START_") || STRNEQ((sp)->name, "_MODULE_INIT_END_")) || \<br>
-    (STRNEQ((sp)->name, "_MODULE_SECTION_")))<br>
+#define MODULE_PSEUDO_SYMBOL(sp)       (STRNEQ((sp)->name, "_MODULE_"))<br>
<br>
 #define MODULE_START(sp) (STRNEQ((sp)->name, "_MODULE_START_"))<br>
 #define MODULE_END(sp)   (STRNEQ((sp)->name, "_MODULE_END_"))<br>
@@ -1280,6 +1313,76 @@ symname_hash_search(struct syment *table[], char *name)<br>
 #define MODULE_SECTION_START(sp) (STRNEQ((sp)->name, "_MODULE_SECTION_START"))<br>
 #define MODULE_SECTION_END(sp)   (STRNEQ((sp)->name, "_MODULE_SECTION_END"))<br>
<br>
+#define MODULE_MEM_START(sp,t) (STRNEQ((sp)->name, module_tag[t].start))<br>
+#define MODULE_MEM_END(sp,t)   (STRNEQ((sp)->name, module_tag[t].end))<br>
+<br>
+/* For 6.4 and later */<br>
+static void<br>
+module_symbol_dump(char *module)<br>
+{<br>
+       int i;<br>
+       struct syment *sp, *sp_end;<br>
+       struct load_module *lm;<br>
+       const char *p1, *p2;<br>
+<br>
+       for (i = 0; i < st->mods_installed; i++) {<br>
+<br>
+               lm = &st->load_modules[i];<br>
+               if (module && !STREQ(module, lm->mod_name))<br>
+                       continue;<br>
+<br>
+               if (received_SIGINT() || output_closed())<br>
+                       return;<br>
+<br>
+               /*<br>
+                * module percpu symbols are within the .data..percpu section,<br>
+                * not in any module memory regions.<br>
+                */<br>
+               if (MODULE_PERCPU_SYMS_LOADED(lm)) {<br>
+                       p1 = "MODULE PERCPU START";<br>
+                       p2 = lm->mod_name;<br>
+                       fprintf(fp, "%lx %s: %s\n", lm->mod_percpu, p1, p2);<br>
+<br>
+                       dump_percpu_symbols(lm);<br>
+<br>
+                       p1 = "MODULE PERCPU END";<br>
+                       fprintf(fp, "%lx %s: %s\n", lm->mod_percpu + lm->mod_percpu_size, p1, p2);<br>
+               }<br>
+<br>
+               for_each_mod_mem_type(t) {<br>
+                       if (!lm->symtable[t])<br>
+                               continue;<br>
+<br>
+                       sp = lm->symtable[t];<br>
+                       sp_end = lm->symend[t];<br>
+<br>
+                       for ( ; sp <= sp_end; sp++) {<br>
+                               if (MODULE_PSEUDO_SYMBOL(sp)) {<br>
+                                       if (MODULE_MEM_START(sp, t)) {<br>
+                                               p1 = module_tag[t].start_str;<br>
+                                               p2 = sp->name + strlen(module_tag[t].start);<br>
+                                       } else if (MODULE_MEM_END(sp, t)) {<br>
+                                               p1 = module_tag[t].end_str;<br>
+                                               p2 = sp->name + strlen(module_tag[t].end);<br>
+                                       } else if (MODULE_SECTION_START(sp)) {<br>
+                                               p1 = sp->name + strlen("_MODULE_SECTION_START ");<br>
+                                               p2 = "section start";<br>
+                                       } else if (MODULE_SECTION_END(sp)) {<br>
+                                               p1 = sp->name + strlen("_MODULE_SECTION_END ");<br>
+                                               p2 = "section end";<br>
+                                       } else {<br>
+                                               p1 = "unknown tag";<br>
+                                               p2 = sp->name;<br>
+                                       }<br>
+<br>
+                                       fprintf(fp, "%lx %s: %s\n", sp->value, p1, p2);<br>
+                               } else<br>
+                                       show_symbol(sp, 0, SHOW_RADIX());<br>
+                       }<br>
+               }<br>
+       }<br>
+}<br>
+<br>
 static void<br>
 symbol_dump(ulong flags, char *module)<br>
 {<br>
@@ -1302,6 +1405,11 @@ symbol_dump(ulong flags, char *module)<br>
        if (!(flags & MODULE_SYMS))<br>
                return;<br>
<br>
+       if (MODULE_MEMORY()) {<br>
+               module_symbol_dump(module);<br>
+               return;<br>
+       }<br>
+<br>
        for (i = 0; i < st->mods_installed; i++) {<br>
<br>
                lm = &st->load_modules[i];<br>
@@ -1389,8 +1497,14 @@ dump_percpu_symbols(struct load_module *lm)<br>
        struct syment *sp, *sp_end;<br>
<br>
        if (MODULE_PERCPU_SYMS_LOADED(lm)) {<br>
-               sp = lm->mod_symtable;<br>
-               sp_end = lm->mod_symend;<br>
+               if (MODULE_MEMORY()) {<br>
+                       /* The lm should have mod_load_symtable. */<br>
+                       sp = lm->mod_load_symtable;<br>
+                       sp_end = lm->mod_load_symend;<br>
+               } else {<br>
+                       sp = lm->mod_symtable;<br>
+                       sp_end = lm->mod_symend;<br>
+               }<br>
                for ( ; sp <= sp_end; sp++) {<br>
                        if (IN_MODULE_PERCPU(sp->value, lm))<br>
                                show_symbol(sp, 0, SHOW_RADIX());<br>
@@ -1425,8 +1539,13 @@ check_for_dups(struct load_module *lm)<br>
 {<br>
        struct syment *sp, *sp_end;<br>
<br>
-        sp = lm->mod_symtable;<br>
-        sp_end = lm->mod_symend;<br>
+       if (MODULE_MEMORY()) {<br>
+               sp = lm->mod_load_symtable;<br>
+               sp_end = lm->mod_load_symend;<br>
+       } else {<br>
+               sp = lm->mod_symtable;<br>
+               sp_end = lm->mod_symend;<br>
+       }<br>
<br>
         for ( ; sp <= sp_end; sp++) {<br>
                 if (symbol_name_count(sp->name) > 1)<br>
@@ -1788,6 +1907,362 @@ modsym_value(ulong syms, union kernel_symbol *modsym, int i)<br>
        return 0;<br>
 }<br>
<br>
+/*<br>
+ * Linux 6.4 introduced module.mem memory layout<br>
+ */<br>
+void<br>
+store_module_symbols_6_4(ulong total, int mods_installed)<br>
+{<br>
+       int i, m;<br>
+       ulong mod, mod_next;<br>
+       char *mod_name;<br>
+       uint nsyms, ngplsyms;<br>
+       ulong syms, gpl_syms;<br>
+       ulong nksyms;<br>
+       long strbuflen;<br>
+       ulong size;<br>
+       int mcnt, lm_mcnt;<br>
+       union kernel_symbol *modsym;<br>
+       size_t kernel_symbol_size;<br>
+       struct load_module *lm;<br>
+       char buf1[BUFSIZE];<br>
+       char buf2[BUFSIZE];<br>
+       char *strbuf = NULL, *modbuf, *modsymbuf;<br>
+       struct syment *sp;<br>
+       ulong first, last;<br>
+<br>
+       st->mods_installed = mods_installed;<br>
+<br>
+       if (!st->mods_installed) {<br>
+               st->flags &= ~MODULE_SYMS;<br>
+               return;<br>
+       }<br>
+<br>
+       /*<br>
+        *  If we've been here before, free up everything and start over.<br>
+        */<br>
+       if (st->flags & MODULE_SYMS)<br>
+               error(FATAL, "re-initialization of module symbols not implemented yet!\n");<br>
+<br>
+       kernel_symbol_size = kernel_symbol_type_init();<br>
+<br>
+       if ((st->ext_module_symtable = (struct syment *)<br>
+           calloc(total, sizeof(struct syment))) == NULL)<br>
+               error(FATAL, "module syment space malloc (%ld symbols): %s\n",<br>
+                       total, strerror(errno));<br>
+<br>
+       if (!namespace_ctl(NAMESPACE_INIT, &st->ext_module_namespace,<br>
+           (void *)total, NULL))<br>
+               error(FATAL, "module namespace malloc: %s\n", strerror(errno));<br>
+<br>
+       if ((st->load_modules = (struct load_module *)calloc<br>
+           (st->mods_installed, sizeof(struct load_module))) == NULL)<br>
+               error(FATAL, "load_module array malloc: %s\n", strerror(errno));<br>
+<br>
+       modbuf = GETBUF(SIZE(module));<br>
+       modsymbuf = NULL;<br>
+       m = mcnt = mod_next = 0;<br>
+<br>
+       for (mod = kt->module_list; mod != kt->kernel_module; mod = mod_next) {<br>
+<br>
+               readmem(mod, KVADDR, modbuf, SIZE(module),<br>
+                       "module buffer", FAULT_ON_ERROR);<br>
+<br>
+               syms = ULONG(modbuf + OFFSET(module_syms));<br>
+               gpl_syms = ULONG(modbuf + OFFSET(module_gpl_syms));<br>
+               nsyms = UINT(modbuf + OFFSET(module_num_syms));<br>
+               ngplsyms = UINT(modbuf + OFFSET(module_num_gpl_syms));<br>
+<br>
+               nksyms = UINT(modbuf + OFFSET(module_num_symtab));<br>
+<br>
+               mod_name = modbuf + OFFSET(module_name);<br>
+<br>
+               lm = &st->load_modules[m++];<br>
+               BZERO(lm, sizeof(struct load_module));<br>
+<br>
+               size = 0;<br>
+               for_each_mod_mem_type(t) {<br>
+                       lm->mem[t].base = ULONG(modbuf + OFFSET(module_mem) +<br>
+                                               SIZE(module_memory) * t + OFFSET(module_memory_base));<br>
+                       lm->mem[t].size = UINT(modbuf + OFFSET(module_mem) +<br>
+                                               SIZE(module_memory) * t + OFFSET(module_memory_size));<br>
+                       if (t < MOD_INIT_TEXT)<br>
+                               size += lm->mem[t].size;<br>
+               }<br>
+               lm->mod_base = lm->mem[MOD_TEXT].base;<br>
+               /* module core size, init not included */<br>
+               lm->mod_size = size;<br>
+               lm->module_struct = mod;<br>
+<br>
+               if (strlen(mod_name) < MAX_MOD_NAME)<br>
+                       strcpy(lm->mod_name, mod_name);<br>
+               else {<br>
+                       error(INFO, "module name greater than MAX_MOD_NAME: %s\n", mod_name);<br>
+                       strncpy(lm->mod_name, mod_name, MAX_MOD_NAME-1);<br>
+               }<br>
+               if (CRASHDEBUG(3))<br>
+                       fprintf(fp, "%lx (%lx): %s syms: %d gplsyms: %d ksyms: %ld\n",<br>
+                               mod, lm->mod_base, lm->mod_name, nsyms, ngplsyms, nksyms);<br>
+<br>
+               lm->mod_flags = MOD_EXT_SYMS;<br>
+               lm->mod_ext_symcnt = mcnt;<br>
+               lm->mod_text_start = lm->mod_base;<br>
+               lm->mod_init_module_ptr = lm->mem[MOD_INIT_TEXT].base;<br>
+               lm->mod_init_size = lm->mem[MOD_INIT_TEXT].size;<br>
+               lm->mod_init_text_size = lm->mem[MOD_INIT_TEXT].size;<br>
+<br>
+               if (VALID_MEMBER(module_percpu))<br>
+                       lm->mod_percpu = ULONG(modbuf + OFFSET(module_percpu));<br>
+<br>
+               lm_mcnt = mcnt;<br>
+               for_each_mod_mem_type(t) {<br>
+                       if (!lm->mem[t].size)<br>
+                               continue;<br>
+<br>
+                       st->ext_module_symtable[mcnt].value = lm->mem[t].base;<br>
+                       st->ext_module_symtable[mcnt].type = 'm';<br>
+                       st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL;<br>
+                       sprintf(buf2, "%s%s", module_tag[t].start, mod_name);<br>
+                       namespace_ctl(NAMESPACE_INSTALL, &st->ext_module_namespace,<br>
+                               &st->ext_module_symtable[mcnt], buf2);<br>
+                       lm_mcnt = mcnt;<br>
+                       mcnt++;<br>
+<br>
+                       if (t >= MOD_INIT_TEXT)<br>
+                               lm->mod_flags |= MOD_INIT;<br>
+               }<br>
+<br>
+               if (nsyms && !IN_MODULE(syms, lm)) {<br>
+                       error(WARNING,<br>
+                           "[%s] module.syms outside of module " "address space (%lx)\n\n",<br>
+                               lm->mod_name, syms);<br>
+                       nsyms = 0;<br>
+               }<br>
+<br>
+               if (nsyms) {<br>
+                       modsymbuf = GETBUF(kernel_symbol_size*nsyms);<br>
+                       readmem((ulong)syms, KVADDR, modsymbuf,<br>
+                               nsyms * kernel_symbol_size,<br>
+                               "module symbols", FAULT_ON_ERROR);<br>
+               }<br>
+<br>
+               for (i = first = last = 0; i < nsyms; i++) {<br>
+                       modsym = (union kernel_symbol *)<br>
+                           (modsymbuf + (i * kernel_symbol_size));<br>
+                       if (!first<br>
+                           || first > modsym_name(syms, modsym, i))<br>
+                               first = modsym_name(syms, modsym, i);<br>
+                       if (modsym_name(syms, modsym, i) > last)<br>
+                               last = modsym_name(syms, modsym, i);<br>
+               }<br>
+<br>
+               if (last > first) {<br>
+                       /* The buffer should not go over the block. */<br>
+                       ulong end = module_mem_end(first, lm);<br>
+<br>
+                       strbuflen = (last-first) + BUFSIZE;<br>
+                       if ((first + strbuflen) >= end) {<br>
+                               strbuflen = end - first;<br>
+<br>
+                       }<br>
+                       strbuf = GETBUF(strbuflen);<br>
+<br>
+                       if (!readmem(first, KVADDR, strbuf, strbuflen,<br>
+                           "module symbol strings", RETURN_ON_ERROR)) {<br>
+                               FREEBUF(strbuf);<br>
+                               strbuf = NULL;<br>
+                       }<br>
+               }<br>
+<br>
+<br>
+               for (i = 0; i < nsyms; i++) {<br>
+                       modsym = (union kernel_symbol *)(modsymbuf + (i * kernel_symbol_size));<br>
+<br>
+                       BZERO(buf1, BUFSIZE);<br>
+<br>
+                       if (strbuf)<br>
+                               strcpy(buf1, &strbuf[modsym_name(syms, modsym, i) - first]);<br>
+                       else<br>
+                               read_string(modsym_name(syms, modsym, i), buf1, BUFSIZE-1);<br>
+<br>
+                       if (strlen(buf1)) {<br>
+                               st->ext_module_symtable[mcnt].value =<br>
+                                       modsym_value(syms, modsym, i);<br>
+                               st->ext_module_symtable[mcnt].type = '?';<br>
+                               st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL;<br>
+                               strip_module_symbol_end(buf1);<br>
+                               strip_symbol_end(buf1, NULL);<br>
+                               namespace_ctl(NAMESPACE_INSTALL,<br>
+                                   &st->ext_module_namespace,<br>
+                                   &st->ext_module_symtable[mcnt], buf1);<br>
+<br>
+                               mcnt++;<br>
+                       }<br>
+               }<br>
+<br>
+               if (modsymbuf) {<br>
+                       FREEBUF(modsymbuf);<br>
+                       modsymbuf = NULL;<br>
+               }<br>
+<br>
+               if (strbuf)<br>
+                       FREEBUF(strbuf);<br>
+<br>
+               if (ngplsyms) {<br>
+                       modsymbuf = GETBUF(kernel_symbol_size * ngplsyms);<br>
+                       readmem((ulong)gpl_syms, KVADDR, modsymbuf,<br>
+                               ngplsyms * kernel_symbol_size,<br>
+                               "module gpl symbols", FAULT_ON_ERROR);<br>
+               }<br>
+<br>
+               for (i = first = last = 0; i < ngplsyms; i++) {<br>
+                       modsym = (union kernel_symbol *)<br>
+                           (modsymbuf + (i * kernel_symbol_size));<br>
+                       if (!first<br>
+                           || first > modsym_name(gpl_syms, modsym, i))<br>
+                               first = modsym_name(gpl_syms, modsym, i);<br>
+                       if (modsym_name(gpl_syms, modsym, i) > last)<br>
+                               last = modsym_name(gpl_syms, modsym, i);<br>
+               }<br>
+<br>
+               if (last > first) {<br>
+                       ulong end = module_mem_end(first, lm);<br>
+<br>
+                       strbuflen = (last-first) + BUFSIZE;<br>
+                       if ((first + strbuflen) >= end) {<br>
+                               strbuflen = end - first;<br>
+<br>
+                       }<br>
+                       strbuf = GETBUF(strbuflen);<br>
+<br>
+                       if (!readmem(first, KVADDR, strbuf, strbuflen,<br>
+                           "module gpl symbol strings", RETURN_ON_ERROR)) {<br>
+                               FREEBUF(strbuf);<br>
+                               strbuf = NULL;<br>
+                       }<br>
+               } else<br>
+                       strbuf = NULL;<br>
+<br>
+               for (i = 0; i < ngplsyms; i++) {<br>
+                       modsym = (union kernel_symbol *) (modsymbuf + (i * kernel_symbol_size));<br>
+<br>
+                       BZERO(buf1, BUFSIZE);<br>
+<br>
+                       if (strbuf)<br>
+                               strcpy(buf1, &strbuf[modsym_name(gpl_syms, modsym, i) - first]);<br>
+                       else<br>
+                               read_string(modsym_name(gpl_syms, modsym, i), buf1, BUFSIZE-1);<br>
+<br>
+                       if (strlen(buf1)) {<br>
+                               st->ext_module_symtable[mcnt].value =<br>
+                                       modsym_value(gpl_syms, modsym, i);<br>
+                               st->ext_module_symtable[mcnt].type = '?';<br>
+                               st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL;<br>
+                               strip_module_symbol_end(buf1);<br>
+                               strip_symbol_end(buf1, NULL);<br>
+                               namespace_ctl(NAMESPACE_INSTALL,<br>
+                                   &st->ext_module_namespace,<br>
+                                   &st->ext_module_symtable[mcnt], buf1);<br>
+<br>
+                               mcnt++;<br>
+                       }<br>
+               }<br>
+<br>
+               if (modsymbuf) {<br>
+                       FREEBUF(modsymbuf);<br>
+                       modsymbuf = NULL;<br>
+               }<br>
+<br>
+               if (strbuf)<br>
+                       FREEBUF(strbuf);<br>
+<br>
+               /*<br>
+                *  If the module was compiled with kallsyms, add them in.<br>
+                */<br>
+               switch (kt->flags & (KALLSYMS_V1|KALLSYMS_V2))<br>
+               {<br>
+               case KALLSYMS_V1:  /* impossible, I hope... */<br>
+                       mcnt += store_module_kallsyms_v1(lm, lm_mcnt, mcnt, modbuf);<br>
+                       break;<br>
+               case KALLSYMS_V2:<br>
+                       mcnt += store_module_kallsyms_v2(lm, lm_mcnt, mcnt, modbuf);<br>
+                       break;<br>
+               }<br>
+<br>
+               for_each_mod_mem_type(t) {<br>
+                       if (!lm->mem[t].size)<br>
+                               continue;<br>
+<br>
+                       st->ext_module_symtable[mcnt].value = lm->mem[t].base + lm->mem[t].size;<br>
+                       st->ext_module_symtable[mcnt].type = 'm';<br>
+                       st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL;<br>
+                       sprintf(buf2, "%s%s", module_tag[t].end, mod_name);<br>
+                       namespace_ctl(NAMESPACE_INSTALL,<br>
+                               &st->ext_module_namespace,<br>
+                               &st->ext_module_symtable[mcnt], buf2);<br>
+                       mcnt++;<br>
+               }<br>
+<br>
+               lm->mod_ext_symcnt = mcnt - lm->mod_ext_symcnt;<br>
+<br>
+               NEXT_MODULE(mod_next, modbuf);<br>
+       }<br>
+<br>
+       FREEBUF(modbuf);<br>
+<br>
+       st->ext_module_symcnt = mcnt;<br>
+       st->ext_module_symend = &st->ext_module_symtable[mcnt];<br>
+<br>
+       namespace_ctl(NAMESPACE_COMPLETE, &st->ext_module_namespace,<br>
+               st->ext_module_symtable, st->ext_module_symend);<br>
+<br>
+       qsort(st->ext_module_symtable, mcnt, sizeof(struct syment),<br>
+               compare_syms);<br>
+<br>
+       /* sort by text base address */<br>
+       qsort(st->load_modules, m, sizeof(struct load_module), compare_mods);<br>
+<br>
+       for (m = 0; m < st->mods_installed; m++) {<br>
+               lm = &st->load_modules[m];<br>
+<br>
+               for_each_mod_mem_type(t) {<br>
+                       if (!lm->mem[t].size)<br>
+                               continue;<br>
+<br>
+                       sprintf(buf1, "%s%s", module_tag[t].start, lm->mod_name);<br>
+                       sprintf(buf2, "%s%s", module_tag[t].end, lm->mod_name);<br>
+<br>
+                       for (sp = st->ext_module_symtable; sp < st->ext_module_symend; sp++) {<br>
+                               if (STREQ(sp->name, buf1)) {<br>
+                                       lm->ext_symtable[t] = sp;<br>
+                                       break;<br>
+                               }<br>
+                       }<br>
+                       for ( ; sp < st->ext_module_symend; sp++) {<br>
+                               if (STREQ(sp->name, buf2)) {<br>
+                                       lm->ext_symend[t] = sp;<br>
+                                       break;<br>
+                               }<br>
+                       }<br>
+<br>
+                       if (lm->ext_symtable[t] && lm->ext_symend[t])<br>
+                               mod_symtable_hash_install_range(lm->ext_symtable[t], lm->ext_symend[t]);<br>
+               }<br>
+               lm->symtable = lm->ext_symtable;<br>
+               lm->symend = lm->ext_symend;<br>
+       }<br>
+<br>
+       st->flags |= MODULE_SYMS;<br>
+<br>
+       if (CRASHDEBUG(2)) {<br>
+               for (sp = st->ext_module_symtable; sp < st->ext_module_symend; sp++)<br>
+                       fprintf(fp, "%16lx %s\n", sp->value, sp->name);<br>
+       }<br>
+<br>
+       if (mcnt > total)<br>
+               error(FATAL, "store_module_symbols_6_4: total: %ld mcnt: %d\n", total, mcnt);<br>
+}<br>
+<br>
 void<br>
 store_module_symbols_v2(ulong total, int mods_installed)<br>
 {<br>
@@ -2384,6 +2859,7 @@ store_module_kallsyms_v2(struct load_module *lm, int start, int curr,<br>
         int mcnt;<br>
         int mcnt_idx;<br>
        char *module_buf_init = NULL;<br>
+       ulong base, base_init, size, size_init;<br>
<br>
        if (!(kt->flags & KALLSYMS_V2))<br>
                return 0;<br>
@@ -2394,9 +2870,22 @@ store_module_kallsyms_v2(struct load_module *lm, int start, int curr,<br>
         ns = &st->ext_module_namespace;<br>
        ec = &elf_common;<br>
<br>
-        module_buf = GETBUF(lm->mod_size);<br>
+       /* kallsyms data looks to be in MOD_DATA region. */<br>
+       if (MODULE_MEMORY()) {<br>
+               base = lm->mem[MOD_DATA].base;<br>
+               size = lm->mem[MOD_DATA].size;<br>
+               base_init = lm->mem[MOD_INIT_DATA].base;<br>
+               size_init = lm->mem[MOD_INIT_DATA].size;<br>
+       } else {<br>
+               base = lm->mod_base;<br>
+               size = lm->mod_size;<br>
+               base_init = lm->mod_init_module_ptr;<br>
+               size_init = lm->mod_init_size;<br>
+       }<br>
<br>
-        if (!readmem(lm->mod_base, KVADDR, module_buf, lm->mod_size,<br>
+       module_buf = GETBUF(size);<br>
+<br>
+       if (!readmem(base, KVADDR, module_buf, size,<br>
             "module (kallsyms)", RETURN_ON_ERROR|QUIET)) {<br>
                 error(WARNING,"cannot access module kallsyms\n");<br>
                 FREEBUF(module_buf);<br>
@@ -2404,10 +2893,10 @@ store_module_kallsyms_v2(struct load_module *lm, int start, int curr,<br>
         }<br>
<br>
        if (lm->mod_init_size > 0) {<br>
-               module_buf_init = GETBUF(lm->mod_init_size);<br>
+               module_buf_init = GETBUF(size_init);<br>
<br>
-               if (!readmem(lm->mod_init_module_ptr, KVADDR, module_buf_init, lm->mod_init_size,<br>
-                                       "module init (kallsyms)", RETURN_ON_ERROR|QUIET)) {<br>
+               if (!readmem(base_init, KVADDR, module_buf_init, size_init,<br>
+                               "module init (kallsyms)", RETURN_ON_ERROR|QUIET)) {<br>
                        error(WARNING,"cannot access module init kallsyms\n");<br>
                        FREEBUF(module_buf_init);<br>
                }<br>
@@ -2429,9 +2918,9 @@ store_module_kallsyms_v2(struct load_module *lm, int start, int curr,<br>
                return 0;<br>
        } <br>
        if (IN_MODULE(ksymtab, lm))<br>
-               locsymtab = module_buf + (ksymtab - lm->mod_base);<br>
+               locsymtab = module_buf + (ksymtab - base);<br>
        else<br>
-               locsymtab = module_buf_init + (ksymtab - lm->mod_init_module_ptr);<br>
+               locsymtab = module_buf_init + (ksymtab - base_init);<br>
<br>
        kstrtab = ULONG(modbuf + OFFSET(module_strtab));<br>
        if (!IN_MODULE(kstrtab, lm) && !IN_MODULE_INIT(kstrtab, lm)) {<br>
@@ -2444,9 +2933,9 @@ store_module_kallsyms_v2(struct load_module *lm, int start, int curr,<br>
                return 0;<br>
        }<br>
        if (IN_MODULE(kstrtab, lm))<br>
-               locstrtab = module_buf + (kstrtab - lm->mod_base);<br>
+               locstrtab = module_buf + (kstrtab - base);<br>
        else<br>
-               locstrtab = module_buf_init + (kstrtab - lm->mod_init_module_ptr);<br>
+               locstrtab = module_buf_init + (kstrtab - base_init);<br>
<br>
        for (i = 1; i < nksyms; i++) {  /* ELF starts real symbols at 1 */<br>
                switch (BITS())<br>
@@ -2461,11 +2950,8 @@ store_module_kallsyms_v2(struct load_module *lm, int start, int curr,<br>
                        break;<br>
                }<br>
<br>
-               if (((ec->st_value < lm->mod_base) ||<br>
-                   (ec->st_value >  (lm->mod_base + lm->mod_size))) &&<br>
-                   ((ec->st_value < lm->mod_init_module_ptr) ||<br>
-                   (ec->st_value > (lm->mod_init_module_ptr + lm->mod_init_size))))<br>
-                               continue;<br>
+               if (!IN_MODULE(ec->st_value, lm) && !IN_MODULE_INIT(ec->st_value, lm))<br>
+                       continue;<br>
<br>
                if (ec->st_shndx == SHN_UNDEF)<br>
                         continue;<br>
@@ -2582,9 +3068,20 @@ lowest_module_address(void)<br>
        lowest = (ulong)(-1);<br>
        for (i = 0; i < st->mods_installed; i++) {<br>
                lm = &st->load_modules[i];<br>
-               low = lm->mod_base;<br>
-               if (low < lowest)<br>
-                       lowest = low;<br>
+               if (MODULE_MEMORY())<br>
+                       for_each_mod_mem_type(t) {<br>
+                               if (!lm->mem[t].size)<br>
+                                       continue;<br>
+<br>
+                               low = lm->mem[t].base;<br>
+                               if (low < lowest)<br>
+                                       lowest = low;<br>
+                       }<br>
+               else {<br>
+                       low = lm->mod_base;<br>
+                       if (low < lowest)<br>
+                               lowest = low;<br>
+               }<br>
        }<br>
<br>
        return lowest;<br>
@@ -2600,9 +3097,20 @@ highest_module_address(void)<br>
        highest = 0;<br>
        for (i = 0; i < st->mods_installed; i++) {<br>
                lm = &st->load_modules[i];<br>
-               high = lm->mod_base + lm->mod_size;<br>
-               if (high > highest)<br>
-                       highest = high;<br>
+               if (MODULE_MEMORY()) {<br>
+                       for_each_mod_mem_type(t) {<br>
+                               if (!lm->mem[t].size)<br>
+                                       continue;<br>
+<br>
+                               high = lm->mem[t].base + lm->mem[t].size;<br>
+                               if (high > highest)<br>
+                                       highest = high;<br>
+                       }<br>
+               } else {<br>
+                       high = lm->mod_base + lm->mod_size;<br>
+                       if (high > highest)<br>
+                               highest = high;<br>
+               }<br>
        }<br>
<br>
        return highest;<br>
@@ -2853,7 +3361,8 @@ compare_syms(const void *v1, const void *v2)<br>
                        return -1;<br>
                if (STRNEQ(s2->name, "__insmod"))<br>
                        return 1;<br>
-               if (STRNEQ(s2->name, "_MODULE_START_"))<br>
+               if (MODULE_MEM_START(s2, MOD_TEXT) ||<br>
+                   STRNEQ(s2->name, "_MODULE_START_"))<br>
                        return 1;<br>
                /* Get pseudo section name. */<br>
                if (MODULE_SECTION_START(s1))<br>
@@ -2986,13 +3495,19 @@ is_kernel_text(ulong value)<br>
                                if (!(lm->mod_section_data[s].flags & SEC_CODE))<br>
                                        continue;<br>
<br>
-                               start = lm->mod_base + <br>
-                                       lm->mod_section_data[s].offset;<br>
+                               if (MODULE_MEMORY())<br>
+                                       start = lm->mod_section_data[s].addr;<br>
+                               else<br>
+                                       start = lm->mod_base + lm->mod_section_data[s].offset;<br>
+<br>
                                end = start + lm->mod_section_data[s].size;<br>
<br>
                                if ((value >= start) && (value < end)) <br>
                                        return TRUE;<br>
                        }<br>
+               } else if (MODULE_MEMORY()) {<br>
+                       if (IN_MODULE_TEXT(value, lm))<br>
+                               return TRUE;<br>
                } else {<br>
                        switch (kt->flags & (KMOD_V1|KMOD_V2))<br>
                        {<br>
@@ -3531,22 +4046,41 @@ dump_symbol_table(void)<br>
                        (ulong)lm->mod_section_data,<br>
                        lm->mod_section_data ? "" : "(not allocated)");<br>
<br>
+               if (MODULE_MEMORY()) {<br>
+                       for_each_mod_mem_type(t) {<br>
+                               fprintf(fp, "                mem[%d]: %lx (%x)\n",<br>
+                                       t, lm->mem[t].base, lm->mem[t].size);<br>
+                       }<br>
+                       fprintf(fp, "              symtable: %lx\n", (ulong)lm->symtable);<br>
+                       fprintf(fp, "          ext_symtable: %lx\n", (ulong)lm->ext_symtable);<br>
+                       for_each_mod_mem_type(t) {<br>
+                               fprintf(fp, "       ext_symtable[%d]: %lx - %lx\n",<br>
+                                       t, (ulong)lm->ext_symtable[t], (ulong)lm->ext_symend[t]);<br>
+                       }<br>
+                       fprintf(fp, "         load_symtable: %lx\n", (ulong)lm->load_symtable);<br>
+                       for_each_mod_mem_type(t) {<br>
+                               fprintf(fp, "      load_symtable[%d]: %lx - %lx\n",<br>
+                                       t, (ulong)lm->load_symtable[t], (ulong)lm->load_symend[t]);<br>
+                       }<br>
+               }<br>
<br>
                for (s = 0; s < lm->mod_sections; s++) {<br>
                        fprintf(fp, <br>
-                "       %12s  prio: %x  flags: %05x  offset: %-8lx size: %lx\n",<br>
+               "       %20s  prio: %x  flags: %08x  %s: %-16lx size: %lx\n",<br>
                                lm->mod_section_data[s].name,<br>
                                lm->mod_section_data[s].priority,<br>
                                lm->mod_section_data[s].flags,<br>
-                               lm->mod_section_data[s].offset,<br>
+                               MODULE_MEMORY() ? "addr" : "offset",<br>
+                               MODULE_MEMORY() ? lm->mod_section_data[s].addr :<br>
+                                               lm->mod_section_data[s].offset,<br>
                                lm->mod_section_data[s].size);<br>
                }<br>
<br>
                fprintf(fp, "        loaded_objfile: %lx\n", (ulong)lm->loaded_objfile);<br>
<br>
-               if (CRASHDEBUG(1)) {<br>
+               if (CRASHDEBUG(1) && lm->mod_load_symtable) {<br>
                        for (sp = lm->mod_load_symtable; <br>
-                            sp < lm->mod_load_symend; sp++) {<br>
+                            sp <= lm->mod_load_symend; sp++) {<br>
                                fprintf(fp, "  %lx  %s\n",<br>
                                        sp->value, sp->name);   <br>
                        }<br>
@@ -4458,8 +4992,11 @@ get_section(ulong vaddr, char *buf)<br>
        if (module_symbol(vaddr, NULL, &lm, NULL, *gdb_output_radix)) {<br>
                if (lm->mod_flags & MOD_LOAD_SYMS) { <br>
                        for (i = (lm->mod_sections-1); i >= 0; i--) {<br>
-                                start = lm->mod_base +<br>
-                                        lm->mod_section_data[i].offset;<br>
+                               if (MODULE_MEMORY())<br>
+                                       start = lm->mod_section_data[i].addr;<br>
+                               else<br>
+                                       start = lm->mod_base +<br>
+                                               lm->mod_section_data[i].offset;<br>
                                 end = start + lm->mod_section_data[i].size;<br>
<br>
                                 if ((vaddr >= start) && (vaddr < end)) {<br>
@@ -4534,6 +5071,60 @@ symbol_query(char *s, char *print_pad, struct syment **spp)<br>
                }<br>
        }<br>
<br>
+       if (!MODULE_MEMORY())<br>
+               goto old_module;<br>
+<br>
+       for (i = 0; i < st->mods_installed; i++) {<br>
+               lm = &st->load_modules[i];<br>
+<br>
+               if (lm->mod_flags & MOD_LOAD_SYMS) {<br>
+                       sp = lm->mod_load_symtable;<br>
+                       sp_end = lm->mod_load_symend;<br>
+<br>
+                       for (; sp < sp_end; sp++) {<br>
+                               if (MODULE_PSEUDO_SYMBOL(sp))<br>
+                                       continue;<br>
+<br>
+                               if (strstr(sp->name, s)) {<br>
+                                       if (print_pad) {<br>
+                                               if (strlen(print_pad))<br>
+                                                       fprintf(fp, "%s", print_pad);<br>
+                                               show_symbol(sp, 0, SHOW_RADIX()|SHOW_MODULE);<br>
+                                       }<br>
+                                       if (spp)<br>
+                                               *spp = sp;<br>
+                                       cnt++;<br>
+                               }<br>
+                       }<br>
+               } else {<br>
+                       for_each_mod_mem_type(t) {<br>
+                               if (!lm->symtable[t])<br>
+                                       continue;<br>
+<br>
+                               sp = lm->symtable[t];<br>
+                               sp_end = lm->symend[t];<br>
+<br>
+                               for (; sp < sp_end; sp++) {<br>
+                                       if (MODULE_PSEUDO_SYMBOL(sp))<br>
+                                               continue;<br>
+<br>
+                                       if (strstr(sp->name, s)) {<br>
+                                               if (print_pad) {<br>
+                                                       if (strlen(print_pad))<br>
+                                                               fprintf(fp, "%s", print_pad);<br>
+                                                       show_symbol(sp, 0, SHOW_RADIX()|SHOW_MODULE);<br>
+                                               }<br>
+                                               if (spp)<br>
+                                                       *spp = sp;<br>
+                                               cnt++;<br>
+                                       }<br>
+                               }<br>
+                       }<br>
+               }<br>
+       }<br>
+       return cnt;<br>
+<br>
+old_module:<br>
        search_init = FALSE;<br>
<br>
        for (i = 0; i < st->mods_installed; i++) {<br>
@@ -4653,6 +5244,37 @@ symbol_name_count(char *s)<br>
                }<br>
         }<br>
<br>
+       if (!MODULE_MEMORY())<br>
+               goto old_module;<br>
+<br>
+       for (i = 0; i < st->mods_installed; i++) {<br>
+               lm = &st->load_modules[i];<br>
+<br>
+               if (lm->mod_flags & MOD_LOAD_SYMS) {<br>
+                       sp = lm->mod_load_symtable;<br>
+                       sp_end = lm->mod_load_symend;<br>
+<br>
+                       for (; sp < sp_end; sp++) {<br>
+                               if (STREQ(s, sp->name))<br>
+                                       count++;<br>
+                       }<br>
+               } else {<br>
+                       for_each_mod_mem_type(t) {<br>
+                               if (!lm->symtable[t])<br>
+                                       continue;<br>
+<br>
+                               sp = lm->symtable[t];<br>
+                               sp_end = lm->symend[t];<br>
+                               for (; sp < sp_end; sp++) {<br>
+                                       if (STREQ(s, sp->name))<br>
+                                               count++;<br>
+                               }<br>
+                       }<br>
+               }<br>
+       }<br>
+       return count++;<br>
+<br>
+old_module:<br>
         pseudos = (strstr(s, "_MODULE_START_") || strstr(s, "_MODULE_END_"));<br>
        search_init = FALSE;<br>
<br>
@@ -4722,6 +5344,38 @@ symbol_search_next(char *s, struct syment *spstart)<br>
                }<br>
         }<br>
<br>
+       if (!MODULE_MEMORY())<br>
+               goto old_module;<br>
+<br>
+       for (i = 0; i < st->mods_installed; i++) {<br>
+               lm = &st->load_modules[i];<br>
+<br>
+               for_each_mod_mem_type(t) {<br>
+                       if (!lm->symtable[t])<br>
+                               continue;<br>
+<br>
+                       sp = lm->symtable[t];<br>
+                       sp_end = lm->symend[t];<br>
+<br>
+                       if (spstart < sp || spstart > sp_end)<br>
+                               continue;<br>
+<br>
+                       for ( ; sp < sp_end; sp++) {<br>
+                               if (sp == spstart) {<br>
+                                       found_start = TRUE;<br>
+                                       continue;<br>
+                               } else if (!found_start)<br>
+                                       continue;<br>
+<br>
+                               if (STREQ(s, sp->name))<br>
+                                       return sp;<br>
+                       }<br>
+               }<br>
+       }<br>
+<br>
+       return NULL;<br>
+<br>
+old_module:<br>
        pseudos = (strstr(s, "_MODULE_START_") || strstr(s, "_MODULE_END_"));<br>
        search_init = FALSE;<br>
<br>
@@ -4831,17 +5485,29 @@ module_symbol(ulong value,<br>
        for (i = 0; i < st->mods_installed; i++) {<br>
                lm = &st->load_modules[i];<br>
<br>
-               if (IN_MODULE(value, lm)) {<br>
-                       base = lm->mod_base;<br>
-                       end = lm->mod_base + lm->mod_size;<br>
-               } else if (IN_MODULE_INIT(value, lm)) {<br>
-                       base = lm->mod_init_module_ptr;<br>
-                       end = lm->mod_init_module_ptr + lm->mod_init_size;<br>
-               } else if (IN_MODULE_PERCPU(value, lm)) {<br>
-                       base = lm->mod_percpu;<br>
-                       end = lm->mod_percpu + lm->mod_percpu_size;<br>
-               } else<br>
-                       continue;<br>
+               if (MODULE_MEMORY()) {<br>
+                       if (IN_MODULE(value, lm) || IN_MODULE_INIT(value, lm)) {<br>
+                               int type = module_mem_type(value, lm);<br>
+                               base = lm->mem[type].base;<br>
+                               end = base + lm->mem[type].size;<br>
+                       } else if (IN_MODULE_PERCPU(value, lm)) {<br>
+                               base = lm->mod_percpu;<br>
+                               end = lm->mod_percpu + lm->mod_percpu_size;<br>
+                       } else<br>
+                               continue;<br>
+               } else {<br>
+                       if (IN_MODULE(value, lm)) {<br>
+                               base = lm->mod_base;<br>
+                               end = lm->mod_base + lm->mod_size;<br>
+                       } else if (IN_MODULE_INIT(value, lm)) {<br>
+                               base = lm->mod_init_module_ptr;<br>
+                               end = lm->mod_init_module_ptr + lm->mod_init_size;<br>
+                       } else if (IN_MODULE_PERCPU(value, lm)) {<br>
+                               base = lm->mod_percpu;<br>
+                               end = lm->mod_percpu + lm->mod_percpu_size;<br>
+                       } else<br>
+                               continue;<br>
+               }<br>
<br>
                if ((value >= base) && (value < end)) {<br>
                        if (lmp) <br>
@@ -4877,6 +5543,71 @@ module_symbol(ulong value,<br>
        return FALSE;<br>
 }<br>
<br>
+struct syment *<br>
+value_search_module_6_4(ulong value, ulong *offset)<br>
+{<br>
+       int i;<br>
+       struct syment *sp, *sp_end, *spnext, *splast;<br>
+       struct load_module *lm;<br>
+<br>
+       for (i = 0; i < st->mods_installed; i++) {<br>
+               lm = &st->load_modules[i];<br>
+<br>
+               if (!IN_MODULE(value, lm) && !IN_MODULE_INIT(value, lm))<br>
+                       continue;<br>
+<br>
+               for_each_mod_mem_type(t) {<br>
+                       sp = lm->symtable[t];<br>
+                       sp_end = lm->symend[t];<br>
+<br>
+                       if (value < sp->value)<br>
+                               continue;<br>
+<br>
+                       splast = NULL;<br>
+                       for ( ; sp <= sp_end; sp++) {<br>
+                               if (machine_type("ARM64") &&<br>
+                                   IN_MODULE_PERCPU(sp->value, lm) &&<br>
+                                   !IN_MODULE_PERCPU(value, lm))<br>
+                                       continue;<br>
+<br>
+                               if (value == sp->value) {<br>
+                                       if (MODULE_MEM_END(sp, t))<br>
+                                               break;<br>
+<br>
+                                       if (MODULE_PSEUDO_SYMBOL(sp)) {<br>
+                                               spnext = sp + 1;<br>
+                                               if (MODULE_PSEUDO_SYMBOL(spnext))<br>
+                                                       continue;<br>
+                                               if (spnext->value == value)<br>
+                                                       sp = spnext;<br>
+                                       }<br>
+                                       if (sp->name[0] == '.') {<br>
+                                               spnext = sp+1;<br>
+                                               if (spnext->value == value)<br>
+                                                       sp = spnext;<br>
+                                       }<br>
+                                       if (offset)<br>
+                                               *offset = 0;<br>
+                                       return sp;<br>
+                               }<br>
+<br>
+                               if (sp->value > value) {<br>
+                                       sp = splast ? splast : sp - 1;<br>
+                                       if (offset)<br>
+                                               *offset = value - sp->value;<br>
+                                       return sp;<br>
+                               }<br>
+<br>
+                               if (!MODULE_PSEUDO_SYMBOL(sp)) {<br>
+                                       splast = sp;<br>
+                               }<br>
+                       }<br>
+               }<br>
+       }<br>
+<br>
+       return NULL;<br>
+}<br>
+<br>
 struct syment *<br>
 value_search_module(ulong value, ulong *offset)<br>
 {<br>
@@ -4885,6 +5616,9 @@ value_search_module(ulong value, ulong *offset)<br>
        struct load_module *lm;<br>
        int search_init_sections, search_init;<br>
<br>
+       if (MODULE_MEMORY())<br>
+               return value_search_module_6_4(value, offset);<br>
+<br>
        search_init = FALSE;<br>
        search_init_sections = 0;<br>
<br>
@@ -5203,6 +5937,99 @@ closest_symbol_value(ulong value)<br>
                 return(0);<br>
 }<br>
<br>
+/* Only for 6.4 and later */<br>
+struct syment *<br>
+next_symbol_by_symname(char *symbol)<br>
+{<br>
+       struct syment *sp;<br>
+<br>
+       if ((sp = symbol_search(symbol))) {<br>
+               sp++;<br>
+               if (MODULE_PSEUDO_SYMBOL(sp) && strstr(sp->name, "_END"))<br>
+                       return next_module_symbol_by_value(sp->value);<br>
+<br>
+               return sp;<br>
+       }<br>
+<br>
+       return NULL;<br>
+}<br>
+<br>
+/* val_in should be a pseudo module end symbol. */<br>
+struct syment *<br>
+next_module_symbol_by_value(ulong val_in)<br>
+{<br>
+       struct load_module *lm;<br>
+       struct syment *sp, *sp_end;<br>
+       ulong start, min;<br>
+       int i;<br>
+<br>
+retry:<br>
+       sp = sp_end = NULL;<br>
+       min = (ulong)-1;<br>
+       for (i = 0; i < st->mods_installed; i++) {<br>
+               lm = &st->load_modules[i];<br>
+<br>
+               /* Search for the next lowest symtable. */<br>
+               for_each_mod_mem_type(t) {<br>
+                       if (!lm->symtable[t])<br>
+                               continue;<br>
+<br>
+                       start = lm->symtable[t]->value;<br>
+                       if (start > val_in && start < min) {<br>
+                               min = start;<br>
+                               sp = lm->symtable[t];<br>
+                               sp_end = lm->symend[t];<br>
+                       }<br>
+               }<br>
+       }<br>
+<br>
+       if (!sp)<br>
+               return NULL;<br>
+<br>
+       for ( ; sp < sp_end; sp++) {<br>
+               if (MODULE_PSEUDO_SYMBOL(sp))<br>
+                       continue;<br>
+               if (sp->value > val_in)<br>
+                       return sp;<br>
+       }<br>
+<br>
+       /* Found a table that has only pseudo symbols. */<br>
+       val_in = sp_end->value;<br>
+       goto retry;<br></blockquote><div><br></div><div>Is it possible for 'retry' to become an infinite loop? And there is also a similar 'retry' in the prev_module_symbol_by_value().</div><div><br></div><div>Thanks.</div><div>Lianbo</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+}<br>
+<br>
+/* Only for 6.4 and later */<br>
+struct syment *<br>
+next_module_symbol_by_syment(struct syment *sp_in)<br>
+{<br>
+       struct load_module *lm;<br>
+       struct syment *sp;<br>
+       int i;<br>
+<br>
+       for (i = 0; i < st->mods_installed; i++) {<br>
+               lm = &st->load_modules[i];<br>
+<br>
+               for_each_mod_mem_type(t) {<br>
+                       if (!lm->symtable[t])<br>
+                               continue;<br>
+<br>
+                       if (sp_in < lm->symtable[t] || sp_in > lm->symend[t])<br>
+                               continue;<br>
+<br>
+                       if (sp_in == lm->symend[t])<br>
+                               return next_module_symbol_by_value(sp_in->value);<br>
+<br>
+                       sp = sp_in + 1;<br>
+                       if (MODULE_PSEUDO_SYMBOL(sp))<br>
+                               return next_module_symbol_by_value(sp->value);<br>
+<br>
+                       return sp;<br>
+               }<br>
+       }<br>
+<br>
+       return NULL;<br>
+}<br>
+<br>
 /*<br>
  *  For a given symbol, return a pointer to the next (higher) symbol's syment. <br>
  *  Either a symbol name or syment pointer may be passed as an argument.<br>
@@ -5230,6 +6057,9 @@ next_symbol(char *symbol, struct syment *sp_in)<br>
                        }<br>
                }<br>
<br>
+               if (MODULE_MEMORY())<br>
+                       return next_module_symbol_by_syment(sp_in);<br>
+<br>
                search_init = FALSE;<br>
<br>
                for (i = 0; i < st->mods_installed; i++) {<br>
@@ -5270,46 +6100,148 @@ next_symbol(char *symbol, struct syment *sp_in)<br>
                        }<br>
                }<br>
<br>
-               return NULL;<br>
+               return NULL;<br>
+       }<br>
+<br>
+       if (MODULE_MEMORY())<br>
+               return next_symbol_by_symname(symbol);<br>
+<br>
+       /*<br>
+        *  Deal with a few special cases...<br>
+        */<br>
+       if (strstr(symbol, " module)")) {<br>
+                sprintf(buf, "_MODULE_START_");<br>
+                strcat(buf, &symbol[1]);<br>
+                p1 = strstr(buf, " module)");<br>
+                *p1 = NULLCHAR;<br>
+                symbol = buf;<br>
+       }<br>
+<br>
+       if (STREQ(symbol, "_end")) {<br>
+               if (!st->mods_installed)<br>
+                       return NULL;<br>
+<br>
+                lm = &st->load_modules[0];<br>
+<br>
+               return lm->mod_symtable;<br>
+       }<br>
+<br>
+        if ((sp = symbol_search(symbol))) {<br>
+               sp++;<br>
+               if (MODULE_END(sp)) {<br>
+                       sp--;<br>
+                       i = load_module_index(sp);<br>
+                       if ((i+1) == st->mods_installed)<br>
+                               return NULL;<br>
+<br>
+                       lm = &st->load_modules[i+1];<br>
+<br>
+                       sp = lm->mod_symtable;<br>
+               }<br>
+               return sp;<br>
+       }<br>
+<br>
+        return NULL;<br>
+}<br>
+<br>
+/* Only for 6.4 and later */<br>
+struct syment *<br>
+prev_symbol_by_symname(char *symbol)<br>
+{<br>
+       struct syment *sp;<br>
+<br>
+        if ((sp = symbol_search(symbol))) {<br>
+               if (sp == st->symtable)<br>
+                       return NULL;<br>
+<br>
+               if (module_symbol(sp->value, NULL, NULL, NULL, 0)) {<br>
+                       if (MODULE_PSEUDO_SYMBOL(sp) && strstr(sp->name, "_START"))<br>
+                               return prev_module_symbol_by_value(sp->value);<br>
+                       else<br>
+                               sp--;<br>
+               } else<br>
+                       sp--;<br>
+<br>
+               return sp;<br>
+       }<br>
+<br>
+        return NULL;<br>
+}<br>
+<br>
+/* val_in should be a pseudo module start symbol. */<br>
+struct syment *<br>
+prev_module_symbol_by_value(ulong val_in)<br>
+{<br>
+       struct load_module *lm;<br>
+       struct syment *sp, *sp_end;<br>
+       ulong end, max;<br>
+       int i;<br>
+<br>
+retry:<br>
+       sp = sp_end = NULL;<br>
+       max = 0;<br>
+       for (i = 0; i < st->mods_installed; i++) {<br>
+               lm = &st->load_modules[i];<br>
+<br>
+               /* Search for the previous highest table. */<br>
+               for_each_mod_mem_type(t) {<br>
+                       if (!lm->symtable[t])<br>
+                               continue;<br>
+<br>
+                       end = lm->symend[t]->value;<br>
+                       if (end < val_in && end > max) {<br>
+                               max = end;<br>
+                               sp = lm->symtable[t];<br>
+                               sp_end = lm->symend[t];<br>
+                       }<br>
+               }<br>
        }<br>
<br>
+       if (!sp)<br>
+               return NULL;<br>
<br>
-       /*<br>
-        *  Deal with a few special cases...<br>
-        */<br>
-       if (strstr(symbol, " module)")) {<br>
-                sprintf(buf, "_MODULE_START_");<br>
-                strcat(buf, &symbol[1]);<br>
-                p1 = strstr(buf, " module)");<br>
-                *p1 = NULLCHAR;<br>
-                symbol = buf;<br>
+       for ( ; sp_end > sp; sp_end--) {<br>
+               if (MODULE_PSEUDO_SYMBOL(sp_end))<br>
+                       continue;<br>
+               if (sp_end->value < val_in)<br>
+                       return sp_end;<br>
        }<br>
<br>
-       if (STREQ(symbol, "_end")) {<br>
-               if (!st->mods_installed)<br>
-                       return NULL;<br>
+       /* Found a table that has only pseudo symbols. */<br>
+       val_in = sp->value;<br>
+       goto retry;<br>
+}<br>
<br>
-                lm = &st->load_modules[0];<br>
+/* Only for 6.4 and later */<br>
+struct syment *<br>
+prev_module_symbol_by_syment(struct syment *sp_in)<br>
+{<br>
+       struct load_module *lm;<br>
+       struct syment *sp;<br>
+       int i;<br>
<br>
-               return lm->mod_symtable;<br>
-       }<br>
+       for (i = 0; i < st->mods_installed; i++) {<br>
+               lm = &st->load_modules[i];<br>
<br>
-        if ((sp = symbol_search(symbol))) {<br>
-               sp++;<br>
-               if (MODULE_END(sp)) {<br>
-                       sp--;<br>
-                       i = load_module_index(sp);<br>
-                       if ((i+1) == st->mods_installed)<br>
-                               return NULL;<br>
+               for_each_mod_mem_type(t) {<br>
+                       if (!lm->symtable[t])<br>
+                               continue;<br>
<br>
-                       lm = &st->load_modules[i+1];<br>
+                       if (sp_in < lm->symtable[t] || sp_in > lm->symend[t])<br>
+                               continue;<br>
<br>
-                       sp = lm->mod_symtable;<br>
+                       if (sp_in == lm->symtable[t])<br>
+                               return prev_module_symbol_by_value(sp_in->value);<br>
+<br>
+                       sp = sp_in - 1;<br>
+                       if (MODULE_PSEUDO_SYMBOL(sp))<br>
+                               return prev_module_symbol_by_value(sp->value);<br>
+<br>
+                       return sp;<br>
                }<br>
-               return sp;<br>
        }<br>
<br>
-        return NULL;<br>
+       return NULL;<br>
 }<br>
<br>
 /*<br>
@@ -5335,6 +6267,9 @@ prev_symbol(char *symbol, struct syment *sp_in)<br>
                        sp_prev = sp;<br>
                 }<br>
<br>
+               if (MODULE_MEMORY())<br>
+                       return prev_module_symbol_by_syment(sp_in);<br>
+<br>
                search_init = FALSE;<br>
<br>
                 for (i = 0; i < st->mods_installed; i++) {<br>
@@ -5378,6 +6313,9 @@ prev_symbol(char *symbol, struct syment *sp_in)<br>
                 return NULL;<br>
        }<br>
<br>
+       if (MODULE_MEMORY())<br>
+               return prev_symbol_by_symname(symbol);<br>
+<br>
         if (strstr(symbol, " module)")) {<br>
                sprintf(buf, "_MODULE_START_");<br>
                 strcat(buf, &symbol[1]);<br>
@@ -5625,6 +6563,31 @@ get_syment_array(char *symbol, struct syment **sp_array, int max)<br>
                }<br>
         }<br>
<br>
+       if (!MODULE_MEMORY())<br>
+               goto old_module;<br>
+<br>
+       for (i = 0; i < st->mods_installed; i++) {<br>
+               lm = &st->load_modules[i];<br>
+<br>
+               for_each_mod_mem_type(t) {<br>
+                       if (!lm->symtable[t])<br>
+                               continue;<br>
+<br>
+                       sp = lm->symtable[t];<br>
+                       sp_end = lm->symend[t];<br>
+                       for (; sp < sp_end; sp++) {<br>
+                               if (STREQ(symbol, sp->name)) {<br>
+                                       if (max && (cnt < max))<br>
+                                               sp_array[cnt] = sp;<br>
+                                       cnt++;<br>
+                               }<br>
+                       }<br>
+               }<br>
+       }<br>
+<br>
+       return cnt;<br>
+<br>
+old_module:<br>
         for (i = 0; i < st->mods_installed; i++) {<br>
                 lm = &st->load_modules[i];<br>
                 sp = lm->mod_symtable;<br>
@@ -9229,6 +10192,9 @@ dump_offset_table(char *spec, ulong makestruct)<br>
                OFFSET(module_strtab));<br>
        fprintf(fp, "                 module_percpu: %ld\n",<br>
                OFFSET(module_percpu));<br>
+       fprintf(fp, "                    module_mem: %ld\n", OFFSET(module_mem));<br>
+       fprintf(fp, "            module_memory_base: %ld\n", OFFSET(module_memory_base));<br>
+       fprintf(fp, "            module_memory_size: %ld\n", OFFSET(module_memory_size));<br>
<br>
        fprintf(fp, "             module_sect_attrs: %ld\n",<br>
                OFFSET(module_sect_attrs));<br>
@@ -10852,6 +11818,7 @@ dump_offset_table(char *spec, ulong makestruct)<br>
                SIZE(super_block)); <br>
        fprintf(fp, "                       irqdesc: %ld\n", SIZE(irqdesc));<br>
        fprintf(fp, "                        module: %ld\n", SIZE(module));<br>
+       fprintf(fp, "                 module_memory: %ld\n", SIZE(module_memory));<br>
        fprintf(fp, "              module_sect_attr: %ld\n", SIZE(module_sect_attr));<br>
        fprintf(fp, "                     list_head: %ld\n", SIZE(list_head));<br>
        fprintf(fp, "                    hlist_head: %ld\n", SIZE(hlist_head));<br>
@@ -11467,6 +12434,13 @@ store_section_data(struct load_module *lm, bfd *bfd, asection *section)<br>
        lm->mod_section_data[i].section = section;<br>
        lm->mod_section_data[i].priority = prio;<br>
        lm->mod_section_data[i].flags = section->flags & ~SEC_FOUND;<br>
+       lm->mod_section_data[i].size = bfd_section_size(section);<br>
+       lm->mod_section_data[i].offset = 0;<br>
+       lm->mod_section_data[i].addr = 0;<br>
+       if (strlen(name) < MAX_MOD_SEC_NAME)<br>
+               strcpy(lm->mod_section_data[i].name, name);<br>
+       else<br>
+               strncpy(lm->mod_section_data[i].name, name, MAX_MOD_SEC_NAME-1);<br>
        /* <br>
         * The percpu section isn't included in kallsyms or module_core area.<br>
         */<br>
@@ -11474,13 +12448,8 @@ store_section_data(struct load_module *lm, bfd *bfd, asection *section)<br>
            (STREQ(name,".data.percpu") || STREQ(name, ".data..percpu"))) {<br>
                lm->mod_percpu_size = bfd_section_size(section);<br>
                lm->mod_section_data[i].flags |= SEC_FOUND;<br>
+               lm->mod_section_data[i].addr = lm->mod_percpu;<br>
        }<br>
-       lm->mod_section_data[i].size = bfd_section_size(section);<br>
-       lm->mod_section_data[i].offset = 0;<br>
-       if (strlen(name) < MAX_MOD_SEC_NAME)<br>
-               strcpy(lm->mod_section_data[i].name, name);<br>
-       else<br>
-               strncpy(lm->mod_section_data[i].name, name, MAX_MOD_SEC_NAME-1);<br>
        lm->mod_sections += 1;<br>
 }<br>
<br>
@@ -11722,6 +12691,124 @@ calculate_load_order_v2(struct load_module *lm, bfd *bfd, int dynamic,<br>
        }<br>
 }<br>
<br>
+/* Linux 6.4 and later */<br>
+static void<br>
+calculate_load_order_6_4(struct load_module *lm, bfd *bfd, int dynamic,<br>
+       void *minisyms, long symcount, unsigned int size)<br>
+{<br>
+       struct syment *s1, *s2;<br>
+       ulong sec_start;<br>
+       bfd_byte *from, *fromend;<br>
+       asymbol *store;<br>
+       asymbol *sym;<br>
+       symbol_info syminfo;<br>
+       char *secname;<br>
+       int i;<br>
+<br>
+       if ((store = bfd_make_empty_symbol(bfd)) == NULL)<br>
+               error(FATAL, "bfd_make_empty_symbol() failed\n");<br>
+<br>
+       for_each_mod_mem_type(t) {<br>
+               s1 = lm->symtable[t];<br>
+               s2 = lm->symend[t];<br>
+               while (s1 < s2) {<br>
+<br>
+                       if (MODULE_PSEUDO_SYMBOL(s1)) {<br>
+                               s1++;<br>
+                               continue;<br>
+                       }<br>
+<br>
+                       /* Skip over symbols whose sections have been identified. */<br>
+                       for (i = 0; i < lm->mod_sections; i++) {<br>
+                               if ((lm->mod_section_data[i].flags & SEC_FOUND) == 0)<br>
+                                       continue;<br>
+<br>
+                               if (s1->value >= lm->mod_section_data[i].addr &&<br>
+                                   s1->value < lm->mod_section_data[i].addr<br>
+                                               + lm->mod_section_data[i].size)<br>
+                                       break;<br>
+                       }<br>
+<br>
+                       /* Matched one of the sections. Skip symbol. */<br>
+                       if (i < lm->mod_sections) {<br>
+                               if (CRASHDEBUG(2))<br>
+                                       fprintf(fp, "skip %lx %s %s\n", s1->value, s1->name,<br>
+                                               lm->mod_section_data[i].name);<br>
+                               s1++;<br>
+                               continue;<br>
+                       }<br>
+<br>
+                       /* Find the symbol in the object file. */<br>
+                       from = (bfd_byte *) minisyms;<br>
+                       fromend = from + symcount * size;<br>
+                       secname = NULL;<br>
+                       for (; from < fromend; from += size) {<br>
+                               if (!(sym = bfd_minisymbol_to_symbol(bfd, dynamic, from, store)))<br>
+                                       error(FATAL, "bfd_minisymbol_to_symbol() failed\n");<br>
+<br>
+                               bfd_get_symbol_info(bfd, sym, &syminfo);<br>
+                               if (CRASHDEBUG(3)) {<br>
+                                       fprintf(fp,"matching sym %s %lx against bfd %s %lx\n",<br>
+                                               s1->name, (long) s1->value, <a href="http://syminfo.name" rel="noreferrer" target="_blank">syminfo.name</a>,<br>
+                                               (long) syminfo.value);<br>
+                               }<br>
+                               if (strcmp(<a href="http://syminfo.name" rel="noreferrer" target="_blank">syminfo.name</a>, s1->name) == 0) {<br>
+                                       secname = (char *)bfd_section_name(sym->section);<br>
+                                       break;<br>
+                               }<br>
+<br>
+                       }<br>
+                       if (secname == NULL) {<br>
+                               if (CRASHDEBUG(1))<br>
+                                       fprintf(fp, "symbol %s not found in module\n", s1->name);<br>
+                               s1++;<br>
+                               continue;<br>
+                       }<br>
+<br>
+                       /* Match the section it came in. */<br>
+                       for (i = 0; i < lm->mod_sections; i++) {<br>
+                               if (STREQ(lm->mod_section_data[i].name, secname))<br>
+                                       break;<br>
+                       }<br>
+<br>
+                       if (i == lm->mod_sections) {<br>
+                               fprintf(fp, "?? Section %s not found for symbol %s\n",<br>
+                                       secname, s1->name);<br>
+                               s1++;<br>
+                               continue;<br>
+                       }<br>
+<br>
+                       if (lm->mod_section_data[i].flags & SEC_FOUND) {<br>
+                               s1++;<br>
+                               continue;<br>
+                       }<br>
+<br>
+                       /* Update the offset information for the section */<br>
+                       sec_start = s1->value - syminfo.value;<br>
+                       /* keep the address instead of offset */<br>
+                       lm->mod_section_data[i].addr = sec_start;<br>
+                       lm->mod_section_data[i].flags |= SEC_FOUND;<br>
+<br>
+                       if (CRASHDEBUG(2))<br>
+                               fprintf(fp, "update sec offset sym %s @ %lx  val %lx  section %s\n",<br>
+                                       s1->name, s1->value, (ulong)syminfo.value, secname);<br>
+<br>
+                       if (strcmp(secname, ".text") == 0)<br>
+                               lm->mod_text_start = sec_start;<br>
+<br>
+                       if (strcmp(secname, ".bss") == 0)<br>
+                               lm->mod_bss_start = sec_start;<br>
+<br>
+                       if (strcmp(secname, ".data") == 0)<br>
+                               lm->mod_data_start = sec_start;<br>
+<br>
+                       if (strcmp(secname, ".rodata") == 0)<br>
+                               lm->mod_rodata_start = sec_start;<br>
+                       s1++;<br>
+               }<br>
+       }<br>
+}<br>
+<br>
 /*<br>
  *  Later versons of insmod store basic address information of each<br>
  *  module in a format that looks like the following example of the<br>
@@ -11927,8 +13014,11 @@ add_symbol_file(struct load_module *lm)<br>
                    (!STREQ(secname, ".text") &&<br>
                     !STREQ(secname, ".data.percpu") &&<br>
                     !STREQ(secname, ".data..percpu"))) {<br>
-                       sprintf(buf, " -s %s 0x%lx", secname, <br>
-                               lm->mod_section_data[i].offset + lm->mod_base);<br>
+                       if (MODULE_MEMORY())<br>
+                               sprintf(buf, " -s %s 0x%lx", secname, lm->mod_section_data[i].addr);<br>
+                       else<br>
+                               sprintf(buf, " -s %s 0x%lx", secname,<br>
+                                       lm->mod_section_data[i].offset + lm->mod_base);<br>
                        len += strlen(buf);<br>
                }<br>
        }<br>
@@ -12276,17 +13366,36 @@ kallsyms_module_symbol(struct load_module *lm, symbol_info *syminfo)<br>
<br>
        sp = NULL;<br>
        cnt = 0;<br>
-       for (spx = lm->mod_ext_symtable; spx <= lm->mod_ext_symend; spx++) {<br>
-               if (!STREQ(spx->name, syminfo->name))<br>
-                       continue;<br>
-               if (spx->cnt) { <br>
-                       cnt++;<br>
-                       continue;<br>
-               } <br>
+       if (MODULE_MEMORY()) {<br>
+               for_each_mod_mem_type(t) {<br>
+                       if (!lm->ext_symtable[t])<br>
+                               continue;<br>
+                       for (spx = lm->ext_symtable[t]; spx <= lm->ext_symend[t]; spx++) {<br>
+                               if (!STREQ(spx->name, syminfo->name))<br>
+                                       continue;<br>
+                               if (spx->cnt) {<br>
+                                       cnt++;<br>
+                                       continue;<br>
+                               }<br>
<br>
-               spx->cnt++;<br>
-               sp = spx;<br>
-               break;<br>
+                               spx->cnt++;<br>
+                               sp = spx;<br>
+                               break;<br>
+                       }<br>
+               }<br>
+       } else {<br>
+               for (spx = lm->mod_ext_symtable; spx <= lm->mod_ext_symend; spx++) {<br>
+                       if (!STREQ(spx->name, syminfo->name))<br>
+                               continue;<br>
+                       if (spx->cnt) {<br>
+                               cnt++;<br>
+                               continue;<br>
+                       }<br>
+<br>
+                       spx->cnt++;<br>
+                       sp = spx;<br>
+                       break;<br>
+               }<br>
        }<br>
<br>
        if (CRASHDEBUG(2)) {<br>
@@ -12323,7 +13432,7 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms,<br>
        char *nameptr, *secname;<br>
        long index;<br>
        long symalloc;<br>
-       int found;<br>
+       int found = FALSE;<br>
<br>
         if ((store = bfd_make_empty_symbol(bfd)) == NULL)<br>
                 error(FATAL, "bfd_make_empty_symbol() failed\n");<br>
@@ -12380,8 +13489,17 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms,<br>
        lm->mod_rodata_start = lm->mod_bss_start = 0;<br>
        lm->mod_load_symcnt = 0;<br>
        lm->mod_sections = 0;<br>
-               for (spx = lm->mod_ext_symtable; spx <= lm->mod_ext_symend; spx++)<br>
-                       spx->cnt = 0;<br>
+       if (MODULE_MEMORY()) {<br>
+               for_each_mod_mem_type(t) {<br>
+                       if (!lm->ext_symtable[t])<br>
+                               continue;<br>
+                       for (spx = lm->ext_symtable[t]; spx <= lm->ext_symend[t]; spx++)<br>
+                               spx->cnt = 0;<br>
+               }<br>
+       } else {<br>
+               for (spx = lm->mod_ext_symtable; spx <= lm->mod_ext_symend; spx++)<br>
+                       spx->cnt = 0;<br>
+       }<br>
        sp = lm->mod_load_symtable;<br>
<br>
        if (!(lm->mod_section_data = (struct mod_section_data *)<br>
@@ -12392,13 +13510,14 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms,<br>
<br>
         bfd_map_over_sections(bfd, section_header_info, MODULE_SECTIONS);<br>
<br>
-       if (kt->flags & KMOD_V1)<br>
+       if (MODULE_MEMORY())<br>
+               calculate_load_order_6_4(lm, bfd, dynamic, minisyms, symcount, size);<br>
+       else if (kt->flags & KMOD_V1)<br>
                calculate_load_order_v1(lm, bfd);<br>
        else<br>
                calculate_load_order_v2(lm, bfd, dynamic, minisyms,<br>
                        symcount, size);<br>
<br>
-<br>
         from = (bfd_byte *) minisyms;<br>
         fromend = from + symcount * size;<br>
         for (; from < fromend; from += size)<br>
@@ -12501,7 +13620,10 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms,<br>
                                        syminfo.value += lm->mod_percpu;<br>
                                        found = TRUE;<br>
                                } else {<br>
-                                        syminfo.value += lm->mod_section_data[i].offset + lm->mod_base;<br>
+                                       if (MODULE_MEMORY())<br>
+                                               syminfo.value += lm->mod_section_data[i].addr;<br>
+                                       else<br>
+                                               syminfo.value += lm->mod_section_data[i].offset + lm->mod_base;<br>
                                         found = TRUE;<br>
                                 }<br>
                         }<br>
@@ -12536,6 +13658,53 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms,<br>
         *  syminfo data types accepted above, plus the two pseudo symbols.<br>
          *  Note that the new syment name pointers haven't been resolved yet.<br>
         */<br>
+       if (!MODULE_MEMORY())<br>
+               goto old_module;<br>
+<br>
+       for_each_mod_mem_type(t) {<br>
+               if (!lm->ext_symtable[t])<br>
+                       continue;<br>
+               for (spx = lm->ext_symtable[t]; spx <= lm->ext_symend[t]; spx++) {<br>
+                       found = FALSE;<br>
+                       for (sp = lm->mod_load_symtable; sp < lm->mod_load_symend; sp++) {<br>
+                               index = (long)sp->name;<br>
+                               nameptr = &lm->mod_load_namespace.address[index];<br>
+                               if (STREQ(spx->name, nameptr)) {<br>
+                                       found = TRUE;<br>
+                                       if (spx->value == sp->value) {<br>
+                                               if (CRASHDEBUG(2))<br>
+                                                       fprintf(fp, "%s: %s matches!\n",<br>
+                                                                       lm->mod_name, nameptr);<br>
+                                       } else {<br>
+                                               if (CRASHDEBUG(2))<br>
+                                                       fprintf(fp,<br>
+                                              "[%s] %s: %lx != extern'd value: %lx\n",<br>
+                                                               lm->mod_name,<br>
+                                                               nameptr, sp->value,<br>
+                                                               spx->value);<br>
+                                       }<br>
+                                       break;<br>
+                               }<br>
+                       }<br>
+                       if (!found) {<br>
+                               if (CRASHDEBUG(2))<br>
+                                       fprintf(fp, "append ext %s (%lx)\n", spx->name, spx->value);<br>
+                               /* append it here... */<br>
+                               namespace_ctl(NAMESPACE_INSTALL,<br>
+                                       &lm->mod_load_namespace,<br>
+                                       lm->mod_load_symend, spx->name);<br>
+<br>
+                               lm->mod_load_symend->value = spx->value;<br>
+                               lm->mod_load_symend->type = spx->type;<br>
+                               lm->mod_load_symend->flags |= MODULE_SYMBOL;<br>
+                               lm->mod_load_symend++;<br>
+                               lm->mod_load_symcnt++;<br>
+                       }<br>
+               }<br>
+       }<br>
+       goto append_section_symbols;<br>
+<br>
+old_module:<br>
        for (spx = lm->mod_ext_symtable; spx <= lm->mod_ext_symend; spx++) {<br>
                found = FALSE;<br>
                for (sp = lm->mod_load_symtable; <br>
@@ -12578,6 +13747,7 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms,<br>
                } <br>
        }<br>
<br>
+append_section_symbols:<br>
        /*<br>
         * Append helpful pseudo symbols about found out sections.<br>
         * Use 'S' as its type which is never seen in existing symbols.<br>
@@ -12587,8 +13757,11 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms,<br>
                if (!(lm->mod_section_data[i].flags & SEC_FOUND))<br>
                        continue;<br>
                /* Section start */<br>
-               lm->mod_load_symend->value = lm->mod_base +<br>
-                                            lm->mod_section_data[i].offset;<br>
+               if (MODULE_MEMORY())<br>
+                       lm->mod_load_symend->value = lm->mod_section_data[i].addr;<br>
+               else<br>
+                       lm->mod_load_symend->value = lm->mod_base +<br>
+                                                    lm->mod_section_data[i].offset;<br>
                lm->mod_load_symend->type = 'S';<br>
                lm->mod_load_symend->flags |= MODULE_SYMBOL;<br>
                sprintf(name, "_MODULE_SECTION_START [%s]",<br>
@@ -12599,9 +13772,12 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms,<br>
                lm->mod_load_symcnt++;<br>
<br>
                /* Section end */<br>
-               lm->mod_load_symend->value = lm->mod_base +<br>
-                                            lm->mod_section_data[i].offset +<br>
-                                            lm->mod_section_data[i].size;<br>
+               if (MODULE_MEMORY())<br>
+                       lm->mod_load_symend->value = lm->mod_section_data[i].addr;<br>
+               else<br>
+                       lm->mod_load_symend->value = lm->mod_base +<br>
+                                                    lm->mod_section_data[i].offset;<br>
+               lm->mod_load_symend->value += lm->mod_section_data[i].size;<br>
                lm->mod_load_symend->type = 'S';<br>
                lm->mod_load_symend->flags |= MODULE_SYMBOL;<br>
                sprintf(name, "_MODULE_SECTION_END [%s]",<br>
@@ -12618,16 +13794,57 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms,<br>
         qsort(lm->mod_load_symtable, lm->mod_load_symcnt, sizeof(struct syment),<br>
                 compare_syms);<br>
<br>
+       if (MODULE_MEMORY()) {<br>
+               /* keep load symtable addresses to lm->load_symtable[] */<br>
+               /* TODO: make more efficient */<br>
+               for (sp = lm->mod_load_symtable; sp < lm->mod_load_symend; sp++) {<br>
+                       char buf1[BUFSIZE], buf2[BUFSIZE];<br>
+<br>
+                       if (CRASHDEBUG(2))<br>
+                               fprintf(fp, "DEBUG: value %16lx name %s\n", sp->value, sp->name);<br>
+<br>
+                       if (!MODULE_PSEUDO_SYMBOL(sp))<br>
+                               continue;<br>
+<br>
+                       for_each_mod_mem_type(t) {<br>
+                               if (!lm->mem[t].size)<br>
+                                       continue;<br>
+<br>
+                               sprintf(buf1, "%s%s", module_tag[t].start, lm->mod_name);<br>
+                               sprintf(buf2, "%s%s", module_tag[t].end, lm->mod_name);<br>
+<br>
+                               if (STREQ(sp->name, buf1)) {<br>
+                                       lm->load_symtable[t] = sp;<br>
+                                       break;<br>
+                               } else if (STREQ(sp->name, buf2)) {<br>
+                                       lm->load_symend[t] = sp;<br>
+                                       break;<br>
+                               }<br>
+                       }<br>
+               }<br>
+       }<br>
+<br>
        lm->mod_load_symend--;<br>
-       if (!MODULE_END(lm->mod_load_symend) &&<br>
+       if (!MODULE_MEMORY() && !MODULE_END(lm->mod_load_symend) &&<br>
            !IN_MODULE_PERCPU(lm->mod_load_symend->value, lm))<br>
                error(INFO, "%s: last symbol: %s is not _MODULE_END_%s?\n",<br>
                        lm->mod_name, lm->mod_load_symend->name, lm->mod_name);<br>
<br>
-       mod_symtable_hash_remove_range(lm->mod_symtable, lm->mod_symend);<br>
-        lm->mod_symtable = lm->mod_load_symtable;<br>
-        lm->mod_symend = lm->mod_load_symend;<br>
-       mod_symtable_hash_install_range(lm->mod_symtable, lm->mod_symend);<br>
+       if (MODULE_MEMORY()) {<br>
+               for_each_mod_mem_type(t) {<br>
+                       if (!lm->symtable[t])<br>
+                               continue;<br>
+                       mod_symtable_hash_remove_range(lm->symtable[t], lm->symend[t]);<br>
+               }<br>
+               lm->symtable = lm->load_symtable;<br>
+               lm->symend = lm->load_symend;<br>
+               mod_symtable_hash_install_range(lm->mod_load_symtable, lm->mod_load_symend);<br>
+       } else {<br>
+               mod_symtable_hash_remove_range(lm->mod_symtable, lm->mod_symend);<br>
+               lm->mod_symtable = lm->mod_load_symtable;<br>
+               lm->mod_symend = lm->mod_load_symend;<br>
+               mod_symtable_hash_install_range(lm->mod_symtable, lm->mod_symend);<br>
+       }<br>
<br>
        lm->mod_flags &= ~MOD_EXT_SYMS;<br>
        lm->mod_flags |= MOD_LOAD_SYMS;<br>
@@ -12657,7 +13874,18 @@ delete_load_module(ulong base_addr)<br>
                                req->name = lm->mod_namelist;<br>
                                gdb_interface(req); <br>
                        }<br>
-                       mod_symtable_hash_remove_range(lm->mod_symtable, lm->mod_symend);<br>
+                       if (MODULE_MEMORY()) {<br>
+                               if (lm->mod_load_symtable) {<br>
+                                       mod_symtable_hash_remove_range(lm->mod_load_symtable,<br>
+                                                                       lm->mod_load_symend);<br>
+                                       for_each_mod_mem_type(t) {<br>
+                                               lm->load_symtable[t] = NULL;<br>
+                                               lm->load_symend[t] = NULL;<br>
+                                       }<br>
+                               }<br>
+                       } else<br>
+                               mod_symtable_hash_remove_range(lm->mod_symtable, lm->mod_symend);<br>
+<br>
                        if (lm->mod_load_symtable) {<br>
                                free(lm->mod_load_symtable);<br>
                                 namespace_ctl(NAMESPACE_FREE,<br>
@@ -12665,9 +13893,23 @@ delete_load_module(ulong base_addr)<br>
                        }<br>
                        if (lm->mod_flags & MOD_REMOTE)<br>
                                unlink_module(lm);<br>
-                       lm->mod_symtable = lm->mod_ext_symtable;<br>
-                       lm->mod_symend = lm->mod_ext_symend;<br>
-                       mod_symtable_hash_install_range(lm->mod_symtable, lm->mod_symend);<br>
+<br>
+                       if (MODULE_MEMORY()) {<br>
+                               if (lm->mod_load_symtable) { /* still non-NULL */<br>
+                                       lm->symtable = lm->ext_symtable;<br>
+                                       lm->symend = lm->ext_symend;<br>
+                                       for_each_mod_mem_type(t) {<br>
+                                               if (!lm->symtable[t])<br>
+                                                       continue;<br>
+                                               mod_symtable_hash_install_range(lm->symtable[t],<br>
+                                                                               lm->symend[t]);<br>
+                                       }<br>
+                               }<br>
+                       } else {<br>
+                               lm->mod_symtable = lm->mod_ext_symtable;<br>
+                               lm->mod_symend = lm->mod_ext_symend;<br>
+                               mod_symtable_hash_install_range(lm->mod_symtable, lm->mod_symend);<br>
+                       }<br>
                        lm->mod_flags &= ~(MOD_LOAD_SYMS|MOD_REMOTE|MOD_NOPATCH);<br>
                        lm->mod_flags |= MOD_EXT_SYMS;<br>
                        lm->mod_load_symtable = NULL;<br>
@@ -12696,7 +13938,18 @@ delete_load_module(ulong base_addr)<br>
                                req->name = lm->mod_namelist;<br>
                                gdb_interface(req);<br>
                        }<br>
-                       mod_symtable_hash_remove_range(lm->mod_symtable, lm->mod_symend);<br>
+                       if (MODULE_MEMORY()) {<br>
+                               if (lm->mod_load_symtable) {<br>
+                                       mod_symtable_hash_remove_range(lm->mod_load_symtable,<br>
+                                                                       lm->mod_load_symend);<br>
+                                       for_each_mod_mem_type(t) {<br>
+                                               lm->load_symtable[t] = NULL;<br>
+                                               lm->load_symend[t] = NULL;<br>
+                                       }<br>
+                               }<br>
+                       } else<br>
+                               mod_symtable_hash_remove_range(lm->mod_symtable, lm->mod_symend);<br>
+<br>
                        if (lm->mod_load_symtable) {<br>
                                free(lm->mod_load_symtable);<br>
                                namespace_ctl(NAMESPACE_FREE,<br>
@@ -12704,9 +13957,23 @@ delete_load_module(ulong base_addr)<br>
                        }<br>
                        if (lm->mod_flags & MOD_REMOTE)<br>
                                unlink_module(lm);<br>
-                       lm->mod_symtable = lm->mod_ext_symtable;<br>
-                       lm->mod_symend = lm->mod_ext_symend;<br>
-                       mod_symtable_hash_install_range(lm->mod_symtable, lm->mod_symend);<br>
+<br>
+                       if (MODULE_MEMORY()) {<br>
+                               if (lm->mod_load_symtable) {<br>
+                                       lm->symtable = lm->ext_symtable;<br>
+                                       lm->symend = lm->ext_symend;<br>
+                                       for_each_mod_mem_type(t) {<br>
+                                               if (!lm->symtable[t])<br>
+                                                       continue;<br>
+                                               mod_symtable_hash_install_range(lm->symtable[t],<br>
+                                                                               lm->symend[t]);<br>
+                                       }<br>
+                               }<br>
+                       } else {<br>
+                               lm->mod_symtable = lm->mod_ext_symtable;<br>
+                               lm->mod_symend = lm->mod_ext_symend;<br>
+                               mod_symtable_hash_install_range(lm->mod_symtable, lm->mod_symend);<br>
+                       }<br>
                         lm->mod_flags &= ~(MOD_LOAD_SYMS|MOD_REMOTE|MOD_NOPATCH);<br>
                         lm->mod_flags |= MOD_EXT_SYMS;<br>
                         lm->mod_load_symtable = NULL;<br>
@@ -13475,6 +14742,34 @@ symbol_complete_match(const char *match, struct syment *sp_last)<br>
                sp_start = NULL;<br>
        }<br>
<br>
+       if (!MODULE_MEMORY())<br>
+               goto old_module;<br>
+<br>
+       for (i = 0; i < st->mods_installed; i++) {<br>
+               lm = &st->load_modules[i];<br>
+<br>
+               for_each_mod_mem_type(t) {<br>
+                       sp_end = lm->symend[t];<br>
+                       if (!sp_start)<br>
+                               sp_start = lm->symtable[t];<br>
+<br>
+                       if (sp_start < lm->symtable[t] || sp_start > sp_end)<br>
+                               continue;<br>
+<br>
+                       for (sp = sp_start; sp < sp_end; sp++) {<br>
+                               if (MODULE_PSEUDO_SYMBOL(sp))<br>
+                                       continue;<br>
+<br>
+                               if (STRNEQ(sp->name, match))<br>
+                                       return sp;<br>
+                       }<br>
+                       sp_start = NULL;<br>
+               }<br>
+       }<br>
+<br>
+       return NULL;<br>
+<br>
+old_module:<br>
        search_init = FALSE;<br>
<br>
        for (i = 0; i < st->mods_installed; i++) {<br>
@@ -13521,3 +14816,58 @@ symbol_complete_match(const char *match, struct syment *sp_last)<br>
<br>
        return NULL;<br>
 }<br>
+<br>
+/* Returns module memory type if addr is in range, otherwise MOD_INVALID(-1) */<br>
+static int<br>
+in_module_range(ulong addr, struct load_module *lm, int start, int end)<br>
+{<br>
+       ulong base = 0, size = 0;<br>
+       int i;<br>
+<br>
+       if (!MODULE_MEMORY())<br>
+               goto old_module;<br>
+<br>
+       for (i = start ; i <= end; i++) {<br>
+               base = lm->mem[i].base;<br>
+               size = lm->mem[i].size;<br>
+               if (!size)<br>
+                       continue;<br>
+               if ((addr >= base) && (addr < (base + size)))<br>
+                       return i;<br>
+       }<br>
+       return MOD_INVALID;<br>
+<br>
+old_module:<br>
+       if (start == MOD_TEXT) {<br>
+               base = lm->mod_base;<br>
+               size = lm->mod_size;<br>
+       } else if (start == MOD_INIT_TEXT) {<br>
+               base = lm->mod_init_module_ptr;<br>
+               size = lm->mod_init_size;<br>
+       } else<br>
+               error(FATAL, "invalid module memory type!");<br>
+<br>
+       if ((addr >= base) && (addr < (base + size)))<br>
+               return start;<br>
+<br>
+       return MOD_INVALID;<br>
+}<br>
+<br>
+/* Returns module memory type, otherwise MOD_INVALID(-1) */<br>
+static int<br>
+module_mem_type(ulong addr, struct load_module *lm)<br>
+{<br>
+       return in_module_range(addr, lm, MOD_TEXT, MOD_INIT_RODATA);<br>
+}<br>
+<br>
+/* Returns the end address of the module memory region. */<br>
+static ulong<br>
+module_mem_end(ulong addr, struct load_module *lm)<br>
+{<br>
+       int type = module_mem_type(addr, lm);<br>
+<br>
+       if (type == MOD_INVALID)<br>
+               return 0;<br>
+<br>
+       return lm->mem[type].base + lm->mem[type].size;<br>
+}<br>
-- <br>
2.31.1<br>
<br>
</blockquote></div></div>
</blockquote></div></div>