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