SDT marker argument is in N@OP format. Here OP is arch dependent
component. Add powerpc logic to parse OP and convert it to uprobe
compatible format.

Signed-off-by: Ravi Bangoria <ravi.bango...@linux.vnet.ibm.com>
---
 tools/perf/arch/powerpc/util/perf_regs.c | 115 +++++++++++++++++++++++++++++++
 1 file changed, 115 insertions(+)

diff --git a/tools/perf/arch/powerpc/util/perf_regs.c 
b/tools/perf/arch/powerpc/util/perf_regs.c
index a3c3e1c..bbd6f91 100644
--- a/tools/perf/arch/powerpc/util/perf_regs.c
+++ b/tools/perf/arch/powerpc/util/perf_regs.c
@@ -1,5 +1,10 @@
+#include <string.h>
+#include <regex.h>
+
 #include "../../perf.h"
+#include "../../util/util.h"
 #include "../../util/perf_regs.h"
+#include "../../util/debug.h"
 
 const struct sample_reg sample_reg_masks[] = {
        SMPL_REG(r0, PERF_REG_POWERPC_R0),
@@ -47,3 +52,113 @@ const struct sample_reg sample_reg_masks[] = {
        SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR),
        SMPL_REG_END
 };
+
+bool arch_sdt_probe_arg_supp(void)
+{
+       return true;
+}
+
+static regex_t regex1, regex2;
+
+static int init_op_regex(void)
+{
+       static int initialized;
+
+       if (initialized)
+               return 0;
+
+       /* REG or %rREG */
+       if (regcomp(&regex1, "^(%r)?([1-2]?[0-9]|3[0-1])$", REG_EXTENDED))
+               goto error;
+
+       /* -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) */
+       if (regcomp(&regex2, "^(\\-)?([0-9]+)\\((%r)?([1-2]?[0-9]|3[0-1])\\)$",
+                       REG_EXTENDED))
+               goto free_regex1;
+
+       initialized = 1;
+       return 0;
+
+free_regex1:
+       regfree(&regex1);
+error:
+       pr_debug4("Regex compilation error.\n");
+       return -1;
+}
+
+/*
+ * Parse OP and convert it into uprobe format, which is, +/-NUM(%gprREG).
+ * Possible variants of OP are:
+ *     Format          Example
+ *     -------------------------
+ *     NUM(REG)        48(18)
+ *     -NUM(REG)       -48(18)
+ *     NUM(%rREG)      48(%r18)
+ *     -NUM(%rREG)     -48(%r18)
+ *     REG             18
+ *     %rREG           %r18
+ *     iNUM            i0
+ *     i-NUM           i-1
+ *
+ * SDT marker arguments on Powerpc uses %rREG form with -mregnames flag
+ * and REG form with -mno-regnames. Here REG is general purpose register,
+ * which is in 0 to 31 range.
+ *
+ * return value of the function:
+ *     <0 : error
+ *      0 : success
+ *     >0 : skip
+ */
+int arch_sdt_probe_parse_op(char **desc, const char **prefix)
+{
+       char *tmp = NULL;
+       size_t new_len;
+       regmatch_t rm[5];
+
+       /* Constant argument. Uprobe does not support it */
+       if (*desc[0] == 'i') {
+               pr_debug4("Skipping unsupported SDT argument: %s\n", *desc);
+               return 1;
+       }
+
+       if (init_op_regex() < 0)
+               return -1;
+
+       if (!regexec(&regex1, *desc, 3, rm, 0)) {
+               /* REG or %rREG --> %gprREG */
+               new_len = 5;
+               new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
+
+               tmp = zalloc(new_len);
+               if (!tmp)
+                       return -1;
+
+               scnprintf(tmp, new_len, "%%gpr%.*s",
+                       (int)(rm[2].rm_eo - rm[2].rm_so), *desc + rm[2].rm_so);
+       } else if (!regexec(&regex2, *desc, 5, rm, 0)) {
+               /*
+                * -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) -->
+                *      +/-NUM(%gprREG)
+                */
+               *prefix = (rm[1].rm_so == -1) ? "+" : "-";
+
+               new_len = 7;
+               new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
+               new_len += (int)(rm[4].rm_eo - rm[4].rm_so);
+
+               tmp = zalloc(new_len);
+               if (!tmp)
+                       return -1;
+
+               scnprintf(tmp, new_len, "%.*s(%%gpr%.*s)",
+                       (int)(rm[2].rm_eo - rm[2].rm_so), *desc + rm[2].rm_so,
+                       (int)(rm[4].rm_eo - rm[4].rm_so), *desc + rm[4].rm_so);
+       } else {
+               pr_debug4("Skipping unsupported SDT argument: %s\n", *desc);
+               return 1;
+       }
+
+       free(*desc);
+       *desc = tmp;
+       return 0;
+}
-- 
2.9.3

Reply via email to