diff options
Diffstat (limited to 'kernel/trace/trace_kprobe.c')
| -rw-r--r-- | kernel/trace/trace_kprobe.c | 648 |
1 files changed, 396 insertions, 252 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 1251e367bae9..f52b5f50299d 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 */ |
| @@ -202,8 +324,9 @@ struct trace_probe { | |||
| 202 | unsigned long nhit; | 324 | unsigned long nhit; |
| 203 | unsigned int flags; /* For TP_FLAG_* */ | 325 | unsigned int flags; /* For TP_FLAG_* */ |
| 204 | const char *symbol; /* symbol name */ | 326 | const char *symbol; /* symbol name */ |
| 327 | struct ftrace_event_class class; | ||
| 205 | struct ftrace_event_call call; | 328 | struct ftrace_event_call call; |
| 206 | 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 | ||
| @@ -323,6 +404,7 @@ static struct trace_probe *alloc_trace_probe(const char *group, | |||
| 323 | goto error; | 404 | goto error; |
| 324 | } | 405 | } |
| 325 | 406 | ||
| 407 | tp->call.class = &tp->class; | ||
| 326 | tp->call.name = kstrdup(event, GFP_KERNEL); | 408 | tp->call.name = kstrdup(event, GFP_KERNEL); |
| 327 | if (!tp->call.name) | 409 | if (!tp->call.name) |
| 328 | goto error; | 410 | goto error; |
| @@ -332,8 +414,8 @@ static struct trace_probe *alloc_trace_probe(const char *group, | |||
| 332 | goto error; | 414 | goto error; |
| 333 | } | 415 | } |
| 334 | 416 | ||
| 335 | tp->call.system = kstrdup(group, GFP_KERNEL); | 417 | tp->class.system = kstrdup(group, GFP_KERNEL); |
| 336 | if (!tp->call.system) | 418 | if (!tp->class.system) |
| 337 | goto error; | 419 | goto error; |
| 338 | 420 | ||
| 339 | INIT_LIST_HEAD(&tp->list); | 421 | INIT_LIST_HEAD(&tp->list); |
| @@ -347,11 +429,12 @@ error: | |||
| 347 | 429 | ||
| 348 | static void free_probe_arg(struct probe_arg *arg) | 430 | static void free_probe_arg(struct probe_arg *arg) |
| 349 | { | 431 | { |
| 350 | if (arg->fetch.func == fetch_symbol) | 432 | if (CHECK_BASIC_FETCH_FUNCS(deref, arg->fetch.fn)) |
| 433 | free_deref_fetch_param(arg->fetch.data); | ||
| 434 | else if (CHECK_BASIC_FETCH_FUNCS(symbol, arg->fetch.fn)) | ||
| 351 | free_symbol_cache(arg->fetch.data); | 435 | 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); | 436 | kfree(arg->name); |
| 437 | kfree(arg->comm); | ||
| 355 | } | 438 | } |
| 356 | 439 | ||
| 357 | static void free_trace_probe(struct trace_probe *tp) | 440 | static void free_trace_probe(struct trace_probe *tp) |
| @@ -361,7 +444,7 @@ static void free_trace_probe(struct trace_probe *tp) | |||
| 361 | for (i = 0; i < tp->nr_args; i++) | 444 | for (i = 0; i < tp->nr_args; i++) |
| 362 | free_probe_arg(&tp->args[i]); | 445 | free_probe_arg(&tp->args[i]); |
| 363 | 446 | ||
| 364 | kfree(tp->call.system); | 447 | kfree(tp->call.class->system); |
| 365 | kfree(tp->call.name); | 448 | kfree(tp->call.name); |
| 366 | kfree(tp->symbol); | 449 | kfree(tp->symbol); |
| 367 | kfree(tp); | 450 | kfree(tp); |
| @@ -374,7 +457,7 @@ static struct trace_probe *find_probe_event(const char *event, | |||
| 374 | 457 | ||
| 375 | list_for_each_entry(tp, &probe_list, list) | 458 | list_for_each_entry(tp, &probe_list, list) |
| 376 | if (strcmp(tp->call.name, event) == 0 && | 459 | if (strcmp(tp->call.name, event) == 0 && |
| 377 | strcmp(tp->call.system, group) == 0) | 460 | strcmp(tp->call.class->system, group) == 0) |
| 378 | return tp; | 461 | return tp; |
| 379 | return NULL; | 462 | return NULL; |
| 380 | } | 463 | } |
| @@ -399,7 +482,7 @@ static int register_trace_probe(struct trace_probe *tp) | |||
| 399 | mutex_lock(&probe_lock); | 482 | mutex_lock(&probe_lock); |
| 400 | 483 | ||
| 401 | /* register as an event */ | 484 | /* register as an event */ |
| 402 | old_tp = find_probe_event(tp->call.name, tp->call.system); | 485 | old_tp = find_probe_event(tp->call.name, tp->call.class->system); |
| 403 | if (old_tp) { | 486 | if (old_tp) { |
| 404 | /* delete old event */ | 487 | /* delete old event */ |
| 405 | unregister_trace_probe(old_tp); | 488 | unregister_trace_probe(old_tp); |
| @@ -457,28 +540,30 @@ static int split_symbol_offset(char *symbol, unsigned long *offset) | |||
| 457 | #define PARAM_MAX_ARGS 16 | 540 | #define PARAM_MAX_ARGS 16 |
| 458 | #define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long)) | 541 | #define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long)) |
| 459 | 542 | ||
| 460 | static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return) | 543 | static int parse_probe_vars(char *arg, const struct fetch_type *t, |
| 544 | struct fetch_param *f, int is_return) | ||
| 461 | { | 545 | { |
| 462 | int ret = 0; | 546 | int ret = 0; |
| 463 | unsigned long param; | 547 | unsigned long param; |
| 464 | 548 | ||
| 465 | if (strcmp(arg, "retval") == 0) { | 549 | if (strcmp(arg, "retval") == 0) { |
| 466 | if (is_return) { | 550 | if (is_return) |
| 467 | ff->func = fetch_retvalue; | 551 | f->fn = t->retval; |
| 468 | ff->data = NULL; | 552 | else |
| 469 | } else | ||
| 470 | ret = -EINVAL; | 553 | ret = -EINVAL; |
| 471 | } else if (strncmp(arg, "stack", 5) == 0) { | 554 | } else if (strncmp(arg, "stack", 5) == 0) { |
| 472 | if (arg[5] == '\0') { | 555 | if (arg[5] == '\0') { |
| 473 | ff->func = fetch_stack_address; | 556 | if (strcmp(t->name, DEFAULT_FETCH_TYPE_STR) == 0) |
| 474 | ff->data = NULL; | 557 | f->fn = fetch_stack_address; |
| 558 | else | ||
| 559 | ret = -EINVAL; | ||
| 475 | } else if (isdigit(arg[5])) { | 560 | } else if (isdigit(arg[5])) { |
| 476 | ret = strict_strtoul(arg + 5, 10, ¶m); | 561 | ret = strict_strtoul(arg + 5, 10, ¶m); |
| 477 | if (ret || param > PARAM_MAX_STACK) | 562 | if (ret || param > PARAM_MAX_STACK) |
| 478 | ret = -EINVAL; | 563 | ret = -EINVAL; |
| 479 | else { | 564 | else { |
| 480 | ff->func = fetch_stack; | 565 | f->fn = t->stack; |
| 481 | ff->data = (void *)param; | 566 | f->data = (void *)param; |
| 482 | } | 567 | } |
| 483 | } else | 568 | } else |
| 484 | ret = -EINVAL; | 569 | ret = -EINVAL; |
| @@ -488,7 +573,8 @@ static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return) | |||
| 488 | } | 573 | } |
| 489 | 574 | ||
| 490 | /* Recursive argument parser */ | 575 | /* Recursive argument parser */ |
| 491 | static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | 576 | static int __parse_probe_arg(char *arg, const struct fetch_type *t, |
| 577 | struct fetch_param *f, int is_return) | ||
| 492 | { | 578 | { |
| 493 | int ret = 0; | 579 | int ret = 0; |
| 494 | unsigned long param; | 580 | unsigned long param; |
| @@ -497,13 +583,13 @@ static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | |||
| 497 | 583 | ||
| 498 | switch (arg[0]) { | 584 | switch (arg[0]) { |
| 499 | case '$': | 585 | case '$': |
| 500 | ret = parse_probe_vars(arg + 1, ff, is_return); | 586 | ret = parse_probe_vars(arg + 1, t, f, is_return); |
| 501 | break; | 587 | break; |
| 502 | case '%': /* named register */ | 588 | case '%': /* named register */ |
| 503 | ret = regs_query_register_offset(arg + 1); | 589 | ret = regs_query_register_offset(arg + 1); |
| 504 | if (ret >= 0) { | 590 | if (ret >= 0) { |
| 505 | ff->func = fetch_register; | 591 | f->fn = t->reg; |
| 506 | ff->data = (void *)(unsigned long)ret; | 592 | f->data = (void *)(unsigned long)ret; |
| 507 | ret = 0; | 593 | ret = 0; |
| 508 | } | 594 | } |
| 509 | break; | 595 | break; |
| @@ -512,26 +598,22 @@ static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | |||
| 512 | ret = strict_strtoul(arg + 1, 0, ¶m); | 598 | ret = strict_strtoul(arg + 1, 0, ¶m); |
| 513 | if (ret) | 599 | if (ret) |
| 514 | break; | 600 | break; |
| 515 | ff->func = fetch_memory; | 601 | f->fn = t->memory; |
| 516 | ff->data = (void *)param; | 602 | f->data = (void *)param; |
| 517 | } else { | 603 | } else { |
| 518 | ret = split_symbol_offset(arg + 1, &offset); | 604 | ret = split_symbol_offset(arg + 1, &offset); |
| 519 | if (ret) | 605 | if (ret) |
| 520 | break; | 606 | break; |
| 521 | ff->data = alloc_symbol_cache(arg + 1, offset); | 607 | f->data = alloc_symbol_cache(arg + 1, offset); |
| 522 | if (ff->data) | 608 | if (f->data) |
| 523 | ff->func = fetch_symbol; | 609 | f->fn = t->symbol; |
| 524 | else | ||
| 525 | ret = -EINVAL; | ||
| 526 | } | 610 | } |
| 527 | break; | 611 | break; |
| 528 | case '+': /* indirect memory */ | 612 | case '+': /* deref memory */ |
| 529 | case '-': | 613 | case '-': |
| 530 | tmp = strchr(arg, '('); | 614 | tmp = strchr(arg, '('); |
| 531 | if (!tmp) { | 615 | if (!tmp) |
| 532 | ret = -EINVAL; | ||
| 533 | break; | 616 | break; |
| 534 | } | ||
| 535 | *tmp = '\0'; | 617 | *tmp = '\0'; |
| 536 | ret = strict_strtol(arg + 1, 0, &offset); | 618 | ret = strict_strtol(arg + 1, 0, &offset); |
| 537 | if (ret) | 619 | if (ret) |
| @@ -541,38 +623,58 @@ static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | |||
| 541 | arg = tmp + 1; | 623 | arg = tmp + 1; |
| 542 | tmp = strrchr(arg, ')'); | 624 | tmp = strrchr(arg, ')'); |
| 543 | if (tmp) { | 625 | if (tmp) { |
| 544 | struct indirect_fetch_data *id; | 626 | struct deref_fetch_param *dprm; |
| 627 | const struct fetch_type *t2 = find_fetch_type(NULL); | ||
| 545 | *tmp = '\0'; | 628 | *tmp = '\0'; |
| 546 | id = kzalloc(sizeof(struct indirect_fetch_data), | 629 | dprm = kzalloc(sizeof(struct deref_fetch_param), |
| 547 | GFP_KERNEL); | 630 | GFP_KERNEL); |
| 548 | if (!id) | 631 | if (!dprm) |
| 549 | return -ENOMEM; | 632 | return -ENOMEM; |
| 550 | id->offset = offset; | 633 | dprm->offset = offset; |
| 551 | ret = __parse_probe_arg(arg, &id->orig, is_return); | 634 | ret = __parse_probe_arg(arg, t2, &dprm->orig, |
| 635 | is_return); | ||
| 552 | if (ret) | 636 | if (ret) |
| 553 | kfree(id); | 637 | kfree(dprm); |
| 554 | else { | 638 | else { |
| 555 | ff->func = fetch_indirect; | 639 | f->fn = t->deref; |
| 556 | ff->data = (void *)id; | 640 | f->data = (void *)dprm; |
| 557 | } | 641 | } |
| 558 | } else | 642 | } |
| 559 | ret = -EINVAL; | ||
| 560 | break; | 643 | break; |
| 561 | default: | ||
| 562 | /* TODO: support custom handler */ | ||
| 563 | ret = -EINVAL; | ||
| 564 | } | 644 | } |
| 645 | if (!ret && !f->fn) | ||
| 646 | ret = -EINVAL; | ||
| 565 | return ret; | 647 | return ret; |
| 566 | } | 648 | } |
| 567 | 649 | ||
| 568 | /* String length checking wrapper */ | 650 | /* String length checking wrapper */ |
| 569 | static int parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | 651 | static int parse_probe_arg(char *arg, struct trace_probe *tp, |
| 652 | struct probe_arg *parg, int is_return) | ||
| 570 | { | 653 | { |
| 654 | const char *t; | ||
| 655 | |||
| 571 | if (strlen(arg) > MAX_ARGSTR_LEN) { | 656 | if (strlen(arg) > MAX_ARGSTR_LEN) { |
| 572 | pr_info("Argument is too long.: %s\n", arg); | 657 | pr_info("Argument is too long.: %s\n", arg); |
| 573 | return -ENOSPC; | 658 | return -ENOSPC; |
| 574 | } | 659 | } |
| 575 | return __parse_probe_arg(arg, ff, is_return); | 660 | parg->comm = kstrdup(arg, GFP_KERNEL); |
| 661 | if (!parg->comm) { | ||
| 662 | pr_info("Failed to allocate memory for command '%s'.\n", arg); | ||
| 663 | return -ENOMEM; | ||
| 664 | } | ||
| 665 | t = strchr(parg->comm, ':'); | ||
| 666 | if (t) { | ||
| 667 | arg[t - parg->comm] = '\0'; | ||
| 668 | t++; | ||
| 669 | } | ||
| 670 | parg->type = find_fetch_type(t); | ||
| 671 | if (!parg->type) { | ||
| 672 | pr_info("Unsupported type: %s\n", t); | ||
| 673 | return -EINVAL; | ||
| 674 | } | ||
| 675 | parg->offset = tp->size; | ||
| 676 | tp->size += parg->type->size; | ||
| 677 | return __parse_probe_arg(arg, parg->type, &parg->fetch, is_return); | ||
| 576 | } | 678 | } |
| 577 | 679 | ||
| 578 | /* Return 1 if name is reserved or already used by another argument */ | 680 | /* Return 1 if name is reserved or already used by another argument */ |
| @@ -602,15 +704,18 @@ static int create_trace_probe(int argc, char **argv) | |||
| 602 | * @ADDR : fetch memory at ADDR (ADDR should be in kernel) | 704 | * @ADDR : fetch memory at ADDR (ADDR should be in kernel) |
| 603 | * @SYM[+|-offs] : fetch memory at SYM +|- offs (SYM is a data symbol) | 705 | * @SYM[+|-offs] : fetch memory at SYM +|- offs (SYM is a data symbol) |
| 604 | * %REG : fetch register REG | 706 | * %REG : fetch register REG |
| 605 | * Indirect memory fetch: | 707 | * Dereferencing memory fetch: |
| 606 | * +|-offs(ARG) : fetch memory at ARG +|- offs address. | 708 | * +|-offs(ARG) : fetch memory at ARG +|- offs address. |
| 607 | * Alias name of args: | 709 | * Alias name of args: |
| 608 | * NAME=FETCHARG : set NAME as alias of FETCHARG. | 710 | * NAME=FETCHARG : set NAME as alias of FETCHARG. |
| 711 | * Type of args: | ||
| 712 | * FETCHARG:TYPE : use TYPE instead of unsigned long. | ||
| 609 | */ | 713 | */ |
| 610 | struct trace_probe *tp; | 714 | struct trace_probe *tp; |
| 611 | int i, ret = 0; | 715 | int i, ret = 0; |
| 612 | int is_return = 0, is_delete = 0; | 716 | int is_return = 0, is_delete = 0; |
| 613 | char *symbol = NULL, *event = NULL, *arg = NULL, *group = NULL; | 717 | char *symbol = NULL, *event = NULL, *group = NULL; |
| 718 | char *arg, *tmp; | ||
| 614 | unsigned long offset = 0; | 719 | unsigned long offset = 0; |
| 615 | void *addr = NULL; | 720 | void *addr = NULL; |
| 616 | char buf[MAX_EVENT_NAME_LEN]; | 721 | char buf[MAX_EVENT_NAME_LEN]; |
| @@ -723,13 +828,6 @@ static int create_trace_probe(int argc, char **argv) | |||
| 723 | else | 828 | else |
| 724 | arg = argv[i]; | 829 | arg = argv[i]; |
| 725 | 830 | ||
| 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); | 831 | tp->args[i].name = kstrdup(argv[i], GFP_KERNEL); |
| 734 | if (!tp->args[i].name) { | 832 | if (!tp->args[i].name) { |
| 735 | pr_info("Failed to allocate argument%d name '%s'.\n", | 833 | pr_info("Failed to allocate argument%d name '%s'.\n", |
| @@ -737,9 +835,19 @@ static int create_trace_probe(int argc, char **argv) | |||
| 737 | ret = -ENOMEM; | 835 | ret = -ENOMEM; |
| 738 | goto error; | 836 | goto error; |
| 739 | } | 837 | } |
| 838 | tmp = strchr(tp->args[i].name, ':'); | ||
| 839 | if (tmp) | ||
| 840 | *tmp = '_'; /* convert : to _ */ | ||
| 841 | |||
| 842 | if (conflict_field_name(tp->args[i].name, tp->args, i)) { | ||
| 843 | pr_info("Argument%d name '%s' conflicts with " | ||
| 844 | "another field.\n", i, argv[i]); | ||
| 845 | ret = -EINVAL; | ||
| 846 | goto error; | ||
| 847 | } | ||
| 740 | 848 | ||
| 741 | /* Parse fetch argument */ | 849 | /* Parse fetch argument */ |
| 742 | ret = parse_probe_arg(arg, &tp->args[i].fetch, is_return); | 850 | ret = parse_probe_arg(arg, tp, &tp->args[i], is_return); |
| 743 | if (ret) { | 851 | if (ret) { |
| 744 | pr_info("Parse error at argument%d. (%d)\n", i, ret); | 852 | pr_info("Parse error at argument%d. (%d)\n", i, ret); |
| 745 | kfree(tp->args[i].name); | 853 | kfree(tp->args[i].name); |
| @@ -794,11 +902,10 @@ static void probes_seq_stop(struct seq_file *m, void *v) | |||
| 794 | static int probes_seq_show(struct seq_file *m, void *v) | 902 | static int probes_seq_show(struct seq_file *m, void *v) |
| 795 | { | 903 | { |
| 796 | struct trace_probe *tp = v; | 904 | struct trace_probe *tp = v; |
| 797 | int i, ret; | 905 | int i; |
| 798 | char buf[MAX_ARGSTR_LEN + 1]; | ||
| 799 | 906 | ||
| 800 | seq_printf(m, "%c", probe_is_return(tp) ? 'r' : 'p'); | 907 | seq_printf(m, "%c", probe_is_return(tp) ? 'r' : 'p'); |
| 801 | seq_printf(m, ":%s/%s", tp->call.system, tp->call.name); | 908 | seq_printf(m, ":%s/%s", tp->call.class->system, tp->call.name); |
| 802 | 909 | ||
| 803 | if (!tp->symbol) | 910 | if (!tp->symbol) |
| 804 | seq_printf(m, " 0x%p", tp->rp.kp.addr); | 911 | seq_printf(m, " 0x%p", tp->rp.kp.addr); |
| @@ -807,15 +914,10 @@ static int probes_seq_show(struct seq_file *m, void *v) | |||
| 807 | else | 914 | else |
| 808 | seq_printf(m, " %s", probe_symbol(tp)); | 915 | seq_printf(m, " %s", probe_symbol(tp)); |
| 809 | 916 | ||
| 810 | for (i = 0; i < tp->nr_args; i++) { | 917 | for (i = 0; i < tp->nr_args; i++) |
| 811 | ret = probe_arg_string(buf, MAX_ARGSTR_LEN, &tp->args[i].fetch); | 918 | 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"); | 919 | seq_printf(m, "\n"); |
| 920 | |||
| 819 | return 0; | 921 | return 0; |
| 820 | } | 922 | } |
| 821 | 923 | ||
| @@ -945,9 +1047,10 @@ static const struct file_operations kprobe_profile_ops = { | |||
| 945 | static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | 1047 | static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) |
| 946 | { | 1048 | { |
| 947 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); | 1049 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); |
| 948 | struct kprobe_trace_entry *entry; | 1050 | struct kprobe_trace_entry_head *entry; |
| 949 | struct ring_buffer_event *event; | 1051 | struct ring_buffer_event *event; |
| 950 | struct ring_buffer *buffer; | 1052 | struct ring_buffer *buffer; |
| 1053 | u8 *data; | ||
| 951 | int size, i, pc; | 1054 | int size, i, pc; |
| 952 | unsigned long irq_flags; | 1055 | unsigned long irq_flags; |
| 953 | struct ftrace_event_call *call = &tp->call; | 1056 | struct ftrace_event_call *call = &tp->call; |
| @@ -957,18 +1060,18 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
| 957 | local_save_flags(irq_flags); | 1060 | local_save_flags(irq_flags); |
| 958 | pc = preempt_count(); | 1061 | pc = preempt_count(); |
| 959 | 1062 | ||
| 960 | size = SIZEOF_KPROBE_TRACE_ENTRY(tp->nr_args); | 1063 | size = sizeof(*entry) + tp->size; |
| 961 | 1064 | ||
| 962 | event = trace_current_buffer_lock_reserve(&buffer, call->id, size, | 1065 | event = trace_current_buffer_lock_reserve(&buffer, call->event.type, |
| 963 | irq_flags, pc); | 1066 | size, irq_flags, pc); |
| 964 | if (!event) | 1067 | if (!event) |
| 965 | return; | 1068 | return; |
| 966 | 1069 | ||
| 967 | entry = ring_buffer_event_data(event); | 1070 | entry = ring_buffer_event_data(event); |
| 968 | entry->nargs = tp->nr_args; | ||
| 969 | entry->ip = (unsigned long)kp->addr; | 1071 | entry->ip = (unsigned long)kp->addr; |
| 1072 | data = (u8 *)&entry[1]; | ||
| 970 | for (i = 0; i < tp->nr_args; i++) | 1073 | for (i = 0; i < tp->nr_args; i++) |
| 971 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); | 1074 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); |
| 972 | 1075 | ||
| 973 | if (!filter_current_check_discard(buffer, call, entry, event)) | 1076 | if (!filter_current_check_discard(buffer, call, entry, event)) |
| 974 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); | 1077 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); |
| @@ -979,9 +1082,10 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | |||
| 979 | struct pt_regs *regs) | 1082 | struct pt_regs *regs) |
| 980 | { | 1083 | { |
| 981 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); | 1084 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); |
| 982 | struct kretprobe_trace_entry *entry; | 1085 | struct kretprobe_trace_entry_head *entry; |
| 983 | struct ring_buffer_event *event; | 1086 | struct ring_buffer_event *event; |
| 984 | struct ring_buffer *buffer; | 1087 | struct ring_buffer *buffer; |
| 1088 | u8 *data; | ||
| 985 | int size, i, pc; | 1089 | int size, i, pc; |
| 986 | unsigned long irq_flags; | 1090 | unsigned long irq_flags; |
| 987 | struct ftrace_event_call *call = &tp->call; | 1091 | struct ftrace_event_call *call = &tp->call; |
| @@ -989,19 +1093,19 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | |||
| 989 | local_save_flags(irq_flags); | 1093 | local_save_flags(irq_flags); |
| 990 | pc = preempt_count(); | 1094 | pc = preempt_count(); |
| 991 | 1095 | ||
| 992 | size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args); | 1096 | size = sizeof(*entry) + tp->size; |
| 993 | 1097 | ||
| 994 | event = trace_current_buffer_lock_reserve(&buffer, call->id, size, | 1098 | event = trace_current_buffer_lock_reserve(&buffer, call->event.type, |
| 995 | irq_flags, pc); | 1099 | size, irq_flags, pc); |
| 996 | if (!event) | 1100 | if (!event) |
| 997 | return; | 1101 | return; |
| 998 | 1102 | ||
| 999 | entry = ring_buffer_event_data(event); | 1103 | entry = ring_buffer_event_data(event); |
| 1000 | entry->nargs = tp->nr_args; | ||
| 1001 | entry->func = (unsigned long)tp->rp.kp.addr; | 1104 | entry->func = (unsigned long)tp->rp.kp.addr; |
| 1002 | entry->ret_ip = (unsigned long)ri->ret_addr; | 1105 | entry->ret_ip = (unsigned long)ri->ret_addr; |
| 1106 | data = (u8 *)&entry[1]; | ||
| 1003 | for (i = 0; i < tp->nr_args; i++) | 1107 | for (i = 0; i < tp->nr_args; i++) |
| 1004 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); | 1108 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); |
| 1005 | 1109 | ||
| 1006 | if (!filter_current_check_discard(buffer, call, entry, event)) | 1110 | if (!filter_current_check_discard(buffer, call, entry, event)) |
| 1007 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); | 1111 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); |
| @@ -1009,17 +1113,17 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | |||
| 1009 | 1113 | ||
| 1010 | /* Event entry printers */ | 1114 | /* Event entry printers */ |
| 1011 | enum print_line_t | 1115 | enum print_line_t |
| 1012 | print_kprobe_event(struct trace_iterator *iter, int flags) | 1116 | print_kprobe_event(struct trace_iterator *iter, int flags, |
| 1117 | struct trace_event *event) | ||
| 1013 | { | 1118 | { |
| 1014 | struct kprobe_trace_entry *field; | 1119 | struct kprobe_trace_entry_head *field; |
| 1015 | struct trace_seq *s = &iter->seq; | 1120 | struct trace_seq *s = &iter->seq; |
| 1016 | struct trace_event *event; | ||
| 1017 | struct trace_probe *tp; | 1121 | struct trace_probe *tp; |
| 1122 | u8 *data; | ||
| 1018 | int i; | 1123 | int i; |
| 1019 | 1124 | ||
| 1020 | field = (struct kprobe_trace_entry *)iter->ent; | 1125 | field = (struct kprobe_trace_entry_head *)iter->ent; |
| 1021 | event = ftrace_find_event(field->ent.type); | 1126 | tp = container_of(event, struct trace_probe, call.event); |
| 1022 | tp = container_of(event, struct trace_probe, event); | ||
| 1023 | 1127 | ||
| 1024 | if (!trace_seq_printf(s, "%s: (", tp->call.name)) | 1128 | if (!trace_seq_printf(s, "%s: (", tp->call.name)) |
| 1025 | goto partial; | 1129 | goto partial; |
| @@ -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")) |
| @@ -1044,17 +1149,17 @@ partial: | |||
| 1044 | } | 1149 | } |
| 1045 | 1150 | ||
| 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, |
| 1153 | struct trace_event *event) | ||
| 1048 | { | 1154 | { |
| 1049 | struct kretprobe_trace_entry *field; | 1155 | struct kretprobe_trace_entry_head *field; |
| 1050 | struct trace_seq *s = &iter->seq; | 1156 | struct trace_seq *s = &iter->seq; |
| 1051 | 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 | tp = container_of(event, struct trace_probe, call.event); |
| 1057 | tp = container_of(event, struct trace_probe, event); | ||
| 1058 | 1163 | ||
| 1059 | if (!trace_seq_printf(s, "%s: (", tp->call.name)) | 1164 | if (!trace_seq_printf(s, "%s: (", tp->call.name)) |
| 1060 | goto partial; | 1165 | goto partial; |
| @@ -1071,9 +1176,10 @@ print_kretprobe_event(struct trace_iterator *iter, int flags) | |||
| 1071 | if (!trace_seq_puts(s, ")")) | 1176 | if (!trace_seq_puts(s, ")")) |
| 1072 | goto partial; | 1177 | goto partial; |
| 1073 | 1178 | ||
| 1074 | for (i = 0; i < field->nargs; i++) | 1179 | data = (u8 *)&field[1]; |
| 1075 | if (!trace_seq_printf(s, " %s=%lx", | 1180 | for (i = 0; i < tp->nr_args; i++) |
| 1076 | tp->args[i].name, field->args[i])) | 1181 | if (!tp->args[i].type->print(s, tp->args[i].name, |
| 1182 | data + tp->args[i].offset)) | ||
| 1077 | goto partial; | 1183 | goto partial; |
| 1078 | 1184 | ||
| 1079 | if (!trace_seq_puts(s, "\n")) | 1185 | if (!trace_seq_puts(s, "\n")) |
| @@ -1110,8 +1216,6 @@ static void probe_event_disable(struct ftrace_event_call *call) | |||
| 1110 | 1216 | ||
| 1111 | static int probe_event_raw_init(struct ftrace_event_call *event_call) | 1217 | static int probe_event_raw_init(struct ftrace_event_call *event_call) |
| 1112 | { | 1218 | { |
| 1113 | INIT_LIST_HEAD(&event_call->fields); | ||
| 1114 | |||
| 1115 | return 0; | 1219 | return 0; |
| 1116 | } | 1220 | } |
| 1117 | 1221 | ||
| @@ -1129,29 +1233,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) | 1233 | static int kprobe_event_define_fields(struct ftrace_event_call *event_call) |
| 1130 | { | 1234 | { |
| 1131 | int ret, i; | 1235 | int ret, i; |
| 1132 | struct kprobe_trace_entry field; | 1236 | struct kprobe_trace_entry_head field; |
| 1133 | struct trace_probe *tp = (struct trace_probe *)event_call->data; | 1237 | struct trace_probe *tp = (struct trace_probe *)event_call->data; |
| 1134 | 1238 | ||
| 1135 | DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0); | 1239 | DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0); |
| 1136 | DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1); | ||
| 1137 | /* Set argument names as fields */ | 1240 | /* Set argument names as fields */ |
| 1138 | for (i = 0; i < tp->nr_args; i++) | 1241 | for (i = 0; i < tp->nr_args; i++) { |
| 1139 | DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0); | 1242 | ret = trace_define_field(event_call, tp->args[i].type->name, |
| 1243 | tp->args[i].name, | ||
| 1244 | sizeof(field) + tp->args[i].offset, | ||
| 1245 | tp->args[i].type->size, | ||
| 1246 | tp->args[i].type->is_signed, | ||
| 1247 | FILTER_OTHER); | ||
| 1248 | if (ret) | ||
| 1249 | return ret; | ||
| 1250 | } | ||
| 1140 | return 0; | 1251 | return 0; |
| 1141 | } | 1252 | } |
| 1142 | 1253 | ||
| 1143 | static int kretprobe_event_define_fields(struct ftrace_event_call *event_call) | 1254 | static int kretprobe_event_define_fields(struct ftrace_event_call *event_call) |
| 1144 | { | 1255 | { |
| 1145 | int ret, i; | 1256 | int ret, i; |
| 1146 | struct kretprobe_trace_entry field; | 1257 | struct kretprobe_trace_entry_head field; |
| 1147 | struct trace_probe *tp = (struct trace_probe *)event_call->data; | 1258 | struct trace_probe *tp = (struct trace_probe *)event_call->data; |
| 1148 | 1259 | ||
| 1149 | DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0); | 1260 | DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0); |
| 1150 | DEFINE_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP, 0); | 1261 | 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 */ | 1262 | /* Set argument names as fields */ |
| 1153 | for (i = 0; i < tp->nr_args; i++) | 1263 | for (i = 0; i < tp->nr_args; i++) { |
| 1154 | DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0); | 1264 | ret = trace_define_field(event_call, tp->args[i].type->name, |
| 1265 | tp->args[i].name, | ||
| 1266 | sizeof(field) + tp->args[i].offset, | ||
| 1267 | tp->args[i].type->size, | ||
| 1268 | tp->args[i].type->is_signed, | ||
| 1269 | FILTER_OTHER); | ||
| 1270 | if (ret) | ||
| 1271 | return ret; | ||
| 1272 | } | ||
| 1155 | return 0; | 1273 | return 0; |
| 1156 | } | 1274 | } |
| 1157 | 1275 | ||
| @@ -1176,8 +1294,8 @@ static int __set_print_fmt(struct trace_probe *tp, char *buf, int len) | |||
| 1176 | pos += snprintf(buf + pos, LEN_OR_ZERO, "\"%s", fmt); | 1294 | pos += snprintf(buf + pos, LEN_OR_ZERO, "\"%s", fmt); |
| 1177 | 1295 | ||
| 1178 | for (i = 0; i < tp->nr_args; i++) { | 1296 | for (i = 0; i < tp->nr_args; i++) { |
| 1179 | pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=%%lx", | 1297 | pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=%s", |
| 1180 | tp->args[i].name); | 1298 | tp->args[i].name, tp->args[i].type->fmt); |
| 1181 | } | 1299 | } |
| 1182 | 1300 | ||
| 1183 | pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg); | 1301 | pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg); |
| @@ -1219,28 +1337,30 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp, | |||
| 1219 | { | 1337 | { |
| 1220 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); | 1338 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); |
| 1221 | struct ftrace_event_call *call = &tp->call; | 1339 | struct ftrace_event_call *call = &tp->call; |
| 1222 | struct kprobe_trace_entry *entry; | 1340 | struct kprobe_trace_entry_head *entry; |
| 1341 | struct hlist_head *head; | ||
| 1342 | u8 *data; | ||
| 1223 | int size, __size, i; | 1343 | int size, __size, i; |
| 1224 | unsigned long irq_flags; | ||
| 1225 | int rctx; | 1344 | int rctx; |
| 1226 | 1345 | ||
| 1227 | __size = SIZEOF_KPROBE_TRACE_ENTRY(tp->nr_args); | 1346 | __size = sizeof(*entry) + tp->size; |
| 1228 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); | 1347 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); |
| 1229 | size -= sizeof(u32); | 1348 | size -= sizeof(u32); |
| 1230 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, | 1349 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, |
| 1231 | "profile buffer not large enough")) | 1350 | "profile buffer not large enough")) |
| 1232 | return; | 1351 | return; |
| 1233 | 1352 | ||
| 1234 | entry = perf_trace_buf_prepare(size, call->id, &rctx, &irq_flags); | 1353 | entry = perf_trace_buf_prepare(size, call->event.type, regs, &rctx); |
| 1235 | if (!entry) | 1354 | if (!entry) |
| 1236 | return; | 1355 | return; |
| 1237 | 1356 | ||
| 1238 | entry->nargs = tp->nr_args; | ||
| 1239 | entry->ip = (unsigned long)kp->addr; | 1357 | entry->ip = (unsigned long)kp->addr; |
| 1358 | data = (u8 *)&entry[1]; | ||
| 1240 | for (i = 0; i < tp->nr_args; i++) | 1359 | for (i = 0; i < tp->nr_args; i++) |
| 1241 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); | 1360 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); |
| 1242 | 1361 | ||
| 1243 | perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags, regs); | 1362 | head = this_cpu_ptr(call->perf_events); |
| 1363 | perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head); | ||
| 1244 | } | 1364 | } |
| 1245 | 1365 | ||
| 1246 | /* Kretprobe profile handler */ | 1366 | /* Kretprobe profile handler */ |
| @@ -1249,30 +1369,31 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, | |||
| 1249 | { | 1369 | { |
| 1250 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); | 1370 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); |
| 1251 | struct ftrace_event_call *call = &tp->call; | 1371 | struct ftrace_event_call *call = &tp->call; |
| 1252 | struct kretprobe_trace_entry *entry; | 1372 | struct kretprobe_trace_entry_head *entry; |
| 1373 | struct hlist_head *head; | ||
| 1374 | u8 *data; | ||
| 1253 | int size, __size, i; | 1375 | int size, __size, i; |
| 1254 | unsigned long irq_flags; | ||
| 1255 | int rctx; | 1376 | int rctx; |
| 1256 | 1377 | ||
| 1257 | __size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args); | 1378 | __size = sizeof(*entry) + tp->size; |
| 1258 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); | 1379 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); |
| 1259 | size -= sizeof(u32); | 1380 | size -= sizeof(u32); |
| 1260 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, | 1381 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, |
| 1261 | "profile buffer not large enough")) | 1382 | "profile buffer not large enough")) |
| 1262 | return; | 1383 | return; |
| 1263 | 1384 | ||
| 1264 | entry = perf_trace_buf_prepare(size, call->id, &rctx, &irq_flags); | 1385 | entry = perf_trace_buf_prepare(size, call->event.type, regs, &rctx); |
| 1265 | if (!entry) | 1386 | if (!entry) |
| 1266 | return; | 1387 | return; |
| 1267 | 1388 | ||
| 1268 | entry->nargs = tp->nr_args; | ||
| 1269 | entry->func = (unsigned long)tp->rp.kp.addr; | 1389 | entry->func = (unsigned long)tp->rp.kp.addr; |
| 1270 | entry->ret_ip = (unsigned long)ri->ret_addr; | 1390 | entry->ret_ip = (unsigned long)ri->ret_addr; |
| 1391 | data = (u8 *)&entry[1]; | ||
| 1271 | for (i = 0; i < tp->nr_args; i++) | 1392 | for (i = 0; i < tp->nr_args; i++) |
| 1272 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); | 1393 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); |
| 1273 | 1394 | ||
| 1274 | perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, | 1395 | head = this_cpu_ptr(call->perf_events); |
| 1275 | irq_flags, regs); | 1396 | perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, regs, head); |
| 1276 | } | 1397 | } |
| 1277 | 1398 | ||
| 1278 | static int probe_perf_enable(struct ftrace_event_call *call) | 1399 | static int probe_perf_enable(struct ftrace_event_call *call) |
| @@ -1302,6 +1423,26 @@ static void probe_perf_disable(struct ftrace_event_call *call) | |||
| 1302 | } | 1423 | } |
| 1303 | #endif /* CONFIG_PERF_EVENTS */ | 1424 | #endif /* CONFIG_PERF_EVENTS */ |
| 1304 | 1425 | ||
| 1426 | static __kprobes | ||
| 1427 | int kprobe_register(struct ftrace_event_call *event, enum trace_reg type) | ||
| 1428 | { | ||
| 1429 | switch (type) { | ||
| 1430 | case TRACE_REG_REGISTER: | ||
| 1431 | return probe_event_enable(event); | ||
| 1432 | case TRACE_REG_UNREGISTER: | ||
| 1433 | probe_event_disable(event); | ||
| 1434 | return 0; | ||
| 1435 | |||
| 1436 | #ifdef CONFIG_PERF_EVENTS | ||
| 1437 | case TRACE_REG_PERF_REGISTER: | ||
| 1438 | return probe_perf_enable(event); | ||
| 1439 | case TRACE_REG_PERF_UNREGISTER: | ||
| 1440 | probe_perf_disable(event); | ||
| 1441 | return 0; | ||
| 1442 | #endif | ||
| 1443 | } | ||
| 1444 | return 0; | ||
| 1445 | } | ||
| 1305 | 1446 | ||
| 1306 | static __kprobes | 1447 | static __kprobes |
| 1307 | int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs) | 1448 | int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs) |
| @@ -1331,6 +1472,14 @@ int kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs) | |||
| 1331 | return 0; /* We don't tweek kernel, so just return 0 */ | 1472 | return 0; /* We don't tweek kernel, so just return 0 */ |
| 1332 | } | 1473 | } |
| 1333 | 1474 | ||
| 1475 | static struct trace_event_functions kretprobe_funcs = { | ||
| 1476 | .trace = print_kretprobe_event | ||
| 1477 | }; | ||
| 1478 | |||
| 1479 | static struct trace_event_functions kprobe_funcs = { | ||
| 1480 | .trace = print_kprobe_event | ||
| 1481 | }; | ||
| 1482 | |||
| 1334 | static int register_probe_event(struct trace_probe *tp) | 1483 | static int register_probe_event(struct trace_probe *tp) |
| 1335 | { | 1484 | { |
| 1336 | struct ftrace_event_call *call = &tp->call; | 1485 | struct ftrace_event_call *call = &tp->call; |
| @@ -1338,36 +1487,31 @@ static int register_probe_event(struct trace_probe *tp) | |||
| 1338 | 1487 | ||
| 1339 | /* Initialize ftrace_event_call */ | 1488 | /* Initialize ftrace_event_call */ |
| 1340 | if (probe_is_return(tp)) { | 1489 | if (probe_is_return(tp)) { |
| 1341 | tp->event.trace = print_kretprobe_event; | 1490 | INIT_LIST_HEAD(&call->class->fields); |
| 1342 | call->raw_init = probe_event_raw_init; | 1491 | call->event.funcs = &kretprobe_funcs; |
| 1343 | call->define_fields = kretprobe_event_define_fields; | 1492 | call->class->raw_init = probe_event_raw_init; |
| 1493 | call->class->define_fields = kretprobe_event_define_fields; | ||
| 1344 | } else { | 1494 | } else { |
| 1345 | tp->event.trace = print_kprobe_event; | 1495 | INIT_LIST_HEAD(&call->class->fields); |
| 1346 | call->raw_init = probe_event_raw_init; | 1496 | call->event.funcs = &kprobe_funcs; |
| 1347 | call->define_fields = kprobe_event_define_fields; | 1497 | call->class->raw_init = probe_event_raw_init; |
| 1498 | call->class->define_fields = kprobe_event_define_fields; | ||
| 1348 | } | 1499 | } |
| 1349 | if (set_print_fmt(tp) < 0) | 1500 | if (set_print_fmt(tp) < 0) |
| 1350 | return -ENOMEM; | 1501 | return -ENOMEM; |
| 1351 | call->event = &tp->event; | 1502 | ret = register_ftrace_event(&call->event); |
| 1352 | call->id = register_ftrace_event(&tp->event); | 1503 | if (!ret) { |
| 1353 | if (!call->id) { | ||
| 1354 | kfree(call->print_fmt); | 1504 | kfree(call->print_fmt); |
| 1355 | return -ENODEV; | 1505 | return -ENODEV; |
| 1356 | } | 1506 | } |
| 1357 | call->enabled = 0; | 1507 | call->flags = 0; |
| 1358 | call->regfunc = probe_event_enable; | 1508 | call->class->reg = kprobe_register; |
| 1359 | call->unregfunc = probe_event_disable; | ||
| 1360 | |||
| 1361 | #ifdef CONFIG_PERF_EVENTS | ||
| 1362 | call->perf_event_enable = probe_perf_enable; | ||
| 1363 | call->perf_event_disable = probe_perf_disable; | ||
| 1364 | #endif | ||
| 1365 | call->data = tp; | 1509 | call->data = tp; |
| 1366 | ret = trace_add_event_call(call); | 1510 | ret = trace_add_event_call(call); |
| 1367 | if (ret) { | 1511 | if (ret) { |
| 1368 | pr_info("Failed to register kprobe event: %s\n", call->name); | 1512 | pr_info("Failed to register kprobe event: %s\n", call->name); |
| 1369 | kfree(call->print_fmt); | 1513 | kfree(call->print_fmt); |
| 1370 | unregister_ftrace_event(&tp->event); | 1514 | unregister_ftrace_event(&call->event); |
| 1371 | } | 1515 | } |
| 1372 | return ret; | 1516 | return ret; |
| 1373 | } | 1517 | } |
