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

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

perf probe: Add bitfield member support



Add bitfield member accessing support to probe arguments.

Suggested-by: default avatarArnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: 2nddept-manager@sdl.hitachi.co.jp
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
LKML-Reference: <20110204125211.9507.60265.stgit@ltc236.sdl.hitachi.co.jp>
Signed-off-by: default avatarMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
[ committer note: Fixed up '%lu' use for return of BYTES_TO_BITS ('%zd') ]
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent a2221796
Loading
Loading
Loading
Loading
+68 −27
Original line number Original line Diff line number Diff line
@@ -33,6 +33,7 @@
#include <ctype.h>
#include <ctype.h>
#include <dwarf-regs.h>
#include <dwarf-regs.h>


#include <linux/bitops.h>
#include "event.h"
#include "event.h"
#include "debug.h"
#include "debug.h"
#include "util.h"
#include "util.h"
@@ -333,13 +334,23 @@ static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
	return vr_die;
	return vr_die;
}
}


static bool die_is_signed_type(Dwarf_Die *tp_die)
static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
			      Dwarf_Word *result)
{
{
	Dwarf_Attribute attr;
	Dwarf_Attribute attr;

	if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
	    dwarf_formudata(&attr, result) != 0)
		return -ENOENT;

	return 0;
}

static bool die_is_signed_type(Dwarf_Die *tp_die)
{
	Dwarf_Word ret;
	Dwarf_Word ret;


	if (dwarf_attr(tp_die, DW_AT_encoding, &attr) == NULL ||
	if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret))
	    dwarf_formudata(&attr, &ret) != 0)
		return false;
		return false;


	return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
	return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
@@ -348,11 +359,29 @@ static bool die_is_signed_type(Dwarf_Die *tp_die)


static int die_get_byte_size(Dwarf_Die *tp_die)
static int die_get_byte_size(Dwarf_Die *tp_die)
{
{
	Dwarf_Attribute attr;
	Dwarf_Word ret;
	Dwarf_Word ret;


	if (dwarf_attr(tp_die, DW_AT_byte_size, &attr) == NULL ||
	if (die_get_attr_udata(tp_die, DW_AT_byte_size, &ret))
	    dwarf_formudata(&attr, &ret) != 0)
		return 0;

	return (int)ret;
}

static int die_get_bit_size(Dwarf_Die *tp_die)
{
	Dwarf_Word ret;

	if (die_get_attr_udata(tp_die, DW_AT_bit_size, &ret))
		return 0;

	return (int)ret;
}

static int die_get_bit_offset(Dwarf_Die *tp_die)
{
	Dwarf_Word ret;

	if (die_get_attr_udata(tp_die, DW_AT_bit_offset, &ret))
		return 0;
		return 0;


	return (int)ret;
	return (int)ret;
@@ -827,6 +856,8 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
	return 0;
	return 0;
}
}


#define BYTES_TO_BITS(nb)	((nb) * BITS_PER_LONG / sizeof(long))

static int convert_variable_type(Dwarf_Die *vr_die,
static int convert_variable_type(Dwarf_Die *vr_die,
				 struct probe_trace_arg *tvar,
				 struct probe_trace_arg *tvar,
				 const char *cast)
				 const char *cast)
@@ -843,6 +874,14 @@ static int convert_variable_type(Dwarf_Die *vr_die,
		return (tvar->type == NULL) ? -ENOMEM : 0;
		return (tvar->type == NULL) ? -ENOMEM : 0;
	}
	}


	if (die_get_bit_size(vr_die) != 0) {
		/* This is a bitfield */
		ret = snprintf(buf, 16, "b%d@%d/%zd", die_get_bit_size(vr_die),
				die_get_bit_offset(vr_die),
				BYTES_TO_BITS(die_get_byte_size(vr_die)));
		goto formatted;
	}

	if (die_get_real_type(vr_die, &type) == NULL) {
	if (die_get_real_type(vr_die, &type) == NULL) {
		pr_warning("Failed to get a type information of %s.\n",
		pr_warning("Failed to get a type information of %s.\n",
			   dwarf_diename(vr_die));
			   dwarf_diename(vr_die));
@@ -887,18 +926,21 @@ static int convert_variable_type(Dwarf_Die *vr_die,
		return (tvar->type == NULL) ? -ENOMEM : 0;
		return (tvar->type == NULL) ? -ENOMEM : 0;
	}
	}


	ret = die_get_byte_size(&type) * 8;
	ret = BYTES_TO_BITS(die_get_byte_size(&type));
	if (ret) {
	if (!ret)
		/* No size ... try to use default type */
		return 0;

	/* Check the bitwidth */
	/* Check the bitwidth */
	if (ret > MAX_BASIC_TYPE_BITS) {
	if (ret > MAX_BASIC_TYPE_BITS) {
			pr_info("%s exceeds max-bitwidth."
		pr_info("%s exceeds max-bitwidth. Cut down to %d bits.\n",
				" Cut down to %d bits.\n",
			dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
			dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
		ret = MAX_BASIC_TYPE_BITS;
		ret = MAX_BASIC_TYPE_BITS;
	}
	}

	ret = snprintf(buf, 16, "%c%d",
	ret = snprintf(buf, 16, "%c%d",
		       die_is_signed_type(&type) ? 's' : 'u', ret);
		       die_is_signed_type(&type) ? 's' : 'u', ret);

formatted:
	if (ret < 0 || ret >= 16) {
	if (ret < 0 || ret >= 16) {
		if (ret >= 16)
		if (ret >= 16)
			ret = -E2BIG;
			ret = -E2BIG;
@@ -909,7 +951,6 @@ static int convert_variable_type(Dwarf_Die *vr_die,
	tvar->type = strdup(buf);
	tvar->type = strdup(buf);
	if (tvar->type == NULL)
	if (tvar->type == NULL)
		return -ENOMEM;
		return -ENOMEM;
	}
	return 0;
	return 0;
}
}