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