#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \
                         2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1)
 
+struct module;
+
 #ifdef CONFIG_KALLSYMS
 /* Lookup the address for a symbol. Returns 0 if not found. */
 unsigned long kallsyms_lookup_name(const char *name);
 
+/* Call a function on each kallsyms symbol in the core kernel */
+int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
+                                     unsigned long),
+                           void *data);
+
 extern int kallsyms_lookup_size_offset(unsigned long addr,
                                  unsigned long *symbolsize,
                                  unsigned long *offset);
        return 0;
 }
 
+static inline int kallsyms_on_each_symbol(int (*fn)(void *, const char *,
+                                                   struct module *,
+                                                   unsigned long),
+                                         void *data)
+{
+       return 0;
+}
+
 static inline int kallsyms_lookup_size_offset(unsigned long addr,
                                              unsigned long *symbolsize,
                                              unsigned long *offset)
 
 /* Look for this name: can be of form module:name. */
 unsigned long module_kallsyms_lookup_name(const char *name);
 
+int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
+                                            struct module *, unsigned long),
+                                  void *data);
+
 extern void __module_put_and_exit(struct module *mod, long code)
        __attribute__((noreturn));
 #define module_put_and_exit(code) __module_put_and_exit(THIS_MODULE, code);
        return 0;
 }
 
+static inline int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
+                                                          struct module *,
+                                                          unsigned long),
+                                                void *data)
+{
+       return 0;
+}
+
 static inline int register_module_notifier(struct notifier_block * nb)
 {
        /* no events will happen anyway, so this can always succeed */
 
        return module_kallsyms_lookup_name(name);
 }
 
+int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
+                                     unsigned long),
+                           void *data)
+{
+       char namebuf[KSYM_NAME_LEN];
+       unsigned long i;
+       unsigned int off;
+       int ret;
+
+       for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
+               off = kallsyms_expand_symbol(off, namebuf);
+               ret = fn(data, namebuf, NULL, kallsyms_addresses[i]);
+               if (ret != 0)
+                       return ret;
+       }
+       return module_kallsyms_on_each_symbol(fn, data);
+}
+EXPORT_SYMBOL_GPL(kallsyms_on_each_symbol);
+
 static unsigned long get_symbol_pos(unsigned long addr,
                                    unsigned long *symbolsize,
                                    unsigned long *offset)
 
        preempt_enable();
        return ret;
 }
+
+int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
+                                            struct module *, unsigned long),
+                                  void *data)
+{
+       struct module *mod;
+       unsigned int i;
+       int ret;
+
+       list_for_each_entry(mod, &modules, list) {
+               for (i = 0; i < mod->num_symtab; i++) {
+                       ret = fn(data, mod->strtab + mod->symtab[i].st_name,
+                                mod, mod->symtab[i].st_value);
+                       if (ret != 0)
+                               return ret;
+               }
+       }
+       return 0;
+}
 #endif /* CONFIG_KALLSYMS */
 
 static char *module_flags(struct module *mod, char *buf)