[Crash-utility] [PATCH] Fix for 4.19-rc1 and later "relative __ksymtab entries"

Dominique Martinet asmadeus at codewreck.org
Tue Aug 28 23:34:50 UTC 2018


kernels which have CONFIG_HAVE_ARCH_PREL32_RELOCATIONS will now store
module symbol values relative to themselves since linux kernel's commit
7290d580957 ("module: use relative references for __ksymtab entries")

Do the lookup one way or another depending on the kernel's kernel_symbol
struct, the case without the ARCH_PREL32_RELOCATIONS is the same as the
old behaviour

---
Hi! This is a follow-up on the bz I opened yesterday[1]

I'll let you commit your part of the tasks_struct pids, with both patches
I can start crash normally and could check that address of symbols within
a module look correct when compared to /proc/kallsyms, so I guess this
isn't too bad.
I also tried with an older kernel without problem.

[1] https://bugzilla.redhat.com/show_bug.cgi?id=1623127

 defs.h    |  1 +
 symbols.c | 98 +++++++++++++++++++++++++++++++++++++------------------
 2 files changed, 68 insertions(+), 31 deletions(-)

diff --git a/defs.h b/defs.h
index 8687ff1..166ee48 100644
--- a/defs.h
+++ b/defs.h
@@ -2036,6 +2036,7 @@ struct offset_table {                    /* stash of commonly-used offsets */
 	long memcg_cache_params___root_caches_node;
 	long memcg_cache_params_children;
 	long memcg_cache_params_children_node;
+	long kernel_symbol_value;
 };
 
 struct size_table {         /* stash of commonly-used sizes */
diff --git a/symbols.c b/symbols.c
index 2e6713a..7e73bad 100644
--- a/symbols.c
+++ b/symbols.c
@@ -1595,12 +1595,40 @@ store_module_symbols_v1(ulong total, int mods_installed)
                 st->flags |= INSMOD_BUILTIN;
 }
 
-struct kernel_symbol
-{
-        unsigned long value;
-        const char *name;
+union kernel_symbol {
+	struct kernel_symbol_v1 {
+		unsigned long value;
+		const char *name;
+	} v1;
+	/* kernel 4.19 introduced relative symbol positionning */
+	struct kernel_symbol_v2 {
+		int value_offset;
+		int name_offset;
+	} v2;
 };
 
+static ulong
+modsym_name(ulong syms, union kernel_symbol *modsym, int i)
+{
+	if (VALID_MEMBER(kernel_symbol_value))
+		return (ulong)modsym->v1.name;
+
+	return syms + i * sizeof(struct kernel_symbol_v2) +
+		offsetof(struct kernel_symbol_v2, name_offset) +
+		modsym->v2.name_offset;
+}
+
+static ulong
+modsym_value(ulong syms, union kernel_symbol *modsym, int i)
+{
+	if (VALID_MEMBER(kernel_symbol_value))
+		return (ulong)modsym->v1.value;
+
+	return syms + i * sizeof(struct kernel_symbol_v2) +
+		offsetof(struct kernel_symbol_v2, value_offset) +
+		modsym->v2.value_offset;
+}
+
 void
 store_module_symbols_v2(ulong total, int mods_installed)
 {
@@ -1614,7 +1642,8 @@ store_module_symbols_v2(ulong total, int mods_installed)
 	long strbuflen;
 	ulong size;
 	int mcnt, lm_mcnt;
-	struct kernel_symbol *modsym;
+	union kernel_symbol *modsym;
+	size_t kernel_symbol_size;
 	struct load_module *lm;
 	char buf1[BUFSIZE];
 	char buf2[BUFSIZE];
@@ -1639,6 +1668,13 @@ store_module_symbols_v2(ulong total, int mods_installed)
 		  "re-initialization of module symbols not implemented yet!\n");
 	}
 
+	MEMBER_OFFSET_INIT(kernel_symbol_value, "kernel_symbol", "value");
+	if (VALID_MEMBER(kernel_symbol_value)) {
+		kernel_symbol_size = sizeof(struct kernel_symbol_v1);
+	} else {
+		kernel_symbol_size = sizeof(struct kernel_symbol_v2);
+	}
+
         if ((st->ext_module_symtable = (struct syment *)
              calloc(total, sizeof(struct syment))) == NULL)
                 error(FATAL, "v2 module syment space malloc (%ld symbols): %s\n",
@@ -1750,20 +1786,20 @@ store_module_symbols_v2(ulong total, int mods_installed)
 		}
 
 		if (nsyms) {
-			modsymbuf = GETBUF(sizeof(struct kernel_symbol)*nsyms);
+			modsymbuf = GETBUF(kernel_symbol_size*nsyms);
 			readmem((ulong)syms, KVADDR, modsymbuf,
-				nsyms * sizeof(struct kernel_symbol),
+				nsyms * kernel_symbol_size,
 				"module symbols", FAULT_ON_ERROR);
 		} 
 
 		for (i = first = last = 0; i < nsyms; i++) {
-			modsym = (struct kernel_symbol *)
-			    (modsymbuf + (i * sizeof(struct kernel_symbol)));
+			modsym = (union kernel_symbol *)
+			    (modsymbuf + (i * kernel_symbol_size));
 			if (!first
-			    || first > (ulong)modsym->name)
-				first = (ulong)modsym->name;
-			if ((ulong)modsym->name > last)
-				last = (ulong)modsym->name;
+			    || first > modsym_name(syms, modsym, i))
+				first = modsym_name(syms, modsym, i);
+			if (modsym_name(syms, modsym, i) > last)
+				last = modsym_name(syms, modsym, i);
 		}
 
 		if (last > first) {
@@ -1787,21 +1823,21 @@ store_module_symbols_v2(ulong total, int mods_installed)
 
 		for (i = 0; i < nsyms; i++) {
 
-			modsym = (struct kernel_symbol *)
-			    (modsymbuf + (i * sizeof(struct kernel_symbol)));
+			modsym = (union kernel_symbol *)
+			    (modsymbuf + (i * kernel_symbol_size));
 
 			BZERO(buf1, BUFSIZE);
 
 			if (strbuf) 
 				strcpy(buf1,
-					&strbuf[(ulong)modsym->name - first]);
+					&strbuf[modsym_name(syms, modsym, i) - first]);
 			else 
-				read_string((ulong)modsym->name, buf1,
+				read_string(modsym_name(syms, modsym, i), buf1,
                             		BUFSIZE-1);
 
                 	if (strlen(buf1)) {
 				st->ext_module_symtable[mcnt].value = 
-					modsym->value;
+					modsym_value(syms, modsym, i);
 				st->ext_module_symtable[mcnt].type = '?'; 
 				st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL;
 				strip_module_symbol_end(buf1);
@@ -1823,21 +1859,21 @@ store_module_symbols_v2(ulong total, int mods_installed)
 			FREEBUF(strbuf);
 
 		if (ngplsyms) {
-			modsymbuf = GETBUF(sizeof(struct kernel_symbol) *
+			modsymbuf = GETBUF(kernel_symbol_size *
 				ngplsyms);
 			readmem((ulong)gpl_syms, KVADDR, modsymbuf,
-				ngplsyms * sizeof(struct kernel_symbol),
+				ngplsyms * kernel_symbol_size,
 				"module gpl symbols", FAULT_ON_ERROR);
 		} 
 
 		for (i = first = last = 0; i < ngplsyms; i++) {
-			modsym = (struct kernel_symbol *)
-			    (modsymbuf + (i * sizeof(struct kernel_symbol)));
+			modsym = (union kernel_symbol *)
+			    (modsymbuf + (i * kernel_symbol_size));
 			if (!first
-			    || first > (ulong)modsym->name)
-				first = (ulong)modsym->name;
-			if ((ulong)modsym->name > last)
-				last = (ulong)modsym->name;
+			    || first > modsym_name(gpl_syms, modsym, i))
+				first = modsym_name(gpl_syms, modsym, i);
+			if (modsym_name(gpl_syms, modsym, i) > last)
+				last = modsym_name(gpl_syms, modsym, i);
 		}
 
 		if (last > first) {
@@ -1860,21 +1896,21 @@ store_module_symbols_v2(ulong total, int mods_installed)
 
 		for (i = 0; i < ngplsyms; i++) {
 
-			modsym = (struct kernel_symbol *)
-			    (modsymbuf + (i * sizeof(struct kernel_symbol)));
+			modsym = (union kernel_symbol *)
+			    (modsymbuf + (i * kernel_symbol_size));
 
 			BZERO(buf1, BUFSIZE);
 
 			if (strbuf) 
 				strcpy(buf1,
-					&strbuf[(ulong)modsym->name - first]);
+					&strbuf[modsym_name(gpl_syms, modsym, i) - first]);
 			else 
-				read_string((ulong)modsym->name, buf1,
+				read_string(modsym_name(gpl_syms, modsym, i), buf1,
                             		BUFSIZE-1);
 
                 	if (strlen(buf1)) {
 				st->ext_module_symtable[mcnt].value = 
-					modsym->value;
+					modsym_value(gpl_syms, modsym, i);
 				st->ext_module_symtable[mcnt].type = '?'; 
 				st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL;
 				strip_module_symbol_end(buf1);
-- 
2.17.1




More information about the Crash-utility mailing list