Adding kallsyms_lookupname()

olof at austin.ibm.com olof at austin.ibm.com
Thu Feb 26 09:32:41 EST 2004


Rusty,

Attached patch adds a kallsyms_lookupname() function for lookups of a
symbol name to an address.

I've attempted to be somewhat efficient and skip all "stems" where the
base part of the name doesn't match. I also added a loop through module
symbols to try finding the symbol there in case it's not found in the
kernel table. That part is not as efficient, but that's OK.

Furthermore, it's intentionally not exported as a symbol for module use,
since it can be used to circumvent other symbol export restrictions.


Please consider for upstream inclusion.


Thanks,

-Olof

Olof Johansson                                        Office: 4E002/905
Linux on Power Development                            IBM Systems Group
Email: olof at austin.ibm.com                          Phone: 512-838-9858
All opinions are my own and not those of IBM
-------------- next part --------------
===== include/linux/kallsyms.h 1.3 vs edited =====
--- 1.3/include/linux/kallsyms.h	Wed Dec 25 21:46:20 2002
+++ edited/include/linux/kallsyms.h	Tue Feb 24 21:59:20 2004
@@ -8,6 +8,9 @@
 #include <linux/config.h>
 
 #ifdef CONFIG_KALLSYMS
+/* Lookup the address of a symbol. Returns 0 if not found. */
+unsigned long kallsyms_lookupname(char *name);
+
 /* Lookup an address.  modname is set to NULL if it's in the kernel. */
 const char *kallsyms_lookup(unsigned long addr,
 			    unsigned long *symbolsize,
@@ -18,6 +21,11 @@
 extern void __print_symbol(const char *fmt, unsigned long address);
 
 #else /* !CONFIG_KALLSYMS */
+
+static inline const unsigned long kallsyms_lookupname(unsigned long addr)
+{
+	return 0;
+}
 
 static inline const char *kallsyms_lookup(unsigned long addr,
 					  unsigned long *symbolsize,
===== kernel/kallsyms.c 1.14 vs edited =====
--- 1.14/kernel/kallsyms.c	Sun Aug 31 18:14:13 2003
+++ edited/kernel/kallsyms.c	Wed Feb 25 16:29:42 2004
@@ -37,6 +37,58 @@
 	return 0;
 }
 
+/* Lookup the address of a symbol. Returns 0 if not found. */
+unsigned long kallsyms_lookupname(char *name)
+{
+	unsigned long i;
+	char namebuf[128];
+	char *knames = kallsyms_names;
+	unsigned int namelen = strlen(name);
+	unsigned long val;
+	char type;
+
+	/* This kernel should never had been booted. */
+	BUG_ON(!kallsyms_addresses);
+
+	namebuf[0] = 0;
+
+	for (i = 0; i < kallsyms_num_syms; i++) { 
+		unsigned prefix = *knames++;
+		unsigned len = strlen(knames);
+
+		/* Skip over as long as prefix at 0 doesn't match */
+		if (!prefix && len <= namelen &&
+		    strncmp(knames, name, len)) {
+			do {
+				knames += len + 1;
+				prefix = *knames++;
+				len = strlen(knames);
+				i++;
+			} while (prefix && i < kallsyms_num_syms);
+		}
+
+		strncpy(namebuf + prefix, knames, 127 - prefix);
+
+		if (prefix + len == namelen &&
+		     !strncmp(namebuf, name, namelen))
+			return kallsyms_addresses[i];
+		knames += len + 1;
+	}
+
+	/* If not found above, try looking up the name in modules.
+	 * This isn't all that efficient, but performance isn't critical
+	 * here.
+	 */
+	i = 0;
+	while (module_get_kallsym(i++, &val, &type, namebuf)) {
+		namebuf[127] = 0; /* Just in case */
+		if (!strcmp(namebuf, name))
+			return val;
+	}
+
+	return 0;
+}
+
 /* Lookup an address.  modname is set to NULL if it's in the kernel. */
 const char *kallsyms_lookup(unsigned long addr,
 			    unsigned long *symbolsize,


More information about the Linuxppc64-dev mailing list