[RFC PATCH 06/15] Support "mod -s|-S" options

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Support "mod -s|-S" with introducing lm->load_sym{table,end}

but many functions like "mod -d|-D" are still not supported.

Signed-off-by: Kazuhito Hagio <k-hagio-ab@xxxxxxx>
---
 defs.h         |   9 +-
 gdb-10.2.patch |  16 +++
 symbols.c      | 350 ++++++++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 340 insertions(+), 35 deletions(-)

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

--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://listman.redhat.com/mailman/listinfo/crash-utility
Contribution Guidelines: https://github.com/crash-utility/crash/wiki




[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux