You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
6.8 KiB
225 lines
6.8 KiB
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ |
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ |
|
╞══════════════════════════════════════════════════════════════════════════════╡ |
|
│ Copyright 2020 Justine Alexandra Roberts Tunney │ |
|
│ │ |
|
│ This program is free software; you can redistribute it and/or modify │ |
|
│ it under the terms of the GNU General Public License as published by │ |
|
│ the Free Software Foundation; version 2 of the License. │ |
|
│ │ |
|
│ This program is distributed in the hope that it will be useful, but │ |
|
│ WITHOUT ANY WARRANTY; without even the implied warranty of │ |
|
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │ |
|
│ General Public License for more details. │ |
|
│ │ |
|
│ You should have received a copy of the GNU General Public License │ |
|
│ along with this program; if not, write to the Free Software │ |
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │ |
|
│ 02110-1301 USA │ |
|
╚─────────────────────────────────────────────────────────────────────────────*/ |
|
#include "libc/bits/bits.h" |
|
#include "libc/macros.h" |
|
#include "libc/runtime/runtime.h" |
|
#include "libc/stdio/stdio.h" |
|
#include "libc/str/str.h" |
|
#include "libc/sysv/consts/ex.h" |
|
#include "libc/sysv/consts/exit.h" |
|
#include "third_party/getopt/getopt.h" |
|
#include "third_party/xed/x86.h" |
|
#include "tool/decode/lib/idname.h" |
|
#include "tool/decode/lib/xederrors.h" |
|
|
|
const struct IdName kXedModeNames[] = { |
|
{XED_MACHINE_MODE_LONG_64, "long"}, |
|
{XED_MACHINE_MODE_LONG_COMPAT_32, "long32"}, |
|
{XED_MACHINE_MODE_LONG_COMPAT_16, "long16"}, |
|
{XED_MACHINE_MODE_LEGACY_32, "legacy"}, |
|
{XED_MACHINE_MODE_LEGACY_16, "legacy16"}, |
|
{XED_MACHINE_MODE_REAL, "real"}, |
|
{XED_MACHINE_MODE_UNREAL, "unreal"}, |
|
}; |
|
|
|
enum XedMachineMode g_mode; |
|
struct XedDecodedInst g_xedd; |
|
|
|
noreturn void ShowUsage(int rc, FILE *f) { |
|
size_t i; |
|
fputs("Usage: ", f); |
|
fputs(program_invocation_name, f); |
|
fputs(" [-rl] [-m MODE] HEX\n MODE ∊ {", f); |
|
fputs(kXedModeNames[0].name, f); |
|
for (i = 1; i < ARRAYLEN(kXedModeNames); ++i) { |
|
fputc(',', f); |
|
fputs(kXedModeNames[i].name, f); |
|
} |
|
fputs("}\n", f); |
|
exit(rc); |
|
} |
|
|
|
void SetMachineMode(const char *s) { |
|
size_t i; |
|
for (i = 0; i < ARRAYLEN(kXedModeNames); ++i) { |
|
if (strcasecmp(s, kXedModeNames[i].name) == 0) { |
|
g_mode = kXedModeNames[i].id; |
|
return; |
|
} |
|
} |
|
fputs("error: bad mode\n", stderr); |
|
ShowUsage(EXIT_FAILURE, stderr); |
|
} |
|
|
|
void GetOpts(int argc, char *argv[]) { |
|
int opt; |
|
g_mode = XED_MACHINE_MODE_LONG_64; |
|
while ((opt = getopt(argc, argv, "?hrlm:")) != -1) { |
|
switch (opt) { |
|
case 'r': |
|
g_mode = XED_MACHINE_MODE_REAL; |
|
break; |
|
case 'l': |
|
g_mode = XED_MACHINE_MODE_LEGACY_32; |
|
break; |
|
case 'm': |
|
SetMachineMode(optarg); |
|
break; |
|
case '?': |
|
case 'h': |
|
ShowUsage(EXIT_SUCCESS, stdout); |
|
default: |
|
ShowUsage(EX_USAGE, stderr); |
|
} |
|
} |
|
} |
|
|
|
void CheckHex(const char *s) { |
|
size_t i, n; |
|
if ((n = strlen(s)) % 2 == 1) { |
|
ShowUsage(EX_DATAERR, stderr); |
|
} |
|
for (i = 0; i < n; ++i) { |
|
if (!isxdigit(s[i + 0])) { |
|
ShowUsage(EX_DATAERR, stderr); |
|
} |
|
} |
|
} |
|
|
|
void ShowField(const char *name, uint64_t value) { |
|
if (value) { |
|
printf("/\t%-20s = %#lx\n", name, value); |
|
} |
|
} |
|
|
|
void ShowField2(const char *name, uint64_t value, bool cond) { |
|
if (value || cond) { |
|
printf("/\t%-20s = %#lx\n", name, value); |
|
} |
|
} |
|
|
|
void ShowOffset(const char *name, uint64_t off) { |
|
printf("/\t%-20s = %#lx\n", name, off); |
|
} |
|
|
|
int main(int argc, char *argv[]) { |
|
int err; |
|
size_t i, j, k; |
|
uint8_t buf[XED_MAX_INSTRUCTION_BYTES]; |
|
|
|
GetOpts(argc, argv); |
|
|
|
for (k = 0, i = optind; i < argc; ++i) { |
|
CheckHex(argv[i]); |
|
for (j = 0; argv[i][j]; j += 2) { |
|
if (++k > XED_MAX_INSTRUCTION_BYTES) ShowUsage(EX_DATAERR, stderr); |
|
buf[k - 1] = hextoint(argv[i][j + 0]) << 4 | hextoint(argv[i][j + 1]); |
|
} |
|
} |
|
|
|
xed_decoded_inst_zero_set_mode(&g_xedd, g_mode); |
|
if ((err = xed_instruction_length_decode(&g_xedd, buf, k)) != |
|
XED_ERROR_NONE) { |
|
fputs("XED_ERROR_", stderr); |
|
fputs(findnamebyid(kXedErrorIdNames, err), stderr); |
|
fputc('\n', stderr); |
|
exit(EXIT_FAILURE); |
|
} |
|
|
|
#define SHOWOP(F) ShowField(#F, g_xedd.op.F) |
|
#define SHOWOP2(F, C) ShowField2(#F, g_xedd.op.F, C) |
|
|
|
printf("/\t%-20s = %d\n", "length", g_xedd.length); |
|
SHOWOP(error); |
|
|
|
SHOWOP(lock); |
|
SHOWOP(osz); |
|
SHOWOP(asz); |
|
SHOWOP(rep); |
|
SHOWOP(rex); |
|
SHOWOP(rexb); |
|
SHOWOP(rexr); |
|
SHOWOP(rexrr); |
|
SHOWOP(rexw); |
|
SHOWOP(rexx); |
|
|
|
SHOWOP(map); |
|
SHOWOP(opcode); |
|
|
|
if (g_xedd.op.has_modrm) { |
|
printf("\n"); |
|
printf("/\t%-20s = 0b%02hhb (%d)\n", "mod", g_xedd.op.mod, g_xedd.op.mod); |
|
printf("/\t%-20s = 0b%03hhb (%d)\n", "reg", g_xedd.op.reg, g_xedd.op.reg); |
|
printf("/\t%-20s = 0b%03hhb (%d)\n", "rm", g_xedd.op.rm, g_xedd.op.rm); |
|
printf("\n"); |
|
} |
|
|
|
if (g_xedd.op.has_sib) { |
|
printf("/\t%-20s = 0b%02hhb (%d)\n", "scale", xed_sib_scale(g_xedd.op.sib), |
|
xed_sib_scale(g_xedd.op.sib)); |
|
printf("/\t%-20s = 0b%03hhb (%d)\n", "index", xed_sib_index(g_xedd.op.sib), |
|
xed_sib_index(g_xedd.op.sib)); |
|
printf("/\t%-20s = 0b%03hhb (%d)\n", "base", xed_sib_base(g_xedd.op.sib), |
|
xed_sib_base(g_xedd.op.sib)); |
|
printf("\n"); |
|
} |
|
|
|
SHOWOP2(disp, !!g_xedd.op.pos_disp); |
|
SHOWOP2(uimm0, !!g_xedd.op.pos_imm); |
|
SHOWOP2(uimm1, !!g_xedd.op.pos_imm1); |
|
|
|
SHOWOP(mode); |
|
SHOWOP(amd3dnow); |
|
SHOWOP(bcrc); |
|
SHOWOP(disp_width); |
|
SHOWOP(hint); |
|
SHOWOP(ild_f2); |
|
SHOWOP(ild_f3); |
|
SHOWOP(imm1_bytes); |
|
SHOWOP(imm_width); |
|
SHOWOP(imm_signed); |
|
SHOWOP(llrc); |
|
SHOWOP(mask); |
|
SHOWOP(max_bytes); |
|
SHOWOP(mode_first_prefix); |
|
SHOWOP(nprefixes); |
|
SHOWOP(nrexes); |
|
SHOWOP(nseg_prefixes); |
|
SHOWOP(out_of_bytes); |
|
SHOWOP(pos_disp); |
|
SHOWOP(pos_imm); |
|
SHOWOP(pos_imm1); |
|
SHOWOP(pos_modrm); |
|
SHOWOP(pos_opcode); |
|
SHOWOP(pos_sib); |
|
SHOWOP(realmode); |
|
SHOWOP(seg_ovd); |
|
SHOWOP(srm); |
|
SHOWOP(ubit); |
|
SHOWOP(vex_prefix); |
|
SHOWOP(vexdest210); |
|
SHOWOP(vexdest3); |
|
SHOWOP(vexdest4); |
|
SHOWOP(vexvalid); |
|
SHOWOP(vl); |
|
SHOWOP(zeroing); |
|
|
|
return 0; |
|
}
|
|
|