diff options
| -rw-r--r-- | Documentation/trace/kprobetrace.txt | 4 | ||||
| -rw-r--r-- | kernel/trace/trace.h | 16 | ||||
| -rw-r--r-- | kernel/trace/trace_kprobe.c | 535 |
3 files changed, 334 insertions, 221 deletions
diff --git a/Documentation/trace/kprobetrace.txt b/Documentation/trace/kprobetrace.txt index a9100b28eb84..ec94748ae65b 100644 --- a/Documentation/trace/kprobetrace.txt +++ b/Documentation/trace/kprobetrace.txt | |||
| @@ -40,7 +40,9 @@ Synopsis of kprobe_events | |||
| 40 | $stack : Fetch stack address. | 40 | $stack : Fetch stack address. |
| 41 | $retval : Fetch return value.(*) | 41 | $retval : Fetch return value.(*) |
| 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 | ||
| 45 | (u8/u16/u32/u64/s8/s16/s32/s64) are supported. | ||
| 44 | 46 | ||
| 45 | (*) only for return probe. | 47 | (*) only for return probe. |
| 46 | (**) 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.h b/kernel/trace/trace.h index bec2c973ff0c..3ebdb6bd2362 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
| @@ -102,29 +102,17 @@ struct syscall_trace_exit { | |||
| 102 | long ret; | 102 | long ret; |
| 103 | }; | 103 | }; |
| 104 | 104 | ||
| 105 | struct kprobe_trace_entry { | 105 | struct kprobe_trace_entry_head { |
| 106 | struct trace_entry ent; | 106 | struct trace_entry ent; |
| 107 | unsigned long ip; | 107 | unsigned long ip; |
| 108 | int nargs; | ||
| 109 | unsigned long args[]; | ||
| 110 | }; | 108 | }; |
| 111 | 109 | ||
| 112 | #define SIZEOF_KPROBE_TRACE_ENTRY(n) \ | 110 | struct kretprobe_trace_entry_head { |
| 113 | (offsetof(struct kprobe_trace_entry, args) + \ | ||
| 114 | (sizeof(unsigned long) * (n))) | ||
| 115 | |||
| 116 | struct kretprobe_trace_entry { | ||
| 117 | struct trace_entry ent; | 111 | struct trace_entry ent; |
| 118 | unsigned long func; | 112 | unsigned long func; |
| 119 | unsigned long ret_ip; | 113 | unsigned long ret_ip; |
| 120 | int nargs; | ||
| 121 | unsigned long args[]; | ||
| 122 | }; | 114 | }; |
| 123 | 115 | ||
| 124 | #define SIZEOF_KRETPROBE_TRACE_ENTRY(n) \ | ||
| 125 | (offsetof(struct kretprobe_trace_entry, args) + \ | ||
| 126 | (sizeof(unsigned long) * (n))) | ||
| 127 | |||
| 128 | /* | 116 | /* |
| 129 | * trace_flag_type is an enumeration that holds different | 117 | * trace_flag_type is an enumeration that holds different |
| 130 | * states when a trace occurs. These are: | 118 | * states when a trace occurs. These are: |
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 1251e367bae9..a7514326052b 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
| @@ -29,6 +29,8 @@ | |||
| 29 | #include <linux/ctype.h> | 29 | #include <linux/ctype.h> |
| 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> | ||
| 33 | #include <asm/bitsperlong.h> | ||
| 32 | 34 | ||
| 33 | #include "trace.h" | 35 | #include "trace.h" |
| 34 | #include "trace_output.h" | 36 | #include "trace_output.h" |
| @@ -40,7 +42,6 @@ | |||
| 40 | 42 | ||
| 41 | /* Reserved field names */ | 43 | /* Reserved field names */ |
| 42 | #define FIELD_STRING_IP "__probe_ip" | 44 | #define FIELD_STRING_IP "__probe_ip" |
| 43 | #define FIELD_STRING_NARGS "__probe_nargs" | ||
| 44 | #define FIELD_STRING_RETIP "__probe_ret_ip" | 45 | #define FIELD_STRING_RETIP "__probe_ret_ip" |
| 45 | #define FIELD_STRING_FUNC "__probe_func" | 46 | #define FIELD_STRING_FUNC "__probe_func" |
| 46 | 47 | ||
| @@ -52,56 +53,102 @@ const char *reserved_field_names[] = { | |||
| 52 | "common_tgid", | 53 | "common_tgid", |
| 53 | "common_lock_depth", | 54 | "common_lock_depth", |
| 54 | FIELD_STRING_IP, | 55 | FIELD_STRING_IP, |
| 55 | FIELD_STRING_NARGS, | ||
| 56 | FIELD_STRING_RETIP, | 56 | FIELD_STRING_RETIP, |
| 57 | FIELD_STRING_FUNC, | 57 | FIELD_STRING_FUNC, |
| 58 | }; | 58 | }; |
| 59 | 59 | ||
| 60 | struct fetch_func { | 60 | /* Printing function type */ |
| 61 | unsigned long (*func)(struct pt_regs *, void *); | 61 | typedef int (*print_type_func_t)(struct trace_seq *, const char *, void *); |
| 62 | #define PRINT_TYPE_FUNC_NAME(type) print_type_##type | ||
| 63 | #define PRINT_TYPE_FMT_NAME(type) print_type_format_##type | ||
| 64 | |||
| 65 | /* Printing in basic type function template */ | ||
| 66 | #define DEFINE_BASIC_PRINT_TYPE_FUNC(type, fmt, cast) \ | ||
| 67 | static __kprobes int PRINT_TYPE_FUNC_NAME(type)(struct trace_seq *s, \ | ||
| 68 | const char *name, void *data)\ | ||
| 69 | { \ | ||
| 70 | return trace_seq_printf(s, " %s=" fmt, name, (cast)*(type *)data);\ | ||
| 71 | } \ | ||
| 72 | static const char PRINT_TYPE_FMT_NAME(type)[] = fmt; | ||
| 73 | |||
| 74 | DEFINE_BASIC_PRINT_TYPE_FUNC(u8, "%x", unsigned int) | ||
| 75 | DEFINE_BASIC_PRINT_TYPE_FUNC(u16, "%x", unsigned int) | ||
| 76 | DEFINE_BASIC_PRINT_TYPE_FUNC(u32, "%lx", unsigned long) | ||
| 77 | DEFINE_BASIC_PRINT_TYPE_FUNC(u64, "%llx", unsigned long long) | ||
| 78 | DEFINE_BASIC_PRINT_TYPE_FUNC(s8, "%d", int) | ||
| 79 | DEFINE_BASIC_PRINT_TYPE_FUNC(s16, "%d", int) | ||
| 80 | DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%ld", long) | ||
| 81 | DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%lld", long long) | ||
| 82 | |||
| 83 | /* Data fetch function type */ | ||
| 84 | typedef void (*fetch_func_t)(struct pt_regs *, void *, void *); | ||
| 85 | |||
| 86 | struct fetch_param { | ||
| 87 | fetch_func_t fn; | ||
| 62 | void *data; | 88 | void *data; |
| 63 | }; | 89 | }; |
| 64 | 90 | ||
| 65 | static __kprobes unsigned long call_fetch(struct fetch_func *f, | 91 | static __kprobes void call_fetch(struct fetch_param *fprm, |
| 66 | struct pt_regs *regs) | 92 | struct pt_regs *regs, void *dest) |
| 67 | { | 93 | { |
| 68 | return f->func(regs, f->data); | 94 | return fprm->fn(regs, fprm->data, dest); |
| 69 | } | 95 | } |
| 70 | 96 | ||
| 71 | /* fetch handlers */ | 97 | #define FETCH_FUNC_NAME(kind, type) fetch_##kind##_##type |
| 72 | static __kprobes unsigned long fetch_register(struct pt_regs *regs, | 98 | /* |
| 73 | void *offset) | 99 | * Define macro for basic types - we don't need to define s* types, because |
| 74 | { | 100 | * we have to care only about bitwidth at recording time. |
| 75 | return regs_get_register(regs, (unsigned int)((unsigned long)offset)); | 101 | */ |
| 102 | #define DEFINE_BASIC_FETCH_FUNCS(kind) \ | ||
| 103 | DEFINE_FETCH_##kind(u8) \ | ||
| 104 | DEFINE_FETCH_##kind(u16) \ | ||
| 105 | DEFINE_FETCH_##kind(u32) \ | ||
| 106 | DEFINE_FETCH_##kind(u64) | ||
| 107 | |||
| 108 | #define CHECK_BASIC_FETCH_FUNCS(kind, fn) \ | ||
| 109 | ((FETCH_FUNC_NAME(kind, u8) == fn) || \ | ||
| 110 | (FETCH_FUNC_NAME(kind, u16) == fn) || \ | ||
| 111 | (FETCH_FUNC_NAME(kind, u32) == fn) || \ | ||
| 112 | (FETCH_FUNC_NAME(kind, u64) == fn)) | ||
| 113 | |||
| 114 | /* Data fetch function templates */ | ||
| 115 | #define DEFINE_FETCH_reg(type) \ | ||
| 116 | static __kprobes void FETCH_FUNC_NAME(reg, type)(struct pt_regs *regs, \ | ||
| 117 | void *offset, void *dest) \ | ||
| 118 | { \ | ||
| 119 | *(type *)dest = (type)regs_get_register(regs, \ | ||
| 120 | (unsigned int)((unsigned long)offset)); \ | ||
| 76 | } | 121 | } |
| 77 | 122 | DEFINE_BASIC_FETCH_FUNCS(reg) | |
| 78 | static __kprobes unsigned long fetch_stack(struct pt_regs *regs, | 123 | |
| 79 | void *num) | 124 | #define DEFINE_FETCH_stack(type) \ |
| 80 | { | 125 | static __kprobes void FETCH_FUNC_NAME(stack, type)(struct pt_regs *regs,\ |
| 81 | return regs_get_kernel_stack_nth(regs, | 126 | void *offset, void *dest) \ |
| 82 | (unsigned int)((unsigned long)num)); | 127 | { \ |
| 128 | *(type *)dest = (type)regs_get_kernel_stack_nth(regs, \ | ||
| 129 | (unsigned int)((unsigned long)offset)); \ | ||
| 83 | } | 130 | } |
| 131 | DEFINE_BASIC_FETCH_FUNCS(stack) | ||
| 84 | 132 | ||
| 85 | static __kprobes unsigned long fetch_memory(struct pt_regs *regs, void *addr) | 133 | #define DEFINE_FETCH_retval(type) \ |
| 86 | { | 134 | static __kprobes void FETCH_FUNC_NAME(retval, type)(struct pt_regs *regs,\ |
| 87 | unsigned long retval; | 135 | void *dummy, void *dest) \ |
| 88 | 136 | { \ | |
| 89 | if (probe_kernel_address(addr, retval)) | 137 | *(type *)dest = (type)regs_return_value(regs); \ |
| 90 | return 0; | ||
| 91 | return retval; | ||
| 92 | } | 138 | } |
| 93 | 139 | DEFINE_BASIC_FETCH_FUNCS(retval) | |
| 94 | static __kprobes unsigned long fetch_retvalue(struct pt_regs *regs, | 140 | |
| 95 | void *dummy) | 141 | #define DEFINE_FETCH_memory(type) \ |
| 96 | { | 142 | static __kprobes void FETCH_FUNC_NAME(memory, type)(struct pt_regs *regs,\ |
| 97 | return regs_return_value(regs); | 143 | void *addr, void *dest) \ |
| 98 | } | 144 | { \ |
| 99 | 145 | type retval; \ | |
| 100 | static __kprobes unsigned long fetch_stack_address(struct pt_regs *regs, | 146 | if (probe_kernel_address(addr, retval)) \ |
| 101 | void *dummy) | 147 | *(type *)dest = 0; \ |
| 102 | { | 148 | else \ |
| 103 | return kernel_stack_pointer(regs); | 149 | *(type *)dest = retval; \ |
| 104 | } | 150 | } |
| 151 | DEFINE_BASIC_FETCH_FUNCS(memory) | ||
| 105 | 152 | ||
| 106 | /* Memory fetching by symbol */ | 153 | /* Memory fetching by symbol */ |
| 107 | struct symbol_cache { | 154 | struct symbol_cache { |
| @@ -145,51 +192,126 @@ static struct symbol_cache *alloc_symbol_cache(const char *sym, long offset) | |||
| 145 | return sc; | 192 | return sc; |
| 146 | } | 193 | } |
| 147 | 194 | ||
| 148 | static __kprobes unsigned long fetch_symbol(struct pt_regs *regs, void *data) | 195 | #define DEFINE_FETCH_symbol(type) \ |
| 149 | { | 196 | static __kprobes void FETCH_FUNC_NAME(symbol, type)(struct pt_regs *regs,\ |
| 150 | struct symbol_cache *sc = data; | 197 | void *data, void *dest) \ |
| 151 | 198 | { \ | |
| 152 | if (sc->addr) | 199 | struct symbol_cache *sc = data; \ |
| 153 | return fetch_memory(regs, (void *)sc->addr); | 200 | if (sc->addr) \ |
| 154 | else | 201 | fetch_memory_##type(regs, (void *)sc->addr, dest); \ |
| 155 | return 0; | 202 | else \ |
| 203 | *(type *)dest = 0; \ | ||
| 156 | } | 204 | } |
| 205 | DEFINE_BASIC_FETCH_FUNCS(symbol) | ||
| 157 | 206 | ||
| 158 | /* Special indirect memory access interface */ | 207 | /* Dereference memory access function */ |
| 159 | struct indirect_fetch_data { | 208 | struct deref_fetch_param { |
| 160 | struct fetch_func orig; | 209 | struct fetch_param orig; |
| 161 | long offset; | 210 | long offset; |
| 162 | }; | 211 | }; |
| 163 | 212 | ||
| 164 | static __kprobes unsigned long fetch_indirect(struct pt_regs *regs, void *data) | 213 | #define DEFINE_FETCH_deref(type) \ |
| 165 | { | 214 | static __kprobes void FETCH_FUNC_NAME(deref, type)(struct pt_regs *regs,\ |
| 166 | struct indirect_fetch_data *ind = data; | 215 | void *data, void *dest) \ |
| 167 | unsigned long addr; | 216 | { \ |
| 168 | 217 | struct deref_fetch_param *dprm = data; \ | |
| 169 | addr = call_fetch(&ind->orig, regs); | 218 | unsigned long addr; \ |
| 170 | if (addr) { | 219 | call_fetch(&dprm->orig, regs, &addr); \ |
| 171 | addr += ind->offset; | 220 | if (addr) { \ |
| 172 | return fetch_memory(regs, (void *)addr); | 221 | addr += dprm->offset; \ |
| 173 | } else | 222 | fetch_memory_##type(regs, (void *)addr, dest); \ |
| 174 | return 0; | 223 | } else \ |
| 224 | *(type *)dest = 0; \ | ||
| 175 | } | 225 | } |
| 226 | DEFINE_BASIC_FETCH_FUNCS(deref) | ||
| 176 | 227 | ||
| 177 | static __kprobes void free_indirect_fetch_data(struct indirect_fetch_data *data) | 228 | static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data) |
| 178 | { | 229 | { |
| 179 | if (data->orig.func == fetch_indirect) | 230 | if (CHECK_BASIC_FETCH_FUNCS(deref, data->orig.fn)) |
| 180 | free_indirect_fetch_data(data->orig.data); | 231 | free_deref_fetch_param(data->orig.data); |
| 181 | else if (data->orig.func == fetch_symbol) | 232 | else if (CHECK_BASIC_FETCH_FUNCS(symbol, data->orig.fn)) |
| 182 | free_symbol_cache(data->orig.data); | 233 | free_symbol_cache(data->orig.data); |
| 183 | kfree(data); | 234 | kfree(data); |
| 184 | } | 235 | } |
| 185 | 236 | ||
| 237 | /* Default (unsigned long) fetch type */ | ||
| 238 | #define __DEFAULT_FETCH_TYPE(t) u##t | ||
| 239 | #define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t) | ||
| 240 | #define DEFAULT_FETCH_TYPE _DEFAULT_FETCH_TYPE(BITS_PER_LONG) | ||
| 241 | #define DEFAULT_FETCH_TYPE_STR __stringify(DEFAULT_FETCH_TYPE) | ||
| 242 | |||
| 243 | #define ASSIGN_FETCH_FUNC(kind, type) \ | ||
| 244 | .kind = FETCH_FUNC_NAME(kind, type) | ||
| 245 | |||
| 246 | #define ASSIGN_FETCH_TYPE(ptype, ftype, sign) \ | ||
| 247 | {.name = #ptype, \ | ||
| 248 | .size = sizeof(ftype), \ | ||
| 249 | .is_signed = sign, \ | ||
| 250 | .print = PRINT_TYPE_FUNC_NAME(ptype), \ | ||
| 251 | .fmt = PRINT_TYPE_FMT_NAME(ptype), \ | ||
| 252 | ASSIGN_FETCH_FUNC(reg, ftype), \ | ||
| 253 | ASSIGN_FETCH_FUNC(stack, ftype), \ | ||
| 254 | ASSIGN_FETCH_FUNC(retval, ftype), \ | ||
| 255 | ASSIGN_FETCH_FUNC(memory, ftype), \ | ||
| 256 | ASSIGN_FETCH_FUNC(symbol, ftype), \ | ||
| 257 | ASSIGN_FETCH_FUNC(deref, ftype), \ | ||
| 258 | } | ||
| 259 | |||
| 260 | /* Fetch type information table */ | ||
| 261 | static const struct fetch_type { | ||
| 262 | const char *name; /* Name of type */ | ||
| 263 | size_t size; /* Byte size of type */ | ||
| 264 | int is_signed; /* Signed flag */ | ||
| 265 | print_type_func_t print; /* Print functions */ | ||
| 266 | const char *fmt; /* Fromat string */ | ||
| 267 | /* Fetch functions */ | ||
| 268 | fetch_func_t reg; | ||
| 269 | fetch_func_t stack; | ||
| 270 | fetch_func_t retval; | ||
| 271 | fetch_func_t memory; | ||
| 272 | fetch_func_t symbol; | ||
| 273 | fetch_func_t deref; | ||
| 274 | } fetch_type_table[] = { | ||
| 275 | ASSIGN_FETCH_TYPE(u8, u8, 0), | ||
| 276 | ASSIGN_FETCH_TYPE(u16, u16, 0), | ||
| 277 | ASSIGN_FETCH_TYPE(u32, u32, 0), | ||
| 278 | ASSIGN_FETCH_TYPE(u64, u64, 0), | ||
| 279 | ASSIGN_FETCH_TYPE(s8, u8, 1), | ||
| 280 | ASSIGN_FETCH_TYPE(s16, u16, 1), | ||
| 281 | ASSIGN_FETCH_TYPE(s32, u32, 1), | ||
| 282 | ASSIGN_FETCH_TYPE(s64, u64, 1), | ||
| 283 | }; | ||
| 284 | |||
| 285 | static const struct fetch_type *find_fetch_type(const char *type) | ||
| 286 | { | ||
| 287 | int i; | ||
| 288 | |||
| 289 | if (!type) | ||
| 290 | type = DEFAULT_FETCH_TYPE_STR; | ||
| 291 | |||
| 292 | for (i = 0; i < ARRAY_SIZE(fetch_type_table); i++) | ||
| 293 | if (strcmp(type, fetch_type_table[i].name) == 0) | ||
| 294 | return &fetch_type_table[i]; | ||
| 295 | return NULL; | ||
| 296 | } | ||
| 297 | |||
| 298 | /* Special function : only accept unsigned long */ | ||
| 299 | static __kprobes void fetch_stack_address(struct pt_regs *regs, | ||
| 300 | void *dummy, void *dest) | ||
| 301 | { | ||
| 302 | *(unsigned long *)dest = kernel_stack_pointer(regs); | ||
| 303 | } | ||
| 304 | |||
| 186 | /** | 305 | /** |
| 187 | * Kprobe event core functions | 306 | * Kprobe event core functions |
| 188 | */ | 307 | */ |
| 189 | 308 | ||
| 190 | struct probe_arg { | 309 | struct probe_arg { |
| 191 | struct fetch_func fetch; | 310 | struct fetch_param fetch; |
| 192 | const char *name; | 311 | unsigned int offset; /* Offset from argument entry */ |
| 312 | const char *name; /* Name of this argument */ | ||
| 313 | const char *comm; /* Command of this argument */ | ||
| 314 | const struct fetch_type *type; /* Type of this argument */ | ||
| 193 | }; | 315 | }; |
| 194 | 316 | ||
| 195 | /* Flags for trace_probe */ | 317 | /* Flags for trace_probe */ |
| @@ -204,6 +326,7 @@ struct trace_probe { | |||
| 204 | const char *symbol; /* symbol name */ | 326 | const char *symbol; /* symbol name */ |
| 205 | struct ftrace_event_call call; | 327 | struct ftrace_event_call call; |
| 206 | struct trace_event event; | 328 | struct trace_event event; |
| 329 | ssize_t size; /* trace entry size */ | ||
| 207 | unsigned int nr_args; | 330 | unsigned int nr_args; |
| 208 | struct probe_arg args[]; | 331 | struct probe_arg args[]; |
| 209 | }; | 332 | }; |
| @@ -212,6 +335,7 @@ struct trace_probe { | |||
| 212 | (offsetof(struct trace_probe, args) + \ | 335 | (offsetof(struct trace_probe, args) + \ |
| 213 | (sizeof(struct probe_arg) * (n))) | 336 | (sizeof(struct probe_arg) * (n))) |
| 214 | 337 | ||
| 338 | |||
| 215 | static __kprobes int probe_is_return(struct trace_probe *tp) | 339 | static __kprobes int probe_is_return(struct trace_probe *tp) |
| 216 | { | 340 | { |
| 217 | return tp->rp.handler != NULL; | 341 | return tp->rp.handler != NULL; |
| @@ -222,49 +346,6 @@ static __kprobes const char *probe_symbol(struct trace_probe *tp) | |||
| 222 | return tp->symbol ? tp->symbol : "unknown"; | 346 | return tp->symbol ? tp->symbol : "unknown"; |
| 223 | } | 347 | } |
| 224 | 348 | ||
| 225 | static int probe_arg_string(char *buf, size_t n, struct fetch_func *ff) | ||
| 226 | { | ||
| 227 | int ret = -EINVAL; | ||
| 228 | |||
| 229 | if (ff->func == fetch_register) { | ||
| 230 | const char *name; | ||
| 231 | name = regs_query_register_name((unsigned int)((long)ff->data)); | ||
| 232 | ret = snprintf(buf, n, "%%%s", name); | ||
| 233 | } else if (ff->func == fetch_stack) | ||
| 234 | ret = snprintf(buf, n, "$stack%lu", (unsigned long)ff->data); | ||
| 235 | else if (ff->func == fetch_memory) | ||
| 236 | ret = snprintf(buf, n, "@0x%p", ff->data); | ||
| 237 | else if (ff->func == fetch_symbol) { | ||
| 238 | struct symbol_cache *sc = ff->data; | ||
| 239 | if (sc->offset) | ||
| 240 | ret = snprintf(buf, n, "@%s%+ld", sc->symbol, | ||
| 241 | sc->offset); | ||
| 242 | else | ||
| 243 | ret = snprintf(buf, n, "@%s", sc->symbol); | ||
| 244 | } else if (ff->func == fetch_retvalue) | ||
| 245 | ret = snprintf(buf, n, "$retval"); | ||
| 246 | else if (ff->func == fetch_stack_address) | ||
| 247 | ret = snprintf(buf, n, "$stack"); | ||
| 248 | else if (ff->func == fetch_indirect) { | ||
| 249 | struct indirect_fetch_data *id = ff->data; | ||
| 250 | size_t l = 0; | ||
| 251 | ret = snprintf(buf, n, "%+ld(", id->offset); | ||
| 252 | if (ret >= n) | ||
| 253 | goto end; | ||
| 254 | l += ret; | ||
| 255 | ret = probe_arg_string(buf + l, n - l, &id->orig); | ||
| 256 | if (ret < 0) | ||
| 257 | goto end; | ||
| 258 | l += ret; | ||
| 259 | ret = snprintf(buf + l, n - l, ")"); | ||
| 260 | ret += l; | ||
| 261 | } | ||
| 262 | end: | ||
| 263 | if (ret >= n) | ||
| 264 | return -ENOSPC; | ||
| 265 | return ret; | ||
| 266 | } | ||
| 267 | |||
| 268 | static int register_probe_event(struct trace_probe *tp); | 349 | static int register_probe_event(struct trace_probe *tp); |
| 269 | static void unregister_probe_event(struct trace_probe *tp); | 350 | static void unregister_probe_event(struct trace_probe *tp); |
| 270 | 351 | ||
| @@ -347,11 +428,12 @@ error: | |||
| 347 | 428 | ||
| 348 | static void free_probe_arg(struct probe_arg *arg) | 429 | static void free_probe_arg(struct probe_arg *arg) |
| 349 | { | 430 | { |
| 350 | if (arg->fetch.func == fetch_symbol) | 431 | if (CHECK_BASIC_FETCH_FUNCS(deref, arg->fetch.fn)) |
| 432 | free_deref_fetch_param(arg->fetch.data); | ||
| 433 | else if (CHECK_BASIC_FETCH_FUNCS(symbol, arg->fetch.fn)) | ||
| 351 | free_symbol_cache(arg->fetch.data); | 434 | free_symbol_cache(arg->fetch.data); |
| 352 | else if (arg->fetch.func == fetch_indirect) | ||
| 353 | free_indirect_fetch_data(arg->fetch.data); | ||
| 354 | kfree(arg->name); | 435 | kfree(arg->name); |
| 436 | kfree(arg->comm); | ||
| 355 | } | 437 | } |
| 356 | 438 | ||
| 357 | static void free_trace_probe(struct trace_probe *tp) | 439 | static void free_trace_probe(struct trace_probe *tp) |
| @@ -457,28 +539,30 @@ static int split_symbol_offset(char *symbol, unsigned long *offset) | |||
| 457 | #define PARAM_MAX_ARGS 16 | 539 | #define PARAM_MAX_ARGS 16 |
| 458 | #define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long)) | 540 | #define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long)) |
| 459 | 541 | ||
| 460 | static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return) | 542 | static int parse_probe_vars(char *arg, const struct fetch_type *t, |
| 543 | struct fetch_param *f, int is_return) | ||
| 461 | { | 544 | { |
| 462 | int ret = 0; | 545 | int ret = 0; |
| 463 | unsigned long param; | 546 | unsigned long param; |
| 464 | 547 | ||
| 465 | if (strcmp(arg, "retval") == 0) { | 548 | if (strcmp(arg, "retval") == 0) { |
| 466 | if (is_return) { | 549 | if (is_return) |
| 467 | ff->func = fetch_retvalue; | 550 | f->fn = t->retval; |
| 468 | ff->data = NULL; | 551 | else |
| 469 | } else | ||
| 470 | ret = -EINVAL; | 552 | ret = -EINVAL; |
| 471 | } else if (strncmp(arg, "stack", 5) == 0) { | 553 | } else if (strncmp(arg, "stack", 5) == 0) { |
| 472 | if (arg[5] == '\0') { | 554 | if (arg[5] == '\0') { |
| 473 | ff->func = fetch_stack_address; | 555 | if (strcmp(t->name, DEFAULT_FETCH_TYPE_STR) == 0) |
| 474 | ff->data = NULL; | 556 | f->fn = fetch_stack_address; |
| 557 | else | ||
| 558 | ret = -EINVAL; | ||
| 475 | } else if (isdigit(arg[5])) { | 559 | } else if (isdigit(arg[5])) { |
| 476 | ret = strict_strtoul(arg + 5, 10, ¶m); | 560 | ret = strict_strtoul(arg + 5, 10, ¶m); |
| 477 | if (ret || param > PARAM_MAX_STACK) | 561 | if (ret || param > PARAM_MAX_STACK) |
| 478 | ret = -EINVAL; | 562 | ret = -EINVAL; |
| 479 | else { | 563 | else { |
| 480 | ff->func = fetch_stack; | 564 | f->fn = t->stack; |
| 481 | ff->data = (void *)param; | 565 | f->data = (void *)param; |
| 482 | } | 566 | } |
| 483 | } else | 567 | } else |
| 484 | ret = -EINVAL; | 568 | ret = -EINVAL; |
| @@ -488,7 +572,8 @@ static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return) | |||
| 488 | } | 572 | } |
| 489 | 573 | ||
| 490 | /* Recursive argument parser */ | 574 | /* Recursive argument parser */ |
| 491 | static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | 575 | static int __parse_probe_arg(char *arg, const struct fetch_type *t, |
| 576 | struct fetch_param *f, int is_return) | ||
| 492 | { | 577 | { |
| 493 | int ret = 0; | 578 | int ret = 0; |
| 494 | unsigned long param; | 579 | unsigned long param; |
| @@ -497,13 +582,13 @@ static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | |||
| 497 | 582 | ||
| 498 | switch (arg[0]) { | 583 | switch (arg[0]) { |
| 499 | case '$': | 584 | case '$': |
| 500 | ret = parse_probe_vars(arg + 1, ff, is_return); | 585 | ret = parse_probe_vars(arg + 1, t, f, is_return); |
| 501 | break; | 586 | break; |
| 502 | case '%': /* named register */ | 587 | case '%': /* named register */ |
| 503 | ret = regs_query_register_offset(arg + 1); | 588 | ret = regs_query_register_offset(arg + 1); |
| 504 | if (ret >= 0) { | 589 | if (ret >= 0) { |
| 505 | ff->func = fetch_register; | 590 | f->fn = t->reg; |
| 506 | ff->data = (void *)(unsigned long)ret; | 591 | f->data = (void *)(unsigned long)ret; |
| 507 | ret = 0; | 592 | ret = 0; |
| 508 | } | 593 | } |
| 509 | break; | 594 | break; |
| @@ -512,26 +597,22 @@ static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | |||
| 512 | ret = strict_strtoul(arg + 1, 0, ¶m); | 597 | ret = strict_strtoul(arg + 1, 0, ¶m); |
| 513 | if (ret) | 598 | if (ret) |
| 514 | break; | 599 | break; |
| 515 | ff->func = fetch_memory; | 600 | f->fn = t->memory; |
| 516 | ff->data = (void *)param; | 601 | f->data = (void *)param; |
| 517 | } else { | 602 | } else { |
| 518 | ret = split_symbol_offset(arg + 1, &offset); | 603 | ret = split_symbol_offset(arg + 1, &offset); |
| 519 | if (ret) | 604 | if (ret) |
| 520 | break; | 605 | break; |
| 521 | ff->data = alloc_symbol_cache(arg + 1, offset); | 606 | f->data = alloc_symbol_cache(arg + 1, offset); |
| 522 | if (ff->data) | 607 | if (f->data) |
| 523 | ff->func = fetch_symbol; | 608 | f->fn = t->symbol; |
| 524 | else | ||
| 525 | ret = -EINVAL; | ||
| 526 | } | 609 | } |
| 527 | break; | 610 | break; |
| 528 | case '+': /* indirect memory */ | 611 | case '+': /* deref memory */ |
| 529 | case '-': | 612 | case '-': |
| 530 | tmp = strchr(arg, '('); | 613 | tmp = strchr(arg, '('); |
| 531 | if (!tmp) { | 614 | if (!tmp) |
| 532 | ret = -EINVAL; | ||
| 533 | break; | 615 | break; |
| 534 | } | ||
| 535 | *tmp = '\0'; | 616 | *tmp = '\0'; |
| 536 | ret = strict_strtol(arg + 1, 0, &offset); | 617 | ret = strict_strtol(arg + 1, 0, &offset); |
| 537 | if (ret) | 618 | if (ret) |
| @@ -541,38 +622,58 @@ static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | |||
| 541 | arg = tmp + 1; | 622 | arg = tmp + 1; |
| 542 | tmp = strrchr(arg, ')'); | 623 | tmp = strrchr(arg, ')'); |
| 543 | if (tmp) { | 624 | if (tmp) { |
| 544 | struct indirect_fetch_data *id; | 625 | struct deref_fetch_param *dprm; |
| 626 | const struct fetch_type *t2 = find_fetch_type(NULL); | ||
| 545 | *tmp = '\0'; | 627 | *tmp = '\0'; |
| 546 | id = kzalloc(sizeof(struct indirect_fetch_data), | 628 | dprm = kzalloc(sizeof(struct deref_fetch_param), |
| 547 | GFP_KERNEL); | 629 | GFP_KERNEL); |
| 548 | if (!id) | 630 | if (!dprm) |
| 549 | return -ENOMEM; | 631 | return -ENOMEM; |
| 550 | id->offset = offset; | 632 | dprm->offset = offset; |
| 551 | ret = __parse_probe_arg(arg, &id->orig, is_return); | 633 | ret = __parse_probe_arg(arg, t2, &dprm->orig, |
| 634 | is_return); | ||
| 552 | if (ret) | 635 | if (ret) |
| 553 | kfree(id); | 636 | kfree(dprm); |
| 554 | else { | 637 | else { |
| 555 | ff->func = fetch_indirect; | 638 | f->fn = t->deref; |
| 556 | ff->data = (void *)id; | 639 | f->data = (void *)dprm; |
| 557 | } | 640 | } |
| 558 | } else | 641 | } |
| 559 | ret = -EINVAL; | ||
| 560 | break; | 642 | break; |
| 561 | default: | ||
| 562 | /* TODO: support custom handler */ | ||
| 563 | ret = -EINVAL; | ||
| 564 | } | 643 | } |
| 644 | if (!ret && !f->fn) | ||
| 645 | ret = -EINVAL; | ||
| 565 | return ret; | 646 | return ret; |
| 566 | } | 647 | } |
| 567 | 648 | ||
| 568 | /* String length checking wrapper */ | 649 | /* String length checking wrapper */ |
| 569 | static int parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | 650 | static int parse_probe_arg(char *arg, struct trace_probe *tp, |
| 651 | struct probe_arg *parg, int is_return) | ||
| 570 | { | 652 | { |
| 653 | const char *t; | ||
| 654 | |||
| 571 | if (strlen(arg) > MAX_ARGSTR_LEN) { | 655 | if (strlen(arg) > MAX_ARGSTR_LEN) { |
| 572 | pr_info("Argument is too long.: %s\n", arg); | 656 | pr_info("Argument is too long.: %s\n", arg); |
| 573 | return -ENOSPC; | 657 | return -ENOSPC; |
| 574 | } | 658 | } |
| 575 | return __parse_probe_arg(arg, ff, is_return); | 659 | parg->comm = kstrdup(arg, GFP_KERNEL); |
| 660 | if (!parg->comm) { | ||
| 661 | pr_info("Failed to allocate memory for command '%s'.\n", arg); | ||
| 662 | return -ENOMEM; | ||
| 663 | } | ||
| 664 | t = strchr(parg->comm, ':'); | ||
| 665 | if (t) { | ||
| 666 | arg[t - parg->comm] = '\0'; | ||
| 667 | t++; | ||
| 668 | } | ||
| 669 | parg->type = find_fetch_type(t); | ||
| 670 | if (!parg->type) { | ||
| 671 | pr_info("Unsupported type: %s\n", t); | ||
| 672 | return -EINVAL; | ||
| 673 | } | ||
| 674 | parg->offset = tp->size; | ||
| 675 | tp->size += parg->type->size; | ||
| 676 | return __parse_probe_arg(arg, parg->type, &parg->fetch, is_return); | ||
| 576 | } | 677 | } |
| 577 | 678 | ||
| 578 | /* Return 1 if name is reserved or already used by another argument */ | 679 | /* Return 1 if name is reserved or already used by another argument */ |
| @@ -602,15 +703,18 @@ static int create_trace_probe(int argc, char **argv) | |||
| 602 | * @ADDR : fetch memory at ADDR (ADDR should be in kernel) | 703 | * @ADDR : fetch memory at ADDR (ADDR should be in kernel) |
| 603 | * @SYM[+|-offs] : fetch memory at SYM +|- offs (SYM is a data symbol) | 704 | * @SYM[+|-offs] : fetch memory at SYM +|- offs (SYM is a data symbol) |
| 604 | * %REG : fetch register REG | 705 | * %REG : fetch register REG |
| 605 | * Indirect memory fetch: | 706 | * Dereferencing memory fetch: |
| 606 | * +|-offs(ARG) : fetch memory at ARG +|- offs address. | 707 | * +|-offs(ARG) : fetch memory at ARG +|- offs address. |
| 607 | * Alias name of args: | 708 | * Alias name of args: |
| 608 | * NAME=FETCHARG : set NAME as alias of FETCHARG. | 709 | * NAME=FETCHARG : set NAME as alias of FETCHARG. |
| 710 | * Type of args: | ||
| 711 | * FETCHARG:TYPE : use TYPE instead of unsigned long. | ||
| 609 | */ | 712 | */ |
| 610 | struct trace_probe *tp; | 713 | struct trace_probe *tp; |
| 611 | int i, ret = 0; | 714 | int i, ret = 0; |
| 612 | int is_return = 0, is_delete = 0; | 715 | int is_return = 0, is_delete = 0; |
| 613 | char *symbol = NULL, *event = NULL, *arg = NULL, *group = NULL; | 716 | char *symbol = NULL, *event = NULL, *group = NULL; |
| 717 | char *arg, *tmp; | ||
| 614 | unsigned long offset = 0; | 718 | unsigned long offset = 0; |
| 615 | void *addr = NULL; | 719 | void *addr = NULL; |
| 616 | char buf[MAX_EVENT_NAME_LEN]; | 720 | char buf[MAX_EVENT_NAME_LEN]; |
| @@ -723,13 +827,6 @@ static int create_trace_probe(int argc, char **argv) | |||
| 723 | else | 827 | else |
| 724 | arg = argv[i]; | 828 | arg = argv[i]; |
| 725 | 829 | ||
| 726 | if (conflict_field_name(argv[i], tp->args, i)) { | ||
| 727 | pr_info("Argument%d name '%s' conflicts with " | ||
| 728 | "another field.\n", i, argv[i]); | ||
| 729 | ret = -EINVAL; | ||
| 730 | goto error; | ||
| 731 | } | ||
| 732 | |||
| 733 | tp->args[i].name = kstrdup(argv[i], GFP_KERNEL); | 830 | tp->args[i].name = kstrdup(argv[i], GFP_KERNEL); |
| 734 | if (!tp->args[i].name) { | 831 | if (!tp->args[i].name) { |
| 735 | pr_info("Failed to allocate argument%d name '%s'.\n", | 832 | pr_info("Failed to allocate argument%d name '%s'.\n", |
| @@ -737,9 +834,19 @@ static int create_trace_probe(int argc, char **argv) | |||
| 737 | ret = -ENOMEM; | 834 | ret = -ENOMEM; |
| 738 | goto error; | 835 | goto error; |
| 739 | } | 836 | } |
| 837 | tmp = strchr(tp->args[i].name, ':'); | ||
| 838 | if (tmp) | ||
| 839 | *tmp = '_'; /* convert : to _ */ | ||
| 840 | |||
| 841 | if (conflict_field_name(tp->args[i].name, tp->args, i)) { | ||
| 842 | pr_info("Argument%d name '%s' conflicts with " | ||
| 843 | "another field.\n", i, argv[i]); | ||
| 844 | ret = -EINVAL; | ||
| 845 | goto error; | ||
| 846 | } | ||
| 740 | 847 | ||
| 741 | /* Parse fetch argument */ | 848 | /* Parse fetch argument */ |
| 742 | ret = parse_probe_arg(arg, &tp->args[i].fetch, is_return); | 849 | ret = parse_probe_arg(arg, tp, &tp->args[i], is_return); |
| 743 | if (ret) { | 850 | if (ret) { |
| 744 | pr_info("Parse error at argument%d. (%d)\n", i, ret); | 851 | pr_info("Parse error at argument%d. (%d)\n", i, ret); |
| 745 | kfree(tp->args[i].name); | 852 | kfree(tp->args[i].name); |
| @@ -794,8 +901,7 @@ static void probes_seq_stop(struct seq_file *m, void *v) | |||
| 794 | static int probes_seq_show(struct seq_file *m, void *v) | 901 | static int probes_seq_show(struct seq_file *m, void *v) |
| 795 | { | 902 | { |
| 796 | struct trace_probe *tp = v; | 903 | struct trace_probe *tp = v; |
| 797 | int i, ret; | 904 | int i; |
| 798 | char buf[MAX_ARGSTR_LEN + 1]; | ||
| 799 | 905 | ||
| 800 | seq_printf(m, "%c", probe_is_return(tp) ? 'r' : 'p'); | 906 | seq_printf(m, "%c", probe_is_return(tp) ? 'r' : 'p'); |
| 801 | seq_printf(m, ":%s/%s", tp->call.system, tp->call.name); | 907 | seq_printf(m, ":%s/%s", tp->call.system, tp->call.name); |
| @@ -807,15 +913,10 @@ static int probes_seq_show(struct seq_file *m, void *v) | |||
| 807 | else | 913 | else |
| 808 | seq_printf(m, " %s", probe_symbol(tp)); | 914 | seq_printf(m, " %s", probe_symbol(tp)); |
| 809 | 915 | ||
| 810 | for (i = 0; i < tp->nr_args; i++) { | 916 | for (i = 0; i < tp->nr_args; i++) |
| 811 | ret = probe_arg_string(buf, MAX_ARGSTR_LEN, &tp->args[i].fetch); | 917 | seq_printf(m, " %s=%s", tp->args[i].name, tp->args[i].comm); |
| 812 | if (ret < 0) { | ||
| 813 | pr_warning("Argument%d decoding error(%d).\n", i, ret); | ||
| 814 | return ret; | ||
| 815 | } | ||
| 816 | seq_printf(m, " %s=%s", tp->args[i].name, buf); | ||
| 817 | } | ||
| 818 | seq_printf(m, "\n"); | 918 | seq_printf(m, "\n"); |
| 919 | |||
| 819 | return 0; | 920 | return 0; |
| 820 | } | 921 | } |
| 821 | 922 | ||
| @@ -945,9 +1046,10 @@ static const struct file_operations kprobe_profile_ops = { | |||
| 945 | static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | 1046 | static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) |
| 946 | { | 1047 | { |
| 947 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); | 1048 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); |
| 948 | struct kprobe_trace_entry *entry; | 1049 | struct kprobe_trace_entry_head *entry; |
| 949 | struct ring_buffer_event *event; | 1050 | struct ring_buffer_event *event; |
| 950 | struct ring_buffer *buffer; | 1051 | struct ring_buffer *buffer; |
| 1052 | u8 *data; | ||
| 951 | int size, i, pc; | 1053 | int size, i, pc; |
| 952 | unsigned long irq_flags; | 1054 | unsigned long irq_flags; |
| 953 | struct ftrace_event_call *call = &tp->call; | 1055 | struct ftrace_event_call *call = &tp->call; |
| @@ -957,7 +1059,7 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
| 957 | local_save_flags(irq_flags); | 1059 | local_save_flags(irq_flags); |
| 958 | pc = preempt_count(); | 1060 | pc = preempt_count(); |
| 959 | 1061 | ||
| 960 | size = SIZEOF_KPROBE_TRACE_ENTRY(tp->nr_args); | 1062 | size = sizeof(*entry) + tp->size; |
| 961 | 1063 | ||
| 962 | event = trace_current_buffer_lock_reserve(&buffer, call->id, size, | 1064 | event = trace_current_buffer_lock_reserve(&buffer, call->id, size, |
| 963 | irq_flags, pc); | 1065 | irq_flags, pc); |
| @@ -965,10 +1067,10 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
| 965 | return; | 1067 | return; |
| 966 | 1068 | ||
| 967 | entry = ring_buffer_event_data(event); | 1069 | entry = ring_buffer_event_data(event); |
| 968 | entry->nargs = tp->nr_args; | ||
| 969 | entry->ip = (unsigned long)kp->addr; | 1070 | entry->ip = (unsigned long)kp->addr; |
| 1071 | data = (u8 *)&entry[1]; | ||
| 970 | for (i = 0; i < tp->nr_args; i++) | 1072 | for (i = 0; i < tp->nr_args; i++) |
| 971 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); | 1073 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); |
| 972 | 1074 | ||
| 973 | if (!filter_current_check_discard(buffer, call, entry, event)) | 1075 | if (!filter_current_check_discard(buffer, call, entry, event)) |
| 974 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); | 1076 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); |
| @@ -979,9 +1081,10 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | |||
| 979 | struct pt_regs *regs) | 1081 | struct pt_regs *regs) |
| 980 | { | 1082 | { |
| 981 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); | 1083 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); |
| 982 | struct kretprobe_trace_entry *entry; | 1084 | struct kretprobe_trace_entry_head *entry; |
| 983 | struct ring_buffer_event *event; | 1085 | struct ring_buffer_event *event; |
| 984 | struct ring_buffer *buffer; | 1086 | struct ring_buffer *buffer; |
| 1087 | u8 *data; | ||
| 985 | int size, i, pc; | 1088 | int size, i, pc; |
| 986 | unsigned long irq_flags; | 1089 | unsigned long irq_flags; |
| 987 | struct ftrace_event_call *call = &tp->call; | 1090 | struct ftrace_event_call *call = &tp->call; |
| @@ -989,7 +1092,7 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | |||
| 989 | local_save_flags(irq_flags); | 1092 | local_save_flags(irq_flags); |
| 990 | pc = preempt_count(); | 1093 | pc = preempt_count(); |
| 991 | 1094 | ||
| 992 | size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args); | 1095 | size = sizeof(*entry) + tp->size; |
| 993 | 1096 | ||
| 994 | event = trace_current_buffer_lock_reserve(&buffer, call->id, size, | 1097 | event = trace_current_buffer_lock_reserve(&buffer, call->id, size, |
| 995 | irq_flags, pc); | 1098 | irq_flags, pc); |
| @@ -997,11 +1100,11 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | |||
| 997 | return; | 1100 | return; |
| 998 | 1101 | ||
| 999 | entry = ring_buffer_event_data(event); | 1102 | entry = ring_buffer_event_data(event); |
| 1000 | entry->nargs = tp->nr_args; | ||
| 1001 | entry->func = (unsigned long)tp->rp.kp.addr; | 1103 | entry->func = (unsigned long)tp->rp.kp.addr; |
| 1002 | entry->ret_ip = (unsigned long)ri->ret_addr; | 1104 | entry->ret_ip = (unsigned long)ri->ret_addr; |
| 1105 | data = (u8 *)&entry[1]; | ||
| 1003 | for (i = 0; i < tp->nr_args; i++) | 1106 | for (i = 0; i < tp->nr_args; i++) |
| 1004 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); | 1107 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); |
| 1005 | 1108 | ||
| 1006 | if (!filter_current_check_discard(buffer, call, entry, event)) | 1109 | if (!filter_current_check_discard(buffer, call, entry, event)) |
| 1007 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); | 1110 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); |
| @@ -1011,13 +1114,14 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | |||
| 1011 | enum print_line_t | 1114 | enum print_line_t |
| 1012 | print_kprobe_event(struct trace_iterator *iter, int flags) | 1115 | print_kprobe_event(struct trace_iterator *iter, int flags) |
| 1013 | { | 1116 | { |
| 1014 | struct kprobe_trace_entry *field; | 1117 | struct kprobe_trace_entry_head *field; |
| 1015 | struct trace_seq *s = &iter->seq; | 1118 | struct trace_seq *s = &iter->seq; |
| 1016 | struct trace_event *event; | 1119 | struct trace_event *event; |
| 1017 | struct trace_probe *tp; | 1120 | struct trace_probe *tp; |
| 1121 | u8 *data; | ||
| 1018 | int i; | 1122 | int i; |
| 1019 | 1123 | ||
| 1020 | field = (struct kprobe_trace_entry *)iter->ent; | 1124 | field = (struct kprobe_trace_entry_head *)iter->ent; |
| 1021 | event = ftrace_find_event(field->ent.type); | 1125 | event = ftrace_find_event(field->ent.type); |
| 1022 | tp = container_of(event, struct trace_probe, event); | 1126 | tp = container_of(event, struct trace_probe, event); |
| 1023 | 1127 | ||
| @@ -1030,9 +1134,10 @@ print_kprobe_event(struct trace_iterator *iter, int flags) | |||
| 1030 | if (!trace_seq_puts(s, ")")) | 1134 | if (!trace_seq_puts(s, ")")) |
| 1031 | goto partial; | 1135 | goto partial; |
| 1032 | 1136 | ||
| 1033 | for (i = 0; i < field->nargs; i++) | 1137 | data = (u8 *)&field[1]; |
| 1034 | if (!trace_seq_printf(s, " %s=%lx", | 1138 | for (i = 0; i < tp->nr_args; i++) |
| 1035 | tp->args[i].name, field->args[i])) | 1139 | if (!tp->args[i].type->print(s, tp->args[i].name, |
| 1140 | data + tp->args[i].offset)) | ||
| 1036 | goto partial; | 1141 | goto partial; |
| 1037 | 1142 | ||
| 1038 | if (!trace_seq_puts(s, "\n")) | 1143 | if (!trace_seq_puts(s, "\n")) |
| @@ -1046,13 +1151,14 @@ partial: | |||
| 1046 | enum print_line_t | 1151 | enum print_line_t |
| 1047 | print_kretprobe_event(struct trace_iterator *iter, int flags) | 1152 | print_kretprobe_event(struct trace_iterator *iter, int flags) |
| 1048 | { | 1153 | { |
| 1049 | struct kretprobe_trace_entry *field; | 1154 | struct kretprobe_trace_entry_head *field; |
| 1050 | struct trace_seq *s = &iter->seq; | 1155 | struct trace_seq *s = &iter->seq; |
| 1051 | struct trace_event *event; | 1156 | struct trace_event *event; |
| 1052 | struct trace_probe *tp; | 1157 | struct trace_probe *tp; |
| 1158 | u8 *data; | ||
| 1053 | int i; | 1159 | int i; |
| 1054 | 1160 | ||
| 1055 | field = (struct kretprobe_trace_entry *)iter->ent; | 1161 | field = (struct kretprobe_trace_entry_head *)iter->ent; |
| 1056 | event = ftrace_find_event(field->ent.type); | 1162 | event = ftrace_find_event(field->ent.type); |
| 1057 | tp = container_of(event, struct trace_probe, event); | 1163 | tp = container_of(event, struct trace_probe, event); |
| 1058 | 1164 | ||
| @@ -1071,9 +1177,10 @@ print_kretprobe_event(struct trace_iterator *iter, int flags) | |||
| 1071 | if (!trace_seq_puts(s, ")")) | 1177 | if (!trace_seq_puts(s, ")")) |
| 1072 | goto partial; | 1178 | goto partial; |
| 1073 | 1179 | ||
| 1074 | for (i = 0; i < field->nargs; i++) | 1180 | data = (u8 *)&field[1]; |
| 1075 | if (!trace_seq_printf(s, " %s=%lx", | 1181 | for (i = 0; i < tp->nr_args; i++) |
| 1076 | tp->args[i].name, field->args[i])) | 1182 | if (!tp->args[i].type->print(s, tp->args[i].name, |
| 1183 | data + tp->args[i].offset)) | ||
| 1077 | goto partial; | 1184 | goto partial; |
| 1078 | 1185 | ||
| 1079 | if (!trace_seq_puts(s, "\n")) | 1186 | if (!trace_seq_puts(s, "\n")) |
| @@ -1129,29 +1236,43 @@ static int probe_event_raw_init(struct ftrace_event_call *event_call) | |||
| 1129 | static int kprobe_event_define_fields(struct ftrace_event_call *event_call) | 1236 | static int kprobe_event_define_fields(struct ftrace_event_call *event_call) |
| 1130 | { | 1237 | { |
| 1131 | int ret, i; | 1238 | int ret, i; |
| 1132 | struct kprobe_trace_entry field; | 1239 | struct kprobe_trace_entry_head field; |
| 1133 | struct trace_probe *tp = (struct trace_probe *)event_call->data; | 1240 | struct trace_probe *tp = (struct trace_probe *)event_call->data; |
| 1134 | 1241 | ||
| 1135 | DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0); | 1242 | DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0); |
| 1136 | DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1); | ||
| 1137 | /* Set argument names as fields */ | 1243 | /* Set argument names as fields */ |
| 1138 | for (i = 0; i < tp->nr_args; i++) | 1244 | for (i = 0; i < tp->nr_args; i++) { |
| 1139 | DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0); | 1245 | ret = trace_define_field(event_call, tp->args[i].type->name, |
| 1246 | tp->args[i].name, | ||
| 1247 | sizeof(field) + tp->args[i].offset, | ||
| 1248 | tp->args[i].type->size, | ||
| 1249 | tp->args[i].type->is_signed, | ||
| 1250 | FILTER_OTHER); | ||
| 1251 | if (ret) | ||
| 1252 | return ret; | ||
| 1253 | } | ||
| 1140 | return 0; | 1254 | return 0; |
| 1141 | } | 1255 | } |
| 1142 | 1256 | ||
| 1143 | static int kretprobe_event_define_fields(struct ftrace_event_call *event_call) | 1257 | static int kretprobe_event_define_fields(struct ftrace_event_call *event_call) |
| 1144 | { | 1258 | { |
| 1145 | int ret, i; | 1259 | int ret, i; |
| 1146 | struct kretprobe_trace_entry field; | 1260 | struct kretprobe_trace_entry_head field; |
| 1147 | struct trace_probe *tp = (struct trace_probe *)event_call->data; | 1261 | struct trace_probe *tp = (struct trace_probe *)event_call->data; |
| 1148 | 1262 | ||
| 1149 | DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0); | 1263 | DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0); |
| 1150 | DEFINE_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP, 0); | 1264 | DEFINE_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP, 0); |
| 1151 | DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1); | ||
| 1152 | /* Set argument names as fields */ | 1265 | /* Set argument names as fields */ |
| 1153 | for (i = 0; i < tp->nr_args; i++) | 1266 | for (i = 0; i < tp->nr_args; i++) { |
| 1154 | DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0); | 1267 | ret = trace_define_field(event_call, tp->args[i].type->name, |
| 1268 | tp->args[i].name, | ||
| 1269 | sizeof(field) + tp->args[i].offset, | ||
| 1270 | tp->args[i].type->size, | ||
| 1271 | tp->args[i].type->is_signed, | ||
| 1272 | FILTER_OTHER); | ||
| 1273 | if (ret) | ||
| 1274 | return ret; | ||
| 1275 | } | ||
| 1155 | return 0; | 1276 | return 0; |
| 1156 | } | 1277 | } |
| 1157 | 1278 | ||
| @@ -1176,8 +1297,8 @@ static int __set_print_fmt(struct trace_probe *tp, char *buf, int len) | |||
| 1176 | pos += snprintf(buf + pos, LEN_OR_ZERO, "\"%s", fmt); | 1297 | pos += snprintf(buf + pos, LEN_OR_ZERO, "\"%s", fmt); |
| 1177 | 1298 | ||
| 1178 | for (i = 0; i < tp->nr_args; i++) { | 1299 | for (i = 0; i < tp->nr_args; i++) { |
| 1179 | pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=%%lx", | 1300 | pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=%s", |
| 1180 | tp->args[i].name); | 1301 | tp->args[i].name, tp->args[i].type->fmt); |
| 1181 | } | 1302 | } |
| 1182 | 1303 | ||
| 1183 | pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg); | 1304 | pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg); |
| @@ -1219,12 +1340,13 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp, | |||
| 1219 | { | 1340 | { |
| 1220 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); | 1341 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); |
| 1221 | struct ftrace_event_call *call = &tp->call; | 1342 | struct ftrace_event_call *call = &tp->call; |
| 1222 | struct kprobe_trace_entry *entry; | 1343 | struct kprobe_trace_entry_head *entry; |
| 1344 | u8 *data; | ||
| 1223 | int size, __size, i; | 1345 | int size, __size, i; |
| 1224 | unsigned long irq_flags; | 1346 | unsigned long irq_flags; |
| 1225 | int rctx; | 1347 | int rctx; |
| 1226 | 1348 | ||
| 1227 | __size = SIZEOF_KPROBE_TRACE_ENTRY(tp->nr_args); | 1349 | __size = sizeof(*entry) + tp->size; |
| 1228 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); | 1350 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); |
| 1229 | size -= sizeof(u32); | 1351 | size -= sizeof(u32); |
| 1230 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, | 1352 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, |
| @@ -1235,10 +1357,10 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp, | |||
| 1235 | if (!entry) | 1357 | if (!entry) |
| 1236 | return; | 1358 | return; |
| 1237 | 1359 | ||
| 1238 | entry->nargs = tp->nr_args; | ||
| 1239 | entry->ip = (unsigned long)kp->addr; | 1360 | entry->ip = (unsigned long)kp->addr; |
| 1361 | data = (u8 *)&entry[1]; | ||
| 1240 | for (i = 0; i < tp->nr_args; i++) | 1362 | for (i = 0; i < tp->nr_args; i++) |
| 1241 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); | 1363 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); |
| 1242 | 1364 | ||
| 1243 | perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags, regs); | 1365 | perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags, regs); |
| 1244 | } | 1366 | } |
| @@ -1249,12 +1371,13 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, | |||
| 1249 | { | 1371 | { |
| 1250 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); | 1372 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); |
| 1251 | struct ftrace_event_call *call = &tp->call; | 1373 | struct ftrace_event_call *call = &tp->call; |
| 1252 | struct kretprobe_trace_entry *entry; | 1374 | struct kretprobe_trace_entry_head *entry; |
| 1375 | u8 *data; | ||
| 1253 | int size, __size, i; | 1376 | int size, __size, i; |
| 1254 | unsigned long irq_flags; | 1377 | unsigned long irq_flags; |
| 1255 | int rctx; | 1378 | int rctx; |
| 1256 | 1379 | ||
| 1257 | __size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args); | 1380 | __size = sizeof(*entry) + tp->size; |
| 1258 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); | 1381 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); |
| 1259 | size -= sizeof(u32); | 1382 | size -= sizeof(u32); |
| 1260 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, | 1383 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, |
| @@ -1265,11 +1388,11 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, | |||
| 1265 | if (!entry) | 1388 | if (!entry) |
| 1266 | return; | 1389 | return; |
| 1267 | 1390 | ||
| 1268 | entry->nargs = tp->nr_args; | ||
| 1269 | entry->func = (unsigned long)tp->rp.kp.addr; | 1391 | entry->func = (unsigned long)tp->rp.kp.addr; |
| 1270 | entry->ret_ip = (unsigned long)ri->ret_addr; | 1392 | entry->ret_ip = (unsigned long)ri->ret_addr; |
| 1393 | data = (u8 *)&entry[1]; | ||
| 1271 | for (i = 0; i < tp->nr_args; i++) | 1394 | for (i = 0; i < tp->nr_args; i++) |
| 1272 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); | 1395 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); |
| 1273 | 1396 | ||
| 1274 | perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, | 1397 | perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, |
| 1275 | irq_flags, regs); | 1398 | irq_flags, regs); |
