Blame view

kernel/trace/trace_probe.c 26.4 KB
bcea3f96e   Steven Rostedt (VMware)   tracing: Add SPDX...
1
  // SPDX-License-Identifier: GPL-2.0
8ab83f564   Srikar Dronamraju   tracing: Extract ...
2
3
4
  /*
   * Common code for probe-based Dynamic events.
   *
8ab83f564   Srikar Dronamraju   tracing: Extract ...
5
6
7
8
9
10
11
   * This code was copied from kernel/trace/trace_kprobe.c written by
   * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
   *
   * Updates to make this generic:
   * Copyright (C) IBM Corporation, 2010-2011
   * Author:     Srikar Dronamraju
   */
725763413   Masami Hiramatsu   tracing/probe: Sh...
12
  #define pr_fmt(fmt)	"trace_probe: " fmt
8ab83f564   Srikar Dronamraju   tracing: Extract ...
13
14
  
  #include "trace_probe.h"
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
15
16
17
18
  #undef C
  #define C(a, b)		b
  
  static const char *trace_probe_err_text[] = { ERRORS };
084162520   Valdis Kletnieks   tracing/probes: M...
19
  static const char *reserved_field_names[] = {
8ab83f564   Srikar Dronamraju   tracing: Extract ...
20
21
22
23
24
25
26
27
28
  	"common_type",
  	"common_flags",
  	"common_preempt_count",
  	"common_pid",
  	"common_tgid",
  	FIELD_STRING_IP,
  	FIELD_STRING_RETIP,
  	FIELD_STRING_FUNC,
  };
8ab83f564   Srikar Dronamraju   tracing: Extract ...
29
  /* Printing  in basic type function template */
17ce3dc7e   Masami Hiramatsu   ftrace: kprobe: u...
30
  #define DEFINE_BASIC_PRINT_TYPE_FUNC(tname, type, fmt)			\
56de76305   Masami Hiramatsu   tracing: probeeve...
31
  int PRINT_TYPE_FUNC_NAME(tname)(struct trace_seq *s, void *data, void *ent)\
8ab83f564   Srikar Dronamraju   tracing: Extract ...
32
  {									\
56de76305   Masami Hiramatsu   tracing: probeeve...
33
  	trace_seq_printf(s, fmt, *(type *)data);			\
d2b0191a3   Steven Rostedt (Red Hat)   tracing/probes: D...
34
  	return !trace_seq_has_overflowed(s);				\
8ab83f564   Srikar Dronamraju   tracing: Extract ...
35
  }									\
7bfbc63ed   Masami Hiramatsu   tracing: probeeve...
36
  const char PRINT_TYPE_FMT_NAME(tname)[] = fmt;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
37

bdca79c2b   Masami Hiramatsu   ftrace: kprobe: u...
38
39
40
41
  DEFINE_BASIC_PRINT_TYPE_FUNC(u8,  u8,  "%u")
  DEFINE_BASIC_PRINT_TYPE_FUNC(u16, u16, "%u")
  DEFINE_BASIC_PRINT_TYPE_FUNC(u32, u32, "%u")
  DEFINE_BASIC_PRINT_TYPE_FUNC(u64, u64, "%Lu")
17ce3dc7e   Masami Hiramatsu   ftrace: kprobe: u...
42
43
44
45
46
47
48
49
  DEFINE_BASIC_PRINT_TYPE_FUNC(s8,  s8,  "%d")
  DEFINE_BASIC_PRINT_TYPE_FUNC(s16, s16, "%d")
  DEFINE_BASIC_PRINT_TYPE_FUNC(s32, s32, "%d")
  DEFINE_BASIC_PRINT_TYPE_FUNC(s64, s64, "%Ld")
  DEFINE_BASIC_PRINT_TYPE_FUNC(x8,  u8,  "0x%x")
  DEFINE_BASIC_PRINT_TYPE_FUNC(x16, u16, "0x%x")
  DEFINE_BASIC_PRINT_TYPE_FUNC(x32, u32, "0x%x")
  DEFINE_BASIC_PRINT_TYPE_FUNC(x64, u64, "0x%Lx")
8ab83f564   Srikar Dronamraju   tracing: Extract ...
50

60c2e0ceb   Masami Hiramatsu   tracing: probeeve...
51
52
53
54
55
56
  int PRINT_TYPE_FUNC_NAME(symbol)(struct trace_seq *s, void *data, void *ent)
  {
  	trace_seq_printf(s, "%pS", (void *)*(unsigned long *)data);
  	return !trace_seq_has_overflowed(s);
  }
  const char PRINT_TYPE_FMT_NAME(symbol)[] = "%pS";
8ab83f564   Srikar Dronamraju   tracing: Extract ...
57
  /* Print type function for string type */
56de76305   Masami Hiramatsu   tracing: probeeve...
58
  int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, void *data, void *ent)
8ab83f564   Srikar Dronamraju   tracing: Extract ...
59
60
61
62
  {
  	int len = *(u32 *)data >> 16;
  
  	if (!len)
56de76305   Masami Hiramatsu   tracing: probeeve...
63
  		trace_seq_puts(s, "(fault)");
8ab83f564   Srikar Dronamraju   tracing: Extract ...
64
  	else
56de76305   Masami Hiramatsu   tracing: probeeve...
65
  		trace_seq_printf(s, "\"%s\"",
d2b0191a3   Steven Rostedt (Red Hat)   tracing/probes: D...
66
67
  				 (const char *)get_loc_data(data, ent));
  	return !trace_seq_has_overflowed(s);
8ab83f564   Srikar Dronamraju   tracing: Extract ...
68
  }
b26c74e11   Namhyung Kim   tracing/probes: M...
69
  const char PRINT_TYPE_FMT_NAME(string)[] = "\\\"%s\\\"";
8ab83f564   Srikar Dronamraju   tracing: Extract ...
70

f451bc89d   Masami Hiramatsu   tracing: probeeve...
71
72
73
74
75
  /* Fetch type information table */
  static const struct fetch_type probe_fetch_types[] = {
  	/* Special types */
  	__ASSIGN_FETCH_TYPE("string", string, string, sizeof(u32), 1,
  			    "__data_loc char[]"),
88903c464   Masami Hiramatsu   tracing/probe: Ad...
76
77
  	__ASSIGN_FETCH_TYPE("ustring", string, string, sizeof(u32), 1,
  			    "__data_loc char[]"),
f451bc89d   Masami Hiramatsu   tracing: probeeve...
78
79
80
81
82
83
84
85
86
87
88
89
90
  	/* Basic types */
  	ASSIGN_FETCH_TYPE(u8,  u8,  0),
  	ASSIGN_FETCH_TYPE(u16, u16, 0),
  	ASSIGN_FETCH_TYPE(u32, u32, 0),
  	ASSIGN_FETCH_TYPE(u64, u64, 0),
  	ASSIGN_FETCH_TYPE(s8,  u8,  1),
  	ASSIGN_FETCH_TYPE(s16, u16, 1),
  	ASSIGN_FETCH_TYPE(s32, u32, 1),
  	ASSIGN_FETCH_TYPE(s64, u64, 1),
  	ASSIGN_FETCH_TYPE_ALIAS(x8,  u8,  u8,  0),
  	ASSIGN_FETCH_TYPE_ALIAS(x16, u16, u16, 0),
  	ASSIGN_FETCH_TYPE_ALIAS(x32, u32, u32, 0),
  	ASSIGN_FETCH_TYPE_ALIAS(x64, u64, u64, 0),
60c2e0ceb   Masami Hiramatsu   tracing: probeeve...
91
  	ASSIGN_FETCH_TYPE_ALIAS(symbol, ADDR_FETCH_TYPE, ADDR_FETCH_TYPE, 0),
f451bc89d   Masami Hiramatsu   tracing: probeeve...
92
93
94
95
96
  
  	ASSIGN_FETCH_TYPE_END
  };
  
  static const struct fetch_type *find_fetch_type(const char *type)
8ab83f564   Srikar Dronamraju   tracing: Extract ...
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
  {
  	int i;
  
  	if (!type)
  		type = DEFAULT_FETCH_TYPE_STR;
  
  	/* Special case: bitfield */
  	if (*type == 'b') {
  		unsigned long bs;
  
  		type = strchr(type, '/');
  		if (!type)
  			goto fail;
  
  		type++;
bcd83ea6c   Daniel Walter   tracing: Replace ...
112
  		if (kstrtoul(type, 0, &bs))
8ab83f564   Srikar Dronamraju   tracing: Extract ...
113
114
115
116
  			goto fail;
  
  		switch (bs) {
  		case 8:
f451bc89d   Masami Hiramatsu   tracing: probeeve...
117
  			return find_fetch_type("u8");
8ab83f564   Srikar Dronamraju   tracing: Extract ...
118
  		case 16:
f451bc89d   Masami Hiramatsu   tracing: probeeve...
119
  			return find_fetch_type("u16");
8ab83f564   Srikar Dronamraju   tracing: Extract ...
120
  		case 32:
f451bc89d   Masami Hiramatsu   tracing: probeeve...
121
  			return find_fetch_type("u32");
8ab83f564   Srikar Dronamraju   tracing: Extract ...
122
  		case 64:
f451bc89d   Masami Hiramatsu   tracing: probeeve...
123
  			return find_fetch_type("u64");
8ab83f564   Srikar Dronamraju   tracing: Extract ...
124
125
126
127
  		default:
  			goto fail;
  		}
  	}
f451bc89d   Masami Hiramatsu   tracing: probeeve...
128
129
130
  	for (i = 0; probe_fetch_types[i].name; i++) {
  		if (strcmp(type, probe_fetch_types[i].name) == 0)
  			return &probe_fetch_types[i];
34fee3a10   Namhyung Kim   tracing/probes: S...
131
  	}
8ab83f564   Srikar Dronamraju   tracing: Extract ...
132
133
134
135
  
  fail:
  	return NULL;
  }
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  static struct trace_probe_log trace_probe_log;
  
  void trace_probe_log_init(const char *subsystem, int argc, const char **argv)
  {
  	trace_probe_log.subsystem = subsystem;
  	trace_probe_log.argc = argc;
  	trace_probe_log.argv = argv;
  	trace_probe_log.index = 0;
  }
  
  void trace_probe_log_clear(void)
  {
  	memset(&trace_probe_log, 0, sizeof(trace_probe_log));
  }
  
  void trace_probe_log_set_index(int index)
  {
  	trace_probe_log.index = index;
  }
  
  void __trace_probe_log_err(int offset, int err_type)
  {
  	char *command, *p;
  	int i, len = 0, pos = 0;
  
  	if (!trace_probe_log.argv)
  		return;
  
  	/* Recalcurate the length and allocate buffer */
  	for (i = 0; i < trace_probe_log.argc; i++) {
  		if (i == trace_probe_log.index)
  			pos = len;
  		len += strlen(trace_probe_log.argv[i]) + 1;
  	}
  	command = kzalloc(len, GFP_KERNEL);
  	if (!command)
  		return;
d2aea95a1   Masami Hiramatsu   tracing/probe: Fi...
173
174
175
176
177
178
179
180
181
  	if (trace_probe_log.index >= trace_probe_log.argc) {
  		/**
  		 * Set the error position is next to the last arg + space.
  		 * Note that len includes the terminal null and the cursor
  		 * appaers at pos + 1.
  		 */
  		pos = len;
  		offset = 0;
  	}
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
182
183
184
185
186
187
188
189
190
  	/* And make a command string from argv array */
  	p = command;
  	for (i = 0; i < trace_probe_log.argc; i++) {
  		len = strlen(trace_probe_log.argv[i]);
  		strcpy(p, trace_probe_log.argv[i]);
  		p[len] = ' ';
  		p += len + 1;
  	}
  	*(p - 1) = '\0';
2f754e771   Steven Rostedt (VMware)   tracing: Have the...
191
  	tracing_log_err(NULL, trace_probe_log.subsystem, command,
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
192
193
194
195
  			trace_probe_err_text, err_type, pos + offset);
  
  	kfree(command);
  }
8ab83f564   Srikar Dronamraju   tracing: Extract ...
196
  /* Split symbol and offset. */
c5d343b6b   Masami Hiramatsu   tracing: probeeve...
197
  int traceprobe_split_symbol_offset(char *symbol, long *offset)
8ab83f564   Srikar Dronamraju   tracing: Extract ...
198
199
200
201
202
203
  {
  	char *tmp;
  	int ret;
  
  	if (!offset)
  		return -EINVAL;
c5d343b6b   Masami Hiramatsu   tracing: probeeve...
204
  	tmp = strpbrk(symbol, "+-");
8ab83f564   Srikar Dronamraju   tracing: Extract ...
205
  	if (tmp) {
c5d343b6b   Masami Hiramatsu   tracing: probeeve...
206
  		ret = kstrtol(tmp, 0, offset);
8ab83f564   Srikar Dronamraju   tracing: Extract ...
207
208
  		if (ret)
  			return ret;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
209
210
211
212
213
214
  		*tmp = '\0';
  	} else
  		*offset = 0;
  
  	return 0;
  }
6212dd296   Masami Hiramatsu   tracing/kprobes: ...
215
216
  /* @buf must has MAX_EVENT_NAME_LEN size */
  int traceprobe_parse_event_name(const char **pevent, const char **pgroup,
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
217
  				char *buf, int offset)
6212dd296   Masami Hiramatsu   tracing/kprobes: ...
218
219
  {
  	const char *slash, *event = *pevent;
dec65d79f   Masami Hiramatsu   tracing/probe: Ch...
220
  	int len;
6212dd296   Masami Hiramatsu   tracing/kprobes: ...
221
222
223
224
  
  	slash = strchr(event, '/');
  	if (slash) {
  		if (slash == event) {
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
225
  			trace_probe_log_err(offset, NO_GROUP_NAME);
6212dd296   Masami Hiramatsu   tracing/kprobes: ...
226
227
228
  			return -EINVAL;
  		}
  		if (slash - event + 1 > MAX_EVENT_NAME_LEN) {
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
229
230
  			trace_probe_log_err(offset, GROUP_TOO_LONG);
  			return -EINVAL;
6212dd296   Masami Hiramatsu   tracing/kprobes: ...
231
232
  		}
  		strlcpy(buf, event, slash - event + 1);
5b7a96220   Masami Hiramatsu   tracing/probe: Ch...
233
  		if (!is_good_name(buf)) {
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
234
  			trace_probe_log_err(offset, BAD_GROUP_NAME);
5b7a96220   Masami Hiramatsu   tracing/probe: Ch...
235
236
  			return -EINVAL;
  		}
6212dd296   Masami Hiramatsu   tracing/kprobes: ...
237
238
  		*pgroup = buf;
  		*pevent = slash + 1;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
239
  		offset += slash - event + 1;
dec65d79f   Masami Hiramatsu   tracing/probe: Ch...
240
  		event = *pevent;
6212dd296   Masami Hiramatsu   tracing/kprobes: ...
241
  	}
dec65d79f   Masami Hiramatsu   tracing/probe: Ch...
242
243
  	len = strlen(event);
  	if (len == 0) {
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
244
  		trace_probe_log_err(offset, NO_EVENT_NAME);
6212dd296   Masami Hiramatsu   tracing/kprobes: ...
245
  		return -EINVAL;
dec65d79f   Masami Hiramatsu   tracing/probe: Ch...
246
  	} else if (len > MAX_EVENT_NAME_LEN) {
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
247
248
  		trace_probe_log_err(offset, EVENT_TOO_LONG);
  		return -EINVAL;
6212dd296   Masami Hiramatsu   tracing/kprobes: ...
249
  	}
5b7a96220   Masami Hiramatsu   tracing/probe: Ch...
250
  	if (!is_good_name(event)) {
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
251
  		trace_probe_log_err(offset, BAD_EVENT_NAME);
5b7a96220   Masami Hiramatsu   tracing/probe: Ch...
252
253
  		return -EINVAL;
  	}
6212dd296   Masami Hiramatsu   tracing/kprobes: ...
254
255
  	return 0;
  }
8ab83f564   Srikar Dronamraju   tracing: Extract ...
256
257
258
  #define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long))
  
  static int parse_probe_vars(char *arg, const struct fetch_type *t,
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
259
  			struct fetch_insn *code, unsigned int flags, int offs)
8ab83f564   Srikar Dronamraju   tracing: Extract ...
260
  {
8ab83f564   Srikar Dronamraju   tracing: Extract ...
261
  	unsigned long param;
3d739c1f6   Steven Rostedt (VMware)   tracing: Use the ...
262
263
  	int ret = 0;
  	int len;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
264
265
  
  	if (strcmp(arg, "retval") == 0) {
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
266
  		if (flags & TPARG_FL_RETURN) {
533059281   Masami Hiramatsu   tracing: probeeve...
267
  			code->op = FETCH_OP_RETVAL;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
268
269
  		} else {
  			trace_probe_log_err(offs, RETVAL_ON_PROBE);
8ab83f564   Srikar Dronamraju   tracing: Extract ...
270
  			ret = -EINVAL;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
271
  		}
3d739c1f6   Steven Rostedt (VMware)   tracing: Use the ...
272
273
  	} else if ((len = str_has_prefix(arg, "stack"))) {
  		if (arg[len] == '\0') {
533059281   Masami Hiramatsu   tracing: probeeve...
274
  			code->op = FETCH_OP_STACKP;
3d739c1f6   Steven Rostedt (VMware)   tracing: Use the ...
275
276
  		} else if (isdigit(arg[len])) {
  			ret = kstrtoul(arg + len, 10, &param);
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
277
278
279
280
281
  			if (ret) {
  				goto inval_var;
  			} else if ((flags & TPARG_FL_KERNEL) &&
  				    param > PARAM_MAX_STACK) {
  				trace_probe_log_err(offs, BAD_STACK_NUM);
8ab83f564   Srikar Dronamraju   tracing: Extract ...
282
  				ret = -EINVAL;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
283
  			} else {
533059281   Masami Hiramatsu   tracing: probeeve...
284
285
  				code->op = FETCH_OP_STACK;
  				code->param = (unsigned int)param;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
286
287
  			}
  		} else
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
288
  			goto inval_var;
35abb67de   Omar Sandoval   tracing: expose c...
289
  	} else if (strcmp(arg, "comm") == 0) {
533059281   Masami Hiramatsu   tracing: probeeve...
290
  		code->op = FETCH_OP_COMM;
a1303af5d   Masami Hiramatsu   tracing: probeeve...
291
292
293
  #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
  	} else if (((flags & TPARG_FL_MASK) ==
  		    (TPARG_FL_KERNEL | TPARG_FL_FENTRY)) &&
3d739c1f6   Steven Rostedt (VMware)   tracing: Use the ...
294
  		   (len = str_has_prefix(arg, "arg"))) {
3d739c1f6   Steven Rostedt (VMware)   tracing: Use the ...
295
  		ret = kstrtoul(arg + len, 10, &param);
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
296
297
298
299
  		if (ret) {
  			goto inval_var;
  		} else if (!param || param > PARAM_MAX_STACK) {
  			trace_probe_log_err(offs, BAD_ARG_NUM);
a1303af5d   Masami Hiramatsu   tracing: probeeve...
300
  			return -EINVAL;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
301
  		}
a1303af5d   Masami Hiramatsu   tracing: probeeve...
302
303
304
  		code->op = FETCH_OP_ARG;
  		code->param = (unsigned int)param - 1;
  #endif
8ab83f564   Srikar Dronamraju   tracing: Extract ...
305
  	} else
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
306
  		goto inval_var;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
307
308
  
  	return ret;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
309
310
311
312
  
  inval_var:
  	trace_probe_log_err(offs, BAD_VAR);
  	return -EINVAL;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
313
  }
6218bf9f4   Masami Hiramatsu   tracing/probe: Ad...
314
315
316
317
318
319
320
321
322
323
  static int str_to_immediate(char *str, unsigned long *imm)
  {
  	if (isdigit(str[0]))
  		return kstrtoul(str, 0, imm);
  	else if (str[0] == '-')
  		return kstrtol(str, 0, (long *)imm);
  	else if (str[0] == '+')
  		return kstrtol(str + 1, 0, (long *)imm);
  	return -EINVAL;
  }
a42e3c4de   Masami Hiramatsu   tracing/probe: Ad...
324
325
326
327
328
329
330
331
332
333
334
  static int __parse_imm_string(char *str, char **pbuf, int offs)
  {
  	size_t len = strlen(str);
  
  	if (str[len - 1] != '"') {
  		trace_probe_log_err(offs + len, IMMSTR_NO_CLOSE);
  		return -EINVAL;
  	}
  	*pbuf = kstrndup(str, len - 1, GFP_KERNEL);
  	return 0;
  }
8ab83f564   Srikar Dronamraju   tracing: Extract ...
335
  /* Recursive argument parser */
533059281   Masami Hiramatsu   tracing: probeeve...
336
337
338
  static int
  parse_probe_arg(char *arg, const struct fetch_type *type,
  		struct fetch_insn **pcode, struct fetch_insn *end,
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
339
  		unsigned int flags, int offs)
8ab83f564   Srikar Dronamraju   tracing: Extract ...
340
  {
533059281   Masami Hiramatsu   tracing: probeeve...
341
  	struct fetch_insn *code = *pcode;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
342
  	unsigned long param;
e65f7ae7f   Masami Hiramatsu   tracing/probe: Su...
343
  	int deref = FETCH_OP_DEREF;
bf173ca92   Steven Rostedt (VMware)   tracing: probeeve...
344
  	long offset = 0;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
345
  	char *tmp;
34fee3a10   Namhyung Kim   tracing/probes: S...
346
  	int ret = 0;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
347

8ab83f564   Srikar Dronamraju   tracing: Extract ...
348
349
  	switch (arg[0]) {
  	case '$':
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
350
  		ret = parse_probe_vars(arg + 1, type, code, flags, offs);
8ab83f564   Srikar Dronamraju   tracing: Extract ...
351
352
353
354
355
  		break;
  
  	case '%':	/* named register */
  		ret = regs_query_register_offset(arg + 1);
  		if (ret >= 0) {
533059281   Masami Hiramatsu   tracing: probeeve...
356
357
  			code->op = FETCH_OP_REG;
  			code->param = (unsigned int)ret;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
358
  			ret = 0;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
359
360
  		} else
  			trace_probe_log_err(offs, BAD_REG_NAME);
8ab83f564   Srikar Dronamraju   tracing: Extract ...
361
  		break;
b7e0bf341   Namhyung Kim   tracing/uprobes: ...
362
  	case '@':	/* memory, file-offset or symbol */
8ab83f564   Srikar Dronamraju   tracing: Extract ...
363
  		if (isdigit(arg[1])) {
bcd83ea6c   Daniel Walter   tracing: Replace ...
364
  			ret = kstrtoul(arg + 1, 0, &param);
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
365
366
  			if (ret) {
  				trace_probe_log_err(offs, BAD_MEM_ADDR);
8ab83f564   Srikar Dronamraju   tracing: Extract ...
367
  				break;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
368
  			}
533059281   Masami Hiramatsu   tracing: probeeve...
369
370
371
  			/* load address */
  			code->op = FETCH_OP_IMM;
  			code->immediate = param;
b7e0bf341   Namhyung Kim   tracing/uprobes: ...
372
373
  		} else if (arg[1] == '+') {
  			/* kprobes don't support file offsets */
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
374
375
  			if (flags & TPARG_FL_KERNEL) {
  				trace_probe_log_err(offs, FILE_ON_KPROBE);
b7e0bf341   Namhyung Kim   tracing/uprobes: ...
376
  				return -EINVAL;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
377
  			}
b7e0bf341   Namhyung Kim   tracing/uprobes: ...
378
  			ret = kstrtol(arg + 2, 0, &offset);
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
379
380
  			if (ret) {
  				trace_probe_log_err(offs, BAD_FILE_OFFS);
b7e0bf341   Namhyung Kim   tracing/uprobes: ...
381
  				break;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
382
  			}
b7e0bf341   Namhyung Kim   tracing/uprobes: ...
383

533059281   Masami Hiramatsu   tracing: probeeve...
384
385
  			code->op = FETCH_OP_FOFFS;
  			code->immediate = (unsigned long)offset;  // imm64?
8ab83f564   Srikar Dronamraju   tracing: Extract ...
386
  		} else {
b079d374f   Namhyung Kim   tracing/uprobes: ...
387
  			/* uprobes don't support symbols */
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
388
389
  			if (!(flags & TPARG_FL_KERNEL)) {
  				trace_probe_log_err(offs, SYM_ON_UPROBE);
b079d374f   Namhyung Kim   tracing/uprobes: ...
390
  				return -EINVAL;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
391
  			}
a6682814f   Masami Hiramatsu   tracing/kprobes: ...
392
393
394
395
396
  			/* Preserve symbol for updating */
  			code->op = FETCH_NOP_SYMBOL;
  			code->data = kstrdup(arg + 1, GFP_KERNEL);
  			if (!code->data)
  				return -ENOMEM;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
397
398
399
400
  			if (++code == end) {
  				trace_probe_log_err(offs, TOO_MANY_OPS);
  				return -EINVAL;
  			}
533059281   Masami Hiramatsu   tracing: probeeve...
401
  			code->op = FETCH_OP_IMM;
a6682814f   Masami Hiramatsu   tracing/kprobes: ...
402
  			code->immediate = 0;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
403
  		}
533059281   Masami Hiramatsu   tracing: probeeve...
404
  		/* These are fetching from memory */
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
405
406
407
408
  		if (++code == end) {
  			trace_probe_log_err(offs, TOO_MANY_OPS);
  			return -EINVAL;
  		}
533059281   Masami Hiramatsu   tracing: probeeve...
409
410
411
  		*pcode = code;
  		code->op = FETCH_OP_DEREF;
  		code->offset = offset;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
412
413
414
  		break;
  
  	case '+':	/* deref memory */
8ab83f564   Srikar Dronamraju   tracing: Extract ...
415
  	case '-':
e65f7ae7f   Masami Hiramatsu   tracing/probe: Su...
416
417
418
419
420
421
422
  		if (arg[1] == 'u') {
  			deref = FETCH_OP_UDEREF;
  			arg[1] = arg[0];
  			arg++;
  		}
  		if (arg[0] == '+')
  			arg++;	/* Skip '+', because kstrtol() rejects it. */
8ab83f564   Srikar Dronamraju   tracing: Extract ...
423
  		tmp = strchr(arg, '(');
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
424
425
  		if (!tmp) {
  			trace_probe_log_err(offs, DEREF_NEED_BRACE);
533059281   Masami Hiramatsu   tracing: probeeve...
426
  			return -EINVAL;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
427
  		}
8ab83f564   Srikar Dronamraju   tracing: Extract ...
428
  		*tmp = '\0';
bcd83ea6c   Daniel Walter   tracing: Replace ...
429
  		ret = kstrtol(arg, 0, &offset);
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
430
431
  		if (ret) {
  			trace_probe_log_err(offs, BAD_DEREF_OFFS);
8ab83f564   Srikar Dronamraju   tracing: Extract ...
432
  			break;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
433
434
  		}
  		offs += (tmp + 1 - arg) + (arg[0] != '-' ? 1 : 0);
8ab83f564   Srikar Dronamraju   tracing: Extract ...
435
436
  		arg = tmp + 1;
  		tmp = strrchr(arg, ')');
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
437
438
439
440
441
  		if (!tmp) {
  			trace_probe_log_err(offs + strlen(arg),
  					    DEREF_OPEN_BRACE);
  			return -EINVAL;
  		} else {
f451bc89d   Masami Hiramatsu   tracing: probeeve...
442
  			const struct fetch_type *t2 = find_fetch_type(NULL);
8ab83f564   Srikar Dronamraju   tracing: Extract ...
443

8ab83f564   Srikar Dronamraju   tracing: Extract ...
444
  			*tmp = '\0';
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
445
  			ret = parse_probe_arg(arg, t2, &code, end, flags, offs);
8ab83f564   Srikar Dronamraju   tracing: Extract ...
446
  			if (ret)
533059281   Masami Hiramatsu   tracing: probeeve...
447
  				break;
a42e3c4de   Masami Hiramatsu   tracing/probe: Ad...
448
449
  			if (code->op == FETCH_OP_COMM ||
  			    code->op == FETCH_OP_DATA) {
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
450
451
452
453
454
  				trace_probe_log_err(offs, COMM_CANT_DEREF);
  				return -EINVAL;
  			}
  			if (++code == end) {
  				trace_probe_log_err(offs, TOO_MANY_OPS);
533059281   Masami Hiramatsu   tracing: probeeve...
455
  				return -EINVAL;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
456
  			}
533059281   Masami Hiramatsu   tracing: probeeve...
457
  			*pcode = code;
e65f7ae7f   Masami Hiramatsu   tracing/probe: Su...
458
  			code->op = deref;
533059281   Masami Hiramatsu   tracing: probeeve...
459
  			code->offset = offset;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
460
461
  		}
  		break;
6218bf9f4   Masami Hiramatsu   tracing/probe: Ad...
462
  	case '\\':	/* Immediate value */
a42e3c4de   Masami Hiramatsu   tracing/probe: Ad...
463
464
465
466
467
468
469
470
471
472
473
474
475
  		if (arg[1] == '"') {	/* Immediate string */
  			ret = __parse_imm_string(arg + 2, &tmp, offs + 2);
  			if (ret)
  				break;
  			code->op = FETCH_OP_DATA;
  			code->data = tmp;
  		} else {
  			ret = str_to_immediate(arg + 1, &code->immediate);
  			if (ret)
  				trace_probe_log_err(offs + 1, BAD_IMM);
  			else
  				code->op = FETCH_OP_IMM;
  		}
6218bf9f4   Masami Hiramatsu   tracing/probe: Ad...
476
  		break;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
477
  	}
533059281   Masami Hiramatsu   tracing: probeeve...
478
479
  	if (!ret && code->op == FETCH_OP_NOP) {
  		/* Parsed, but do not find fetch method */
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
480
  		trace_probe_log_err(offs, BAD_FETCH_ARG);
8ab83f564   Srikar Dronamraju   tracing: Extract ...
481
482
  		ret = -EINVAL;
  	}
8ab83f564   Srikar Dronamraju   tracing: Extract ...
483
484
485
486
487
488
489
490
  	return ret;
  }
  
  #define BYTES_TO_BITS(nb)	((BITS_PER_LONG * (nb)) / sizeof(long))
  
  /* Bitfield type needs to be parsed into a fetch function */
  static int __parse_bitfield_probe_arg(const char *bf,
  				      const struct fetch_type *t,
533059281   Masami Hiramatsu   tracing: probeeve...
491
  				      struct fetch_insn **pcode)
8ab83f564   Srikar Dronamraju   tracing: Extract ...
492
  {
533059281   Masami Hiramatsu   tracing: probeeve...
493
  	struct fetch_insn *code = *pcode;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
494
495
496
497
498
  	unsigned long bw, bo;
  	char *tail;
  
  	if (*bf != 'b')
  		return 0;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
499
500
501
502
503
504
505
506
507
508
  	bw = simple_strtoul(bf + 1, &tail, 0);	/* Use simple one */
  
  	if (bw == 0 || *tail != '@')
  		return -EINVAL;
  
  	bf = tail + 1;
  	bo = simple_strtoul(bf, &tail, 0);
  
  	if (tail == bf || *tail != '/')
  		return -EINVAL;
533059281   Masami Hiramatsu   tracing: probeeve...
509
510
  	code++;
  	if (code->op != FETCH_OP_NOP)
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
511
  		return -EINVAL;
533059281   Masami Hiramatsu   tracing: probeeve...
512
  	*pcode = code;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
513

533059281   Masami Hiramatsu   tracing: probeeve...
514
515
516
517
  	code->op = FETCH_OP_MOD_BF;
  	code->lshift = BYTES_TO_BITS(t->size) - (bw + bo);
  	code->rshift = BYTES_TO_BITS(t->size) - bw;
  	code->basesize = t->size;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
518
519
520
521
522
  
  	return (BYTES_TO_BITS(t->size) < (bw + bo)) ? -EINVAL : 0;
  }
  
  /* String length checking wrapper */
d00bbea94   Masami Hiramatsu   tracing: Integrat...
523
  static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size,
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
524
  		struct probe_arg *parg, unsigned int flags, int offset)
8ab83f564   Srikar Dronamraju   tracing: Extract ...
525
  {
40b53b771   Masami Hiramatsu   tracing: probeeve...
526
  	struct fetch_insn *code, *scode, *tmp = NULL;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
527
  	char *t, *t2, *t3;
40b53b771   Masami Hiramatsu   tracing: probeeve...
528
  	int ret, len;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
529

ab105a4fb   Masami Hiramatsu   tracing: Use trac...
530
531
532
533
534
535
536
  	len = strlen(arg);
  	if (len > MAX_ARGSTR_LEN) {
  		trace_probe_log_err(offset, ARG_TOO_LONG);
  		return -EINVAL;
  	} else if (len == 0) {
  		trace_probe_log_err(offset, NO_ARG_BODY);
  		return -EINVAL;
8ab83f564   Srikar Dronamraju   tracing: Extract ...
537
  	}
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
538

8ab83f564   Srikar Dronamraju   tracing: Extract ...
539
  	parg->comm = kstrdup(arg, GFP_KERNEL);
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
540
  	if (!parg->comm)
8ab83f564   Srikar Dronamraju   tracing: Extract ...
541
  		return -ENOMEM;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
542

40b53b771   Masami Hiramatsu   tracing: probeeve...
543
  	t = strchr(arg, ':');
8ab83f564   Srikar Dronamraju   tracing: Extract ...
544
  	if (t) {
40b53b771   Masami Hiramatsu   tracing: probeeve...
545
546
547
  		*t = '\0';
  		t2 = strchr(++t, '[');
  		if (t2) {
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
  			*t2++ = '\0';
  			t3 = strchr(t2, ']');
  			if (!t3) {
  				offset += t2 + strlen(t2) - arg;
  				trace_probe_log_err(offset,
  						    ARRAY_NO_CLOSE);
  				return -EINVAL;
  			} else if (t3[1] != '\0') {
  				trace_probe_log_err(offset + t3 + 1 - arg,
  						    BAD_ARRAY_SUFFIX);
  				return -EINVAL;
  			}
  			*t3 = '\0';
  			if (kstrtouint(t2, 0, &parg->count) || !parg->count) {
  				trace_probe_log_err(offset + t2 - arg,
  						    BAD_ARRAY_NUM);
40b53b771   Masami Hiramatsu   tracing: probeeve...
564
  				return -EINVAL;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
565
566
567
568
569
570
  			}
  			if (parg->count > MAX_ARRAY_LEN) {
  				trace_probe_log_err(offset + t2 - arg,
  						    ARRAY_TOO_BIG);
  				return -EINVAL;
  			}
40b53b771   Masami Hiramatsu   tracing: probeeve...
571
  		}
8ab83f564   Srikar Dronamraju   tracing: Extract ...
572
  	}
3dd1f7f24   Masami Hiramatsu   tracing: probeeve...
573

a42e3c4de   Masami Hiramatsu   tracing/probe: Ad...
574
575
576
577
578
  	/*
  	 * Since $comm and immediate string can not be dereferred,
  	 * we can find those by strcmp.
  	 */
  	if (strcmp(arg, "$comm") == 0 || strncmp(arg, "\\\"", 2) == 0) {
3dd1f7f24   Masami Hiramatsu   tracing: probeeve...
579
580
581
  		/* The type of $comm must be "string", and not an array. */
  		if (parg->count || (t && strcmp(t, "string")))
  			return -EINVAL;
40b53b771   Masami Hiramatsu   tracing: probeeve...
582
  		parg->type = find_fetch_type("string");
3dd1f7f24   Masami Hiramatsu   tracing: probeeve...
583
  	} else
40b53b771   Masami Hiramatsu   tracing: probeeve...
584
  		parg->type = find_fetch_type(t);
8ab83f564   Srikar Dronamraju   tracing: Extract ...
585
  	if (!parg->type) {
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
586
  		trace_probe_log_err(offset + (t ? (t - arg) : 0), BAD_TYPE);
8ab83f564   Srikar Dronamraju   tracing: Extract ...
587
588
589
  		return -EINVAL;
  	}
  	parg->offset = *size;
40b53b771   Masami Hiramatsu   tracing: probeeve...
590
591
592
593
594
595
596
597
598
599
  	*size += parg->type->size * (parg->count ?: 1);
  
  	if (parg->count) {
  		len = strlen(parg->type->fmttype) + 6;
  		parg->fmt = kmalloc(len, GFP_KERNEL);
  		if (!parg->fmt)
  			return -ENOMEM;
  		snprintf(parg->fmt, len, "%s[%d]", parg->type->fmttype,
  			 parg->count);
  	}
8ab83f564   Srikar Dronamraju   tracing: Extract ...
600

8623b0067   Gustavo A. R. Silva   tracing: Replace ...
601
  	code = tmp = kcalloc(FETCH_INSN_MAX, sizeof(*code), GFP_KERNEL);
533059281   Masami Hiramatsu   tracing: probeeve...
602
603
604
605
606
  	if (!code)
  		return -ENOMEM;
  	code[FETCH_INSN_MAX - 1].op = FETCH_OP_END;
  
  	ret = parse_probe_arg(arg, parg->type, &code, &code[FETCH_INSN_MAX - 1],
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
607
  			      flags, offset);
533059281   Masami Hiramatsu   tracing: probeeve...
608
609
610
611
  	if (ret)
  		goto fail;
  
  	/* Store operation */
88903c464   Masami Hiramatsu   tracing/probe: Ad...
612
613
  	if (!strcmp(parg->type->name, "string") ||
  	    !strcmp(parg->type->name, "ustring")) {
e65f7ae7f   Masami Hiramatsu   tracing/probe: Su...
614
  		if (code->op != FETCH_OP_DEREF && code->op != FETCH_OP_UDEREF &&
a42e3c4de   Masami Hiramatsu   tracing/probe: Ad...
615
616
  		    code->op != FETCH_OP_IMM && code->op != FETCH_OP_COMM &&
  		    code->op != FETCH_OP_DATA) {
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
617
618
  			trace_probe_log_err(offset + (t ? (t - arg) : 0),
  					    BAD_STRING);
533059281   Masami Hiramatsu   tracing: probeeve...
619
620
621
  			ret = -EINVAL;
  			goto fail;
  		}
3aa8fdc37   Vamshi K Sthambamkadi   tracing/probe: Fi...
622
623
  		if ((code->op == FETCH_OP_IMM || code->op == FETCH_OP_COMM ||
  		     code->op == FETCH_OP_DATA) || parg->count) {
40b53b771   Masami Hiramatsu   tracing: probeeve...
624
  			/*
a42e3c4de   Masami Hiramatsu   tracing/probe: Ad...
625
626
627
628
  			 * IMM, DATA and COMM is pointing actual address, those
  			 * must be kept, and if parg->count != 0, this is an
  			 * array of string pointers instead of string address
  			 * itself.
40b53b771   Masami Hiramatsu   tracing: probeeve...
629
  			 */
533059281   Masami Hiramatsu   tracing: probeeve...
630
  			code++;
40b53b771   Masami Hiramatsu   tracing: probeeve...
631
  			if (code->op != FETCH_OP_NOP) {
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
632
633
  				trace_probe_log_err(offset, TOO_MANY_OPS);
  				ret = -EINVAL;
40b53b771   Masami Hiramatsu   tracing: probeeve...
634
635
636
  				goto fail;
  			}
  		}
88903c464   Masami Hiramatsu   tracing/probe: Ad...
637
  		/* If op == DEREF, replace it with STRING */
e65f7ae7f   Masami Hiramatsu   tracing/probe: Su...
638
639
  		if (!strcmp(parg->type->name, "ustring") ||
  		    code->op == FETCH_OP_UDEREF)
88903c464   Masami Hiramatsu   tracing/probe: Ad...
640
641
642
  			code->op = FETCH_OP_ST_USTRING;
  		else
  			code->op = FETCH_OP_ST_STRING;
40b53b771   Masami Hiramatsu   tracing: probeeve...
643
  		code->size = parg->type->size;
533059281   Masami Hiramatsu   tracing: probeeve...
644
645
646
647
  		parg->dynamic = true;
  	} else if (code->op == FETCH_OP_DEREF) {
  		code->op = FETCH_OP_ST_MEM;
  		code->size = parg->type->size;
e65f7ae7f   Masami Hiramatsu   tracing/probe: Su...
648
649
650
  	} else if (code->op == FETCH_OP_UDEREF) {
  		code->op = FETCH_OP_ST_UMEM;
  		code->size = parg->type->size;
533059281   Masami Hiramatsu   tracing: probeeve...
651
652
653
  	} else {
  		code++;
  		if (code->op != FETCH_OP_NOP) {
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
654
655
  			trace_probe_log_err(offset, TOO_MANY_OPS);
  			ret = -EINVAL;
533059281   Masami Hiramatsu   tracing: probeeve...
656
657
658
659
660
  			goto fail;
  		}
  		code->op = FETCH_OP_ST_RAW;
  		code->size = parg->type->size;
  	}
40b53b771   Masami Hiramatsu   tracing: probeeve...
661
  	scode = code;
533059281   Masami Hiramatsu   tracing: probeeve...
662
663
664
  	/* Modify operation */
  	if (t != NULL) {
  		ret = __parse_bitfield_probe_arg(t, parg->type, &code);
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
665
666
  		if (ret) {
  			trace_probe_log_err(offset + t - arg, BAD_BITFIELD);
533059281   Masami Hiramatsu   tracing: probeeve...
667
  			goto fail;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
668
  		}
8ab83f564   Srikar Dronamraju   tracing: Extract ...
669
  	}
40b53b771   Masami Hiramatsu   tracing: probeeve...
670
671
672
  	/* Loop(Array) operation */
  	if (parg->count) {
  		if (scode->op != FETCH_OP_ST_MEM &&
88903c464   Masami Hiramatsu   tracing/probe: Ad...
673
674
  		    scode->op != FETCH_OP_ST_STRING &&
  		    scode->op != FETCH_OP_ST_USTRING) {
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
675
676
  			trace_probe_log_err(offset + (t ? (t - arg) : 0),
  					    BAD_STRING);
40b53b771   Masami Hiramatsu   tracing: probeeve...
677
678
679
680
681
  			ret = -EINVAL;
  			goto fail;
  		}
  		code++;
  		if (code->op != FETCH_OP_NOP) {
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
682
683
  			trace_probe_log_err(offset, TOO_MANY_OPS);
  			ret = -EINVAL;
40b53b771   Masami Hiramatsu   tracing: probeeve...
684
685
686
687
688
  			goto fail;
  		}
  		code->op = FETCH_OP_LP_ARRAY;
  		code->param = parg->count;
  	}
533059281   Masami Hiramatsu   tracing: probeeve...
689
690
691
692
  	code++;
  	code->op = FETCH_OP_END;
  
  	/* Shrink down the code buffer */
8623b0067   Gustavo A. R. Silva   tracing: Replace ...
693
  	parg->code = kcalloc(code - tmp + 1, sizeof(*code), GFP_KERNEL);
533059281   Masami Hiramatsu   tracing: probeeve...
694
695
696
697
698
699
  	if (!parg->code)
  		ret = -ENOMEM;
  	else
  		memcpy(parg->code, tmp, sizeof(*code) * (code - tmp + 1));
  
  fail:
a6682814f   Masami Hiramatsu   tracing/kprobes: ...
700
701
  	if (ret) {
  		for (code = tmp; code < tmp + FETCH_INSN_MAX; code++)
a42e3c4de   Masami Hiramatsu   tracing/probe: Ad...
702
703
  			if (code->op == FETCH_NOP_SYMBOL ||
  			    code->op == FETCH_OP_DATA)
a6682814f   Masami Hiramatsu   tracing/kprobes: ...
704
705
  				kfree(code->data);
  	}
533059281   Masami Hiramatsu   tracing: probeeve...
706
  	kfree(tmp);
8ab83f564   Srikar Dronamraju   tracing: Extract ...
707
708
709
710
711
  
  	return ret;
  }
  
  /* Return 1 if name is reserved or already used by another argument */
d00bbea94   Masami Hiramatsu   tracing: Integrat...
712
713
  static int traceprobe_conflict_field_name(const char *name,
  					  struct probe_arg *args, int narg)
8ab83f564   Srikar Dronamraju   tracing: Extract ...
714
715
716
717
718
719
720
721
722
723
724
725
726
  {
  	int i;
  
  	for (i = 0; i < ARRAY_SIZE(reserved_field_names); i++)
  		if (strcmp(reserved_field_names[i], name) == 0)
  			return 1;
  
  	for (i = 0; i < narg; i++)
  		if (strcmp(args[i].name, name) == 0)
  			return 1;
  
  	return 0;
  }
d00bbea94   Masami Hiramatsu   tracing: Integrat...
727
728
729
730
731
  int traceprobe_parse_probe_arg(struct trace_probe *tp, int i, char *arg,
  				unsigned int flags)
  {
  	struct probe_arg *parg = &tp->args[i];
  	char *body;
d00bbea94   Masami Hiramatsu   tracing: Integrat...
732
733
734
735
736
737
  
  	/* Increment count for freeing args in error case */
  	tp->nr_args++;
  
  	body = strchr(arg, '=');
  	if (body) {
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
738
739
740
741
742
  		if (body - arg > MAX_ARG_NAME_LEN) {
  			trace_probe_log_err(0, ARG_NAME_TOO_LONG);
  			return -EINVAL;
  		} else if (body == arg) {
  			trace_probe_log_err(0, NO_ARG_NAME);
b4443c17a   Masami Hiramatsu   tracing/probe: Ch...
743
  			return -EINVAL;
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
744
  		}
d00bbea94   Masami Hiramatsu   tracing: Integrat...
745
746
747
748
749
750
751
752
753
754
755
  		parg->name = kmemdup_nul(arg, body - arg, GFP_KERNEL);
  		body++;
  	} else {
  		/* If argument name is omitted, set "argN" */
  		parg->name = kasprintf(GFP_KERNEL, "arg%d", i + 1);
  		body = arg;
  	}
  	if (!parg->name)
  		return -ENOMEM;
  
  	if (!is_good_name(parg->name)) {
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
756
  		trace_probe_log_err(0, BAD_ARG_NAME);
d00bbea94   Masami Hiramatsu   tracing: Integrat...
757
758
  		return -EINVAL;
  	}
d00bbea94   Masami Hiramatsu   tracing: Integrat...
759
  	if (traceprobe_conflict_field_name(parg->name, tp->args, i)) {
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
760
  		trace_probe_log_err(0, USED_ARG_NAME);
d00bbea94   Masami Hiramatsu   tracing: Integrat...
761
762
  		return -EINVAL;
  	}
d00bbea94   Masami Hiramatsu   tracing: Integrat...
763
  	/* Parse fetch argument */
ab105a4fb   Masami Hiramatsu   tracing: Use trac...
764
765
  	return traceprobe_parse_probe_arg_body(body, &tp->size, parg, flags,
  					       body - arg);
d00bbea94   Masami Hiramatsu   tracing: Integrat...
766
  }
8ab83f564   Srikar Dronamraju   tracing: Extract ...
767
768
  void traceprobe_free_probe_arg(struct probe_arg *arg)
  {
a6682814f   Masami Hiramatsu   tracing/kprobes: ...
769
770
771
  	struct fetch_insn *code = arg->code;
  
  	while (code && code->op != FETCH_OP_END) {
a42e3c4de   Masami Hiramatsu   tracing/probe: Ad...
772
773
  		if (code->op == FETCH_NOP_SYMBOL ||
  		    code->op == FETCH_OP_DATA)
a6682814f   Masami Hiramatsu   tracing/kprobes: ...
774
775
776
  			kfree(code->data);
  		code++;
  	}
533059281   Masami Hiramatsu   tracing: probeeve...
777
  	kfree(arg->code);
8ab83f564   Srikar Dronamraju   tracing: Extract ...
778
779
  	kfree(arg->name);
  	kfree(arg->comm);
40b53b771   Masami Hiramatsu   tracing: probeeve...
780
  	kfree(arg->fmt);
8ab83f564   Srikar Dronamraju   tracing: Extract ...
781
  }
a6682814f   Masami Hiramatsu   tracing/kprobes: ...
782
783
784
785
786
787
788
789
790
791
792
793
  int traceprobe_update_arg(struct probe_arg *arg)
  {
  	struct fetch_insn *code = arg->code;
  	long offset;
  	char *tmp;
  	char c;
  	int ret = 0;
  
  	while (code && code->op != FETCH_OP_END) {
  		if (code->op == FETCH_NOP_SYMBOL) {
  			if (code[1].op != FETCH_OP_IMM)
  				return -EINVAL;
ee474b81f   Masami Hiramatsu   tracing/kprobes: ...
794
  			tmp = strpbrk(code->data, "+-");
a6682814f   Masami Hiramatsu   tracing/kprobes: ...
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
  			if (tmp)
  				c = *tmp;
  			ret = traceprobe_split_symbol_offset(code->data,
  							     &offset);
  			if (ret)
  				return ret;
  
  			code[1].immediate =
  				(unsigned long)kallsyms_lookup_name(code->data);
  			if (tmp)
  				*tmp = c;
  			if (!code[1].immediate)
  				return -ENOENT;
  			code[1].immediate += offset;
  		}
  		code++;
  	}
  	return 0;
  }
40b53b771   Masami Hiramatsu   tracing: probeeve...
814
815
  /* When len=0, we just calculate the needed length */
  #define LEN_OR_ZERO (len ? len - pos : 0)
5bf652aaf   Namhyung Kim   tracing/probes: I...
816
817
818
  static int __set_print_fmt(struct trace_probe *tp, char *buf, int len,
  			   bool is_return)
  {
40b53b771   Masami Hiramatsu   tracing: probeeve...
819
820
  	struct probe_arg *parg;
  	int i, j;
5bf652aaf   Namhyung Kim   tracing/probes: I...
821
  	int pos = 0;
5bf652aaf   Namhyung Kim   tracing/probes: I...
822
823
824
825
826
827
828
829
830
  	const char *fmt, *arg;
  
  	if (!is_return) {
  		fmt = "(%lx)";
  		arg = "REC->" FIELD_STRING_IP;
  	} else {
  		fmt = "(%lx <- %lx)";
  		arg = "REC->" FIELD_STRING_FUNC ", REC->" FIELD_STRING_RETIP;
  	}
5bf652aaf   Namhyung Kim   tracing/probes: I...
831
832
833
  	pos += snprintf(buf + pos, LEN_OR_ZERO, "\"%s", fmt);
  
  	for (i = 0; i < tp->nr_args; i++) {
40b53b771   Masami Hiramatsu   tracing: probeeve...
834
835
836
837
838
839
840
841
842
843
844
845
  		parg = tp->args + i;
  		pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=", parg->name);
  		if (parg->count) {
  			pos += snprintf(buf + pos, LEN_OR_ZERO, "{%s",
  					parg->type->fmt);
  			for (j = 1; j < parg->count; j++)
  				pos += snprintf(buf + pos, LEN_OR_ZERO, ",%s",
  						parg->type->fmt);
  			pos += snprintf(buf + pos, LEN_OR_ZERO, "}");
  		} else
  			pos += snprintf(buf + pos, LEN_OR_ZERO, "%s",
  					parg->type->fmt);
5bf652aaf   Namhyung Kim   tracing/probes: I...
846
847
848
849
850
  	}
  
  	pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg);
  
  	for (i = 0; i < tp->nr_args; i++) {
40b53b771   Masami Hiramatsu   tracing: probeeve...
851
852
  		parg = tp->args + i;
  		if (parg->count) {
20279420a   Steven Rostedt (VMware)   tracing/kprobes: ...
853
854
  			if ((strcmp(parg->type->name, "string") == 0) ||
  			    (strcmp(parg->type->name, "ustring") == 0))
40b53b771   Masami Hiramatsu   tracing: probeeve...
855
856
857
858
859
860
861
  				fmt = ", __get_str(%s[%d])";
  			else
  				fmt = ", REC->%s[%d]";
  			for (j = 0; j < parg->count; j++)
  				pos += snprintf(buf + pos, LEN_OR_ZERO,
  						fmt, parg->name, j);
  		} else {
20279420a   Steven Rostedt (VMware)   tracing/kprobes: ...
862
863
  			if ((strcmp(parg->type->name, "string") == 0) ||
  			    (strcmp(parg->type->name, "ustring") == 0))
40b53b771   Masami Hiramatsu   tracing: probeeve...
864
865
866
  				fmt = ", __get_str(%s)";
  			else
  				fmt = ", REC->%s";
5bf652aaf   Namhyung Kim   tracing/probes: I...
867
  			pos += snprintf(buf + pos, LEN_OR_ZERO,
40b53b771   Masami Hiramatsu   tracing: probeeve...
868
869
  					fmt, parg->name);
  		}
5bf652aaf   Namhyung Kim   tracing/probes: I...
870
  	}
5bf652aaf   Namhyung Kim   tracing/probes: I...
871
872
873
  	/* return the length of print_fmt */
  	return pos;
  }
40b53b771   Masami Hiramatsu   tracing: probeeve...
874
  #undef LEN_OR_ZERO
5bf652aaf   Namhyung Kim   tracing/probes: I...
875

0a46c8549   Masami Hiramatsu   tracing: probeeve...
876
  int traceprobe_set_print_fmt(struct trace_probe *tp, bool is_return)
5bf652aaf   Namhyung Kim   tracing/probes: I...
877
  {
e3dc9f898   Masami Hiramatsu   tracing/probe: Ad...
878
  	struct trace_event_call *call = trace_probe_event_call(tp);
5bf652aaf   Namhyung Kim   tracing/probes: I...
879
880
881
882
883
884
885
886
887
888
889
  	int len;
  	char *print_fmt;
  
  	/* First: called with 0 length to calculate the needed length */
  	len = __set_print_fmt(tp, NULL, 0, is_return);
  	print_fmt = kmalloc(len + 1, GFP_KERNEL);
  	if (!print_fmt)
  		return -ENOMEM;
  
  	/* Second: actually write the @print_fmt */
  	__set_print_fmt(tp, print_fmt, len + 1, is_return);
e3dc9f898   Masami Hiramatsu   tracing/probe: Ad...
890
  	call->print_fmt = print_fmt;
5bf652aaf   Namhyung Kim   tracing/probes: I...
891
892
893
  
  	return 0;
  }
eeb07b061   Masami Hiramatsu   tracing: probeeve...
894
895
896
897
898
899
900
901
902
  
  int traceprobe_define_arg_fields(struct trace_event_call *event_call,
  				 size_t offset, struct trace_probe *tp)
  {
  	int ret, i;
  
  	/* Set argument names as fields */
  	for (i = 0; i < tp->nr_args; i++) {
  		struct probe_arg *parg = &tp->args[i];
40b53b771   Masami Hiramatsu   tracing: probeeve...
903
904
905
906
907
908
909
910
911
  		const char *fmt = parg->type->fmttype;
  		int size = parg->type->size;
  
  		if (parg->fmt)
  			fmt = parg->fmt;
  		if (parg->count)
  			size *= parg->count;
  		ret = trace_define_field(event_call, fmt, parg->name,
  					 offset + parg->offset, size,
eeb07b061   Masami Hiramatsu   tracing: probeeve...
912
913
914
915
916
917
918
  					 parg->type->is_signed,
  					 FILTER_OTHER);
  		if (ret)
  			return ret;
  	}
  	return 0;
  }
455b28997   Masami Hiramatsu   tracing/probe: Ad...
919

ca89bc071   Masami Hiramatsu   tracing/kprobe: A...
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
  static void trace_probe_event_free(struct trace_probe_event *tpe)
  {
  	kfree(tpe->class.system);
  	kfree(tpe->call.name);
  	kfree(tpe->call.print_fmt);
  	kfree(tpe);
  }
  
  int trace_probe_append(struct trace_probe *tp, struct trace_probe *to)
  {
  	if (trace_probe_has_sibling(tp))
  		return -EBUSY;
  
  	list_del_init(&tp->list);
  	trace_probe_event_free(tp->event);
  
  	tp->event = to->event;
  	list_add_tail(&tp->list, trace_probe_probe_list(to));
  
  	return 0;
  }
  
  void trace_probe_unlink(struct trace_probe *tp)
  {
  	list_del_init(&tp->list);
  	if (list_empty(trace_probe_probe_list(tp)))
  		trace_probe_event_free(tp->event);
  	tp->event = NULL;
  }
455b28997   Masami Hiramatsu   tracing/probe: Ad...
949
950
951
952
953
954
955
  
  void trace_probe_cleanup(struct trace_probe *tp)
  {
  	int i;
  
  	for (i = 0; i < tp->nr_args; i++)
  		traceprobe_free_probe_arg(&tp->args[i]);
ca89bc071   Masami Hiramatsu   tracing/kprobe: A...
956
957
  	if (tp->event)
  		trace_probe_unlink(tp);
455b28997   Masami Hiramatsu   tracing/probe: Ad...
958
959
960
  }
  
  int trace_probe_init(struct trace_probe *tp, const char *event,
b61387cb7   Masami Hiramatsu   tracing/uprobe: F...
961
  		     const char *group, bool alloc_filter)
455b28997   Masami Hiramatsu   tracing/probe: Ad...
962
  {
60d53e2c3   Masami Hiramatsu   tracing/probe: Sp...
963
  	struct trace_event_call *call;
b61387cb7   Masami Hiramatsu   tracing/uprobe: F...
964
  	size_t size = sizeof(struct trace_probe_event);
60d53e2c3   Masami Hiramatsu   tracing/probe: Sp...
965
  	int ret = 0;
e3dc9f898   Masami Hiramatsu   tracing/probe: Ad...
966

455b28997   Masami Hiramatsu   tracing/probe: Ad...
967
968
  	if (!event || !group)
  		return -EINVAL;
b61387cb7   Masami Hiramatsu   tracing/uprobe: F...
969
970
971
972
  	if (alloc_filter)
  		size += sizeof(struct trace_uprobe_filter);
  
  	tp->event = kzalloc(size, GFP_KERNEL);
60d53e2c3   Masami Hiramatsu   tracing/probe: Sp...
973
  	if (!tp->event)
455b28997   Masami Hiramatsu   tracing/probe: Ad...
974
  		return -ENOMEM;
d59fae6fe   Masami Hiramatsu   tracing/kprobe: F...
975
976
977
978
  	INIT_LIST_HEAD(&tp->event->files);
  	INIT_LIST_HEAD(&tp->event->class.fields);
  	INIT_LIST_HEAD(&tp->event->probes);
  	INIT_LIST_HEAD(&tp->list);
fc9d276f2   Julia Lawall   tracing/probe: re...
979
  	list_add(&tp->list, &tp->event->probes);
d59fae6fe   Masami Hiramatsu   tracing/kprobe: F...
980

60d53e2c3   Masami Hiramatsu   tracing/probe: Sp...
981
982
983
984
985
986
987
988
989
990
991
992
  	call = trace_probe_event_call(tp);
  	call->class = &tp->event->class;
  	call->name = kstrdup(event, GFP_KERNEL);
  	if (!call->name) {
  		ret = -ENOMEM;
  		goto error;
  	}
  
  	tp->event->class.system = kstrdup(group, GFP_KERNEL);
  	if (!tp->event->class.system) {
  		ret = -ENOMEM;
  		goto error;
455b28997   Masami Hiramatsu   tracing/probe: Ad...
993
  	}
455b28997   Masami Hiramatsu   tracing/probe: Ad...
994
995
  
  	return 0;
60d53e2c3   Masami Hiramatsu   tracing/probe: Sp...
996
997
998
999
  
  error:
  	trace_probe_cleanup(tp);
  	return ret;
455b28997   Masami Hiramatsu   tracing/probe: Ad...
1000
  }
46e5376d4   Masami Hiramatsu   tracing/probe: Ad...
1001
1002
1003
  
  int trace_probe_register_event_call(struct trace_probe *tp)
  {
e3dc9f898   Masami Hiramatsu   tracing/probe: Ad...
1004
  	struct trace_event_call *call = trace_probe_event_call(tp);
46e5376d4   Masami Hiramatsu   tracing/probe: Ad...
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
  	int ret;
  
  	ret = register_trace_event(&call->event);
  	if (!ret)
  		return -ENODEV;
  
  	ret = trace_add_event_call(call);
  	if (ret)
  		unregister_trace_event(&call->event);
  
  	return ret;
  }
b5f935ee1   Masami Hiramatsu   tracing/probe: Ad...
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
  
  int trace_probe_add_file(struct trace_probe *tp, struct trace_event_file *file)
  {
  	struct event_file_link *link;
  
  	link = kmalloc(sizeof(*link), GFP_KERNEL);
  	if (!link)
  		return -ENOMEM;
  
  	link->file = file;
  	INIT_LIST_HEAD(&link->list);
60d53e2c3   Masami Hiramatsu   tracing/probe: Sp...
1028
  	list_add_tail_rcu(&link->list, &tp->event->files);
747774d6b   Masami Hiramatsu   tracing/probe: Ad...
1029
  	trace_probe_set_flag(tp, TP_FLAG_TRACE);
b5f935ee1   Masami Hiramatsu   tracing/probe: Ad...
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
  	return 0;
  }
  
  struct event_file_link *trace_probe_get_file_link(struct trace_probe *tp,
  						  struct trace_event_file *file)
  {
  	struct event_file_link *link;
  
  	trace_probe_for_each_link(link, tp) {
  		if (link->file == file)
  			return link;
  	}
  
  	return NULL;
  }
  
  int trace_probe_remove_file(struct trace_probe *tp,
  			    struct trace_event_file *file)
  {
  	struct event_file_link *link;
  
  	link = trace_probe_get_file_link(tp, file);
  	if (!link)
  		return -ENOENT;
  
  	list_del_rcu(&link->list);
  	synchronize_rcu();
  	kfree(link);
60d53e2c3   Masami Hiramatsu   tracing/probe: Sp...
1058
  	if (list_empty(&tp->event->files))
747774d6b   Masami Hiramatsu   tracing/probe: Ad...
1059
  		trace_probe_clear_flag(tp, TP_FLAG_TRACE);
b5f935ee1   Masami Hiramatsu   tracing/probe: Ad...
1060
1061
1062
  
  	return 0;
  }
ca89bc071   Masami Hiramatsu   tracing/kprobe: A...
1063
1064
1065
1066
1067
1068
1069
1070
  
  /*
   * Return the smallest index of different type argument (start from 1).
   * If all argument types and name are same, return 0.
   */
  int trace_probe_compare_arg_type(struct trace_probe *a, struct trace_probe *b)
  {
  	int i;
d2aea95a1   Masami Hiramatsu   tracing/probe: Fi...
1071
1072
1073
1074
1075
  	/* In case of more arguments */
  	if (a->nr_args < b->nr_args)
  		return a->nr_args + 1;
  	if (a->nr_args > b->nr_args)
  		return b->nr_args + 1;
ca89bc071   Masami Hiramatsu   tracing/kprobe: A...
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
  	for (i = 0; i < a->nr_args; i++) {
  		if ((b->nr_args <= i) ||
  		    ((a->args[i].type != b->args[i].type) ||
  		     (a->args[i].count != b->args[i].count) ||
  		     strcmp(a->args[i].name, b->args[i].name)))
  			return i + 1;
  	}
  
  	return 0;
  }
eb5bf8133   Masami Hiramatsu   tracing/kprobe: A...
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
  
  bool trace_probe_match_command_args(struct trace_probe *tp,
  				    int argc, const char **argv)
  {
  	char buf[MAX_ARGSTR_LEN + 1];
  	int i;
  
  	if (tp->nr_args < argc)
  		return false;
  
  	for (i = 0; i < argc; i++) {
  		snprintf(buf, sizeof(buf), "%s=%s",
  			 tp->args[i].name, tp->args[i].comm);
  		if (strcmp(buf, argv[i]))
  			return false;
  	}
  	return true;
  }