diff options
| author | Masami Hiramatsu <mhiramat@redhat.com> | 2010-07-05 14:54:45 -0400 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-07-05 14:54:45 -0400 |
| commit | e09c8614b32915c16f68e039ac7040e602d73e35 (patch) | |
| tree | 725c768b1d2fbd569e447e7d4a2044dc0aa7a1d5 | |
| parent | 167a58f10d9cd1bdf6a911aa1eecbdff596de156 (diff) | |
tracing/kprobes: Support "string" type
Support string type tracing and printing in kprobe-tracer.
This allows user to trace string data in kernel including __user data. Note
that sometimes __user data may not be accessed if it is paged-out (sorry, but
kprobes operation should be done in atomic, we can not wait for page-in).
Commiter note: Fixed up conflicts with b7e2ece.
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <20100519195724.2885.18788.stgit@localhost6.localdomain6>
Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
| -rw-r--r-- | Documentation/trace/kprobetrace.txt | 2 | ||||
| -rw-r--r-- | kernel/trace/trace_kprobe.c | 370 |
2 files changed, 293 insertions, 79 deletions
diff --git a/Documentation/trace/kprobetrace.txt b/Documentation/trace/kprobetrace.txt index ec94748ae65b..5f77d94598dd 100644 --- a/Documentation/trace/kprobetrace.txt +++ b/Documentation/trace/kprobetrace.txt | |||
| @@ -42,7 +42,7 @@ Synopsis of kprobe_events | |||
| 42 | +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**) | 42 | +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**) |
| 43 | NAME=FETCHARG : Set NAME as the argument name of FETCHARG. | 43 | NAME=FETCHARG : Set NAME as the argument name of FETCHARG. |
| 44 | FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types | 44 | FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types |
| 45 | (u8/u16/u32/u64/s8/s16/s32/s64) are supported. | 45 | (u8/u16/u32/u64/s8/s16/s32/s64) and string are supported. |
| 46 | 46 | ||
| 47 | (*) only for return probe. | 47 | (*) only for return probe. |
| 48 | (**) this is useful for fetching a field of data structures. | 48 | (**) this is useful for fetching a field of data structures. |
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 3b831d8e201e..1b79d1c15726 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
| @@ -30,6 +30,8 @@ | |||
| 30 | #include <linux/ptrace.h> | 30 | #include <linux/ptrace.h> |
| 31 | #include <linux/perf_event.h> | 31 | #include <linux/perf_event.h> |
| 32 | #include <linux/stringify.h> | 32 | #include <linux/stringify.h> |
| 33 | #include <linux/limits.h> | ||
| 34 | #include <linux/uaccess.h> | ||
| 33 | #include <asm/bitsperlong.h> | 35 | #include <asm/bitsperlong.h> |
| 34 | 36 | ||
| 35 | #include "trace.h" | 37 | #include "trace.h" |
| @@ -38,6 +40,7 @@ | |||
| 38 | #define MAX_TRACE_ARGS 128 | 40 | #define MAX_TRACE_ARGS 128 |
| 39 | #define MAX_ARGSTR_LEN 63 | 41 | #define MAX_ARGSTR_LEN 63 |
| 40 | #define MAX_EVENT_NAME_LEN 64 | 42 | #define MAX_EVENT_NAME_LEN 64 |
| 43 | #define MAX_STRING_SIZE PATH_MAX | ||
| 41 | #define KPROBE_EVENT_SYSTEM "kprobes" | 44 | #define KPROBE_EVENT_SYSTEM "kprobes" |
| 42 | 45 | ||
| 43 | /* Reserved field names */ | 46 | /* Reserved field names */ |
| @@ -58,14 +61,16 @@ const char *reserved_field_names[] = { | |||
| 58 | }; | 61 | }; |
| 59 | 62 | ||
| 60 | /* Printing function type */ | 63 | /* Printing function type */ |
| 61 | typedef int (*print_type_func_t)(struct trace_seq *, const char *, void *); | 64 | typedef int (*print_type_func_t)(struct trace_seq *, const char *, void *, |
| 65 | void *); | ||
| 62 | #define PRINT_TYPE_FUNC_NAME(type) print_type_##type | 66 | #define PRINT_TYPE_FUNC_NAME(type) print_type_##type |
| 63 | #define PRINT_TYPE_FMT_NAME(type) print_type_format_##type | 67 | #define PRINT_TYPE_FMT_NAME(type) print_type_format_##type |
| 64 | 68 | ||
| 65 | /* Printing in basic type function template */ | 69 | /* Printing in basic type function template */ |
| 66 | #define DEFINE_BASIC_PRINT_TYPE_FUNC(type, fmt, cast) \ | 70 | #define DEFINE_BASIC_PRINT_TYPE_FUNC(type, fmt, cast) \ |
| 67 | static __kprobes int PRINT_TYPE_FUNC_NAME(type)(struct trace_seq *s, \ | 71 | static __kprobes int PRINT_TYPE_FUNC_NAME(type)(struct trace_seq *s, \ |
| 68 | const char *name, void *data)\ | 72 | const char *name, \ |
| 73 | void *data, void *ent)\ | ||
| 69 | { \ | 74 | { \ |
| 70 | return trace_seq_printf(s, " %s=" fmt, name, (cast)*(type *)data);\ | 75 | return trace_seq_printf(s, " %s=" fmt, name, (cast)*(type *)data);\ |
| 71 | } \ | 76 | } \ |
| @@ -80,6 +85,49 @@ DEFINE_BASIC_PRINT_TYPE_FUNC(s16, "%d", int) | |||
| 80 | DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%ld", long) | 85 | DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%ld", long) |
| 81 | DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%lld", long long) | 86 | DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%lld", long long) |
| 82 | 87 | ||
| 88 | /* data_rloc: data relative location, compatible with u32 */ | ||
| 89 | #define make_data_rloc(len, roffs) \ | ||
| 90 | (((u32)(len) << 16) | ((u32)(roffs) & 0xffff)) | ||
| 91 | #define get_rloc_len(dl) ((u32)(dl) >> 16) | ||
| 92 | #define get_rloc_offs(dl) ((u32)(dl) & 0xffff) | ||
| 93 | |||
| 94 | static inline void *get_rloc_data(u32 *dl) | ||
| 95 | { | ||
| 96 | return (u8 *)dl + get_rloc_offs(*dl); | ||
| 97 | } | ||
| 98 | |||
| 99 | /* For data_loc conversion */ | ||
| 100 | static inline void *get_loc_data(u32 *dl, void *ent) | ||
| 101 | { | ||
| 102 | return (u8 *)ent + get_rloc_offs(*dl); | ||
| 103 | } | ||
| 104 | |||
| 105 | /* | ||
| 106 | * Convert data_rloc to data_loc: | ||
| 107 | * data_rloc stores the offset from data_rloc itself, but data_loc | ||
| 108 | * stores the offset from event entry. | ||
| 109 | */ | ||
| 110 | #define convert_rloc_to_loc(dl, offs) ((u32)(dl) + (offs)) | ||
| 111 | |||
| 112 | /* For defining macros, define string/string_size types */ | ||
| 113 | typedef u32 string; | ||
| 114 | typedef u32 string_size; | ||
| 115 | |||
| 116 | /* Print type function for string type */ | ||
| 117 | static __kprobes int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, | ||
| 118 | const char *name, | ||
| 119 | void *data, void *ent) | ||
| 120 | { | ||
| 121 | int len = *(u32 *)data >> 16; | ||
| 122 | |||
| 123 | if (!len) | ||
| 124 | return trace_seq_printf(s, " %s=(fault)", name); | ||
| 125 | else | ||
| 126 | return trace_seq_printf(s, " %s=\"%s\"", name, | ||
| 127 | (const char *)get_loc_data(data, ent)); | ||
| 128 | } | ||
| 129 | static const char PRINT_TYPE_FMT_NAME(string)[] = "\\\"%s\\\""; | ||
| 130 | |||
| 83 | /* Data fetch function type */ | 131 | /* Data fetch function type */ |
| 84 | typedef void (*fetch_func_t)(struct pt_regs *, void *, void *); | 132 | typedef void (*fetch_func_t)(struct pt_regs *, void *, void *); |
| 85 | 133 | ||
| @@ -94,32 +142,38 @@ static __kprobes void call_fetch(struct fetch_param *fprm, | |||
| 94 | return fprm->fn(regs, fprm->data, dest); | 142 | return fprm->fn(regs, fprm->data, dest); |
| 95 | } | 143 | } |
| 96 | 144 | ||
| 97 | #define FETCH_FUNC_NAME(kind, type) fetch_##kind##_##type | 145 | #define FETCH_FUNC_NAME(method, type) fetch_##method##_##type |
| 98 | /* | 146 | /* |
| 99 | * Define macro for basic types - we don't need to define s* types, because | 147 | * Define macro for basic types - we don't need to define s* types, because |
| 100 | * we have to care only about bitwidth at recording time. | 148 | * we have to care only about bitwidth at recording time. |
| 101 | */ | 149 | */ |
| 102 | #define DEFINE_BASIC_FETCH_FUNCS(kind) \ | 150 | #define DEFINE_BASIC_FETCH_FUNCS(method) \ |
| 103 | DEFINE_FETCH_##kind(u8) \ | 151 | DEFINE_FETCH_##method(u8) \ |
| 104 | DEFINE_FETCH_##kind(u16) \ | 152 | DEFINE_FETCH_##method(u16) \ |
| 105 | DEFINE_FETCH_##kind(u32) \ | 153 | DEFINE_FETCH_##method(u32) \ |
| 106 | DEFINE_FETCH_##kind(u64) | 154 | DEFINE_FETCH_##method(u64) |
| 107 | 155 | ||
| 108 | #define CHECK_BASIC_FETCH_FUNCS(kind, fn) \ | 156 | #define CHECK_FETCH_FUNCS(method, fn) \ |
| 109 | ((FETCH_FUNC_NAME(kind, u8) == fn) || \ | 157 | (((FETCH_FUNC_NAME(method, u8) == fn) || \ |
| 110 | (FETCH_FUNC_NAME(kind, u16) == fn) || \ | 158 | (FETCH_FUNC_NAME(method, u16) == fn) || \ |
| 111 | (FETCH_FUNC_NAME(kind, u32) == fn) || \ | 159 | (FETCH_FUNC_NAME(method, u32) == fn) || \ |
| 112 | (FETCH_FUNC_NAME(kind, u64) == fn)) | 160 | (FETCH_FUNC_NAME(method, u64) == fn) || \ |
| 161 | (FETCH_FUNC_NAME(method, string) == fn) || \ | ||
| 162 | (FETCH_FUNC_NAME(method, string_size) == fn)) \ | ||
| 163 | && (fn != NULL)) | ||
| 113 | 164 | ||
| 114 | /* Data fetch function templates */ | 165 | /* Data fetch function templates */ |
| 115 | #define DEFINE_FETCH_reg(type) \ | 166 | #define DEFINE_FETCH_reg(type) \ |
| 116 | static __kprobes void FETCH_FUNC_NAME(reg, type)(struct pt_regs *regs, \ | 167 | static __kprobes void FETCH_FUNC_NAME(reg, type)(struct pt_regs *regs, \ |
| 117 | void *offset, void *dest) \ | 168 | void *offset, void *dest) \ |
| 118 | { \ | 169 | { \ |
| 119 | *(type *)dest = (type)regs_get_register(regs, \ | 170 | *(type *)dest = (type)regs_get_register(regs, \ |
| 120 | (unsigned int)((unsigned long)offset)); \ | 171 | (unsigned int)((unsigned long)offset)); \ |
| 121 | } | 172 | } |
| 122 | DEFINE_BASIC_FETCH_FUNCS(reg) | 173 | DEFINE_BASIC_FETCH_FUNCS(reg) |
| 174 | /* No string on the register */ | ||
| 175 | #define fetch_reg_string NULL | ||
| 176 | #define fetch_reg_string_size NULL | ||
| 123 | 177 | ||
| 124 | #define DEFINE_FETCH_stack(type) \ | 178 | #define DEFINE_FETCH_stack(type) \ |
| 125 | static __kprobes void FETCH_FUNC_NAME(stack, type)(struct pt_regs *regs,\ | 179 | static __kprobes void FETCH_FUNC_NAME(stack, type)(struct pt_regs *regs,\ |
| @@ -129,6 +183,9 @@ static __kprobes void FETCH_FUNC_NAME(stack, type)(struct pt_regs *regs,\ | |||
| 129 | (unsigned int)((unsigned long)offset)); \ | 183 | (unsigned int)((unsigned long)offset)); \ |
| 130 | } | 184 | } |
| 131 | DEFINE_BASIC_FETCH_FUNCS(stack) | 185 | DEFINE_BASIC_FETCH_FUNCS(stack) |
| 186 | /* No string on the stack entry */ | ||
| 187 | #define fetch_stack_string NULL | ||
| 188 | #define fetch_stack_string_size NULL | ||
| 132 | 189 | ||
| 133 | #define DEFINE_FETCH_retval(type) \ | 190 | #define DEFINE_FETCH_retval(type) \ |
| 134 | static __kprobes void FETCH_FUNC_NAME(retval, type)(struct pt_regs *regs,\ | 191 | static __kprobes void FETCH_FUNC_NAME(retval, type)(struct pt_regs *regs,\ |
| @@ -137,6 +194,9 @@ static __kprobes void FETCH_FUNC_NAME(retval, type)(struct pt_regs *regs,\ | |||
| 137 | *(type *)dest = (type)regs_return_value(regs); \ | 194 | |
