0001
0002
0003
0004
0005
0006
0007 #include <stdlib.h>
0008 #include <stdio.h>
0009 #include <string.h>
0010 #include <assert.h>
0011 #include <unistd.h>
0012 #include <stdarg.h>
0013
0014 #define unlikely(cond) (cond)
0015
0016 #include <asm/insn.h>
0017 #include <inat.c>
0018 #include <insn.c>
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 const char *prog;
0029 static int verbose;
0030 static int x86_64;
0031
0032 static void usage(void)
0033 {
0034 fprintf(stderr, "Usage: objdump -d a.out | awk -f objdump_reformat.awk"
0035 " | %s [-y|-n] [-v]\n", prog);
0036 fprintf(stderr, "\t-y 64bit mode\n");
0037 fprintf(stderr, "\t-n 32bit mode\n");
0038 fprintf(stderr, "\t-v verbose mode\n");
0039 exit(1);
0040 }
0041
0042 static void malformed_line(const char *line, int line_nr)
0043 {
0044 fprintf(stderr, "%s: error: malformed line %d:\n%s",
0045 prog, line_nr, line);
0046 exit(3);
0047 }
0048
0049 static void pr_warn(const char *fmt, ...)
0050 {
0051 va_list ap;
0052
0053 fprintf(stderr, "%s: warning: ", prog);
0054 va_start(ap, fmt);
0055 vfprintf(stderr, fmt, ap);
0056 va_end(ap);
0057 }
0058
0059 static void dump_field(FILE *fp, const char *name, const char *indent,
0060 struct insn_field *field)
0061 {
0062 fprintf(fp, "%s.%s = {\n", indent, name);
0063 fprintf(fp, "%s\t.value = %d, bytes[] = {%x, %x, %x, %x},\n",
0064 indent, field->value, field->bytes[0], field->bytes[1],
0065 field->bytes[2], field->bytes[3]);
0066 fprintf(fp, "%s\t.got = %d, .nbytes = %d},\n", indent,
0067 field->got, field->nbytes);
0068 }
0069
0070 static void dump_insn(FILE *fp, struct insn *insn)
0071 {
0072 fprintf(fp, "Instruction = {\n");
0073 dump_field(fp, "prefixes", "\t", &insn->prefixes);
0074 dump_field(fp, "rex_prefix", "\t", &insn->rex_prefix);
0075 dump_field(fp, "vex_prefix", "\t", &insn->vex_prefix);
0076 dump_field(fp, "opcode", "\t", &insn->opcode);
0077 dump_field(fp, "modrm", "\t", &insn->modrm);
0078 dump_field(fp, "sib", "\t", &insn->sib);
0079 dump_field(fp, "displacement", "\t", &insn->displacement);
0080 dump_field(fp, "immediate1", "\t", &insn->immediate1);
0081 dump_field(fp, "immediate2", "\t", &insn->immediate2);
0082 fprintf(fp, "\t.attr = %x, .opnd_bytes = %d, .addr_bytes = %d,\n",
0083 insn->attr, insn->opnd_bytes, insn->addr_bytes);
0084 fprintf(fp, "\t.length = %d, .x86_64 = %d, .kaddr = %p}\n",
0085 insn->length, insn->x86_64, insn->kaddr);
0086 }
0087
0088 static void parse_args(int argc, char **argv)
0089 {
0090 int c;
0091 prog = argv[0];
0092 while ((c = getopt(argc, argv, "ynv")) != -1) {
0093 switch (c) {
0094 case 'y':
0095 x86_64 = 1;
0096 break;
0097 case 'n':
0098 x86_64 = 0;
0099 break;
0100 case 'v':
0101 verbose = 1;
0102 break;
0103 default:
0104 usage();
0105 }
0106 }
0107 }
0108
0109 #define BUFSIZE 256
0110
0111 int main(int argc, char **argv)
0112 {
0113 char line[BUFSIZE], sym[BUFSIZE] = "<unknown>";
0114 unsigned char insn_buff[16];
0115 struct insn insn;
0116 int insns = 0;
0117 int warnings = 0;
0118
0119 parse_args(argc, argv);
0120
0121 while (fgets(line, BUFSIZE, stdin)) {
0122 char copy[BUFSIZE], *s, *tab1, *tab2;
0123 int nb = 0, ret;
0124 unsigned int b;
0125
0126 if (line[0] == '<') {
0127
0128 strcpy(sym, line);
0129 continue;
0130 }
0131
0132 insns++;
0133 memset(insn_buff, 0, 16);
0134 strcpy(copy, line);
0135 tab1 = strchr(copy, '\t');
0136 if (!tab1)
0137 malformed_line(line, insns);
0138 s = tab1 + 1;
0139 s += strspn(s, " ");
0140 tab2 = strchr(s, '\t');
0141 if (!tab2)
0142 malformed_line(line, insns);
0143 *tab2 = '\0';
0144 while (s < tab2) {
0145 if (sscanf(s, "%x", &b) == 1) {
0146 insn_buff[nb++] = (unsigned char) b;
0147 s += 3;
0148 } else
0149 break;
0150 }
0151
0152
0153 ret = insn_decode(&insn, insn_buff, sizeof(insn_buff),
0154 x86_64 ? INSN_MODE_64 : INSN_MODE_32);
0155
0156 if (ret < 0 || insn.length != nb) {
0157 warnings++;
0158 pr_warn("Found an x86 instruction decoder bug, "
0159 "please report this.\n", sym);
0160 pr_warn("%s", line);
0161 pr_warn("objdump says %d bytes, but insn_get_length() "
0162 "says %d\n", nb, insn.length);
0163 if (verbose)
0164 dump_insn(stderr, &insn);
0165 }
0166 }
0167 if (warnings)
0168 pr_warn("Decoded and checked %d instructions with %d "
0169 "failures\n", insns, warnings);
0170 else
0171 fprintf(stdout, "%s: success: Decoded and checked %d"
0172 " instructions\n", prog, insns);
0173 return 0;
0174 }