root/tools/perf/arch/s390/annotate/instructions.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. s390_call__parse
  2. s390_mov__parse
  3. s390__associate_ins_ops
  4. s390__cpuid_parse
  5. s390__annotate_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <linux/compiler.h>
   3 
   4 static int s390_call__parse(struct arch *arch, struct ins_operands *ops,
   5                             struct map_symbol *ms)
   6 {
   7         char *endptr, *tok, *name;
   8         struct map *map = ms->map;
   9         struct addr_map_symbol target = {
  10                 .map = map,
  11         };
  12 
  13         tok = strchr(ops->raw, ',');
  14         if (!tok)
  15                 return -1;
  16 
  17         ops->target.addr = strtoull(tok + 1, &endptr, 16);
  18 
  19         name = strchr(endptr, '<');
  20         if (name == NULL)
  21                 return -1;
  22 
  23         name++;
  24 
  25         if (arch->objdump.skip_functions_char &&
  26             strchr(name, arch->objdump.skip_functions_char))
  27                 return -1;
  28 
  29         tok = strchr(name, '>');
  30         if (tok == NULL)
  31                 return -1;
  32 
  33         *tok = '\0';
  34         ops->target.name = strdup(name);
  35         *tok = '>';
  36 
  37         if (ops->target.name == NULL)
  38                 return -1;
  39         target.addr = map__objdump_2mem(map, ops->target.addr);
  40 
  41         if (map_groups__find_ams(&target) == 0 &&
  42             map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr)
  43                 ops->target.sym = target.sym;
  44 
  45         return 0;
  46 }
  47 
  48 static int call__scnprintf(struct ins *ins, char *bf, size_t size,
  49                            struct ins_operands *ops, int max_ins_name);
  50 
  51 static struct ins_ops s390_call_ops = {
  52         .parse     = s390_call__parse,
  53         .scnprintf = call__scnprintf,
  54 };
  55 
  56 static int s390_mov__parse(struct arch *arch __maybe_unused,
  57                            struct ins_operands *ops,
  58                            struct map_symbol *ms __maybe_unused)
  59 {
  60         char *s = strchr(ops->raw, ','), *target, *endptr;
  61 
  62         if (s == NULL)
  63                 return -1;
  64 
  65         *s = '\0';
  66         ops->source.raw = strdup(ops->raw);
  67         *s = ',';
  68 
  69         if (ops->source.raw == NULL)
  70                 return -1;
  71 
  72         target = ++s;
  73         ops->target.raw = strdup(target);
  74         if (ops->target.raw == NULL)
  75                 goto out_free_source;
  76 
  77         ops->target.addr = strtoull(target, &endptr, 16);
  78         if (endptr == target)
  79                 goto out_free_target;
  80 
  81         s = strchr(endptr, '<');
  82         if (s == NULL)
  83                 goto out_free_target;
  84         endptr = strchr(s + 1, '>');
  85         if (endptr == NULL)
  86                 goto out_free_target;
  87 
  88         *endptr = '\0';
  89         ops->target.name = strdup(s + 1);
  90         *endptr = '>';
  91         if (ops->target.name == NULL)
  92                 goto out_free_target;
  93 
  94         return 0;
  95 
  96 out_free_target:
  97         zfree(&ops->target.raw);
  98 out_free_source:
  99         zfree(&ops->source.raw);
 100         return -1;
 101 }
 102 
 103 
 104 static struct ins_ops s390_mov_ops = {
 105         .parse     = s390_mov__parse,
 106         .scnprintf = mov__scnprintf,
 107 };
 108 
 109 static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *name)
 110 {
 111         struct ins_ops *ops = NULL;
 112 
 113         /* catch all kind of jumps */
 114         if (strchr(name, 'j') ||
 115             !strncmp(name, "bct", 3) ||
 116             !strncmp(name, "br", 2))
 117                 ops = &jump_ops;
 118         /* override call/returns */
 119         if (!strcmp(name, "bras") ||
 120             !strcmp(name, "brasl") ||
 121             !strcmp(name, "basr"))
 122                 ops = &s390_call_ops;
 123         if (!strcmp(name, "br"))
 124                 ops = &ret_ops;
 125         /* override load/store relative to PC */
 126         if (!strcmp(name, "lrl") ||
 127             !strcmp(name, "lgrl") ||
 128             !strcmp(name, "lgfrl") ||
 129             !strcmp(name, "llgfrl") ||
 130             !strcmp(name, "strl") ||
 131             !strcmp(name, "stgrl"))
 132                 ops = &s390_mov_ops;
 133 
 134         if (ops)
 135                 arch__associate_ins_ops(arch, name, ops);
 136         return ops;
 137 }
 138 
 139 static int s390__cpuid_parse(struct arch *arch, char *cpuid)
 140 {
 141         unsigned int family;
 142         char model[16], model_c[16], cpumf_v[16], cpumf_a[16];
 143         int ret;
 144 
 145         /*
 146          * cpuid string format:
 147          * "IBM,family,model-capacity,model[,cpum_cf-version,cpum_cf-authorization]"
 148          */
 149         ret = sscanf(cpuid, "%*[^,],%u,%[^,],%[^,],%[^,],%s", &family, model_c,
 150                      model, cpumf_v, cpumf_a);
 151         if (ret >= 2) {
 152                 arch->family = family;
 153                 arch->model = 0;
 154                 return 0;
 155         }
 156 
 157         return -1;
 158 }
 159 
 160 static int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
 161 {
 162         int err = 0;
 163 
 164         if (!arch->initialized) {
 165                 arch->initialized = true;
 166                 arch->associate_instruction_ops = s390__associate_ins_ops;
 167                 if (cpuid) {
 168                         if (s390__cpuid_parse(arch, cpuid))
 169                                 err = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING;
 170                 }
 171         }
 172 
 173         return err;
 174 }

/* [<][>][^][v][top][bottom][index][help] */