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