<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>