Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/compiler.h>
0003 #include <sys/types.h>
0004 #include <regex.h>
0005 #include <stdlib.h>
0006 
0007 struct arm64_annotate {
0008     regex_t call_insn,
0009         jump_insn;
0010 };
0011 
0012 static int arm64_mov__parse(struct arch *arch __maybe_unused,
0013                 struct ins_operands *ops,
0014                 struct map_symbol *ms __maybe_unused)
0015 {
0016     char *s = strchr(ops->raw, ','), *target, *endptr;
0017 
0018     if (s == NULL)
0019         return -1;
0020 
0021     *s = '\0';
0022     ops->source.raw = strdup(ops->raw);
0023     *s = ',';
0024 
0025     if (ops->source.raw == NULL)
0026         return -1;
0027 
0028     target = ++s;
0029     ops->target.raw = strdup(target);
0030     if (ops->target.raw == NULL)
0031         goto out_free_source;
0032 
0033     ops->target.addr = strtoull(target, &endptr, 16);
0034     if (endptr == target)
0035         goto out_free_target;
0036 
0037     s = strchr(endptr, '<');
0038     if (s == NULL)
0039         goto out_free_target;
0040     endptr = strchr(s + 1, '>');
0041     if (endptr == NULL)
0042         goto out_free_target;
0043 
0044     *endptr = '\0';
0045     *s = ' ';
0046     ops->target.name = strdup(s);
0047     *s = '<';
0048     *endptr = '>';
0049     if (ops->target.name == NULL)
0050         goto out_free_target;
0051 
0052     return 0;
0053 
0054 out_free_target:
0055     zfree(&ops->target.raw);
0056 out_free_source:
0057     zfree(&ops->source.raw);
0058     return -1;
0059 }
0060 
0061 static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
0062               struct ins_operands *ops, int max_ins_name);
0063 
0064 static struct ins_ops arm64_mov_ops = {
0065     .parse     = arm64_mov__parse,
0066     .scnprintf = mov__scnprintf,
0067 };
0068 
0069 static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const char *name)
0070 {
0071     struct arm64_annotate *arm = arch->priv;
0072     struct ins_ops *ops;
0073     regmatch_t match[2];
0074 
0075     if (!regexec(&arm->jump_insn, name, 2, match, 0))
0076         ops = &jump_ops;
0077     else if (!regexec(&arm->call_insn, name, 2, match, 0))
0078         ops = &call_ops;
0079     else if (!strcmp(name, "ret"))
0080         ops = &ret_ops;
0081     else
0082         ops = &arm64_mov_ops;
0083 
0084     arch__associate_ins_ops(arch, name, ops);
0085     return ops;
0086 }
0087 
0088 static int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
0089 {
0090     struct arm64_annotate *arm;
0091     int err;
0092 
0093     if (arch->initialized)
0094         return 0;
0095 
0096     arm = zalloc(sizeof(*arm));
0097     if (!arm)
0098         return ENOMEM;
0099 
0100     /* bl, blr */
0101     err = regcomp(&arm->call_insn, "^blr?$", REG_EXTENDED);
0102     if (err)
0103         goto out_free_arm;
0104     /* b, b.cond, br, cbz/cbnz, tbz/tbnz */
0105     err = regcomp(&arm->jump_insn, "^[ct]?br?\\.?(cc|cs|eq|ge|gt|hi|le|ls|lt|mi|ne|pl)?n?z?$",
0106               REG_EXTENDED);
0107     if (err)
0108         goto out_free_call;
0109 
0110     arch->initialized = true;
0111     arch->priv    = arm;
0112     arch->associate_instruction_ops   = arm64__associate_instruction_ops;
0113     arch->objdump.comment_char    = '/';
0114     arch->objdump.skip_functions_char = '+';
0115     return 0;
0116 
0117 out_free_call:
0118     regfree(&arm->call_insn);
0119 out_free_arm:
0120     free(arm);
0121     return SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_REGEXP;
0122 }