|
@@ -88,6 +88,51 @@ static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs);
|
|
static int kretprobe_dispatcher(struct kretprobe_instance *ri,
|
|
static int kretprobe_dispatcher(struct kretprobe_instance *ri,
|
|
struct pt_regs *regs);
|
|
struct pt_regs *regs);
|
|
|
|
|
|
|
|
+/* Memory fetching by symbol */
|
|
|
|
+struct symbol_cache {
|
|
|
|
+ char *symbol;
|
|
|
|
+ long offset;
|
|
|
|
+ unsigned long addr;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+unsigned long update_symbol_cache(struct symbol_cache *sc)
|
|
|
|
+{
|
|
|
|
+ sc->addr = (unsigned long)kallsyms_lookup_name(sc->symbol);
|
|
|
|
+
|
|
|
|
+ if (sc->addr)
|
|
|
|
+ sc->addr += sc->offset;
|
|
|
|
+
|
|
|
|
+ return sc->addr;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void free_symbol_cache(struct symbol_cache *sc)
|
|
|
|
+{
|
|
|
|
+ kfree(sc->symbol);
|
|
|
|
+ kfree(sc);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+struct symbol_cache *alloc_symbol_cache(const char *sym, long offset)
|
|
|
|
+{
|
|
|
|
+ struct symbol_cache *sc;
|
|
|
|
+
|
|
|
|
+ if (!sym || strlen(sym) == 0)
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ sc = kzalloc(sizeof(struct symbol_cache), GFP_KERNEL);
|
|
|
|
+ if (!sc)
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ sc->symbol = kstrdup(sym, GFP_KERNEL);
|
|
|
|
+ if (!sc->symbol) {
|
|
|
|
+ kfree(sc);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+ sc->offset = offset;
|
|
|
|
+ update_symbol_cache(sc);
|
|
|
|
+
|
|
|
|
+ return sc;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Kprobes-specific fetch functions
|
|
* Kprobes-specific fetch functions
|
|
*/
|
|
*/
|
|
@@ -103,6 +148,20 @@ DEFINE_BASIC_FETCH_FUNCS(stack)
|
|
#define fetch_stack_string NULL
|
|
#define fetch_stack_string NULL
|
|
#define fetch_stack_string_size NULL
|
|
#define fetch_stack_string_size NULL
|
|
|
|
|
|
|
|
+#define DEFINE_FETCH_symbol(type) \
|
|
|
|
+__kprobes void FETCH_FUNC_NAME(symbol, type)(struct pt_regs *regs, \
|
|
|
|
+ void *data, void *dest) \
|
|
|
|
+{ \
|
|
|
|
+ struct symbol_cache *sc = data; \
|
|
|
|
+ if (sc->addr) \
|
|
|
|
+ fetch_memory_##type(regs, (void *)sc->addr, dest); \
|
|
|
|
+ else \
|
|
|
|
+ *(type *)dest = 0; \
|
|
|
|
+}
|
|
|
|
+DEFINE_BASIC_FETCH_FUNCS(symbol)
|
|
|
|
+DEFINE_FETCH_symbol(string)
|
|
|
|
+DEFINE_FETCH_symbol(string_size)
|
|
|
|
+
|
|
/* Fetch type information table */
|
|
/* Fetch type information table */
|
|
const struct fetch_type kprobes_fetch_type_table[] = {
|
|
const struct fetch_type kprobes_fetch_type_table[] = {
|
|
/* Special types */
|
|
/* Special types */
|