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

Commit de1439d8 authored by Masami Hiramatsu's avatar Masami Hiramatsu Committed by Arnaldo Carvalho de Melo
Browse files

perf probe: Support DW_OP_plus_uconst in DW_AT_data_member_location



DW_OP_plus_uconst can be used for DW_AT_data_member_location.
This patch adds DW_OP_plus_uconst support when getting
structure member offset.

Commiter note:

Fixed up the size_t format specifier in one case:

cc1: warnings being treated as errors
util/probe-finder.c: In function ‘die_get_data_member_location’:
util/probe-finder.c:270: error: format ‘%d’ expects type ‘int’, but argument 4 has type ‘size_t’
make: *** [/home/acme/git/build/perf/util/probe-finder.o] Error 1

LKML-Reference: <20100414223958.14630.5230.stgit@localhost6.localdomain6>
Signed-off-by: default avatarMasami Hiramatsu <mhiramat@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent dda4ab34
Loading
Loading
Loading
Loading
+32 −5
Original line number Diff line number Diff line
@@ -249,6 +249,33 @@ static int die_get_byte_size(Dwarf_Die *tp_die)
	return (int)ret;
}

/* Get data_member_location offset */
static int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
{
	Dwarf_Attribute attr;
	Dwarf_Op *expr;
	size_t nexpr;
	int ret;

	if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
		return -ENOENT;

	if (dwarf_formudata(&attr, offs) != 0) {
		/* DW_AT_data_member_location should be DW_OP_plus_uconst */
		ret = dwarf_getlocation(&attr, &expr, &nexpr);
		if (ret < 0 || nexpr == 0)
			return -ENOENT;

		if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
			pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
				 expr[0].atom, nexpr);
			return -ENOTSUP;
		}
		*offs = (Dwarf_Word)expr[0].number;
	}
	return 0;
}

/* Return values for die_find callbacks */
enum {
	DIE_FIND_CB_FOUND = 0,		/* End of Search */
@@ -482,9 +509,9 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
				    Dwarf_Die *die_mem)
{
	struct kprobe_trace_arg_ref *ref = *ref_ptr;
	Dwarf_Attribute attr;
	Dwarf_Die type;
	Dwarf_Word offs;
	int ret;

	pr_debug("converting %s in %s\n", field->name, varname);
	if (die_get_real_type(vr_die, &type) == NULL) {
@@ -542,10 +569,10 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
	}

	/* Get the offset of the field */
	if (dwarf_attr(die_mem, DW_AT_data_member_location, &attr) == NULL ||
	    dwarf_formudata(&attr, &offs) != 0) {
	ret = die_get_data_member_location(die_mem, &offs);
	if (ret < 0) {
		pr_warning("Failed to get the offset of %s.\n", field->name);
		return -ENOENT;
		return ret;
	}
	ref->offset += (long)offs;