]> Git Repo - linux.git/blob - tools/perf/arch/arm64/annotate/instructions.c
Linux 6.14-rc3
[linux.git] / tools / perf / arch / arm64 / annotate / instructions.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/compiler.h>
3 #include <sys/types.h>
4 #include <regex.h>
5 #include <stdlib.h>
6
7 struct arm64_annotate {
8         regex_t call_insn,
9                 jump_insn;
10 };
11
12 static int arm64_mov__parse(struct arch *arch __maybe_unused,
13                             struct ins_operands *ops,
14                             struct map_symbol *ms __maybe_unused,
15                             struct disasm_line *dl __maybe_unused)
16 {
17         char *s = strchr(ops->raw, ','), *target, *endptr;
18
19         if (s == NULL)
20                 return -1;
21
22         *s = '\0';
23         ops->source.raw = strdup(ops->raw);
24         *s = ',';
25
26         if (ops->source.raw == NULL)
27                 return -1;
28
29         target = ++s;
30         ops->target.raw = strdup(target);
31         if (ops->target.raw == NULL)
32                 goto out_free_source;
33
34         ops->target.addr = strtoull(target, &endptr, 16);
35         if (endptr == target)
36                 goto out_free_target;
37
38         s = strchr(endptr, '<');
39         if (s == NULL)
40                 goto out_free_target;
41         endptr = strchr(s + 1, '>');
42         if (endptr == NULL)
43                 goto out_free_target;
44
45         *endptr = '\0';
46         *s = ' ';
47         ops->target.name = strdup(s);
48         *s = '<';
49         *endptr = '>';
50         if (ops->target.name == NULL)
51                 goto out_free_target;
52
53         return 0;
54
55 out_free_target:
56         zfree(&ops->target.raw);
57 out_free_source:
58         zfree(&ops->source.raw);
59         return -1;
60 }
61
62 static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
63                           struct ins_operands *ops, int max_ins_name);
64
65 static struct ins_ops arm64_mov_ops = {
66         .parse     = arm64_mov__parse,
67         .scnprintf = mov__scnprintf,
68 };
69
70 static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const char *name)
71 {
72         struct arm64_annotate *arm = arch->priv;
73         struct ins_ops *ops;
74         regmatch_t match[2];
75
76         if (!regexec(&arm->jump_insn, name, 2, match, 0))
77                 ops = &jump_ops;
78         else if (!regexec(&arm->call_insn, name, 2, match, 0))
79                 ops = &call_ops;
80         else if (!strcmp(name, "ret"))
81                 ops = &ret_ops;
82         else
83                 ops = &arm64_mov_ops;
84
85         arch__associate_ins_ops(arch, name, ops);
86         return ops;
87 }
88
89 static int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
90 {
91         struct arm64_annotate *arm;
92         int err;
93
94         if (arch->initialized)
95                 return 0;
96
97         arm = zalloc(sizeof(*arm));
98         if (!arm)
99                 return ENOMEM;
100
101         /* bl, blr */
102         err = regcomp(&arm->call_insn, "^blr?$", REG_EXTENDED);
103         if (err)
104                 goto out_free_arm;
105         /* b, b.cond, br, cbz/cbnz, tbz/tbnz */
106         err = regcomp(&arm->jump_insn, "^[ct]?br?\\.?(cc|cs|eq|ge|gt|hi|hs|le|lo|ls|lt|mi|ne|pl|vc|vs)?n?z?$",
107                       REG_EXTENDED);
108         if (err)
109                 goto out_free_call;
110
111         arch->initialized = true;
112         arch->priv        = arm;
113         arch->associate_instruction_ops   = arm64__associate_instruction_ops;
114         arch->objdump.comment_char        = '/';
115         arch->objdump.skip_functions_char = '+';
116         arch->e_machine = EM_AARCH64;
117         arch->e_flags = 0;
118         return 0;
119
120 out_free_call:
121         regfree(&arm->call_insn);
122 out_free_arm:
123         free(arm);
124         return SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_REGEXP;
125 }
This page took 0.034326 seconds and 4 git commands to generate.