config KPROBES
        bool "Kprobes (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && MODULES
+       depends on KALLSYMS && EXPERIMENTAL && MODULES
        help
          Kprobes allows you to trap at almost any kernel address and
          execute a callback function.  register_kprobe() establishes
 
 
 config KPROBES
        bool "Kprobes (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && MODULES
+       depends on KALLSYMS && EXPERIMENTAL && MODULES
        help
          Kprobes allows you to trap at almost any kernel address and
          execute a callback function.  register_kprobe() establishes
 
 
 config KPROBES
        bool "Kprobes (EXPERIMENTAL)"
-       depends on PPC64 && EXPERIMENTAL && MODULES
+       depends on PPC64 && KALLSYMS && EXPERIMENTAL && MODULES
        help
          Kprobes allows you to trap at almost any kernel address and
          execute a callback function.  register_kprobe() establishes
 
 
 config KPROBES
        bool "Kprobes (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && MODULES
+       depends on KALLSYMS && EXPERIMENTAL && MODULES
        help
          Kprobes allows you to trap at almost any kernel address and
          execute a callback function.  register_kprobe() establishes
 
 
 config KPROBES
        bool "Kprobes (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && MODULES
+       depends on KALLSYMS && EXPERIMENTAL && MODULES
        help
          Kprobes allows you to trap at almost any kernel address and
          execute a callback function.  register_kprobe() establishes
 
 #define IS_TDI(instr)          (((instr) & 0xfc000000) == 0x08000000)
 #define IS_TWI(instr)          (((instr) & 0xfc000000) == 0x0c000000)
 
+/*
+ * 64bit powerpc uses function descriptors.
+ * Handle cases where:
+ *             - User passes a <.symbol>
+ *             - User passes a <symbol>
+ *             - User passes a non-existant symbol, kallsyms_lookup_name
+ *               returns 0. Don't deref the NULL pointer in that case
+ */
+#define kprobe_lookup_name(name, addr)                                 \
+{                                                                      \
+       addr = (kprobe_opcode_t *)kallsyms_lookup_name(name);           \
+       if (!(name[0] == '.') && addr)                                  \
+               addr = *(kprobe_opcode_t **)addr;                       \
+}
+
 #define JPROBE_ENTRY(pentry)   (kprobe_opcode_t *)((func_descr_t *)pentry)
 
 #define is_trap(instr) (IS_TW(instr) || IS_TD(instr) || \
 
        /* location of the probe point */
        kprobe_opcode_t *addr;
 
+       /* Allow user to indicate symbol name of the probe point */
+       char *symbol_name;
+
+       /* Offset into the symbol */
+       unsigned int offset;
+
        /* Called before addr is executed. */
        kprobe_pre_handler_t pre_handler;
 
 
        }
        return module_kallsyms_lookup_name(name);
 }
-EXPORT_SYMBOL_GPL(kallsyms_lookup_name);
 
 /*
  * Lookup an address
 
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/moduleloader.h>
+#include <linux/kallsyms.h>
 #include <asm-generic/sections.h>
 #include <asm/cacheflush.h>
 #include <asm/errno.h>
 #define KPROBE_HASH_BITS 6
 #define KPROBE_TABLE_SIZE (1 << KPROBE_HASH_BITS)
 
+
+/*
+ * Some oddball architectures like 64bit powerpc have function descriptors
+ * so this must be overridable.
+ */
+#ifndef kprobe_lookup_name
+#define kprobe_lookup_name(name, addr) \
+       addr = ((kprobe_opcode_t *)(kallsyms_lookup_name(name)))
+#endif
+
 static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
 static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
 static atomic_t kprobe_count;
        struct kprobe *old_p;
        struct module *probed_mod;
 
+       /*
+        * If we have a symbol_name argument look it up,
+        * and add it to the address.  That way the addr
+        * field can either be global or relative to a symbol.
+        */
+       if (p->symbol_name) {
+               if (p->addr)
+                       return -EINVAL;
+               kprobe_lookup_name(p->symbol_name, p->addr);
+       }
+
+       if (!p->addr)
+               return -EINVAL;
+       p->addr = (kprobe_opcode_t *)(((char *)p->addr)+ p->offset);
+
        if ((!kernel_text_address((unsigned long) p->addr)) ||
                in_kprobes_functions((unsigned long) p->addr))
                return -EINVAL;
 
 }
 
 static struct jprobe tcp_send_probe = {
-       .kp = { .addr = (kprobe_opcode_t *) &tcp_sendmsg, },
-       .entry = (kprobe_opcode_t *) &jtcp_sendmsg,
+       .kp = {
+               .symbol_name    = "tcp_sendmsg",
+       },
+       .entry  = JPROBE_ENTRY(jtcp_sendmsg),
 };