hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/kernel/trace/trace_probe.c
....@@ -13,7 +13,12 @@
1313
1414 #include "trace_probe.h"
1515
16
-const char *reserved_field_names[] = {
16
+#undef C
17
+#define C(a, b) b
18
+
19
+static const char *trace_probe_err_text[] = { ERRORS };
20
+
21
+static const char *reserved_field_names[] = {
1722 "common_type",
1823 "common_flags",
1924 "common_preempt_count",
....@@ -26,14 +31,12 @@
2631
2732 /* Printing in basic type function template */
2833 #define DEFINE_BASIC_PRINT_TYPE_FUNC(tname, type, fmt) \
29
-int PRINT_TYPE_FUNC_NAME(tname)(struct trace_seq *s, const char *name, \
30
- void *data, void *ent) \
34
+int PRINT_TYPE_FUNC_NAME(tname)(struct trace_seq *s, void *data, void *ent)\
3135 { \
32
- trace_seq_printf(s, " %s=" fmt, name, *(type *)data); \
36
+ trace_seq_printf(s, fmt, *(type *)data); \
3337 return !trace_seq_has_overflowed(s); \
3438 } \
35
-const char PRINT_TYPE_FMT_NAME(tname)[] = fmt; \
36
-NOKPROBE_SYMBOL(PRINT_TYPE_FUNC_NAME(tname));
39
+const char PRINT_TYPE_FMT_NAME(tname)[] = fmt;
3740
3841 DEFINE_BASIC_PRINT_TYPE_FUNC(u8, u8, "%u")
3942 DEFINE_BASIC_PRINT_TYPE_FUNC(u16, u16, "%u")
....@@ -48,193 +51,54 @@
4851 DEFINE_BASIC_PRINT_TYPE_FUNC(x32, u32, "0x%x")
4952 DEFINE_BASIC_PRINT_TYPE_FUNC(x64, u64, "0x%Lx")
5053
54
+int PRINT_TYPE_FUNC_NAME(symbol)(struct trace_seq *s, void *data, void *ent)
55
+{
56
+ trace_seq_printf(s, "%pS", (void *)*(unsigned long *)data);
57
+ return !trace_seq_has_overflowed(s);
58
+}
59
+const char PRINT_TYPE_FMT_NAME(symbol)[] = "%pS";
60
+
5161 /* Print type function for string type */
52
-int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, const char *name,
53
- void *data, void *ent)
62
+int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, void *data, void *ent)
5463 {
5564 int len = *(u32 *)data >> 16;
5665
5766 if (!len)
58
- trace_seq_printf(s, " %s=(fault)", name);
67
+ trace_seq_puts(s, "(fault)");
5968 else
60
- trace_seq_printf(s, " %s=\"%s\"", name,
69
+ trace_seq_printf(s, "\"%s\"",
6170 (const char *)get_loc_data(data, ent));
6271 return !trace_seq_has_overflowed(s);
6372 }
64
-NOKPROBE_SYMBOL(PRINT_TYPE_FUNC_NAME(string));
6573
6674 const char PRINT_TYPE_FMT_NAME(string)[] = "\\\"%s\\\"";
6775
68
-#define CHECK_FETCH_FUNCS(method, fn) \
69
- (((FETCH_FUNC_NAME(method, u8) == fn) || \
70
- (FETCH_FUNC_NAME(method, u16) == fn) || \
71
- (FETCH_FUNC_NAME(method, u32) == fn) || \
72
- (FETCH_FUNC_NAME(method, u64) == fn) || \
73
- (FETCH_FUNC_NAME(method, string) == fn) || \
74
- (FETCH_FUNC_NAME(method, string_size) == fn)) \
75
- && (fn != NULL))
76
+/* Fetch type information table */
77
+static const struct fetch_type probe_fetch_types[] = {
78
+ /* Special types */
79
+ __ASSIGN_FETCH_TYPE("string", string, string, sizeof(u32), 1,
80
+ "__data_loc char[]"),
81
+ __ASSIGN_FETCH_TYPE("ustring", string, string, sizeof(u32), 1,
82
+ "__data_loc char[]"),
83
+ /* Basic types */
84
+ ASSIGN_FETCH_TYPE(u8, u8, 0),
85
+ ASSIGN_FETCH_TYPE(u16, u16, 0),
86
+ ASSIGN_FETCH_TYPE(u32, u32, 0),
87
+ ASSIGN_FETCH_TYPE(u64, u64, 0),
88
+ ASSIGN_FETCH_TYPE(s8, u8, 1),
89
+ ASSIGN_FETCH_TYPE(s16, u16, 1),
90
+ ASSIGN_FETCH_TYPE(s32, u32, 1),
91
+ ASSIGN_FETCH_TYPE(s64, u64, 1),
92
+ ASSIGN_FETCH_TYPE_ALIAS(x8, u8, u8, 0),
93
+ ASSIGN_FETCH_TYPE_ALIAS(x16, u16, u16, 0),
94
+ ASSIGN_FETCH_TYPE_ALIAS(x32, u32, u32, 0),
95
+ ASSIGN_FETCH_TYPE_ALIAS(x64, u64, u64, 0),
96
+ ASSIGN_FETCH_TYPE_ALIAS(symbol, ADDR_FETCH_TYPE, ADDR_FETCH_TYPE, 0),
7697
77
-/* Data fetch function templates */
78
-#define DEFINE_FETCH_reg(type) \
79
-void FETCH_FUNC_NAME(reg, type)(struct pt_regs *regs, void *offset, void *dest) \
80
-{ \
81
- *(type *)dest = (type)regs_get_register(regs, \
82
- (unsigned int)((unsigned long)offset)); \
83
-} \
84
-NOKPROBE_SYMBOL(FETCH_FUNC_NAME(reg, type));
85
-DEFINE_BASIC_FETCH_FUNCS(reg)
86
-/* No string on the register */
87
-#define fetch_reg_string NULL
88
-#define fetch_reg_string_size NULL
89
-
90
-#define DEFINE_FETCH_retval(type) \
91
-void FETCH_FUNC_NAME(retval, type)(struct pt_regs *regs, \
92
- void *dummy, void *dest) \
93
-{ \
94
- *(type *)dest = (type)regs_return_value(regs); \
95
-} \
96
-NOKPROBE_SYMBOL(FETCH_FUNC_NAME(retval, type));
97
-DEFINE_BASIC_FETCH_FUNCS(retval)
98
-/* No string on the retval */
99
-#define fetch_retval_string NULL
100
-#define fetch_retval_string_size NULL
101
-
102
-/* Dereference memory access function */
103
-struct deref_fetch_param {
104
- struct fetch_param orig;
105
- long offset;
106
- fetch_func_t fetch;
107
- fetch_func_t fetch_size;
98
+ ASSIGN_FETCH_TYPE_END
10899 };
109100
110
-#define DEFINE_FETCH_deref(type) \
111
-void FETCH_FUNC_NAME(deref, type)(struct pt_regs *regs, \
112
- void *data, void *dest) \
113
-{ \
114
- struct deref_fetch_param *dprm = data; \
115
- unsigned long addr; \
116
- call_fetch(&dprm->orig, regs, &addr); \
117
- if (addr) { \
118
- addr += dprm->offset; \
119
- dprm->fetch(regs, (void *)addr, dest); \
120
- } else \
121
- *(type *)dest = 0; \
122
-} \
123
-NOKPROBE_SYMBOL(FETCH_FUNC_NAME(deref, type));
124
-DEFINE_BASIC_FETCH_FUNCS(deref)
125
-DEFINE_FETCH_deref(string)
126
-
127
-void FETCH_FUNC_NAME(deref, string_size)(struct pt_regs *regs,
128
- void *data, void *dest)
129
-{
130
- struct deref_fetch_param *dprm = data;
131
- unsigned long addr;
132
-
133
- call_fetch(&dprm->orig, regs, &addr);
134
- if (addr && dprm->fetch_size) {
135
- addr += dprm->offset;
136
- dprm->fetch_size(regs, (void *)addr, dest);
137
- } else
138
- *(string_size *)dest = 0;
139
-}
140
-NOKPROBE_SYMBOL(FETCH_FUNC_NAME(deref, string_size));
141
-
142
-static void update_deref_fetch_param(struct deref_fetch_param *data)
143
-{
144
- if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
145
- update_deref_fetch_param(data->orig.data);
146
- else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
147
- update_symbol_cache(data->orig.data);
148
-}
149
-NOKPROBE_SYMBOL(update_deref_fetch_param);
150
-
151
-static void free_deref_fetch_param(struct deref_fetch_param *data)
152
-{
153
- if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
154
- free_deref_fetch_param(data->orig.data);
155
- else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
156
- free_symbol_cache(data->orig.data);
157
- kfree(data);
158
-}
159
-NOKPROBE_SYMBOL(free_deref_fetch_param);
160
-
161
-/* Bitfield fetch function */
162
-struct bitfield_fetch_param {
163
- struct fetch_param orig;
164
- unsigned char hi_shift;
165
- unsigned char low_shift;
166
-};
167
-
168
-#define DEFINE_FETCH_bitfield(type) \
169
-void FETCH_FUNC_NAME(bitfield, type)(struct pt_regs *regs, \
170
- void *data, void *dest) \
171
-{ \
172
- struct bitfield_fetch_param *bprm = data; \
173
- type buf = 0; \
174
- call_fetch(&bprm->orig, regs, &buf); \
175
- if (buf) { \
176
- buf <<= bprm->hi_shift; \
177
- buf >>= bprm->low_shift; \
178
- } \
179
- *(type *)dest = buf; \
180
-} \
181
-NOKPROBE_SYMBOL(FETCH_FUNC_NAME(bitfield, type));
182
-DEFINE_BASIC_FETCH_FUNCS(bitfield)
183
-#define fetch_bitfield_string NULL
184
-#define fetch_bitfield_string_size NULL
185
-
186
-static void
187
-update_bitfield_fetch_param(struct bitfield_fetch_param *data)
188
-{
189
- /*
190
- * Don't check the bitfield itself, because this must be the
191
- * last fetch function.
192
- */
193
- if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
194
- update_deref_fetch_param(data->orig.data);
195
- else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
196
- update_symbol_cache(data->orig.data);
197
-}
198
-
199
-static void
200
-free_bitfield_fetch_param(struct bitfield_fetch_param *data)
201
-{
202
- /*
203
- * Don't check the bitfield itself, because this must be the
204
- * last fetch function.
205
- */
206
- if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
207
- free_deref_fetch_param(data->orig.data);
208
- else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
209
- free_symbol_cache(data->orig.data);
210
-
211
- kfree(data);
212
-}
213
-
214
-void FETCH_FUNC_NAME(comm, string)(struct pt_regs *regs,
215
- void *data, void *dest)
216
-{
217
- int maxlen = get_rloc_len(*(u32 *)dest);
218
- u8 *dst = get_rloc_data(dest);
219
- long ret;
220
-
221
- if (!maxlen)
222
- return;
223
-
224
- ret = strlcpy(dst, current->comm, maxlen);
225
- *(u32 *)dest = make_data_rloc(ret, get_rloc_offs(*(u32 *)dest));
226
-}
227
-NOKPROBE_SYMBOL(FETCH_FUNC_NAME(comm, string));
228
-
229
-void FETCH_FUNC_NAME(comm, string_size)(struct pt_regs *regs,
230
- void *data, void *dest)
231
-{
232
- *(u32 *)dest = strlen(current->comm) + 1;
233
-}
234
-NOKPROBE_SYMBOL(FETCH_FUNC_NAME(comm, string_size));
235
-
236
-static const struct fetch_type *find_fetch_type(const char *type,
237
- const struct fetch_type *ftbl)
101
+static const struct fetch_type *find_fetch_type(const char *type)
238102 {
239103 int i;
240104
....@@ -255,56 +119,89 @@
255119
256120 switch (bs) {
257121 case 8:
258
- return find_fetch_type("u8", ftbl);
122
+ return find_fetch_type("u8");
259123 case 16:
260
- return find_fetch_type("u16", ftbl);
124
+ return find_fetch_type("u16");
261125 case 32:
262
- return find_fetch_type("u32", ftbl);
126
+ return find_fetch_type("u32");
263127 case 64:
264
- return find_fetch_type("u64", ftbl);
128
+ return find_fetch_type("u64");
265129 default:
266130 goto fail;
267131 }
268132 }
269133
270
- for (i = 0; ftbl[i].name; i++) {
271
- if (strcmp(type, ftbl[i].name) == 0)
272
- return &ftbl[i];
134
+ for (i = 0; probe_fetch_types[i].name; i++) {
135
+ if (strcmp(type, probe_fetch_types[i].name) == 0)
136
+ return &probe_fetch_types[i];
273137 }
274138
275139 fail:
276140 return NULL;
277141 }
278142
279
-/* Special function : only accept unsigned long */
280
-static void fetch_kernel_stack_address(struct pt_regs *regs, void *dummy, void *dest)
143
+static struct trace_probe_log trace_probe_log;
144
+
145
+void trace_probe_log_init(const char *subsystem, int argc, const char **argv)
281146 {
282
- *(unsigned long *)dest = kernel_stack_pointer(regs);
147
+ trace_probe_log.subsystem = subsystem;
148
+ trace_probe_log.argc = argc;
149
+ trace_probe_log.argv = argv;
150
+ trace_probe_log.index = 0;
283151 }
284
-NOKPROBE_SYMBOL(fetch_kernel_stack_address);
285152
286
-static void fetch_user_stack_address(struct pt_regs *regs, void *dummy, void *dest)
153
+void trace_probe_log_clear(void)
287154 {
288
- *(unsigned long *)dest = user_stack_pointer(regs);
155
+ memset(&trace_probe_log, 0, sizeof(trace_probe_log));
289156 }
290
-NOKPROBE_SYMBOL(fetch_user_stack_address);
291157
292
-static fetch_func_t get_fetch_size_function(const struct fetch_type *type,
293
- fetch_func_t orig_fn,
294
- const struct fetch_type *ftbl)
158
+void trace_probe_log_set_index(int index)
295159 {
296
- int i;
160
+ trace_probe_log.index = index;
161
+}
297162
298
- if (type != &ftbl[FETCH_TYPE_STRING])
299
- return NULL; /* Only string type needs size function */
163
+void __trace_probe_log_err(int offset, int err_type)
164
+{
165
+ char *command, *p;
166
+ int i, len = 0, pos = 0;
300167
301
- for (i = 0; i < FETCH_MTD_END; i++)
302
- if (type->fetch[i] == orig_fn)
303
- return ftbl[FETCH_TYPE_STRSIZE].fetch[i];
168
+ if (!trace_probe_log.argv)
169
+ return;
304170
305
- WARN_ON(1); /* This should not happen */
171
+ /* Recalcurate the length and allocate buffer */
172
+ for (i = 0; i < trace_probe_log.argc; i++) {
173
+ if (i == trace_probe_log.index)
174
+ pos = len;
175
+ len += strlen(trace_probe_log.argv[i]) + 1;
176
+ }
177
+ command = kzalloc(len, GFP_KERNEL);
178
+ if (!command)
179
+ return;
306180
307
- return NULL;
181
+ if (trace_probe_log.index >= trace_probe_log.argc) {
182
+ /**
183
+ * Set the error position is next to the last arg + space.
184
+ * Note that len includes the terminal null and the cursor
185
+ * appaers at pos + 1.
186
+ */
187
+ pos = len;
188
+ offset = 0;
189
+ }
190
+
191
+ /* And make a command string from argv array */
192
+ p = command;
193
+ for (i = 0; i < trace_probe_log.argc; i++) {
194
+ len = strlen(trace_probe_log.argv[i]);
195
+ strcpy(p, trace_probe_log.argv[i]);
196
+ p[len] = ' ';
197
+ p += len + 1;
198
+ }
199
+ *(p - 1) = '\0';
200
+
201
+ tracing_log_err(NULL, trace_probe_log.subsystem, command,
202
+ trace_probe_err_text, err_type, pos + offset);
203
+
204
+ kfree(command);
308205 }
309206
310207 /* Split symbol and offset. */
....@@ -328,155 +225,280 @@
328225 return 0;
329226 }
330227
228
+/* @buf must has MAX_EVENT_NAME_LEN size */
229
+int traceprobe_parse_event_name(const char **pevent, const char **pgroup,
230
+ char *buf, int offset)
231
+{
232
+ const char *slash, *event = *pevent;
233
+ int len;
234
+
235
+ slash = strchr(event, '/');
236
+ if (slash) {
237
+ if (slash == event) {
238
+ trace_probe_log_err(offset, NO_GROUP_NAME);
239
+ return -EINVAL;
240
+ }
241
+ if (slash - event + 1 > MAX_EVENT_NAME_LEN) {
242
+ trace_probe_log_err(offset, GROUP_TOO_LONG);
243
+ return -EINVAL;
244
+ }
245
+ strlcpy(buf, event, slash - event + 1);
246
+ if (!is_good_name(buf)) {
247
+ trace_probe_log_err(offset, BAD_GROUP_NAME);
248
+ return -EINVAL;
249
+ }
250
+ *pgroup = buf;
251
+ *pevent = slash + 1;
252
+ offset += slash - event + 1;
253
+ event = *pevent;
254
+ }
255
+ len = strlen(event);
256
+ if (len == 0) {
257
+ trace_probe_log_err(offset, NO_EVENT_NAME);
258
+ return -EINVAL;
259
+ } else if (len > MAX_EVENT_NAME_LEN) {
260
+ trace_probe_log_err(offset, EVENT_TOO_LONG);
261
+ return -EINVAL;
262
+ }
263
+ if (!is_good_name(event)) {
264
+ trace_probe_log_err(offset, BAD_EVENT_NAME);
265
+ return -EINVAL;
266
+ }
267
+ return 0;
268
+}
269
+
331270 #define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long))
332271
333272 static int parse_probe_vars(char *arg, const struct fetch_type *t,
334
- struct fetch_param *f, bool is_return,
335
- bool is_kprobe)
273
+ struct fetch_insn *code, unsigned int flags, int offs)
336274 {
337
- int ret = 0;
338275 unsigned long param;
276
+ int ret = 0;
277
+ int len;
339278
340279 if (strcmp(arg, "retval") == 0) {
341
- if (is_return)
342
- f->fn = t->fetch[FETCH_MTD_retval];
343
- else
280
+ if (flags & TPARG_FL_RETURN) {
281
+ code->op = FETCH_OP_RETVAL;
282
+ } else {
283
+ trace_probe_log_err(offs, RETVAL_ON_PROBE);
344284 ret = -EINVAL;
345
- } else if (strncmp(arg, "stack", 5) == 0) {
346
- if (arg[5] == '\0') {
347
- if (strcmp(t->name, DEFAULT_FETCH_TYPE_STR))
348
- return -EINVAL;
349
-
350
- if (is_kprobe)
351
- f->fn = fetch_kernel_stack_address;
352
- else
353
- f->fn = fetch_user_stack_address;
354
- } else if (isdigit(arg[5])) {
355
- ret = kstrtoul(arg + 5, 10, &param);
356
- if (ret || (is_kprobe && param > PARAM_MAX_STACK))
285
+ }
286
+ } else if ((len = str_has_prefix(arg, "stack"))) {
287
+ if (arg[len] == '\0') {
288
+ code->op = FETCH_OP_STACKP;
289
+ } else if (isdigit(arg[len])) {
290
+ ret = kstrtoul(arg + len, 10, &param);
291
+ if (ret) {
292
+ goto inval_var;
293
+ } else if ((flags & TPARG_FL_KERNEL) &&
294
+ param > PARAM_MAX_STACK) {
295
+ trace_probe_log_err(offs, BAD_STACK_NUM);
357296 ret = -EINVAL;
358
- else {
359
- f->fn = t->fetch[FETCH_MTD_stack];
360
- f->data = (void *)param;
297
+ } else {
298
+ code->op = FETCH_OP_STACK;
299
+ code->param = (unsigned int)param;
361300 }
362301 } else
363
- ret = -EINVAL;
364
- } else if (strcmp(arg, "comm") == 0) {
365
- if (strcmp(t->name, "string") != 0 &&
366
- strcmp(t->name, "string_size") != 0)
302
+ goto inval_var;
303
+ } else if (strcmp(arg, "comm") == 0 || strcmp(arg, "COMM") == 0) {
304
+ code->op = FETCH_OP_COMM;
305
+#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
306
+ } else if (((flags & TPARG_FL_MASK) ==
307
+ (TPARG_FL_KERNEL | TPARG_FL_FENTRY)) &&
308
+ (len = str_has_prefix(arg, "arg"))) {
309
+ ret = kstrtoul(arg + len, 10, &param);
310
+ if (ret) {
311
+ goto inval_var;
312
+ } else if (!param || param > PARAM_MAX_STACK) {
313
+ trace_probe_log_err(offs, BAD_ARG_NUM);
367314 return -EINVAL;
368
- f->fn = t->fetch[FETCH_MTD_comm];
315
+ }
316
+ code->op = FETCH_OP_ARG;
317
+ code->param = (unsigned int)param - 1;
318
+#endif
369319 } else
370
- ret = -EINVAL;
320
+ goto inval_var;
371321
372322 return ret;
323
+
324
+inval_var:
325
+ trace_probe_log_err(offs, BAD_VAR);
326
+ return -EINVAL;
327
+}
328
+
329
+static int str_to_immediate(char *str, unsigned long *imm)
330
+{
331
+ if (isdigit(str[0]))
332
+ return kstrtoul(str, 0, imm);
333
+ else if (str[0] == '-')
334
+ return kstrtol(str, 0, (long *)imm);
335
+ else if (str[0] == '+')
336
+ return kstrtol(str + 1, 0, (long *)imm);
337
+ return -EINVAL;
338
+}
339
+
340
+static int __parse_imm_string(char *str, char **pbuf, int offs)
341
+{
342
+ size_t len = strlen(str);
343
+
344
+ if (str[len - 1] != '"') {
345
+ trace_probe_log_err(offs + len, IMMSTR_NO_CLOSE);
346
+ return -EINVAL;
347
+ }
348
+ *pbuf = kstrndup(str, len - 1, GFP_KERNEL);
349
+ return 0;
373350 }
374351
375352 /* Recursive argument parser */
376
-static int parse_probe_arg(char *arg, const struct fetch_type *t,
377
- struct fetch_param *f, bool is_return, bool is_kprobe,
378
- const struct fetch_type *ftbl)
353
+static int
354
+parse_probe_arg(char *arg, const struct fetch_type *type,
355
+ struct fetch_insn **pcode, struct fetch_insn *end,
356
+ unsigned int flags, int offs)
379357 {
358
+ struct fetch_insn *code = *pcode;
380359 unsigned long param;
381
- long offset;
360
+ int deref = FETCH_OP_DEREF;
361
+ long offset = 0;
382362 char *tmp;
383363 int ret = 0;
384364
385365 switch (arg[0]) {
386366 case '$':
387
- ret = parse_probe_vars(arg + 1, t, f, is_return, is_kprobe);
367
+ ret = parse_probe_vars(arg + 1, type, code, flags, offs);
388368 break;
389369
390370 case '%': /* named register */
391371 ret = regs_query_register_offset(arg + 1);
392372 if (ret >= 0) {
393
- f->fn = t->fetch[FETCH_MTD_reg];
394
- f->data = (void *)(unsigned long)ret;
373
+ code->op = FETCH_OP_REG;
374
+ code->param = (unsigned int)ret;
395375 ret = 0;
396
- }
376
+ } else
377
+ trace_probe_log_err(offs, BAD_REG_NAME);
397378 break;
398379
399380 case '@': /* memory, file-offset or symbol */
400381 if (isdigit(arg[1])) {
401382 ret = kstrtoul(arg + 1, 0, &param);
402
- if (ret)
383
+ if (ret) {
384
+ trace_probe_log_err(offs, BAD_MEM_ADDR);
403385 break;
404
-
405
- f->fn = t->fetch[FETCH_MTD_memory];
406
- f->data = (void *)param;
386
+ }
387
+ /* load address */
388
+ code->op = FETCH_OP_IMM;
389
+ code->immediate = param;
407390 } else if (arg[1] == '+') {
408391 /* kprobes don't support file offsets */
409
- if (is_kprobe)
392
+ if (flags & TPARG_FL_KERNEL) {
393
+ trace_probe_log_err(offs, FILE_ON_KPROBE);
410394 return -EINVAL;
411
-
395
+ }
412396 ret = kstrtol(arg + 2, 0, &offset);
413
- if (ret)
397
+ if (ret) {
398
+ trace_probe_log_err(offs, BAD_FILE_OFFS);
414399 break;
400
+ }
415401
416
- f->fn = t->fetch[FETCH_MTD_file_offset];
417
- f->data = (void *)offset;
402
+ code->op = FETCH_OP_FOFFS;
403
+ code->immediate = (unsigned long)offset; // imm64?
418404 } else {
419405 /* uprobes don't support symbols */
420
- if (!is_kprobe)
406
+ if (!(flags & TPARG_FL_KERNEL)) {
407
+ trace_probe_log_err(offs, SYM_ON_UPROBE);
421408 return -EINVAL;
422
-
423
- ret = traceprobe_split_symbol_offset(arg + 1, &offset);
424
- if (ret)
425
- break;
426
-
427
- f->data = alloc_symbol_cache(arg + 1, offset);
428
- if (f->data)
429
- f->fn = t->fetch[FETCH_MTD_symbol];
409
+ }
410
+ /* Preserve symbol for updating */
411
+ code->op = FETCH_NOP_SYMBOL;
412
+ code->data = kstrdup(arg + 1, GFP_KERNEL);
413
+ if (!code->data)
414
+ return -ENOMEM;
415
+ if (++code == end) {
416
+ trace_probe_log_err(offs, TOO_MANY_OPS);
417
+ return -EINVAL;
418
+ }
419
+ code->op = FETCH_OP_IMM;
420
+ code->immediate = 0;
430421 }
422
+ /* These are fetching from memory */
423
+ if (++code == end) {
424
+ trace_probe_log_err(offs, TOO_MANY_OPS);
425
+ return -EINVAL;
426
+ }
427
+ *pcode = code;
428
+ code->op = FETCH_OP_DEREF;
429
+ code->offset = offset;
431430 break;
432431
433432 case '+': /* deref memory */
434
- arg++; /* Skip '+', because kstrtol() rejects it. */
435433 case '-':
434
+ if (arg[1] == 'u') {
435
+ deref = FETCH_OP_UDEREF;
436
+ arg[1] = arg[0];
437
+ arg++;
438
+ }
439
+ if (arg[0] == '+')
440
+ arg++; /* Skip '+', because kstrtol() rejects it. */
436441 tmp = strchr(arg, '(');
437
- if (!tmp)
438
- break;
439
-
442
+ if (!tmp) {
443
+ trace_probe_log_err(offs, DEREF_NEED_BRACE);
444
+ return -EINVAL;
445
+ }
440446 *tmp = '\0';
441447 ret = kstrtol(arg, 0, &offset);
442
-
443
- if (ret)
448
+ if (ret) {
449
+ trace_probe_log_err(offs, BAD_DEREF_OFFS);
444450 break;
445
-
451
+ }
452
+ offs += (tmp + 1 - arg) + (arg[0] != '-' ? 1 : 0);
446453 arg = tmp + 1;
447454 tmp = strrchr(arg, ')');
455
+ if (!tmp) {
456
+ trace_probe_log_err(offs + strlen(arg),
457
+ DEREF_OPEN_BRACE);
458
+ return -EINVAL;
459
+ } else {
460
+ const struct fetch_type *t2 = find_fetch_type(NULL);
448461
449
- if (tmp) {
450
- struct deref_fetch_param *dprm;
451
- const struct fetch_type *t2;
452
-
453
- t2 = find_fetch_type(NULL, ftbl);
454462 *tmp = '\0';
455
- dprm = kzalloc(sizeof(struct deref_fetch_param), GFP_KERNEL);
456
-
457
- if (!dprm)
458
- return -ENOMEM;
459
-
460
- dprm->offset = offset;
461
- dprm->fetch = t->fetch[FETCH_MTD_memory];
462
- dprm->fetch_size = get_fetch_size_function(t,
463
- dprm->fetch, ftbl);
464
- ret = parse_probe_arg(arg, t2, &dprm->orig, is_return,
465
- is_kprobe, ftbl);
463
+ ret = parse_probe_arg(arg, t2, &code, end, flags, offs);
466464 if (ret)
467
- kfree(dprm);
468
- else {
469
- f->fn = t->fetch[FETCH_MTD_deref];
470
- f->data = (void *)dprm;
465
+ break;
466
+ if (code->op == FETCH_OP_COMM ||
467
+ code->op == FETCH_OP_DATA) {
468
+ trace_probe_log_err(offs, COMM_CANT_DEREF);
469
+ return -EINVAL;
471470 }
471
+ if (++code == end) {
472
+ trace_probe_log_err(offs, TOO_MANY_OPS);
473
+ return -EINVAL;
474
+ }
475
+ *pcode = code;
476
+
477
+ code->op = deref;
478
+ code->offset = offset;
479
+ }
480
+ break;
481
+ case '\\': /* Immediate value */
482
+ if (arg[1] == '"') { /* Immediate string */
483
+ ret = __parse_imm_string(arg + 2, &tmp, offs + 2);
484
+ if (ret)
485
+ break;
486
+ code->op = FETCH_OP_DATA;
487
+ code->data = tmp;
488
+ } else {
489
+ ret = str_to_immediate(arg + 1, &code->immediate);
490
+ if (ret)
491
+ trace_probe_log_err(offs + 1, BAD_IMM);
492
+ else
493
+ code->op = FETCH_OP_IMM;
472494 }
473495 break;
474496 }
475
- if (!ret && !f->fn) { /* Parsed, but do not find fetch method */
476
- pr_info("%s type has no corresponding fetch method.\n", t->name);
497
+ if (!ret && code->op == FETCH_OP_NOP) {
498
+ /* Parsed, but do not find fetch method */
499
+ trace_probe_log_err(offs, BAD_FETCH_ARG);
477500 ret = -EINVAL;
478501 }
479
-
480502 return ret;
481503 }
482504
....@@ -485,22 +507,15 @@
485507 /* Bitfield type needs to be parsed into a fetch function */
486508 static int __parse_bitfield_probe_arg(const char *bf,
487509 const struct fetch_type *t,
488
- struct fetch_param *f)
510
+ struct fetch_insn **pcode)
489511 {
490
- struct bitfield_fetch_param *bprm;
512
+ struct fetch_insn *code = *pcode;
491513 unsigned long bw, bo;
492514 char *tail;
493515
494516 if (*bf != 'b')
495517 return 0;
496518
497
- bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
498
- if (!bprm)
499
- return -ENOMEM;
500
-
501
- bprm->orig = *f;
502
- f->fn = t->fetch[FETCH_MTD_bitfield];
503
- f->data = (void *)bprm;
504519 bw = simple_strtoul(bf + 1, &tail, 0); /* Use simple one */
505520
506521 if (bw == 0 || *tail != '@')
....@@ -511,67 +526,212 @@
511526
512527 if (tail == bf || *tail != '/')
513528 return -EINVAL;
529
+ code++;
530
+ if (code->op != FETCH_OP_NOP)
531
+ return -EINVAL;
532
+ *pcode = code;
514533
515
- bprm->hi_shift = BYTES_TO_BITS(t->size) - (bw + bo);
516
- bprm->low_shift = bprm->hi_shift + bo;
534
+ code->op = FETCH_OP_MOD_BF;
535
+ code->lshift = BYTES_TO_BITS(t->size) - (bw + bo);
536
+ code->rshift = BYTES_TO_BITS(t->size) - bw;
537
+ code->basesize = t->size;
517538
518539 return (BYTES_TO_BITS(t->size) < (bw + bo)) ? -EINVAL : 0;
519540 }
520541
521542 /* String length checking wrapper */
522
-int traceprobe_parse_probe_arg(char *arg, ssize_t *size,
523
- struct probe_arg *parg, bool is_return, bool is_kprobe,
524
- const struct fetch_type *ftbl)
543
+static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size,
544
+ struct probe_arg *parg, unsigned int flags, int offset)
525545 {
526
- const char *t;
527
- int ret;
546
+ struct fetch_insn *code, *scode, *tmp = NULL;
547
+ char *t, *t2, *t3;
548
+ int ret, len;
528549
529
- if (strlen(arg) > MAX_ARGSTR_LEN) {
530
- pr_info("Argument is too long.: %s\n", arg);
531
- return -ENOSPC;
550
+ len = strlen(arg);
551
+ if (len > MAX_ARGSTR_LEN) {
552
+ trace_probe_log_err(offset, ARG_TOO_LONG);
553
+ return -EINVAL;
554
+ } else if (len == 0) {
555
+ trace_probe_log_err(offset, NO_ARG_BODY);
556
+ return -EINVAL;
532557 }
558
+
533559 parg->comm = kstrdup(arg, GFP_KERNEL);
534
- if (!parg->comm) {
535
- pr_info("Failed to allocate memory for command '%s'.\n", arg);
560
+ if (!parg->comm)
536561 return -ENOMEM;
537
- }
538
- t = strchr(parg->comm, ':');
562
+
563
+ t = strchr(arg, ':');
539564 if (t) {
540
- arg[t - parg->comm] = '\0';
541
- t++;
565
+ *t = '\0';
566
+ t2 = strchr(++t, '[');
567
+ if (t2) {
568
+ *t2++ = '\0';
569
+ t3 = strchr(t2, ']');
570
+ if (!t3) {
571
+ offset += t2 + strlen(t2) - arg;
572
+ trace_probe_log_err(offset,
573
+ ARRAY_NO_CLOSE);
574
+ return -EINVAL;
575
+ } else if (t3[1] != '\0') {
576
+ trace_probe_log_err(offset + t3 + 1 - arg,
577
+ BAD_ARRAY_SUFFIX);
578
+ return -EINVAL;
579
+ }
580
+ *t3 = '\0';
581
+ if (kstrtouint(t2, 0, &parg->count) || !parg->count) {
582
+ trace_probe_log_err(offset + t2 - arg,
583
+ BAD_ARRAY_NUM);
584
+ return -EINVAL;
585
+ }
586
+ if (parg->count > MAX_ARRAY_LEN) {
587
+ trace_probe_log_err(offset + t2 - arg,
588
+ ARRAY_TOO_BIG);
589
+ return -EINVAL;
590
+ }
591
+ }
542592 }
593
+
543594 /*
544
- * The default type of $comm should be "string", and it can't be
545
- * dereferenced.
595
+ * Since $comm and immediate string can not be dereferred,
596
+ * we can find those by strcmp.
546597 */
547
- if (!t && strcmp(arg, "$comm") == 0)
548
- t = "string";
549
- parg->type = find_fetch_type(t, ftbl);
598
+ if (strcmp(arg, "$comm") == 0 || strcmp(arg, "$COMM") == 0 ||
599
+ strncmp(arg, "\\\"", 2) == 0) {
600
+ /* The type of $comm must be "string", and not an array. */
601
+ if (parg->count || (t && strcmp(t, "string")))
602
+ return -EINVAL;
603
+ parg->type = find_fetch_type("string");
604
+ } else
605
+ parg->type = find_fetch_type(t);
550606 if (!parg->type) {
551
- pr_info("Unsupported type: %s\n", t);
607
+ trace_probe_log_err(offset + (t ? (t - arg) : 0), BAD_TYPE);
552608 return -EINVAL;
553609 }
554610 parg->offset = *size;
555
- *size += parg->type->size;
556
- ret = parse_probe_arg(arg, parg->type, &parg->fetch, is_return,
557
- is_kprobe, ftbl);
611
+ *size += parg->type->size * (parg->count ?: 1);
558612
559
- if (ret >= 0 && t != NULL)
560
- ret = __parse_bitfield_probe_arg(t, parg->type, &parg->fetch);
561
-
562
- if (ret >= 0) {
563
- parg->fetch_size.fn = get_fetch_size_function(parg->type,
564
- parg->fetch.fn,
565
- ftbl);
566
- parg->fetch_size.data = parg->fetch.data;
613
+ if (parg->count) {
614
+ len = strlen(parg->type->fmttype) + 6;
615
+ parg->fmt = kmalloc(len, GFP_KERNEL);
616
+ if (!parg->fmt)
617
+ return -ENOMEM;
618
+ snprintf(parg->fmt, len, "%s[%d]", parg->type->fmttype,
619
+ parg->count);
567620 }
621
+
622
+ code = tmp = kcalloc(FETCH_INSN_MAX, sizeof(*code), GFP_KERNEL);
623
+ if (!code)
624
+ return -ENOMEM;
625
+ code[FETCH_INSN_MAX - 1].op = FETCH_OP_END;
626
+
627
+ ret = parse_probe_arg(arg, parg->type, &code, &code[FETCH_INSN_MAX - 1],
628
+ flags, offset);
629
+ if (ret)
630
+ goto fail;
631
+
632
+ /* Store operation */
633
+ if (!strcmp(parg->type->name, "string") ||
634
+ !strcmp(parg->type->name, "ustring")) {
635
+ if (code->op != FETCH_OP_DEREF && code->op != FETCH_OP_UDEREF &&
636
+ code->op != FETCH_OP_IMM && code->op != FETCH_OP_COMM &&
637
+ code->op != FETCH_OP_DATA) {
638
+ trace_probe_log_err(offset + (t ? (t - arg) : 0),
639
+ BAD_STRING);
640
+ ret = -EINVAL;
641
+ goto fail;
642
+ }
643
+ if ((code->op == FETCH_OP_IMM || code->op == FETCH_OP_COMM ||
644
+ code->op == FETCH_OP_DATA) || parg->count) {
645
+ /*
646
+ * IMM, DATA and COMM is pointing actual address, those
647
+ * must be kept, and if parg->count != 0, this is an
648
+ * array of string pointers instead of string address
649
+ * itself.
650
+ */
651
+ code++;
652
+ if (code->op != FETCH_OP_NOP) {
653
+ trace_probe_log_err(offset, TOO_MANY_OPS);
654
+ ret = -EINVAL;
655
+ goto fail;
656
+ }
657
+ }
658
+ /* If op == DEREF, replace it with STRING */
659
+ if (!strcmp(parg->type->name, "ustring") ||
660
+ code->op == FETCH_OP_UDEREF)
661
+ code->op = FETCH_OP_ST_USTRING;
662
+ else
663
+ code->op = FETCH_OP_ST_STRING;
664
+ code->size = parg->type->size;
665
+ parg->dynamic = true;
666
+ } else if (code->op == FETCH_OP_DEREF) {
667
+ code->op = FETCH_OP_ST_MEM;
668
+ code->size = parg->type->size;
669
+ } else if (code->op == FETCH_OP_UDEREF) {
670
+ code->op = FETCH_OP_ST_UMEM;
671
+ code->size = parg->type->size;
672
+ } else {
673
+ code++;
674
+ if (code->op != FETCH_OP_NOP) {
675
+ trace_probe_log_err(offset, TOO_MANY_OPS);
676
+ ret = -EINVAL;
677
+ goto fail;
678
+ }
679
+ code->op = FETCH_OP_ST_RAW;
680
+ code->size = parg->type->size;
681
+ }
682
+ scode = code;
683
+ /* Modify operation */
684
+ if (t != NULL) {
685
+ ret = __parse_bitfield_probe_arg(t, parg->type, &code);
686
+ if (ret) {
687
+ trace_probe_log_err(offset + t - arg, BAD_BITFIELD);
688
+ goto fail;
689
+ }
690
+ }
691
+ /* Loop(Array) operation */
692
+ if (parg->count) {
693
+ if (scode->op != FETCH_OP_ST_MEM &&
694
+ scode->op != FETCH_OP_ST_STRING &&
695
+ scode->op != FETCH_OP_ST_USTRING) {
696
+ trace_probe_log_err(offset + (t ? (t - arg) : 0),
697
+ BAD_STRING);
698
+ ret = -EINVAL;
699
+ goto fail;
700
+ }
701
+ code++;
702
+ if (code->op != FETCH_OP_NOP) {
703
+ trace_probe_log_err(offset, TOO_MANY_OPS);
704
+ ret = -EINVAL;
705
+ goto fail;
706
+ }
707
+ code->op = FETCH_OP_LP_ARRAY;
708
+ code->param = parg->count;
709
+ }
710
+ code++;
711
+ code->op = FETCH_OP_END;
712
+
713
+ /* Shrink down the code buffer */
714
+ parg->code = kcalloc(code - tmp + 1, sizeof(*code), GFP_KERNEL);
715
+ if (!parg->code)
716
+ ret = -ENOMEM;
717
+ else
718
+ memcpy(parg->code, tmp, sizeof(*code) * (code - tmp + 1));
719
+
720
+fail:
721
+ if (ret) {
722
+ for (code = tmp; code < tmp + FETCH_INSN_MAX; code++)
723
+ if (code->op == FETCH_NOP_SYMBOL ||
724
+ code->op == FETCH_OP_DATA)
725
+ kfree(code->data);
726
+ }
727
+ kfree(tmp);
568728
569729 return ret;
570730 }
571731
572732 /* Return 1 if name is reserved or already used by another argument */
573
-int traceprobe_conflict_field_name(const char *name,
574
- struct probe_arg *args, int narg)
733
+static int traceprobe_conflict_field_name(const char *name,
734
+ struct probe_arg *args, int narg)
575735 {
576736 int i;
577737
....@@ -586,35 +746,105 @@
586746 return 0;
587747 }
588748
589
-void traceprobe_update_arg(struct probe_arg *arg)
749
+int traceprobe_parse_probe_arg(struct trace_probe *tp, int i, char *arg,
750
+ unsigned int flags)
590751 {
591
- if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn))
592
- update_bitfield_fetch_param(arg->fetch.data);
593
- else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn))
594
- update_deref_fetch_param(arg->fetch.data);
595
- else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn))
596
- update_symbol_cache(arg->fetch.data);
752
+ struct probe_arg *parg = &tp->args[i];
753
+ char *body;
754
+
755
+ /* Increment count for freeing args in error case */
756
+ tp->nr_args++;
757
+
758
+ body = strchr(arg, '=');
759
+ if (body) {
760
+ if (body - arg > MAX_ARG_NAME_LEN) {
761
+ trace_probe_log_err(0, ARG_NAME_TOO_LONG);
762
+ return -EINVAL;
763
+ } else if (body == arg) {
764
+ trace_probe_log_err(0, NO_ARG_NAME);
765
+ return -EINVAL;
766
+ }
767
+ parg->name = kmemdup_nul(arg, body - arg, GFP_KERNEL);
768
+ body++;
769
+ } else {
770
+ /* If argument name is omitted, set "argN" */
771
+ parg->name = kasprintf(GFP_KERNEL, "arg%d", i + 1);
772
+ body = arg;
773
+ }
774
+ if (!parg->name)
775
+ return -ENOMEM;
776
+
777
+ if (!is_good_name(parg->name)) {
778
+ trace_probe_log_err(0, BAD_ARG_NAME);
779
+ return -EINVAL;
780
+ }
781
+ if (traceprobe_conflict_field_name(parg->name, tp->args, i)) {
782
+ trace_probe_log_err(0, USED_ARG_NAME);
783
+ return -EINVAL;
784
+ }
785
+ /* Parse fetch argument */
786
+ return traceprobe_parse_probe_arg_body(body, &tp->size, parg, flags,
787
+ body - arg);
597788 }
598789
599790 void traceprobe_free_probe_arg(struct probe_arg *arg)
600791 {
601
- if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn))
602
- free_bitfield_fetch_param(arg->fetch.data);
603
- else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn))
604
- free_deref_fetch_param(arg->fetch.data);
605
- else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn))
606
- free_symbol_cache(arg->fetch.data);
792
+ struct fetch_insn *code = arg->code;
607793
794
+ while (code && code->op != FETCH_OP_END) {
795
+ if (code->op == FETCH_NOP_SYMBOL ||
796
+ code->op == FETCH_OP_DATA)
797
+ kfree(code->data);
798
+ code++;
799
+ }
800
+ kfree(arg->code);
608801 kfree(arg->name);
609802 kfree(arg->comm);
803
+ kfree(arg->fmt);
610804 }
611805
806
+int traceprobe_update_arg(struct probe_arg *arg)
807
+{
808
+ struct fetch_insn *code = arg->code;
809
+ long offset;
810
+ char *tmp;
811
+ char c;
812
+ int ret = 0;
813
+
814
+ while (code && code->op != FETCH_OP_END) {
815
+ if (code->op == FETCH_NOP_SYMBOL) {
816
+ if (code[1].op != FETCH_OP_IMM)
817
+ return -EINVAL;
818
+
819
+ tmp = strpbrk(code->data, "+-");
820
+ if (tmp)
821
+ c = *tmp;
822
+ ret = traceprobe_split_symbol_offset(code->data,
823
+ &offset);
824
+ if (ret)
825
+ return ret;
826
+
827
+ code[1].immediate =
828
+ (unsigned long)kallsyms_lookup_name(code->data);
829
+ if (tmp)
830
+ *tmp = c;
831
+ if (!code[1].immediate)
832
+ return -ENOENT;
833
+ code[1].immediate += offset;
834
+ }
835
+ code++;
836
+ }
837
+ return 0;
838
+}
839
+
840
+/* When len=0, we just calculate the needed length */
841
+#define LEN_OR_ZERO (len ? len - pos : 0)
612842 static int __set_print_fmt(struct trace_probe *tp, char *buf, int len,
613843 bool is_return)
614844 {
615
- int i;
845
+ struct probe_arg *parg;
846
+ int i, j;
616847 int pos = 0;
617
-
618848 const char *fmt, *arg;
619849
620850 if (!is_return) {
....@@ -625,36 +855,55 @@
625855 arg = "REC->" FIELD_STRING_FUNC ", REC->" FIELD_STRING_RETIP;
626856 }
627857
628
- /* When len=0, we just calculate the needed length */
629
-#define LEN_OR_ZERO (len ? len - pos : 0)
630
-
631858 pos += snprintf(buf + pos, LEN_OR_ZERO, "\"%s", fmt);
632859
633860 for (i = 0; i < tp->nr_args; i++) {
634
- pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=%s",
635
- tp->args[i].name, tp->args[i].type->fmt);
861
+ parg = tp->args + i;
862
+ pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=", parg->name);
863
+ if (parg->count) {
864
+ pos += snprintf(buf + pos, LEN_OR_ZERO, "{%s",
865
+ parg->type->fmt);
866
+ for (j = 1; j < parg->count; j++)
867
+ pos += snprintf(buf + pos, LEN_OR_ZERO, ",%s",
868
+ parg->type->fmt);
869
+ pos += snprintf(buf + pos, LEN_OR_ZERO, "}");
870
+ } else
871
+ pos += snprintf(buf + pos, LEN_OR_ZERO, "%s",
872
+ parg->type->fmt);
636873 }
637874
638875 pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg);
639876
640877 for (i = 0; i < tp->nr_args; i++) {
641
- if (strcmp(tp->args[i].type->name, "string") == 0)
878
+ parg = tp->args + i;
879
+ if (parg->count) {
880
+ if ((strcmp(parg->type->name, "string") == 0) ||
881
+ (strcmp(parg->type->name, "ustring") == 0))
882
+ fmt = ", __get_str(%s[%d])";
883
+ else
884
+ fmt = ", REC->%s[%d]";
885
+ for (j = 0; j < parg->count; j++)
886
+ pos += snprintf(buf + pos, LEN_OR_ZERO,
887
+ fmt, parg->name, j);
888
+ } else {
889
+ if ((strcmp(parg->type->name, "string") == 0) ||
890
+ (strcmp(parg->type->name, "ustring") == 0))
891
+ fmt = ", __get_str(%s)";
892
+ else
893
+ fmt = ", REC->%s";
642894 pos += snprintf(buf + pos, LEN_OR_ZERO,
643
- ", __get_str(%s)",
644
- tp->args[i].name);
645
- else
646
- pos += snprintf(buf + pos, LEN_OR_ZERO, ", REC->%s",
647
- tp->args[i].name);
895
+ fmt, parg->name);
896
+ }
648897 }
649
-
650
-#undef LEN_OR_ZERO
651898
652899 /* return the length of print_fmt */
653900 return pos;
654901 }
902
+#undef LEN_OR_ZERO
655903
656
-int set_print_fmt(struct trace_probe *tp, bool is_return)
904
+int traceprobe_set_print_fmt(struct trace_probe *tp, bool is_return)
657905 {
906
+ struct trace_event_call *call = trace_probe_event_call(tp);
658907 int len;
659908 char *print_fmt;
660909
....@@ -666,7 +915,248 @@
666915
667916 /* Second: actually write the @print_fmt */
668917 __set_print_fmt(tp, print_fmt, len + 1, is_return);
669
- tp->call.print_fmt = print_fmt;
918
+ call->print_fmt = print_fmt;
670919
671920 return 0;
672921 }
922
+
923
+int traceprobe_define_arg_fields(struct trace_event_call *event_call,
924
+ size_t offset, struct trace_probe *tp)
925
+{
926
+ int ret, i;
927
+
928
+ /* Set argument names as fields */
929
+ for (i = 0; i < tp->nr_args; i++) {
930
+ struct probe_arg *parg = &tp->args[i];
931
+ const char *fmt = parg->type->fmttype;
932
+ int size = parg->type->size;
933
+
934
+ if (parg->fmt)
935
+ fmt = parg->fmt;
936
+ if (parg->count)
937
+ size *= parg->count;
938
+ ret = trace_define_field(event_call, fmt, parg->name,
939
+ offset + parg->offset, size,
940
+ parg->type->is_signed,
941
+ FILTER_OTHER);
942
+ if (ret)
943
+ return ret;
944
+ }
945
+ return 0;
946
+}
947
+
948
+static void trace_probe_event_free(struct trace_probe_event *tpe)
949
+{
950
+ kfree(tpe->class.system);
951
+ kfree(tpe->call.name);
952
+ kfree(tpe->call.print_fmt);
953
+ kfree(tpe);
954
+}
955
+
956
+int trace_probe_append(struct trace_probe *tp, struct trace_probe *to)
957
+{
958
+ if (trace_probe_has_sibling(tp))
959
+ return -EBUSY;
960
+
961
+ list_del_init(&tp->list);
962
+ trace_probe_event_free(tp->event);
963
+
964
+ tp->event = to->event;
965
+ list_add_tail(&tp->list, trace_probe_probe_list(to));
966
+
967
+ return 0;
968
+}
969
+
970
+void trace_probe_unlink(struct trace_probe *tp)
971
+{
972
+ list_del_init(&tp->list);
973
+ if (list_empty(trace_probe_probe_list(tp)))
974
+ trace_probe_event_free(tp->event);
975
+ tp->event = NULL;
976
+}
977
+
978
+void trace_probe_cleanup(struct trace_probe *tp)
979
+{
980
+ int i;
981
+
982
+ for (i = 0; i < tp->nr_args; i++)
983
+ traceprobe_free_probe_arg(&tp->args[i]);
984
+
985
+ if (tp->event)
986
+ trace_probe_unlink(tp);
987
+}
988
+
989
+int trace_probe_init(struct trace_probe *tp, const char *event,
990
+ const char *group, bool alloc_filter)
991
+{
992
+ struct trace_event_call *call;
993
+ size_t size = sizeof(struct trace_probe_event);
994
+ int ret = 0;
995
+
996
+ if (!event || !group)
997
+ return -EINVAL;
998
+
999
+ if (alloc_filter)
1000
+ size += sizeof(struct trace_uprobe_filter);
1001
+
1002
+ tp->event = kzalloc(size, GFP_KERNEL);
1003
+ if (!tp->event)
1004
+ return -ENOMEM;
1005
+
1006
+ INIT_LIST_HEAD(&tp->event->files);
1007
+ INIT_LIST_HEAD(&tp->event->class.fields);
1008
+ INIT_LIST_HEAD(&tp->event->probes);
1009
+ INIT_LIST_HEAD(&tp->list);
1010
+ list_add(&tp->list, &tp->event->probes);
1011
+
1012
+ call = trace_probe_event_call(tp);
1013
+ call->class = &tp->event->class;
1014
+ call->name = kstrdup(event, GFP_KERNEL);
1015
+ if (!call->name) {
1016
+ ret = -ENOMEM;
1017
+ goto error;
1018
+ }
1019
+
1020
+ tp->event->class.system = kstrdup(group, GFP_KERNEL);
1021
+ if (!tp->event->class.system) {
1022
+ ret = -ENOMEM;
1023
+ goto error;
1024
+ }
1025
+
1026
+ return 0;
1027
+
1028
+error:
1029
+ trace_probe_cleanup(tp);
1030
+ return ret;
1031
+}
1032
+
1033
+static struct trace_event_call *
1034
+find_trace_event_call(const char *system, const char *event_name)
1035
+{
1036
+ struct trace_event_call *tp_event;
1037
+ const char *name;
1038
+
1039
+ list_for_each_entry(tp_event, &ftrace_events, list) {
1040
+ if (!tp_event->class->system ||
1041
+ strcmp(system, tp_event->class->system))
1042
+ continue;
1043
+ name = trace_event_name(tp_event);
1044
+ if (!name || strcmp(event_name, name))
1045
+ continue;
1046
+ return tp_event;
1047
+ }
1048
+
1049
+ return NULL;
1050
+}
1051
+
1052
+int trace_probe_register_event_call(struct trace_probe *tp)
1053
+{
1054
+ struct trace_event_call *call = trace_probe_event_call(tp);
1055
+ int ret;
1056
+
1057
+ lockdep_assert_held(&event_mutex);
1058
+
1059
+ if (find_trace_event_call(trace_probe_group_name(tp),
1060
+ trace_probe_name(tp)))
1061
+ return -EEXIST;
1062
+
1063
+ ret = register_trace_event(&call->event);
1064
+ if (!ret)
1065
+ return -ENODEV;
1066
+
1067
+ ret = trace_add_event_call(call);
1068
+ if (ret)
1069
+ unregister_trace_event(&call->event);
1070
+
1071
+ return ret;
1072
+}
1073
+
1074
+int trace_probe_add_file(struct trace_probe *tp, struct trace_event_file *file)
1075
+{
1076
+ struct event_file_link *link;
1077
+
1078
+ link = kmalloc(sizeof(*link), GFP_KERNEL);
1079
+ if (!link)
1080
+ return -ENOMEM;
1081
+
1082
+ link->file = file;
1083
+ INIT_LIST_HEAD(&link->list);
1084
+ list_add_tail_rcu(&link->list, &tp->event->files);
1085
+ trace_probe_set_flag(tp, TP_FLAG_TRACE);
1086
+ return 0;
1087
+}
1088
+
1089
+struct event_file_link *trace_probe_get_file_link(struct trace_probe *tp,
1090
+ struct trace_event_file *file)
1091
+{
1092
+ struct event_file_link *link;
1093
+
1094
+ trace_probe_for_each_link(link, tp) {
1095
+ if (link->file == file)
1096
+ return link;
1097
+ }
1098
+
1099
+ return NULL;
1100
+}
1101
+
1102
+int trace_probe_remove_file(struct trace_probe *tp,
1103
+ struct trace_event_file *file)
1104
+{
1105
+ struct event_file_link *link;
1106
+
1107
+ link = trace_probe_get_file_link(tp, file);
1108
+ if (!link)
1109
+ return -ENOENT;
1110
+
1111
+ list_del_rcu(&link->list);
1112
+ synchronize_rcu();
1113
+ kfree(link);
1114
+
1115
+ if (list_empty(&tp->event->files))
1116
+ trace_probe_clear_flag(tp, TP_FLAG_TRACE);
1117
+
1118
+ return 0;
1119
+}
1120
+
1121
+/*
1122
+ * Return the smallest index of different type argument (start from 1).
1123
+ * If all argument types and name are same, return 0.
1124
+ */
1125
+int trace_probe_compare_arg_type(struct trace_probe *a, struct trace_probe *b)
1126
+{
1127
+ int i;
1128
+
1129
+ /* In case of more arguments */
1130
+ if (a->nr_args < b->nr_args)
1131
+ return a->nr_args + 1;
1132
+ if (a->nr_args > b->nr_args)
1133
+ return b->nr_args + 1;
1134
+
1135
+ for (i = 0; i < a->nr_args; i++) {
1136
+ if ((b->nr_args <= i) ||
1137
+ ((a->args[i].type != b->args[i].type) ||
1138
+ (a->args[i].count != b->args[i].count) ||
1139
+ strcmp(a->args[i].name, b->args[i].name)))
1140
+ return i + 1;
1141
+ }
1142
+
1143
+ return 0;
1144
+}
1145
+
1146
+bool trace_probe_match_command_args(struct trace_probe *tp,
1147
+ int argc, const char **argv)
1148
+{
1149
+ char buf[MAX_ARGSTR_LEN + 1];
1150
+ int i;
1151
+
1152
+ if (tp->nr_args < argc)
1153
+ return false;
1154
+
1155
+ for (i = 0; i < argc; i++) {
1156
+ snprintf(buf, sizeof(buf), "%s=%s",
1157
+ tp->args[i].name, tp->args[i].comm);
1158
+ if (strcmp(buf, argv[i]))
1159
+ return false;
1160
+ }
1161
+ return true;
1162
+}