0001
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
0114 if (strchr(name, 'j') ||
0115 !strncmp(name, "bct", 3) ||
0116 !strncmp(name, "br", 2))
0117 ops = &jump_ops;
0118
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
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
0147
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 }