aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/perf_regs.c6
-rw-r--r--tools/perf/util/perf_regs.h11
-rw-r--r--tools/perf/util/probe-file.c132
3 files changed, 47 insertions, 102 deletions
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
index a37e5934aa2a..b2ae039eff85 100644
--- a/tools/perf/util/perf_regs.c
+++ b/tools/perf/util/perf_regs.c
@@ -6,10 +6,10 @@ const struct sample_reg __weak sample_reg_masks[] = {
6 SMPL_REG_END 6 SMPL_REG_END
7}; 7};
8 8
9int __weak sdt_rename_register(char **pdesc __maybe_unused, 9int __weak arch_sdt_arg_parse_op(char *old_op __maybe_unused,
10 char *old_name __maybe_unused) 10 char **new_op __maybe_unused)
11{ 11{
12 return 0; 12 return SDT_ARG_SKIP;
13} 13}
14 14
15#ifdef HAVE_PERF_REGS_SUPPORT 15#ifdef HAVE_PERF_REGS_SUPPORT
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 7544a157e159..32b37d19dcc3 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -15,11 +15,12 @@ struct sample_reg {
15 15
16extern const struct sample_reg sample_reg_masks[]; 16extern const struct sample_reg sample_reg_masks[];
17 17
18/* 18enum {
19 * The table sdt_reg_renamings is used for adjusting gcc/gas-generated 19 SDT_ARG_VALID = 0,
20 * registers before filling the uprobe tracer interface. 20 SDT_ARG_SKIP,
21 */ 21};
22int sdt_rename_register(char **pdesc, char *old_name); 22
23int arch_sdt_arg_parse_op(char *old_op, char **new_op);
23 24
24#ifdef HAVE_PERF_REGS_SUPPORT 25#ifdef HAVE_PERF_REGS_SUPPORT
25#include <perf_regs.h> 26#include <perf_regs.h>
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index d741634cbfc0..88714dec8912 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -694,10 +694,29 @@ static const char * const type_to_suffix[] = {
694 "", ":u8", ":u16", "", ":u32", "", "", "", ":u64" 694 "", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
695}; 695};
696 696
697/*
698 * Isolate the string number and convert it into a decimal value;
699 * this will be an index to get suffix of the uprobe name (defining
700 * the type)
701 */
702static int sdt_arg_parse_size(char *n_ptr, const char **suffix)
703{
704 long type_idx;
705
706 type_idx = strtol(n_ptr, NULL, 10);
707 if (type_idx < -8 || type_idx > 8) {
708 pr_debug4("Failed to get a valid sdt type\n");
709 return -1;
710 }
711
712 *suffix = type_to_suffix[type_idx + 8];
713 return 0;
714}
715
697static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg) 716static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
698{ 717{
699 char *tmp, *desc = strdup(arg); 718 char *op, *desc = strdup(arg), *new_op = NULL;
700 const char *prefix = "", *suffix = ""; 719 const char *suffix = "";
701 int ret = -1; 720 int ret = -1;
702 721
703 if (desc == NULL) { 722 if (desc == NULL) {
@@ -705,112 +724,37 @@ static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
705 return ret; 724 return ret;
706 } 725 }
707 726
708 tmp = strchr(desc, '@');
709 if (tmp) {
710 long type_idx;
711 /*
712 * Isolate the string number and convert it into a
713 * binary value; this will be an index to get suffix
714 * of the uprobe name (defining the type)
715 */
716 tmp[0] = '\0';
717 type_idx = strtol(desc, NULL, 10);
718 /* Check that the conversion went OK */
719 if (type_idx == LONG_MIN || type_idx == LONG_MAX) {
720 pr_debug4("Failed to parse sdt type\n");
721 goto error;
722 }
723 /* Check that the converted value is OK */
724 if (type_idx < -8 || type_idx > 8) {
725 pr_debug4("Failed to get a valid sdt type\n");
726 goto error;
727 }
728 suffix = type_to_suffix[type_idx + 8];
729 /* Get rid of the sdt prefix which is now useless */
730 tmp++;
731 memmove(desc, tmp, strlen(tmp) + 1);
732 }
733
734 /* 727 /*
735 * The uprobe tracer format does not support all the 728 * Argument is in N@OP format. N is size of the argument and OP is
736 * addressing modes (notably: in x86 the scaled mode); so, we 729 * the actual assembly operand. N can be omitted; in that case
737 * detect ',' characters, if there is just one, there is no 730 * argument is just OP(without @).
738 * use converting the sdt arg into a uprobe one.
739 */ 731 */
740 if (strchr(desc, ',')) { 732 op = strchr(desc, '@');
741 pr_debug4("Skipping unsupported SDT argument; %s\n", desc); 733 if (op) {
742 goto out; 734 op[0] = '\0';
743 } 735 op++;
744 736
745 /* 737 if (sdt_arg_parse_size(desc, &suffix))
746 * If the argument addressing mode is indirect, we must check 738 goto error;
747 * a few things... 739 } else {
748 */ 740 op = desc;
749 tmp = strchr(desc, '(');
750 if (tmp) {
751 int j;
752
753 /*
754 * ...if the addressing mode is indirect with a
755 * positive offset (ex.: "1608(%ax)"), we need to add
756 * a '+' prefix so as to be compliant with uprobe
757 * format.
758 */
759 if (desc[0] != '+' && desc[0] != '-')
760 prefix = "+";
761
762 /*
763 * ...or if the addressing mode is indirect with a symbol
764 * as offset, the argument will not be supported by
765 * the uprobe tracer format; so, let's skip this one.
766 */
767 for (j = 0; j < tmp - desc; j++) {
768 if (desc[j] != '+' && desc[j] != '-' &&
769 !isdigit(desc[j])) {
770 pr_debug4("Skipping unsupported SDT argument; "
771 "%s\n", desc);
772 goto out;
773 }
774 }
775 } 741 }
776 742
777 /* 743 ret = arch_sdt_arg_parse_op(op, &new_op);
778 * The uprobe tracer format does not support constants; if we
779 * find one in the current argument, let's skip the argument.
780 */
781 if (strchr(desc, '$')) {
782 pr_debug4("Skipping unsupported SDT argument; %s\n", desc);
783 goto out;
784 }
785 744
786 /* 745 if (ret < 0)
787 * The uprobe parser does not support all gas register names; 746 goto error;
788 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
789 * the loop below looks for the register names (starting with
790 * a '%' and tries to perform the needed renamings.
791 */
792 tmp = strchr(desc, '%');
793 while (tmp) {
794 size_t offset = tmp - desc;
795 747
796 ret = sdt_rename_register(&desc, desc + offset); 748 if (ret == SDT_ARG_VALID) {
749 ret = strbuf_addf(buf, " arg%d=%s%s", i + 1, new_op, suffix);
797 if (ret < 0) 750 if (ret < 0)
798 goto error; 751 goto error;
799
800 /*
801 * The desc pointer might have changed; so, let's not
802 * try to reuse tmp for next lookup
803 */
804 tmp = strchr(desc + offset + 1, '%');
805 } 752 }
806 753
807 if (strbuf_addf(buf, " arg%d=%s%s%s", i + 1, prefix, desc, suffix) < 0)
808 goto error;
809
810out:
811 ret = 0; 754 ret = 0;
812error: 755error:
813 free(desc); 756 free(desc);
757 free(new_op);
814 return ret; 758 return ret;
815} 759}
816 760