diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2010-07-05 14:54:45 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-07-05 14:54:45 -0400 |
commit | e09c8614b32915c16f68e039ac7040e602d73e35 (patch) | |
tree | 725c768b1d2fbd569e447e7d4a2044dc0aa7a1d5 /kernel/trace/trace_kprobe.c | |
parent | 167a58f10d9cd1bdf6a911aa1eecbdff596de156 (diff) |
tracing/kprobes: Support "string" type
Support string type tracing and printing in kprobe-tracer.
This allows user to trace string data in kernel including __user data. Note
that sometimes __user data may not be accessed if it is paged-out (sorry, but
kprobes operation should be done in atomic, we can not wait for page-in).
Commiter note: Fixed up conflicts with b7e2ece.
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <20100519195724.2885.18788.stgit@localhost6.localdomain6>
Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'kernel/trace/trace_kprobe.c')
-rw-r--r-- | kernel/trace/trace_kprobe.c | 370 |
1 files changed, 292 insertions, 78 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 3b831d8e201e..1b79d1c15726 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <linux/ptrace.h> | 30 | #include <linux/ptrace.h> |
31 | #include <linux/perf_event.h> | 31 | #include <linux/perf_event.h> |
32 | #include <linux/stringify.h> | 32 | #include <linux/stringify.h> |
33 | #include <linux/limits.h> | ||
34 | #include <linux/uaccess.h> | ||
33 | #include <asm/bitsperlong.h> | 35 | #include <asm/bitsperlong.h> |
34 | 36 | ||
35 | #include "trace.h" | 37 | #include "trace.h" |
@@ -38,6 +40,7 @@ | |||
38 | #define MAX_TRACE_ARGS 128 | 40 | #define MAX_TRACE_ARGS 128 |
39 | #define MAX_ARGSTR_LEN 63 | 41 | #define MAX_ARGSTR_LEN 63 |
40 | #define MAX_EVENT_NAME_LEN 64 | 42 | #define MAX_EVENT_NAME_LEN 64 |
43 | #define MAX_STRING_SIZE PATH_MAX | ||
41 | #define KPROBE_EVENT_SYSTEM "kprobes" | 44 | #define KPROBE_EVENT_SYSTEM "kprobes" |
42 | 45 | ||
43 | /* Reserved field names */ | 46 | /* Reserved field names */ |
@@ -58,14 +61,16 @@ const char *reserved_field_names[] = { | |||
58 | }; | 61 | }; |
59 | 62 | ||
60 | /* Printing function type */ | 63 | /* Printing function type */ |
61 | typedef int (*print_type_func_t)(struct trace_seq *, const char *, void *); | 64 | typedef int (*print_type_func_t)(struct trace_seq *, const char *, void *, |
65 | void *); | ||
62 | #define PRINT_TYPE_FUNC_NAME(type) print_type_##type | 66 | #define PRINT_TYPE_FUNC_NAME(type) print_type_##type |
63 | #define PRINT_TYPE_FMT_NAME(type) print_type_format_##type | 67 | #define PRINT_TYPE_FMT_NAME(type) print_type_format_##type |
64 | 68 | ||
65 | /* Printing in basic type function template */ | 69 | /* Printing in basic type function template */ |
66 | #define DEFINE_BASIC_PRINT_TYPE_FUNC(type, fmt, cast) \ | 70 | #define DEFINE_BASIC_PRINT_TYPE_FUNC(type, fmt, cast) \ |
67 | static __kprobes int PRINT_TYPE_FUNC_NAME(type)(struct trace_seq *s, \ | 71 | static __kprobes int PRINT_TYPE_FUNC_NAME(type)(struct trace_seq *s, \ |
68 | const char *name, void *data)\ | 72 | const char *name, \ |
73 | void *data, void *ent)\ | ||
69 | { \ | 74 | { \ |
70 | return trace_seq_printf(s, " %s=" fmt, name, (cast)*(type *)data);\ | 75 | return trace_seq_printf(s, " %s=" fmt, name, (cast)*(type *)data);\ |
71 | } \ | 76 | } \ |
@@ -80,6 +85,49 @@ DEFINE_BASIC_PRINT_TYPE_FUNC(s16, "%d", int) | |||
80 | DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%ld", long) | 85 | DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%ld", long) |
81 | DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%lld", long long) | 86 | DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%lld", long long) |
82 | 87 | ||
88 | /* data_rloc: data relative location, compatible with u32 */ | ||
89 | #define make_data_rloc(len, roffs) \ | ||
90 | (((u32)(len) << 16) | ((u32)(roffs) & 0xffff)) | ||
91 | #define get_rloc_len(dl) ((u32)(dl) >> 16) | ||
92 | #define get_rloc_offs(dl) ((u32)(dl) & 0xffff) | ||
93 | |||
94 | static inline void *get_rloc_data(u32 *dl) | ||
95 | { | ||
96 | return (u8 *)dl + get_rloc_offs(*dl); | ||
97 | } | ||
98 | |||
99 | /* For data_loc conversion */ | ||
100 | static inline void *get_loc_data(u32 *dl, void *ent) | ||
101 | { | ||
102 | return (u8 *)ent + get_rloc_offs(*dl); | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | * Convert data_rloc to data_loc: | ||
107 | * data_rloc stores the offset from data_rloc itself, but data_loc | ||
108 | * stores the offset from event entry. | ||
109 | */ | ||
110 | #define convert_rloc_to_loc(dl, offs) ((u32)(dl) + (offs)) | ||
111 | |||
112 | /* For defining macros, define string/string_size types */ | ||
113 | typedef u32 string; | ||
114 | typedef u32 string_size; | ||
115 | |||
116 | /* Print type function for string type */ | ||
117 | static __kprobes int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, | ||
118 | const char *name, | ||
119 | void *data, void *ent) | ||
120 | { | ||
121 | int len = *(u32 *)data >> 16; | ||
122 | |||
123 | if (!len) | ||
124 | return trace_seq_printf(s, " %s=(fault)", name); | ||
125 | else | ||
126 | return trace_seq_printf(s, " %s=\"%s\"", name, | ||
127 | (const char *)get_loc_data(data, ent)); | ||
128 | } | ||
129 | static const char PRINT_TYPE_FMT_NAME(string)[] = "\\\"%s\\\""; | ||
130 | |||
83 | /* Data fetch function type */ | 131 | /* Data fetch function type */ |
84 | typedef void (*fetch_func_t)(struct pt_regs *, void *, void *); | 132 | typedef void (*fetch_func_t)(struct pt_regs *, void *, void *); |
85 | 133 | ||
@@ -94,32 +142,38 @@ static __kprobes void call_fetch(struct fetch_param *fprm, | |||
94 | return fprm->fn(regs, fprm->data, dest); | 142 | return fprm->fn(regs, fprm->data, dest); |
95 | } | 143 | } |
96 | 144 | ||
97 | #define FETCH_FUNC_NAME(kind, type) fetch_##kind##_##type | 145 | #define FETCH_FUNC_NAME(method, type) fetch_##method##_##type |
98 | /* | 146 | /* |
99 | * Define macro for basic types - we don't need to define s* types, because | 147 | * Define macro for basic types - we don't need to define s* types, because |
100 | * we have to care only about bitwidth at recording time. | 148 | * we have to care only about bitwidth at recording time. |
101 | */ | 149 | */ |
102 | #define DEFINE_BASIC_FETCH_FUNCS(kind) \ | 150 | #define DEFINE_BASIC_FETCH_FUNCS(method) \ |
103 | DEFINE_FETCH_##kind(u8) \ | 151 | DEFINE_FETCH_##method(u8) \ |
104 | DEFINE_FETCH_##kind(u16) \ | 152 | DEFINE_FETCH_##method(u16) \ |
105 | DEFINE_FETCH_##kind(u32) \ | 153 | DEFINE_FETCH_##method(u32) \ |
106 | DEFINE_FETCH_##kind(u64) | 154 | DEFINE_FETCH_##method(u64) |
107 | 155 | ||
108 | #define CHECK_BASIC_FETCH_FUNCS(kind, fn) \ | 156 | #define CHECK_FETCH_FUNCS(method, fn) \ |
109 | ((FETCH_FUNC_NAME(kind, u8) == fn) || \ | 157 | (((FETCH_FUNC_NAME(method, u8) == fn) || \ |
110 | (FETCH_FUNC_NAME(kind, u16) == fn) || \ | 158 | (FETCH_FUNC_NAME(method, u16) == fn) || \ |
111 | (FETCH_FUNC_NAME(kind, u32) == fn) || \ | 159 | (FETCH_FUNC_NAME(method, u32) == fn) || \ |
112 | (FETCH_FUNC_NAME(kind, u64) == fn)) | 160 | (FETCH_FUNC_NAME(method, u64) == fn) || \ |
161 | (FETCH_FUNC_NAME(method, string) == fn) || \ | ||
162 | (FETCH_FUNC_NAME(method, string_size) == fn)) \ | ||
163 | && (fn != NULL)) | ||
113 | 164 | ||
114 | /* Data fetch function templates */ | 165 | /* Data fetch function templates */ |
115 | #define DEFINE_FETCH_reg(type) \ | 166 | #define DEFINE_FETCH_reg(type) \ |
116 | static __kprobes void FETCH_FUNC_NAME(reg, type)(struct pt_regs *regs, \ | 167 | static __kprobes void FETCH_FUNC_NAME(reg, type)(struct pt_regs *regs, \ |
117 | void *offset, void *dest) \ | 168 | void *offset, void *dest) \ |
118 | { \ | 169 | { \ |
119 | *(type *)dest = (type)regs_get_register(regs, \ | 170 | *(type *)dest = (type)regs_get_register(regs, \ |
120 | (unsigned int)((unsigned long)offset)); \ | 171 | (unsigned int)((unsigned long)offset)); \ |
121 | } | 172 | } |
122 | DEFINE_BASIC_FETCH_FUNCS(reg) | 173 | DEFINE_BASIC_FETCH_FUNCS(reg) |
174 | /* No string on the register */ | ||
175 | #define fetch_reg_string NULL | ||
176 | #define fetch_reg_string_size NULL | ||
123 | 177 | ||
124 | #define DEFINE_FETCH_stack(type) \ | 178 | #define DEFINE_FETCH_stack(type) \ |
125 | static __kprobes void FETCH_FUNC_NAME(stack, type)(struct pt_regs *regs,\ | 179 | static __kprobes void FETCH_FUNC_NAME(stack, type)(struct pt_regs *regs,\ |
@@ -129,6 +183,9 @@ static __kprobes void FETCH_FUNC_NAME(stack, type)(struct pt_regs *regs,\ | |||
129 | (unsigned int)((unsigned long)offset)); \ | 183 | (unsigned int)((unsigned long)offset)); \ |
130 | } | 184 | } |
131 | DEFINE_BASIC_FETCH_FUNCS(stack) | 185 | DEFINE_BASIC_FETCH_FUNCS(stack) |
186 | /* No string on the stack entry */ | ||
187 | #define fetch_stack_string NULL | ||
188 | #define fetch_stack_string_size NULL | ||
132 | 189 | ||
133 | #define DEFINE_FETCH_retval(type) \ | 190 | #define DEFINE_FETCH_retval(type) \ |
134 | static __kprobes void FETCH_FUNC_NAME(retval, type)(struct pt_regs *regs,\ | 191 | static __kprobes void FETCH_FUNC_NAME(retval, type)(struct pt_regs *regs,\ |
@@ -137,6 +194,9 @@ static __kprobes void FETCH_FUNC_NAME(retval, type)(struct pt_regs *regs,\ | |||
137 | *(type *)dest = (type)regs_return_value(regs); \ | 194 | *(type *)dest = (type)regs_return_value(regs); \ |
138 | } | 195 | } |
139 | DEFINE_BASIC_FETCH_FUNCS(retval) | 196 | DEFINE_BASIC_FETCH_FUNCS(retval) |
197 | /* No string on the retval */ | ||
198 | #define fetch_retval_string NULL | ||
199 | #define fetch_retval_string_size NULL | ||
140 | 200 | ||
141 | #define DEFINE_FETCH_memory(type) \ | 201 | #define DEFINE_FETCH_memory(type) \ |
142 | static __kprobes void FETCH_FUNC_NAME(memory, type)(struct pt_regs *regs,\ | 202 | static __kprobes void FETCH_FUNC_NAME(memory, type)(struct pt_regs *regs,\ |
@@ -149,6 +209,62 @@ static __kprobes void FETCH_FUNC_NAME(memory, type)(struct pt_regs *regs,\ | |||
149 | *(type *)dest = retval; \ | 209 | *(type *)dest = retval; \ |
150 | } | 210 | } |
151 | DEFINE_BASIC_FETCH_FUNCS(memory) | 211 | DEFINE_BASIC_FETCH_FUNCS(memory) |
212 | /* | ||
213 | * Fetch a null-terminated string. Caller MUST set *(u32 *)dest with max | ||
214 | * length and relative data location. | ||
215 | */ | ||
216 | static __kprobes void FETCH_FUNC_NAME(memory, string)(struct pt_regs *regs, | ||
217 | void *addr, void *dest) | ||
218 | { | ||
219 | long ret; | ||
220 | int maxlen = get_rloc_len(*(u32 *)dest); | ||
221 | u8 *dst = get_rloc_data(dest); | ||
222 | u8 *src = addr; | ||
223 | mm_segment_t old_fs = get_fs(); | ||
224 | if (!maxlen) | ||
225 | return; | ||
226 | /* | ||
227 | * Try to get string again, since the string can be changed while | ||
228 | * probing. | ||
229 | */ | ||
230 | set_fs(KERNEL_DS); | ||
231 | pagefault_disable(); | ||
232 | do | ||
233 | ret = __copy_from_user_inatomic(dst++, src++, 1); | ||
234 | while (dst[-1] && ret == 0 && src - (u8 *)addr < maxlen); | ||
235 | dst[-1] = '\0'; | ||
236 | pagefault_enable(); | ||
237 | set_fs(old_fs); | ||
238 | |||
239 | if (ret < 0) { /* Failed to fetch string */ | ||
240 | ((u8 *)get_rloc_data(dest))[0] = '\0'; | ||
241 | *(u32 *)dest = make_data_rloc(0, get_rloc_offs(*(u32 *)dest)); | ||
242 | } else | ||
243 | *(u32 *)dest = make_data_rloc(src - (u8 *)addr, | ||
244 | get_rloc_offs(*(u32 *)dest)); | ||
245 | } | ||
246 | /* Return the length of string -- including null terminal byte */ | ||
247 | static __kprobes void FETCH_FUNC_NAME(memory, string_size)(struct pt_regs *regs, | ||
248 | void *addr, void *dest) | ||
249 | { | ||
250 | int ret, len = 0; | ||
251 | u8 c; | ||
252 | mm_segment_t old_fs = get_fs(); | ||
253 | |||
254 | set_fs(KERNEL_DS); | ||
255 | pagefault_disable(); | ||
256 | do { | ||
257 | ret = __copy_from_user_inatomic(&c, (u8 *)addr + len, 1); | ||
258 | len++; | ||
259 | } while (c && ret == 0 && len < MAX_STRING_SIZE); | ||
260 | pagefault_enable(); | ||
261 | set_fs(old_fs); | ||
262 | |||
263 | if (ret < 0) /* Failed to check the length */ | ||
264 | *(u32 *)dest = 0; | ||
265 | else | ||
266 | *(u32 *)dest = len; | ||
267 | } | ||
152 | 268 | ||
153 | /* Memory fetching by symbol */ | 269 | /* Memory fetching by symbol */ |
154 | struct symbol_cache { | 270 | struct symbol_cache { |
@@ -203,6 +319,8 @@ static __kprobes void FETCH_FUNC_NAME(symbol, type)(struct pt_regs *regs,\ | |||
203 | *(type *)dest = 0; \ | 319 | *(type *)dest = 0; \ |
204 | } | 320 | } |
205 | DEFINE_BASIC_FETCH_FUNCS(symbol) | 321 | DEFINE_BASIC_FETCH_FUNCS(symbol) |
322 | DEFINE_FETCH_symbol(string) | ||
323 | DEFINE_FETCH_symbol(string_size) | ||
206 | 324 | ||
207 | /* Dereference memory access function */ | 325 | /* Dereference memory access function */ |
208 | struct deref_fetch_param { | 326 | struct deref_fetch_param { |
@@ -224,12 +342,14 @@ static __kprobes void FETCH_FUNC_NAME(deref, type)(struct pt_regs *regs,\ | |||
224 | *(type *)dest = 0; \ | 342 | *(type *)dest = 0; \ |
225 | } | 343 | } |
226 | DEFINE_BASIC_FETCH_FUNCS(deref) | 344 | DEFINE_BASIC_FETCH_FUNCS(deref) |
345 | DEFINE_FETCH_deref(string) | ||
346 | DEFINE_FETCH_deref(string_size) | ||
227 | 347 | ||
228 | static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data) | 348 | static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data) |
229 | { | 349 | { |
230 | if (CHECK_BASIC_FETCH_FUNCS(deref, data->orig.fn)) | 350 | if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) |
231 | free_deref_fetch_param(data->orig.data); | 351 | free_deref_fetch_param(data->orig.data); |
232 | else if (CHECK_BASIC_FETCH_FUNCS(symbol, data->orig.fn)) | 352 | else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) |
233 | free_symbol_cache(data->orig.data); | 353 | free_symbol_cache(data->orig.data); |
234 | kfree(data); | 354 | kfree(data); |
235 | } | 355 | } |
@@ -240,23 +360,43 @@ static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data) | |||
240 | #define DEFAULT_FETCH_TYPE _DEFAULT_FETCH_TYPE(BITS_PER_LONG) | 360 | #define DEFAULT_FETCH_TYPE _DEFAULT_FETCH_TYPE(BITS_PER_LONG) |
241 | #define DEFAULT_FETCH_TYPE_STR __stringify(DEFAULT_FETCH_TYPE) | 361 | #define DEFAULT_FETCH_TYPE_STR __stringify(DEFAULT_FETCH_TYPE) |
242 | 362 | ||
243 | #define ASSIGN_FETCH_FUNC(kind, type) \ | 363 | /* Fetch types */ |
244 | .kind = FETCH_FUNC_NAME(kind, type) | 364 | enum { |
245 | 365 | FETCH_MTD_reg = 0, | |
246 | #define ASSIGN_FETCH_TYPE(ptype, ftype, sign) \ | 366 | FETCH_MTD_stack, |
247 | {.name = #ptype, \ | 367 | FETCH_MTD_retval, |
248 | .size = sizeof(ftype), \ | 368 | FETCH_MTD_memory, |
249 | .is_signed = sign, \ | 369 | FETCH_MTD_symbol, |
250 | .print = PRINT_TYPE_FUNC_NAME(ptype), \ | 370 | FETCH_MTD_deref, |
251 | .fmt = PRINT_TYPE_FMT_NAME(ptype), \ | 371 | FETCH_MTD_END, |
252 | ASSIGN_FETCH_FUNC(reg, ftype), \ | 372 | }; |
253 | ASSIGN_FETCH_FUNC(stack, ftype), \ | 373 | |
254 | ASSIGN_FETCH_FUNC(retval, ftype), \ | 374 | #define ASSIGN_FETCH_FUNC(method, type) \ |
255 | ASSIGN_FETCH_FUNC(memory, ftype), \ | 375 | [FETCH_MTD_##method] = FETCH_FUNC_NAME(method, type) |
256 | ASSIGN_FETCH_FUNC(symbol, ftype), \ | 376 | |
257 | ASSIGN_FETCH_FUNC(deref, ftype), \ | 377 | #define __ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, _fmttype) \ |
378 | {.name = _name, \ | ||
379 | .size = _size, \ | ||
380 | .is_signed = sign, \ | ||
381 | .print = PRINT_TYPE_FUNC_NAME(ptype), \ | ||
382 | .fmt = PRINT_TYPE_FMT_NAME(ptype), \ | ||
383 | .fmttype = _fmttype, \ | ||
384 | .fetch = { \ | ||
385 | ASSIGN_FETCH_FUNC(reg, ftype), \ | ||
386 | ASSIGN_FETCH_FUNC(stack, ftype), \ | ||
387 | ASSIGN_FETCH_FUNC(retval, ftype), \ | ||
388 | ASSIGN_FETCH_FUNC(memory, ftype), \ | ||
389 | ASSIGN_FETCH_FUNC(symbol, ftype), \ | ||
390 | ASSIGN_FETCH_FUNC(deref, ftype), \ | ||
391 | } \ | ||
258 | } | 392 | } |
259 | 393 | ||
394 | #define ASSIGN_FETCH_TYPE(ptype, ftype, sign) \ | ||
395 | __ASSIGN_FETCH_TYPE(#ptype, ptype, ftype, sizeof(ftype), sign, #ptype) | ||
396 | |||
397 | #define FETCH_TYPE_STRING 0 | ||
398 | #define FETCH_TYPE_STRSIZE 1 | ||
399 | |||
260 | /* Fetch type information table */ | 400 | /* Fetch type information table */ |
261 | static const struct fetch_type { | 401 | static const struct fetch_type { |
262 | const char *name; /* Name of type */ | 402 | const char *name; /* Name of type */ |
@@ -264,14 +404,16 @@ static const struct fetch_type { | |||
264 | int is_signed; /* Signed flag */ | 404 | int is_signed; /* Signed flag */ |
265 | print_type_func_t print; /* Print functions */ | 405 | print_type_func_t print; /* Print functions */ |
266 | const char *fmt; /* Fromat string */ | 406 | const char *fmt; /* Fromat string */ |
407 | const char *fmttype; /* Name in format file */ | ||
267 | /* Fetch functions */ | 408 | /* Fetch functions */ |
268 | fetch_func_t reg; | 409 | fetch_func_t fetch[FETCH_MTD_END]; |
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[] = { | 410 | } fetch_type_table[] = { |
411 | /* Special types */ | ||
412 | [FETCH_TYPE_STRING] = __ASSIGN_FETCH_TYPE("string", string, string, | ||
413 | sizeof(u32), 1, "__data_loc char[]"), | ||
414 | [FETCH_TYPE_STRSIZE] = __ASSIGN_FETCH_TYPE("string_size", u32, | ||
415 | string_size, sizeof(u32), 0, "u32"), | ||
416 | /* Basic types */ | ||
275 | ASSIGN_FETCH_TYPE(u8, u8, 0), | 417 | ASSIGN_FETCH_TYPE(u8, u8, 0), |
276 | ASSIGN_FETCH_TYPE(u16, u16, 0), | 418 | ASSIGN_FETCH_TYPE(u16, u16, 0), |
277 | ASSIGN_FETCH_TYPE(u32, u32, 0), | 419 | ASSIGN_FETCH_TYPE(u32, u32, 0), |
@@ -302,12 +444,28 @@ static __kprobes void fetch_stack_address(struct pt_regs *regs, | |||
302 | *(unsigned long *)dest = kernel_stack_pointer(regs); | 444 | *(unsigned long *)dest = kernel_stack_pointer(regs); |
303 | } | 445 | } |
304 | 446 | ||
447 | static fetch_func_t get_fetch_size_function(const struct fetch_type *type, | ||
448 | fetch_func_t orig_fn) | ||
449 | { | ||
450 | int i; | ||
451 | |||
452 | if (type != &fetch_type_table[FETCH_TYPE_STRING]) | ||
453 | return NULL; /* Only string type needs size function */ | ||
454 | for (i = 0; i < FETCH_MTD_END; i++) | ||
455 | if (type->fetch[i] == orig_fn) | ||
456 | return fetch_type_table[FETCH_TYPE_STRSIZE].fetch[i]; | ||
457 | |||
458 | WARN_ON(1); /* This should not happen */ | ||
459 | return NULL; | ||
460 | } | ||
461 | |||
305 | /** | 462 | /** |
306 | * Kprobe event core functions | 463 | * Kprobe event core functions |
307 | */ | 464 | */ |
308 | 465 | ||
309 | struct probe_arg { | 466 | struct probe_arg { |
310 | struct fetch_param fetch; | 467 | struct fetch_param fetch; |
468 | struct fetch_param fetch_size; | ||
311 | unsigned int offset; /* Offset from argument entry */ | 469 | unsigned int offset; /* Offset from argument entry */ |
312 | const char *name; /* Name of this argument */ | 470 | const char *name; /* Name of this argument */ |
313 | const char *comm; /* Command of this argument */ | 471 | const char *comm; /* Command of this argument */ |
@@ -429,9 +587,9 @@ error: | |||
429 | 587 | ||
430 | static void free_probe_arg(struct probe_arg *arg) | 588 | static void free_probe_arg(struct probe_arg *arg) |
431 | { | 589 | { |
432 | if (CHECK_BASIC_FETCH_FUNCS(deref, arg->fetch.fn)) | 590 | if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn)) |
433 | free_deref_fetch_param(arg->fetch.data); | 591 | free_deref_fetch_param(arg->fetch.data); |
434 | else if (CHECK_BASIC_FETCH_FUNCS(symbol, arg->fetch.fn)) | 592 | else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn)) |
435 | free_symbol_cache(arg->fetch.data); | 593 | free_symbol_cache(arg->fetch.data); |
436 | kfree(arg->name); | 594 | kfree(arg->name); |
437 | kfree(arg->comm); | 595 | kfree(arg->comm); |
@@ -548,7 +706,7 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t, | |||
548 | 706 | ||
549 | if (strcmp(arg, "retval") == 0) { | 707 | if (strcmp(arg, "retval") == 0) { |
550 | if (is_return) | 708 | if (is_return) |
551 | f->fn = t->retval; | 709 | f->fn = t->fetch[FETCH_MTD_retval]; |
552 | else | 710 | else |
553 | ret = -EINVAL; | 711 | ret = -EINVAL; |
554 | } else if (strncmp(arg, "stack", 5) == 0) { | 712 | } else if (strncmp(arg, "stack", 5) == 0) { |
@@ -562,7 +720,7 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t, | |||
562 | if (ret || param > PARAM_MAX_STACK) | 720 | if (ret || param > PARAM_MAX_STACK) |
563 | ret = -EINVAL; | 721 | ret = -EINVAL; |
564 | else { | 722 | else { |
565 | f->fn = t->stack; | 723 | f->fn = t->fetch[FETCH_MTD_stack]; |
566 | f->data = (void *)param; | 724 | f->data = (void *)param; |
567 | } | 725 | } |
568 | } else | 726 | } else |
@@ -588,7 +746,7 @@ static int __parse_probe_arg(char *arg, const struct fetch_type *t, | |||
588 | case '%': /* named register */ | 746 | case '%': /* named register */ |
589 | ret = regs_query_register_offset(arg + 1); | 747 | ret = regs_query_register_offset(arg + 1); |
590 | if (ret >= 0) { | 748 | if (ret >= 0) { |
591 | f->fn = t->reg; | 749 | f->fn = t->fetch[FETCH_MTD_reg]; |
592 | f->data = (void *)(unsigned long)ret; | 750 | f->data = (void *)(unsigned long)ret; |
593 | ret = 0; | 751 | ret = 0; |
594 | } | 752 | } |
@@ -598,7 +756,7 @@ static int __parse_probe_arg(char *arg, const struct fetch_type *t, | |||
598 | ret = strict_strtoul(arg + 1, 0, ¶m); | 756 | ret = strict_strtoul(arg + 1, 0, ¶m); |
599 | if (ret) | 757 | if (ret) |
600 | break; | 758 | break; |
601 | f->fn = t->memory; | 759 | f->fn = t->fetch[FETCH_MTD_memory]; |
602 | f->data = (void *)param; | 760 | f->data = (void *)param; |
603 | } else { | 761 | } else { |
604 | ret = split_symbol_offset(arg + 1, &offset); | 762 | ret = split_symbol_offset(arg + 1, &offset); |
@@ -606,7 +764,7 @@ static int __parse_probe_arg(char *arg, const struct fetch_type *t, | |||
606 | break; | 764 | break; |
607 | f->data = alloc_symbol_cache(arg + 1, offset); | 765 | f->data = alloc_symbol_cache(arg + 1, offset); |
608 | if (f->data) | 766 | if (f->data) |
609 | f->fn = t->symbol; | 767 | f->fn = t->fetch[FETCH_MTD_symbol]; |
610 | } | 768 | } |
611 | break; | 769 | break; |
612 | case '+': /* deref memory */ | 770 | case '+': /* deref memory */ |
@@ -636,14 +794,17 @@ static int __parse_probe_arg(char *arg, const struct fetch_type *t, | |||
636 | if (ret) | 794 | if (ret) |
637 | kfree(dprm); | 795 | kfree(dprm); |
638 | else { | 796 | else { |
639 | f->fn = t->deref; | 797 | f->fn = t->fetch[FETCH_MTD_deref]; |
640 | f->data = (void *)dprm; | 798 | f->data = (void *)dprm; |
641 | } | 799 | } |
642 | } | 800 | } |
643 | break; | 801 | break; |
644 | } | 802 | } |
645 | if (!ret && !f->fn) | 803 | if (!ret && !f->fn) { /* Parsed, but do not find fetch method */ |
804 | pr_info("%s type has no corresponding fetch method.\n", | ||
805 | t->name); | ||
646 | ret = -EINVAL; | 806 | ret = -EINVAL; |
807 | } | ||
647 | return ret; | 808 | return ret; |
648 | } | 809 | } |
649 | 810 | ||
@@ -652,6 +813,7 @@ static int parse_probe_arg(char *arg, struct trace_probe *tp, | |||
652 | struct probe_arg *parg, int is_return) | 813 | struct probe_arg *parg, int is_return) |
653 | { | 814 | { |
654 | const char *t; | 815 | const char *t; |
816 | int ret; | ||
655 | 817 | ||
656 | if (strlen(arg) > MAX_ARGSTR_LEN) { | 818 | if (strlen(arg) > MAX_ARGSTR_LEN) { |
657 | pr_info("Argument is too long.: %s\n", arg); | 819 | pr_info("Argument is too long.: %s\n", arg); |
@@ -674,7 +836,13 @@ static int parse_probe_arg(char *arg, struct trace_probe *tp, | |||
674 | } | 836 | } |
675 | parg->offset = tp->size; | 837 | parg->offset = tp->size; |
676 | tp->size += parg->type->size; | 838 | tp->size += parg->type->size; |
677 | return __parse_probe_arg(arg, parg->type, &parg->fetch, is_return); | 839 | ret = __parse_probe_arg(arg, parg->type, &parg->fetch, is_return); |
840 | if (ret >= 0) { | ||
841 | parg->fetch_size.fn = get_fetch_size_function(parg->type, | ||
842 | parg->fetch.fn); | ||
843 | parg->fetch_size.data = parg->fetch.data; | ||
844 | } | ||
845 | return ret; | ||
678 | } | 846 | } |
679 | 847 | ||
680 | /* Return 1 if name is reserved or already used by another argument */ | 848 | /* Return 1 if name is reserved or already used by another argument */ |
@@ -1043,6 +1211,54 @@ static const struct file_operations kprobe_profile_ops = { | |||
1043 | .release = seq_release, | 1211 | .release = seq_release, |
1044 | }; | 1212 | }; |
1045 | 1213 | ||
1214 | /* Sum up total data length for dynamic arraies (strings) */ | ||
1215 | static __kprobes int __get_data_size(struct trace_probe *tp, | ||
1216 | struct pt_regs *regs) | ||
1217 | { | ||
1218 | int i, ret = 0; | ||
1219 | u32 len; | ||
1220 | |||
1221 | for (i = 0; i < tp->nr_args; i++) | ||
1222 | if (unlikely(tp->args[i].fetch_size.fn)) { | ||
1223 | call_fetch(&tp->args[i].fetch_size, regs, &len); | ||
1224 | ret += len; | ||
1225 | } | ||
1226 | |||
1227 | return ret; | ||
1228 | } | ||
1229 | |||
1230 | /* Store the value of each argument */ | ||
1231 | static __kprobes void store_trace_args(int ent_size, struct trace_probe *tp, | ||
1232 | struct pt_regs *regs, | ||
1233 | u8 *data, int maxlen) | ||
1234 | { | ||
1235 | int i; | ||
1236 | u32 end = tp->size; | ||
1237 | u32 *dl; /* Data (relative) location */ | ||
1238 | |||
1239 | for (i = 0; i < tp->nr_args; i++) { | ||
1240 | if (unlikely(tp->args[i].fetch_size.fn)) { | ||
1241 | /* | ||
1242 | * First, we set the relative location and | ||
1243 | * maximum data length to *dl | ||
1244 | */ | ||
1245 | dl = (u32 *)(data + tp->args[i].offset); | ||
1246 | *dl = make_data_rloc(maxlen, end - tp->args[i].offset); | ||
1247 | /* Then try to fetch string or dynamic array data */ | ||
1248 | call_fetch(&tp->args[i].fetch, regs, dl); | ||
1249 | /* Reduce maximum length */ | ||
1250 | end += get_rloc_len(*dl); | ||
1251 | maxlen -= get_rloc_len(*dl); | ||
1252 | /* Trick here, convert data_rloc to data_loc */ | ||
1253 | *dl = convert_rloc_to_loc(*dl, | ||
1254 | ent_size + tp->args[i].offset); | ||
1255 | } else | ||
1256 | /* Just fetching data normally */ | ||
1257 | call_fetch(&tp->args[i].fetch, regs, | ||
1258 | data + tp->args[i].offset); | ||
1259 | } | ||
1260 | } | ||
1261 | |||
1046 | /* Kprobe handler */ | 1262 | /* Kprobe handler */ |
1047 | static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | 1263 | static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) |
1048 | { | 1264 | { |
@@ -1050,8 +1266,7 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
1050 | struct kprobe_trace_entry_head *entry; | 1266 | struct kprobe_trace_entry_head *entry; |
1051 | struct ring_buffer_event *event; | 1267 | struct ring_buffer_event *event; |
1052 | struct ring_buffer *buffer; | 1268 | struct ring_buffer *buffer; |
1053 | u8 *data; | 1269 | int size, dsize, pc; |
1054 | int size, i, pc; | ||
1055 | unsigned long irq_flags; | 1270 | unsigned long irq_flags; |
1056 | struct ftrace_event_call *call = &tp->call; | 1271 | struct ftrace_event_call *call = &tp->call; |
1057 | 1272 | ||
@@ -1060,7 +1275,8 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
1060 | local_save_flags(irq_flags); | 1275 | local_save_flags(irq_flags); |
1061 | pc = preempt_count(); | 1276 | pc = preempt_count(); |
1062 | 1277 | ||
1063 | size = sizeof(*entry) + tp->size; | 1278 | dsize = __get_data_size(tp, regs); |
1279 | size = sizeof(*entry) + tp->size + dsize; | ||
1064 | 1280 | ||
1065 | event = trace_current_buffer_lock_reserve(&buffer, call->event.type, | 1281 | event = trace_current_buffer_lock_reserve(&buffer, call->event.type, |
1066 | size, irq_flags, pc); | 1282 | size, irq_flags, pc); |
@@ -1069,9 +1285,7 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
1069 | 1285 | ||
1070 | entry = ring_buffer_event_data(event); | 1286 | entry = ring_buffer_event_data(event); |
1071 | entry->ip = (unsigned long)kp->addr; | 1287 | entry->ip = (unsigned long)kp->addr; |
1072 | data = (u8 *)&entry[1]; | 1288 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); |
1073 | for (i = 0; i < tp->nr_args; i++) | ||
1074 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); | ||
1075 | 1289 | ||
1076 | if (!filter_current_check_discard(buffer, call, entry, event)) | 1290 | if (!filter_current_check_discard(buffer, call, entry, event)) |
1077 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); | 1291 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); |
@@ -1085,15 +1299,15 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | |||
1085 | struct kretprobe_trace_entry_head *entry; | 1299 | struct kretprobe_trace_entry_head *entry; |
1086 | struct ring_buffer_event *event; | 1300 | struct ring_buffer_event *event; |
1087 | struct ring_buffer *buffer; | 1301 | struct ring_buffer *buffer; |
1088 | u8 *data; | 1302 | int size, pc, dsize; |
1089 | int size, i, pc; | ||
1090 | unsigned long irq_flags; | 1303 | unsigned long irq_flags; |
1091 | struct ftrace_event_call *call = &tp->call; | 1304 | struct ftrace_event_call *call = &tp->call; |
1092 | 1305 | ||
1093 | local_save_flags(irq_flags); | 1306 | local_save_flags(irq_flags); |
1094 | pc = preempt_count(); | 1307 | pc = preempt_count(); |
1095 | 1308 | ||
1096 | size = sizeof(*entry) + tp->size; | 1309 | dsize = __get_data_size(tp, regs); |
1310 | size = sizeof(*entry) + tp->size + dsize; | ||
1097 | 1311 | ||
1098 | event = trace_current_buffer_lock_reserve(&buffer, call->event.type, | 1312 | event = trace_current_buffer_lock_reserve(&buffer, call->event.type, |
1099 | size, irq_flags, pc); | 1313 | size, irq_flags, pc); |
@@ -1103,9 +1317,7 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | |||
1103 | entry = ring_buffer_event_data(event); | 1317 | entry = ring_buffer_event_data(event); |
1104 | entry->func = (unsigned long)tp->rp.kp.addr; | 1318 | entry->func = (unsigned long)tp->rp.kp.addr; |
1105 | entry->ret_ip = (unsigned long)ri->ret_addr; | 1319 | entry->ret_ip = (unsigned long)ri->ret_addr; |
1106 | data = (u8 *)&entry[1]; | 1320 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); |
1107 | for (i = 0; i < tp->nr_args; i++) | ||
1108 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); | ||
1109 | 1321 | ||
1110 | if (!filter_current_check_discard(buffer, call, entry, event)) | 1322 | if (!filter_current_check_discard(buffer, call, entry, event)) |
1111 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); | 1323 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); |
@@ -1137,7 +1349,7 @@ print_kprobe_event(struct trace_iterator *iter, int flags, | |||
1137 | data = (u8 *)&field[1]; | 1349 | data = (u8 *)&field[1]; |
1138 | for (i = 0; i < tp->nr_args; i++) | 1350 | for (i = 0; i < tp->nr_args; i++) |
1139 | if (!tp->args[i].type->print(s, tp->args[i].name, | 1351 | if (!tp->args[i].type->print(s, tp->args[i].name, |
1140 | data + tp->args[i].offset)) | 1352 | data + tp->args[i].offset, field)) |
1141 | goto partial; | 1353 | goto partial; |
1142 | 1354 | ||
1143 | if (!trace_seq_puts(s, "\n")) | 1355 | if (!trace_seq_puts(s, "\n")) |
@@ -1179,7 +1391,7 @@ print_kretprobe_event(struct trace_iterator *iter, int flags, | |||
1179 | data = (u8 *)&field[1]; | 1391 | data = (u8 *)&field[1]; |
1180 | for (i = 0; i < tp->nr_args; i++) | 1392 | for (i = 0; i < tp->nr_args; i++) |
1181 | if (!tp->args[i].type->print(s, tp->args[i].name, | 1393 | if (!tp->args[i].type->print(s, tp->args[i].name, |
1182 | data + tp->args[i].offset)) | 1394 | data + tp->args[i].offset, field)) |
1183 | goto partial; | 1395 | goto partial; |
1184 | 1396 | ||
1185 | if (!trace_seq_puts(s, "\n")) | 1397 | if (!trace_seq_puts(s, "\n")) |
@@ -1234,7 +1446,7 @@ static int kprobe_event_define_fields(struct ftrace_event_call *event_call) | |||
1234 | DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0); | 1446 | DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0); |
1235 | /* Set argument names as fields */ | 1447 | /* Set argument names as fields */ |
1236 | for (i = 0; i < tp->nr_args; i++) { | 1448 | for (i = 0; i < tp->nr_args; i++) { |
1237 | ret = trace_define_field(event_call, tp->args[i].type->name, | 1449 | ret = trace_define_field(event_call, tp->args[i].type->fmttype, |
1238 | tp->args[i].name, | 1450 | tp->args[i].name, |
1239 | sizeof(field) + tp->args[i].offset, | 1451 | sizeof(field) + tp->args[i].offset, |
1240 | tp->args[i].type->size, | 1452 | tp->args[i].type->size, |
@@ -1256,7 +1468,7 @@ static int kretprobe_event_define_fields(struct ftrace_event_call *event_call) | |||
1256 | DEFINE_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP, 0); | 1468 | DEFINE_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP, 0); |
1257 | /* Set argument names as fields */ | 1469 | /* Set argument names as fields */ |
1258 | for (i = 0; i < tp->nr_args; i++) { | 1470 | for (i = 0; i < tp->nr_args; i++) { |
1259 | ret = trace_define_field(event_call, tp->args[i].type->name, | 1471 | ret = trace_define_field(event_call, tp->args[i].type->fmttype, |
1260 | tp->args[i].name, | 1472 | tp->args[i].name, |
1261 | sizeof(field) + tp->args[i].offset, | 1473 | sizeof(field) + tp->args[i].offset, |
1262 | tp->args[i].type->size, | 1474 | tp->args[i].type->size, |
@@ -1296,8 +1508,13 @@ static int __set_print_fmt(struct trace_probe *tp, char *buf, int len) | |||
1296 | pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg); | 1508 | pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg); |
1297 | 1509 | ||
1298 | for (i = 0; i < tp->nr_args; i++) { | 1510 | for (i = 0; i < tp->nr_args; i++) { |
1299 | pos += snprintf(buf + pos, LEN_OR_ZERO, ", REC->%s", | 1511 | if (strcmp(tp->args[i].type->name, "string") == 0) |
1300 | tp->args[i].name); | 1512 | pos += snprintf(buf + pos, LEN_OR_ZERO, |
1513 | ", __get_str(%s)", | ||
1514 | tp->args[i].name); | ||
1515 | else | ||
1516 | pos += snprintf(buf + pos, LEN_OR_ZERO, ", REC->%s", | ||
1517 | tp->args[i].name); | ||
1301 | } | 1518 | } |
1302 | 1519 | ||
1303 | #undef LEN_OR_ZERO | 1520 | #undef LEN_OR_ZERO |
@@ -1334,11 +1551,11 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp, | |||
1334 | struct ftrace_event_call *call = &tp->call; | 1551 | struct ftrace_event_call *call = &tp->call; |
1335 | struct kprobe_trace_entry_head *entry; | 1552 | struct kprobe_trace_entry_head *entry; |
1336 | struct hlist_head *head; | 1553 | struct hlist_head *head; |
1337 | u8 *data; | 1554 | int size, __size, dsize; |
1338 | int size, __size, i; | ||
1339 | int rctx; | 1555 | int rctx; |
1340 | 1556 | ||
1341 | __size = sizeof(*entry) + tp->size; | 1557 | dsize = __get_data_size(tp, regs); |
1558 | __size = sizeof(*entry) + tp->size + dsize; | ||
1342 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); | 1559 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); |
1343 | size -= sizeof(u32); | 1560 | size -= sizeof(u32); |
1344 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, | 1561 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, |
@@ -1350,9 +1567,8 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp, | |||
1350 | return; | 1567 | return; |
1351 | 1568 | ||
1352 | entry->ip = (unsigned long)kp->addr; | 1569 | entry->ip = (unsigned long)kp->addr; |
1353 | data = (u8 *)&entry[1]; | 1570 | memset(&entry[1], 0, dsize); |
1354 | for (i = 0; i < tp->nr_args; i++) | 1571 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); |
1355 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); | ||
1356 | 1572 | ||
1357 | head = this_cpu_ptr(call->perf_events); | 1573 | head = this_cpu_ptr(call->perf_events); |
1358 | perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head); | 1574 | perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head); |
@@ -1366,11 +1582,11 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, | |||
1366 | struct ftrace_event_call *call = &tp->call; | 1582 | struct ftrace_event_call *call = &tp->call; |
1367 | struct kretprobe_trace_entry_head *entry; | 1583 | struct kretprobe_trace_entry_head *entry; |
1368 | struct hlist_head *head; | 1584 | struct hlist_head *head; |
1369 | u8 *data; | 1585 | int size, __size, dsize; |
1370 | int size, __size, i; | ||
1371 | int rctx; | 1586 | int rctx; |
1372 | 1587 | ||
1373 | __size = sizeof(*entry) + tp->size; | 1588 | dsize = __get_data_size(tp, regs); |
1589 | __size = sizeof(*entry) + tp->size + dsize; | ||
1374 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); | 1590 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); |
1375 | size -= sizeof(u32); | 1591 | size -= sizeof(u32); |
1376 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, | 1592 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, |
@@ -1383,9 +1599,7 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, | |||
1383 | 1599 | ||
1384 | entry->func = (unsigned long)tp->rp.kp.addr; | 1600 | entry->func = (unsigned long)tp->rp.kp.addr; |
1385 | entry->ret_ip = (unsigned long)ri->ret_addr; | 1601 | entry->ret_ip = (unsigned long)ri->ret_addr; |
1386 | data = (u8 *)&entry[1]; | 1602 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); |
1387 | for (i = 0; i < tp->nr_args; i++) | ||
1388 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); | ||
1389 | 1603 | ||
1390 | head = this_cpu_ptr(call->perf_events); | 1604 | head = this_cpu_ptr(call->perf_events); |
1391 | perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, regs, head); | 1605 | perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, regs, head); |