Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/compiler.h>
0003 
0004 static int s390_call__parse(struct arch *arch, struct ins_operands *ops,
0005                 struct map_symbol *ms)
0006 {
0007     char *endptr, *tok, *name;
0008     struct map *map = ms->map;
0009     struct addr_map_symbol target = {
0010         .ms = { .map = map, },
0011     };
0012 
0013     tok = strchr(ops->raw, ',');
0014     if (!tok)
0015         return -1;
0016 
0017     ops->target.addr = strtoull(tok + 1, &endptr, 16);
0018 
0019     name = strchr(endptr, '<');
0020     if (name == NULL)
0021         return -1;
0022 
0023     name++;
0024 
0025     if (arch->objdump.skip_functions_char &&
0026         strchr(name, arch->objdump.skip_functions_char))
0027         return -1;
0028 
0029     tok = strchr(name, '>');
0030     if (tok == NULL)
0031         return -1;
0032 
0033     *tok = '\0';
0034     ops->target.name = strdup(name);
0035     *tok = '>';
0036 
0037     if (ops->target.name == NULL)
0038         return -1;
0039     target.addr = map__objdump_2mem(map, ops->target.addr);
0040 
0041     if (maps__find_ams(ms->maps, &target) == 0 &&
0042         map__rip_2objdump(target.ms.map, map->map_ip(target.ms.map, target.addr)) == ops->target.addr)
0043         ops->target.sym = target.ms.sym;
0044 
0045     return 0;
0046 }
0047 
0048 static int call__scnprintf(struct ins *ins, char *bf, size_t size,
0049                struct ins_operands *ops, int max_ins_name);
0050 
0051 static struct ins_ops s390_call_ops = {
0052     .parse     = s390_call__parse,
0053     .scnprintf = call__scnprintf,
0054 };
0055 
0056 static int s390_mov__parse(struct arch *arch __maybe_unused,
0057                struct ins_operands *ops,
0058                struct map_symbol *ms __maybe_unused)
0059 {
0060     char *s = strchr(ops->raw, ','), *target, *endptr;
0061 
0062     if (s == NULL)
0063         return -1;
0064 
0065     *s = '\0';
0066     ops->source.raw = strdup(ops->raw);
0067     *s = ',';
0068 
0069     if (ops->source.raw == NULL)
0070         return -1;
0071 
0072     target = ++s;
0073     ops->target.raw = strdup(target);
0074     if (ops->target.raw == NULL)
0075         goto out_free_source;
0076 
0077     ops->target.addr = strtoull(target, &endptr, 16);
0078     if (endptr == target)
0079         goto out_free_target;
0080 
0081     s = strchr(endptr, '<');
0082     if (s == NULL)
0083         goto out_free_target;
0084     endptr = strchr(s + 1, '>');
0085     if (endptr == NULL)
0086         goto out_free_target;
0087 
0088     *endptr = '\0';
0089     ops->target.name = strdup(s + 1);
0090     *endptr = '>';
0091     if (ops->target.name == NULL)
0092         goto out_free_target;
0093 
0094     return 0;
0095 
0096 out_free_target:
0097     zfree(&ops->target.raw);
0098 out_free_source:
0099     zfree(&ops->source.raw);
0100     return -1;
0101 }
0102 
0103 
0104 static struct ins_ops s390_mov_ops = {
0105     .parse     = s390_mov__parse,
0106     .scnprintf = mov__scnprintf,
0107 };
0108 
0109 static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *name)
0110 {
0111     struct ins_ops *ops = NULL;
0112 
0113     /* catch all kind of jumps */
0114     if (strchr(name, 'j') ||
0115         !strncmp(name, "bct", 3) ||
0116         !strncmp(name, "br", 2))
0117         ops = &jump_ops;
0118     /* override call/returns */
0119     if (!strcmp(name, "bras") ||
0120         !strcmp(name, "brasl") ||
0121         !strcmp(name, "basr"))
0122         ops = &s390_call_ops;
0123     if (!strcmp(name, "br"))
0124         ops = &ret_ops;
0125     /* override load/store relative to PC */
0126     if (!strcmp(name, "lrl") ||
0127         !strcmp(name, "lgrl") ||
0128         !strcmp(name, "lgfrl") ||
0129         !strcmp(name, "llgfrl") ||
0130         !strcmp(name, "strl") ||
0131         !strcmp(name, "stgrl"))
0132         ops = &s390_mov_ops;
0133 
0134     if (ops)
0135         arch__associate_ins_ops(arch, name, ops);
0136     return ops;
0137 }
0138 
0139 static int s390__cpuid_parse(struct arch *arch, char *cpuid)
0140 {
0141     unsigned int family;
0142     char model[16], model_c[16], cpumf_v[16], cpumf_a[16];
0143     int ret;
0144 
0145     /*
0146      * cpuid string format:
0147      * "IBM,family,model-capacity,model[,cpum_cf-version,cpum_cf-authorization]"
0148      */
0149     ret = sscanf(cpuid, "%*[^,],%u,%[^,],%[^,],%[^,],%s", &family, model_c,
0150              model, cpumf_v, cpumf_a);
0151     if (ret >= 2) {
0152         arch->family = family;
0153         arch->model = 0;
0154         return 0;
0155     }
0156 
0157     return -1;
0158 }
0159 
0160 static int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
0161 {
0162     int err = 0;
0163 
0164     if (!arch->initialized) {
0165         arch->initialized = true;
0166         arch->associate_instruction_ops = s390__associate_ins_ops;
0167         if (cpuid) {
0168             if (s390__cpuid_parse(arch, cpuid))
0169                 err = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING;
0170         }
0171     }
0172 
0173     return err;
0174 }