1 // SPDX-License-Identifier: GPL-2.0
6 #include "../../perf.h"
7 #include "../../util/util.h"
8 #include "../../util/perf_regs.h"
9 #include "../../util/debug.h"
11 const struct sample_reg sample_reg_masks
[] = {
12 SMPL_REG(AX
, PERF_REG_X86_AX
),
13 SMPL_REG(BX
, PERF_REG_X86_BX
),
14 SMPL_REG(CX
, PERF_REG_X86_CX
),
15 SMPL_REG(DX
, PERF_REG_X86_DX
),
16 SMPL_REG(SI
, PERF_REG_X86_SI
),
17 SMPL_REG(DI
, PERF_REG_X86_DI
),
18 SMPL_REG(BP
, PERF_REG_X86_BP
),
19 SMPL_REG(SP
, PERF_REG_X86_SP
),
20 SMPL_REG(IP
, PERF_REG_X86_IP
),
21 SMPL_REG(FLAGS
, PERF_REG_X86_FLAGS
),
22 SMPL_REG(CS
, PERF_REG_X86_CS
),
23 SMPL_REG(SS
, PERF_REG_X86_SS
),
24 #ifdef HAVE_ARCH_X86_64_SUPPORT
25 SMPL_REG(R8
, PERF_REG_X86_R8
),
26 SMPL_REG(R9
, PERF_REG_X86_R9
),
27 SMPL_REG(R10
, PERF_REG_X86_R10
),
28 SMPL_REG(R11
, PERF_REG_X86_R11
),
29 SMPL_REG(R12
, PERF_REG_X86_R12
),
30 SMPL_REG(R13
, PERF_REG_X86_R13
),
31 SMPL_REG(R14
, PERF_REG_X86_R14
),
32 SMPL_REG(R15
, PERF_REG_X86_R15
),
39 const char *uprobe_name
;
41 #define SDT_NAME_REG(n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}
42 #define SDT_NAME_REG_END {.sdt_name = NULL, .uprobe_name = NULL}
44 static const struct sdt_name_reg sdt_reg_tbl
[] = {
45 SDT_NAME_REG(eax
, ax
),
46 SDT_NAME_REG(rax
, ax
),
49 SDT_NAME_REG(ebx
, bx
),
50 SDT_NAME_REG(rbx
, bx
),
53 SDT_NAME_REG(ecx
, cx
),
54 SDT_NAME_REG(rcx
, cx
),
57 SDT_NAME_REG(edx
, dx
),
58 SDT_NAME_REG(rdx
, dx
),
61 SDT_NAME_REG(esi
, si
),
62 SDT_NAME_REG(rsi
, si
),
63 SDT_NAME_REG(sil
, si
),
64 SDT_NAME_REG(edi
, di
),
65 SDT_NAME_REG(rdi
, di
),
66 SDT_NAME_REG(dil
, di
),
67 SDT_NAME_REG(ebp
, bp
),
68 SDT_NAME_REG(rbp
, bp
),
69 SDT_NAME_REG(bpl
, bp
),
70 SDT_NAME_REG(rsp
, sp
),
71 SDT_NAME_REG(esp
, sp
),
72 SDT_NAME_REG(spl
, sp
),
75 SDT_NAME_REG(r8b
, r8
),
76 SDT_NAME_REG(r8w
, r8
),
77 SDT_NAME_REG(r8d
, r8
),
78 SDT_NAME_REG(r9b
, r9
),
79 SDT_NAME_REG(r9w
, r9
),
80 SDT_NAME_REG(r9d
, r9
),
81 SDT_NAME_REG(r10b
, r10
),
82 SDT_NAME_REG(r10w
, r10
),
83 SDT_NAME_REG(r10d
, r10
),
84 SDT_NAME_REG(r11b
, r11
),
85 SDT_NAME_REG(r11w
, r11
),
86 SDT_NAME_REG(r11d
, r11
),
87 SDT_NAME_REG(r12b
, r12
),
88 SDT_NAME_REG(r12w
, r12
),
89 SDT_NAME_REG(r12d
, r12
),
90 SDT_NAME_REG(r13b
, r13
),
91 SDT_NAME_REG(r13w
, r13
),
92 SDT_NAME_REG(r13d
, r13
),
93 SDT_NAME_REG(r14b
, r14
),
94 SDT_NAME_REG(r14w
, r14
),
95 SDT_NAME_REG(r14d
, r14
),
96 SDT_NAME_REG(r15b
, r15
),
97 SDT_NAME_REG(r15w
, r15
),
98 SDT_NAME_REG(r15d
, r15
),
103 * Perf only supports OP which is in +/-NUM(REG) form.
104 * Here plus-minus sign, NUM and parenthesis are optional,
105 * only REG is mandatory.
107 * SDT events also supports indirect addressing mode with a
108 * symbol as offset, scaled mode and constants in OP. But
109 * perf does not support them yet. Below are few examples.
111 * OP with scaled mode:
115 * OP with indirect addressing mode:
120 * OP with constant values:
125 #define SDT_OP_REGEX "^([+\\-]?)([0-9]*)(\\(?)(%[a-z][a-z0-9]+)(\\)?)$"
127 static regex_t sdt_op_regex
;
129 static int sdt_init_op_regex(void)
131 static int initialized
;
137 ret
= regcomp(&sdt_op_regex
, SDT_OP_REGEX
, REG_EXTENDED
);
139 pr_debug4("Regex compilation error.\n");
148 * Max x86 register name length is 5(ex: %r15d). So, 6th char
149 * should always contain NULL. This helps to find register name
150 * length using strlen, insted of maintaing one more variable.
152 #define SDT_REG_NAME_SIZE 6
155 * The uprobe parser does not support all gas register names;
156 * so, we have to replace them (ex. for x86_64: %rax -> %ax).
157 * Note: If register does not require renaming, just copy
158 * paste as it is, but don't leave it empty.
160 static void sdt_rename_register(char *sdt_reg
, int sdt_len
, char *uprobe_reg
)
164 for (i
= 0; sdt_reg_tbl
[i
].sdt_name
!= NULL
; i
++) {
165 if (!strncmp(sdt_reg_tbl
[i
].sdt_name
, sdt_reg
, sdt_len
)) {
166 strcpy(uprobe_reg
, sdt_reg_tbl
[i
].uprobe_name
);
171 strncpy(uprobe_reg
, sdt_reg
, sdt_len
);
174 int arch_sdt_arg_parse_op(char *old_op
, char **new_op
)
176 char new_reg
[SDT_REG_NAME_SIZE
] = {0};
177 int new_len
= 0, ret
;
188 * Max prefix length is 2 as it may contains sign(+/-)
189 * and displacement 0 (Both sign and displacement 0 are
190 * optional so it may be empty). Use one more character
191 * to hold last NULL so that strlen can be used to find
192 * prefix length, instead of maintaing one more variable.
194 char prefix
[3] = {0};
196 ret
= sdt_init_op_regex();
201 * If unsupported OR does not match with regex OR
202 * register name too long, skip it.
204 if (strchr(old_op
, ',') || strchr(old_op
, '$') ||
205 regexec(&sdt_op_regex
, old_op
, 6, rm
, 0) ||
206 rm
[4].rm_eo
- rm
[4].rm_so
> SDT_REG_NAME_SIZE
) {
207 pr_debug4("Skipping unsupported SDT argument: %s\n", old_op
);
213 * If SDT OP has parenthesis but does not provide
214 * displacement, add 0 for displacement.
216 * -----------------------------
217 * +24(%rdi) +24(%di) +
218 * 24(%rdi) +24(%di) +
221 * -80(%rbx) -80(%bx) -
223 if (rm
[3].rm_so
!= rm
[3].rm_eo
) {
224 if (rm
[1].rm_so
!= rm
[1].rm_eo
)
225 prefix
[0] = *(old_op
+ rm
[1].rm_so
);
226 else if (rm
[2].rm_so
!= rm
[2].rm_eo
)
229 strncpy(prefix
, "+0", 2);
232 /* Rename register */
233 sdt_rename_register(old_op
+ rm
[4].rm_so
, rm
[4].rm_eo
- rm
[4].rm_so
,
236 /* Prepare final OP which should be valid for uprobe_events */
237 new_len
= strlen(prefix
) +
238 (rm
[2].rm_eo
- rm
[2].rm_so
) +
239 (rm
[3].rm_eo
- rm
[3].rm_so
) +
241 (rm
[5].rm_eo
- rm
[5].rm_so
) +
244 *new_op
= zalloc(new_len
);
248 scnprintf(*new_op
, new_len
, "%.*s%.*s%.*s%.*s%.*s",
249 strlen(prefix
), prefix
,
250 (int)(rm
[2].rm_eo
- rm
[2].rm_so
), old_op
+ rm
[2].rm_so
,
251 (int)(rm
[3].rm_eo
- rm
[3].rm_so
), old_op
+ rm
[3].rm_so
,
252 strlen(new_reg
), new_reg
,
253 (int)(rm
[5].rm_eo
- rm
[5].rm_so
), old_op
+ rm
[5].rm_so
);
255 return SDT_ARG_VALID
;