Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8bd0e1be authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge branch 'perf/core' of...

Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
parents 39ef13a4 b7dcb857
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ Synopsis of kprobe_events
  +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**)
  NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
  FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
		  (u8/u16/u32/u64/s8/s16/s32/s64) are supported.
		  (u8/u16/u32/u64/s8/s16/s32/s64) and string are supported.

  (*) only for return probe.
  (**) this is useful for fetching a field of data structures.
+292 −78

File changed.

Preview size limit exceeded, changes collapsed.

+2 −2
Original line number Diff line number Diff line
@@ -94,8 +94,8 @@ Each probe argument follows below syntax.

 [NAME=]LOCALVAR|$retval|%REG|@SYMBOL[:TYPE]

'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.)
'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo.
'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), local array with fixed index (e.g. array[1], var->array[0], var->pointer[2]), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.)
'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo. You can specify 'string' type only for the local variable or structure member which is an array of or a pointer to 'char' or 'unsigned char' type.

LINE SYNTAX
-----------
+25 −23
Original line number Diff line number Diff line
@@ -605,7 +605,8 @@ endif

ifdef NO_DEMANGLE
	BASIC_CFLAGS += -DNO_DEMANGLE
else ifdef HAVE_CPLUS_DEMANGLE
else
        ifdef HAVE_CPLUS_DEMANGLE
		EXTLIBS += -liberty
		BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE
        else
@@ -637,6 +638,7 @@ else
			endif
		endif
	endif
endif

ifndef CC_LD_DYNPATH
	ifdef NO_R_TO_GCC_LINKER
+51 −20
Original line number Diff line number Diff line
@@ -557,7 +557,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
/* Parse perf-probe event argument */
static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
{
	char *tmp;
	char *tmp, *goodname;
	struct perf_probe_arg_field **fieldp;

	pr_debug("parsing arg: %s into ", str);
@@ -580,7 +580,7 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
		pr_debug("type:%s ", arg->type);
	}

	tmp = strpbrk(str, "-.");
	tmp = strpbrk(str, "-.[");
	if (!is_c_varname(str) || !tmp) {
		/* A variable, register, symbol or special value */
		arg->var = strdup(str);
@@ -590,10 +590,11 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
		return 0;
	}

	/* Structure fields */
	/* Structure fields or array element */
	arg->var = strndup(str, tmp - str);
	if (arg->var == NULL)
		return -ENOMEM;
	goodname = arg->var;
	pr_debug("%s, ", arg->var);
	fieldp = &arg->field;

@@ -601,6 +602,19 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
		*fieldp = zalloc(sizeof(struct perf_probe_arg_field));
		if (*fieldp == NULL)
			return -ENOMEM;
		if (*tmp == '[') {	/* Array */
			str = tmp;
			(*fieldp)->index = strtol(str + 1, &tmp, 0);
			(*fieldp)->ref = true;
			if (*tmp != ']' || tmp == str + 1) {
				semantic_error("Array index must be a"
						" number.\n");
				return -EINVAL;
			}
			tmp++;
			if (*tmp == '\0')
				tmp = NULL;
		} else {		/* Structure */
			if (*tmp == '.') {
				str = tmp + 1;
				(*fieldp)->ref = false;
@@ -608,15 +622,18 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
				str = tmp + 2;
				(*fieldp)->ref = true;
			} else {
			semantic_error("Argument parse error: %s\n", str);
				semantic_error("Argument parse error: %s\n",
					       str);
				return -EINVAL;
			}

		tmp = strpbrk(str, "-.");
			tmp = strpbrk(str, "-.[");
		}
		if (tmp) {
			(*fieldp)->name = strndup(str, tmp - str);
			if ((*fieldp)->name == NULL)
				return -ENOMEM;
			if (*str != '[')
				goodname = (*fieldp)->name;
			pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref);
			fieldp = &(*fieldp)->next;
		}
@@ -624,11 +641,13 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
	(*fieldp)->name = strdup(str);
	if ((*fieldp)->name == NULL)
		return -ENOMEM;
	if (*str != '[')
		goodname = (*fieldp)->name;
	pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref);

	/* If no name is specified, set the last field name */
	/* If no name is specified, set the last field name (not array index)*/
	if (!arg->name) {
		arg->name = strdup((*fieldp)->name);
		arg->name = strdup(goodname);
		if (arg->name == NULL)
			return -ENOMEM;
	}
@@ -776,8 +795,11 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
	len -= ret;

	while (field) {
		ret = e_snprintf(tmp, len, "%s%s", field->ref ? "->" : ".",
				 field->name);
		if (field->name[0] == '[')
			ret = e_snprintf(tmp, len, "%s", field->name);
		else
			ret = e_snprintf(tmp, len, "%s%s",
					 field->ref ? "->" : ".", field->name);
		if (ret <= 0)
			goto error;
		tmp += ret;
@@ -904,6 +926,7 @@ static int __synthesize_kprobe_trace_arg_ref(struct kprobe_trace_arg_ref *ref,
static int synthesize_kprobe_trace_arg(struct kprobe_trace_arg *arg,
				       char *buf, size_t buflen)
{
	struct kprobe_trace_arg_ref *ref = arg->ref;
	int ret, depth = 0;
	char *tmp = buf;

@@ -917,15 +940,23 @@ static int synthesize_kprobe_trace_arg(struct kprobe_trace_arg *arg,
	buf += ret;
	buflen -= ret;

	/* Special case: @XXX */
	if (arg->value[0] == '@' && arg->ref)
			ref = ref->next;

	/* Dereferencing arguments */
	if (arg->ref) {
		depth = __synthesize_kprobe_trace_arg_ref(arg->ref, &buf,
	if (ref) {
		depth = __synthesize_kprobe_trace_arg_ref(ref, &buf,
							  &buflen, 1);
		if (depth < 0)
			return depth;
	}

	/* Print argument value */
	if (arg->value[0] == '@' && arg->ref)
		ret = e_snprintf(buf, buflen, "%s%+ld", arg->value,
				 arg->ref->offset);
	else
		ret = e_snprintf(buf, buflen, "%s", arg->value);
	if (ret < 0)
		return ret;
Loading