cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

instructions.c (2645B)


      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}