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

insn_decoder_test.c (4217B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *
      4 * Copyright (C) IBM Corporation, 2009
      5 */
      6
      7#include <stdlib.h>
      8#include <stdio.h>
      9#include <string.h>
     10#include <assert.h>
     11#include <unistd.h>
     12#include <stdarg.h>
     13
     14#define unlikely(cond) (cond)
     15
     16#include <asm/insn.h>
     17#include <inat.c>
     18#include <insn.c>
     19
     20/*
     21 * Test of instruction analysis in general and insn_get_length() in
     22 * particular.  See if insn_get_length() and the disassembler agree
     23 * on the length of each instruction in an elf disassembly.
     24 *
     25 * Usage: objdump -d a.out | awk -f objdump_reformat.awk | ./insn_decoder_test
     26 */
     27
     28const char *prog;
     29static int verbose;
     30static int x86_64;
     31
     32static void usage(void)
     33{
     34	fprintf(stderr, "Usage: objdump -d a.out | awk -f objdump_reformat.awk"
     35		" | %s [-y|-n] [-v]\n", prog);
     36	fprintf(stderr, "\t-y	64bit mode\n");
     37	fprintf(stderr, "\t-n	32bit mode\n");
     38	fprintf(stderr, "\t-v	verbose mode\n");
     39	exit(1);
     40}
     41
     42static void malformed_line(const char *line, int line_nr)
     43{
     44	fprintf(stderr, "%s: error: malformed line %d:\n%s",
     45		prog, line_nr, line);
     46	exit(3);
     47}
     48
     49static void pr_warn(const char *fmt, ...)
     50{
     51	va_list ap;
     52
     53	fprintf(stderr, "%s: warning: ", prog);
     54	va_start(ap, fmt);
     55	vfprintf(stderr, fmt, ap);
     56	va_end(ap);
     57}
     58
     59static void dump_field(FILE *fp, const char *name, const char *indent,
     60		       struct insn_field *field)
     61{
     62	fprintf(fp, "%s.%s = {\n", indent, name);
     63	fprintf(fp, "%s\t.value = %d, bytes[] = {%x, %x, %x, %x},\n",
     64		indent, field->value, field->bytes[0], field->bytes[1],
     65		field->bytes[2], field->bytes[3]);
     66	fprintf(fp, "%s\t.got = %d, .nbytes = %d},\n", indent,
     67		field->got, field->nbytes);
     68}
     69
     70static void dump_insn(FILE *fp, struct insn *insn)
     71{
     72	fprintf(fp, "Instruction = {\n");
     73	dump_field(fp, "prefixes", "\t",	&insn->prefixes);
     74	dump_field(fp, "rex_prefix", "\t",	&insn->rex_prefix);
     75	dump_field(fp, "vex_prefix", "\t",	&insn->vex_prefix);
     76	dump_field(fp, "opcode", "\t",		&insn->opcode);
     77	dump_field(fp, "modrm", "\t",		&insn->modrm);
     78	dump_field(fp, "sib", "\t",		&insn->sib);
     79	dump_field(fp, "displacement", "\t",	&insn->displacement);
     80	dump_field(fp, "immediate1", "\t",	&insn->immediate1);
     81	dump_field(fp, "immediate2", "\t",	&insn->immediate2);
     82	fprintf(fp, "\t.attr = %x, .opnd_bytes = %d, .addr_bytes = %d,\n",
     83		insn->attr, insn->opnd_bytes, insn->addr_bytes);
     84	fprintf(fp, "\t.length = %d, .x86_64 = %d, .kaddr = %p}\n",
     85		insn->length, insn->x86_64, insn->kaddr);
     86}
     87
     88static void parse_args(int argc, char **argv)
     89{
     90	int c;
     91	prog = argv[0];
     92	while ((c = getopt(argc, argv, "ynv")) != -1) {
     93		switch (c) {
     94		case 'y':
     95			x86_64 = 1;
     96			break;
     97		case 'n':
     98			x86_64 = 0;
     99			break;
    100		case 'v':
    101			verbose = 1;
    102			break;
    103		default:
    104			usage();
    105		}
    106	}
    107}
    108
    109#define BUFSIZE 256
    110
    111int main(int argc, char **argv)
    112{
    113	char line[BUFSIZE], sym[BUFSIZE] = "<unknown>";
    114	unsigned char insn_buff[16];
    115	struct insn insn;
    116	int insns = 0;
    117	int warnings = 0;
    118
    119	parse_args(argc, argv);
    120
    121	while (fgets(line, BUFSIZE, stdin)) {
    122		char copy[BUFSIZE], *s, *tab1, *tab2;
    123		int nb = 0, ret;
    124		unsigned int b;
    125
    126		if (line[0] == '<') {
    127			/* Symbol line */
    128			strcpy(sym, line);
    129			continue;
    130		}
    131
    132		insns++;
    133		memset(insn_buff, 0, 16);
    134		strcpy(copy, line);
    135		tab1 = strchr(copy, '\t');
    136		if (!tab1)
    137			malformed_line(line, insns);
    138		s = tab1 + 1;
    139		s += strspn(s, " ");
    140		tab2 = strchr(s, '\t');
    141		if (!tab2)
    142			malformed_line(line, insns);
    143		*tab2 = '\0';	/* Characters beyond tab2 aren't examined */
    144		while (s < tab2) {
    145			if (sscanf(s, "%x", &b) == 1) {
    146				insn_buff[nb++] = (unsigned char) b;
    147				s += 3;
    148			} else
    149				break;
    150		}
    151
    152		/* Decode an instruction */
    153		ret = insn_decode(&insn, insn_buff, sizeof(insn_buff),
    154				  x86_64 ? INSN_MODE_64 : INSN_MODE_32);
    155
    156		if (ret < 0 || insn.length != nb) {
    157			warnings++;
    158			pr_warn("Found an x86 instruction decoder bug, "
    159				"please report this.\n", sym);
    160			pr_warn("%s", line);
    161			pr_warn("objdump says %d bytes, but insn_get_length() "
    162				"says %d\n", nb, insn.length);
    163			if (verbose)
    164				dump_insn(stderr, &insn);
    165		}
    166	}
    167	if (warnings)
    168		pr_warn("Decoded and checked %d instructions with %d "
    169			"failures\n", insns, warnings);
    170	else
    171		fprintf(stdout, "%s: success: Decoded and checked %d"
    172			" instructions\n", prog, insns);
    173	return 0;
    174}