diff options
author | Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> | 2011-02-04 07:52:11 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-02-07 09:48:48 -0500 |
commit | 124bb83cd7de4d851af7595650233fb9e9279d5d (patch) | |
tree | da896030a0703df27c1d0050646a9c7bdadb95eb /tools/perf/util | |
parent | a2221796256ea7b236cec6bf027c1c1de5b8ccd7 (diff) |
perf probe: Add bitfield member support
Add bitfield member accessing support to probe arguments.
Suggested-by: Arnaldo 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: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
[ committer note: Fixed up '%lu' use for return of BYTES_TO_BITS ('%zd') ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/probe-finder.c | 95 |
1 files changed, 68 insertions, 27 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 46addfb3183e..fe461f6559f1 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <ctype.h> | 33 | #include <ctype.h> |
34 | #include <dwarf-regs.h> | 34 | #include <dwarf-regs.h> |
35 | 35 | ||
36 | #include <linux/bitops.h> | ||
36 | #include "event.h" | 37 | #include "event.h" |
37 | #include "debug.h" | 38 | #include "debug.h" |
38 | #include "util.h" | 39 | #include "util.h" |
@@ -333,13 +334,23 @@ static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) | |||
333 | return vr_die; | 334 | return vr_die; |
334 | } | 335 | } |
335 | 336 | ||
336 | static bool die_is_signed_type(Dwarf_Die *tp_die) | 337 | static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name, |
338 | Dwarf_Word *result) | ||
337 | { | 339 | { |
338 | Dwarf_Attribute attr; | 340 | Dwarf_Attribute attr; |
341 | |||
342 | if (dwarf_attr(tp_die, attr_name, &attr) == NULL || | ||
343 | dwarf_formudata(&attr, result) != 0) | ||
344 | return -ENOENT; | ||
345 | |||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | static bool die_is_signed_type(Dwarf_Die *tp_die) | ||
350 | { | ||
339 | Dwarf_Word ret; | 351 | Dwarf_Word ret; |
340 | 352 | ||
341 | if (dwarf_attr(tp_die, DW_AT_encoding, &attr) == NULL || | 353 | if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret)) |
342 | dwarf_formudata(&attr, &ret) != 0) | ||
343 | return false; | 354 | return false; |
344 | 355 | ||
345 | return (ret == DW_ATE_signed_char || ret == DW_ATE_signed || | 356 | return (ret == DW_ATE_signed_char || ret == DW_ATE_signed || |
@@ -348,11 +359,29 @@ static bool die_is_signed_type(Dwarf_Die *tp_die) | |||
348 | 359 | ||
349 | static int die_get_byte_size(Dwarf_Die *tp_die) | 360 | static int die_get_byte_size(Dwarf_Die *tp_die) |
350 | { | 361 | { |
351 | Dwarf_Attribute attr; | ||
352 | Dwarf_Word ret; | 362 | Dwarf_Word ret; |
353 | 363 | ||
354 | if (dwarf_attr(tp_die, DW_AT_byte_size, &attr) == NULL || | 364 | if (die_get_attr_udata(tp_die, DW_AT_byte_size, &ret)) |
355 | dwarf_formudata(&attr, &ret) != 0) | 365 | return 0; |
366 | |||
367 | return (int)ret; | ||
368 | } | ||
369 | |||
370 | static int die_get_bit_size(Dwarf_Die *tp_die) | ||
371 | { | ||
372 | Dwarf_Word ret; | ||
373 | |||
374 | if (die_get_attr_udata(tp_die, DW_AT_bit_size, &ret)) | ||
375 | return 0; | ||
376 | |||
377 | return (int)ret; | ||
378 | } | ||
379 | |||
380 | static int die_get_bit_offset(Dwarf_Die *tp_die) | ||
381 | { | ||
382 | Dwarf_Word ret; | ||
383 | |||
384 | if (die_get_attr_udata(tp_die, DW_AT_bit_offset, &ret)) | ||
356 | return 0; | 385 | return 0; |
357 | 386 | ||
358 | return (int)ret; | 387 | return (int)ret; |
@@ -827,6 +856,8 @@ static_var: | |||
827 | return 0; | 856 | return 0; |
828 | } | 857 | } |
829 | 858 | ||
859 | #define BYTES_TO_BITS(nb) ((nb) * BITS_PER_LONG / sizeof(long)) | ||
860 | |||
830 | static int convert_variable_type(Dwarf_Die *vr_die, | 861 | static int convert_variable_type(Dwarf_Die *vr_die, |
831 | struct probe_trace_arg *tvar, | 862 | struct probe_trace_arg *tvar, |
832 | const char *cast) | 863 | const char *cast) |
@@ -843,6 +874,14 @@ static int convert_variable_type(Dwarf_Die *vr_die, | |||
843 | return (tvar->type == NULL) ? -ENOMEM : 0; | 874 | return (tvar->type == NULL) ? -ENOMEM : 0; |
844 | } | 875 | } |
845 | 876 | ||
877 | if (die_get_bit_size(vr_die) != 0) { | ||
878 | /* This is a bitfield */ | ||
879 | ret = snprintf(buf, 16, "b%d@%d/%zd", die_get_bit_size(vr_die), | ||
880 | die_get_bit_offset(vr_die), | ||
881 | BYTES_TO_BITS(die_get_byte_size(vr_die))); | ||
882 | goto formatted; | ||
883 | } | ||
884 | |||
846 | if (die_get_real_type(vr_die, &type) == NULL) { | 885 | if (die_get_real_type(vr_die, &type) == NULL) { |
847 | pr_warning("Failed to get a type information of %s.\n", | 886 | pr_warning("Failed to get a type information of %s.\n", |
848 | dwarf_diename(vr_die)); | 887 | dwarf_diename(vr_die)); |
@@ -887,29 +926,31 @@ static int convert_variable_type(Dwarf_Die *vr_die, | |||
887 | return (tvar->type == NULL) ? -ENOMEM : 0; | 926 | return (tvar->type == NULL) ? -ENOMEM : 0; |
888 | } | 927 | } |
889 | 928 | ||
890 | ret = die_get_byte_size(&type) * 8; | 929 | ret = BYTES_TO_BITS(die_get_byte_size(&type)); |
891 | if (ret) { | 930 | if (!ret) |
892 | /* Check the bitwidth */ | 931 | /* No size ... try to use default type */ |
893 | if (ret > MAX_BASIC_TYPE_BITS) { | 932 | return 0; |
894 | pr_info("%s exceeds max-bitwidth." | ||
895 | " Cut down to %d bits.\n", | ||
896 | dwarf_diename(&type), MAX_BASIC_TYPE_BITS); | ||
897 | ret = MAX_BASIC_TYPE_BITS; | ||
898 | } | ||
899 | 933 | ||
900 | ret = snprintf(buf, 16, "%c%d", | 934 | /* Check the bitwidth */ |
901 | die_is_signed_type(&type) ? 's' : 'u', ret); | 935 | if (ret > MAX_BASIC_TYPE_BITS) { |
902 | if (ret < 0 || ret >= 16) { | 936 | pr_info("%s exceeds max-bitwidth. Cut down to %d bits.\n", |
903 | if (ret >= 16) | 937 | dwarf_diename(&type), MAX_BASIC_TYPE_BITS); |
904 | ret = -E2BIG; | 938 | ret = MAX_BASIC_TYPE_BITS; |
905 | pr_warning("Failed to convert variable type: %s\n", | 939 | } |
906 | strerror(-ret)); | 940 | ret = snprintf(buf, 16, "%c%d", |
907 | return ret; | 941 | die_is_signed_type(&type) ? 's' : 'u', ret); |
908 | } | 942 | |
909 | tvar->type = strdup(buf); | 943 | formatted: |
910 | if (tvar->type == NULL) | 944 | if (ret < 0 || ret >= 16) { |
911 | return -ENOMEM; | 945 | if (ret >= 16) |
946 | ret = -E2BIG; | ||
947 | pr_warning("Failed to convert variable type: %s\n", | ||
948 | strerror(-ret)); | ||
949 | return ret; | ||
912 | } | 950 | } |
951 | tvar->type = strdup(buf); | ||
952 | if (tvar->type == NULL) | ||
953 | return -ENOMEM; | ||
913 | return 0; | 954 | return 0; |
914 | } | 955 | } |
915 | 956 | ||