History

perf arm64: Add argument support for SDT

Now the two OP formats are used for SDT marker argument in Arm64 ELF, one format is general register xNUM (e.g. x1, x2, etc), another is for using stack pointer to access local variables (e.g. [sp], [sp, 8]). This patch adds support SDT marker argument for Arm64, it parses OP and converts to uprobe compatible format.

Leo Yan committed 5 years ago

Commit feab9991 parent f19b5871 file · +94 −0Browse files

Unified · Split

tools/perf/arch/arm64/util/perf_regs.c+94−0
@@ -1,4 +1,12 @@
1// SPDX-License-Identifier: GPL-2.01// SPDX-License-Identifier: GPL-2.0
2#include <errno.h>
3#include <regex.h>
4#include <string.h>
5#include <linux/kernel.h>
6#include <linux/zalloc.h>
7
8#include "../../../util/debug.h"
9#include "../../../util/event.h"
2#include "../../../util/perf_regs.h"10#include "../../../util/perf_regs.h"
3 11
4const struct sample_reg sample_reg_masks[] = {12const struct sample_reg sample_reg_masks[] = {
@@ -37,3 +45,89 @@ const struct sample_reg sample_reg_masks[] = { · 32 unmodified lines
37 SMPL_REG(pc, PERF_REG_ARM64_PC),45 SMPL_REG(pc, PERF_REG_ARM64_PC),
38 SMPL_REG_END46 SMPL_REG_END
39};47};
48
49/* %xNUM */
50#define SDT_OP_REGEX1 "^(x[1-2]?[0-9]|3[0-1])$"
51
52/* [sp], [sp, NUM] */
53#define SDT_OP_REGEX2 "^\\[sp(, )?([0-9]+)?\\]$"
54
55static regex_t sdt_op_regex1, sdt_op_regex2;
56
57static int sdt_init_op_regex(void)
58{
59 static int initialized;
60 int ret = 0;
61
62 if (initialized)
63 return 0;
64
65 ret = regcomp(&sdt_op_regex1, SDT_OP_REGEX1, REG_EXTENDED);
66 if (ret)
67 goto error;
68
69 ret = regcomp(&sdt_op_regex2, SDT_OP_REGEX2, REG_EXTENDED);
70 if (ret)
71 goto free_regex1;
72
73 initialized = 1;
74 return 0;
75
76free_regex1:
77 regfree(&sdt_op_regex1);
78error:
79 pr_debug4("Regex compilation error.\n");
80 return ret;
81}
82
83/*
84 * SDT marker arguments on Arm64 uses %xREG or [sp, NUM], currently
85 * support these two formats.
86 */
87int arch_sdt_arg_parse_op(char *old_op, char **new_op)
88{
89 int ret, new_len;
90 regmatch_t rm[5];
91
92 ret = sdt_init_op_regex();
93 if (ret < 0)
94 return ret;
95
96 if (!regexec(&sdt_op_regex1, old_op, 3, rm, 0)) {
97 /* Extract xNUM */
98 new_len = 2; /* % NULL */
99 new_len += (int)(rm[1].rm_eo - rm[1].rm_so);
100
101 *new_op = zalloc(new_len);
102 if (!*new_op)
103 return -ENOMEM;
104
105 scnprintf(*new_op, new_len, "%%%.*s",
106 (int)(rm[1].rm_eo - rm[1].rm_so), old_op + rm[1].rm_so);
107 } else if (!regexec(&sdt_op_regex2, old_op, 5, rm, 0)) {
108 /* [sp], [sp, NUM] or [sp,NUM] */
109 new_len = 7; /* + ( % s p ) NULL */
110
111 /* If the arugment is [sp], need to fill offset '0' */
112 if (rm[2].rm_so == -1)
113 new_len += 1;
114 else
115 new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
116
117 *new_op = zalloc(new_len);
118 if (!*new_op)
119 return -ENOMEM;
120
121 if (rm[2].rm_so == -1)
122 scnprintf(*new_op, new_len, "+0(%%sp)");
123 else
124 scnprintf(*new_op, new_len, "+%.*s(%%sp)",
125 (int)(rm[2].rm_eo - rm[2].rm_so),
126 old_op + rm[2].rm_so);
127 } else {
128 pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
129 return SDT_ARG_SKIP;
130 }
131
132 return SDT_ARG_VALID;
133}