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.
bddisasm/disasmtool_lix/rapidjson.cpp

1175 lines
31 KiB

/*
* Copyright (c) 2020 Bitdefender
* SPDX-License-Identifier: Apache-2.0
*/
#include "disasm.hpp"
#include <iostream>
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
using namespace rapidjson;
static void _start_object(Writer<StringBuffer> &writer)
{
writer.StartObject();
}
static void _start_object(Writer<StringBuffer> &writer, const char *key)
{
writer.Key(key);
writer.StartObject();
}
static void _end_object(Writer<StringBuffer> &writer)
{
writer.EndObject();
}
static void _start_array(Writer<StringBuffer> &writer)
{
writer.StartArray();
}
static void _start_array(Writer<StringBuffer> &writer, const char *key)
{
writer.Key(key);
writer.StartArray();
}
static void _end_array(Writer<StringBuffer> &writer)
{
writer.EndArray();
}
static void _write_uint(Writer<StringBuffer> &writer, unsigned int value)
{
writer.Uint(value);
}
static void _write_uint(Writer<StringBuffer> &writer, const char *key, unsigned int value)
{
writer.Key(key);
writer.Uint(value);
}
static void _write_int(Writer<StringBuffer> &writer, int value)
{
writer.Int(value);
}
static void _write_int(Writer<StringBuffer> &writer, const char *key, int value)
{
writer.Key(key);
writer.Int(value);
}
static void _write_uint64(Writer<StringBuffer> &writer, uint64_t value)
{
writer.Int(value);
}
static void _write_uint64(Writer<StringBuffer> &writer, const char *key, uint64_t value)
{
writer.Key(key);
writer.Int(value);
}
static void _write_int64(Writer<StringBuffer> &writer, int64_t value)
{
writer.Int(value);
}
static void _write_int64(Writer<StringBuffer> &writer, const char *key, int64_t value)
{
writer.Key(key);
writer.Int(value);
}
static void _write_string(Writer<StringBuffer> &writer, const std::string& value)
{
writer.String(value.c_str());
}
static void _write_string(Writer<StringBuffer> &writer, const char *key, const std::string& value)
{
writer.Key(key);
writer.String(value.c_str());
}
static void _write_string(Writer<StringBuffer> &writer, const char *value)
{
writer.String(value);
}
static void _write_string(Writer<StringBuffer> &writer, const char *key, const char *value)
{
writer.Key(key);
writer.String(value);
}
static void _write_bool(Writer<StringBuffer> &writer, bool value)
{
writer.Bool(value);
}
static void _write_bool(Writer<StringBuffer> &writer, const char *key, bool value)
{
writer.Key(key);
writer.Bool(value);
}
static int _disasm_size_to_int(const uint8_t mode)
{
switch (mode) {
case 0: return 16;
case 1: return 32;
case 2: return 64;
}
return mode;
}
static void _write_rex(Writer<StringBuffer> &writer, const INSTRUX *instrux)
{
if (!instrux->HasRex)
return;
_start_object(writer, "rex");
_write_uint(writer, "value", instrux->Rex.Rex);
_write_uint(writer, "b", static_cast<uint8_t>(instrux->Rex.b));
_write_uint(writer, "x", static_cast<uint8_t>(instrux->Rex.x));
_write_uint(writer, "r", static_cast<uint8_t>(instrux->Rex.r));
_write_uint(writer, "w", static_cast<uint8_t>(instrux->Rex.w));
_end_object(writer);
}
static void _write_modrm(Writer<StringBuffer> &writer, const INSTRUX *instrux)
{
if (!instrux->HasModRm)
return;
_start_object(writer, "modrm");
_write_uint(writer, "value", instrux->ModRm.ModRm);
_write_uint(writer, "rm", static_cast<uint8_t>(instrux->ModRm.rm));
_write_uint(writer, "reg", static_cast<uint8_t>(instrux->ModRm.reg));
_write_uint(writer, "mod", static_cast<uint8_t>(instrux->ModRm.mod));
_end_object(writer);
}
static void _write_sib(Writer<StringBuffer> &writer, const INSTRUX *instrux)
{
if (!instrux->HasSib)
return;
_start_object(writer, "sib");
_write_uint(writer, "value", instrux->Sib.Sib);
_write_uint(writer, "base", static_cast<uint8_t>(instrux->Sib.base));
_write_uint(writer, "index", static_cast<uint8_t>(instrux->Sib.index));
_write_uint(writer, "scale", static_cast<uint8_t>(instrux->Sib.scale));
_end_object(writer);
}
static void _write_drex(Writer<StringBuffer> &writer, const INSTRUX *instrux)
{
if (!instrux->HasDrex)
return;
_start_object(writer, "drex");
_write_uint(writer, "value", instrux->Drex.Drex);
_write_uint(writer, "b", static_cast<uint8_t>(instrux->Drex.b));
_write_uint(writer, "x", static_cast<uint8_t>(instrux->Drex.x));
_write_uint(writer, "r", static_cast<uint8_t>(instrux->Drex.r));
_write_uint(writer, "oc", static_cast<uint8_t>(instrux->Drex.oc0));
_write_uint(writer, "vd", static_cast<uint8_t>(instrux->Drex.vd));
_write_uint(writer, "d", static_cast<uint8_t>(instrux->Drex.d));
_end_object(writer);
}
static void _write_vex2(Writer<StringBuffer> &writer, const INSTRUX *instrux)
{
if (!instrux->HasVex || ND_VEXM_2B != instrux->VexMode)
return;
_start_object(writer, "vex2");
_start_array(writer, "value");
_write_uint(writer, instrux->Vex2.Vex[0]);
_write_uint(writer, instrux->Vex2.Vex[1]);
_end_array(writer);
_write_uint(writer, "op", instrux->Vex2.op);
_write_uint(writer, "p", static_cast<uint8_t>(instrux->Vex2.p));
_write_uint(writer, "l", static_cast<uint8_t>(instrux->Vex2.l));
_write_uint(writer, "v", static_cast<uint8_t>(instrux->Vex2.v));
_write_uint(writer, "r", static_cast<uint8_t>(instrux->Vex2.r));
_end_object(writer);
}
static void _write_vex3(Writer<StringBuffer> &writer, const INSTRUX *instrux)
{
if (!instrux->HasVex || ND_VEXM_3B != instrux->VexMode)
return;
_start_object(writer, "vex3");
_start_array(writer, "value");
_write_uint(writer, instrux->Vex3.Vex[0]);
_write_uint(writer, instrux->Vex3.Vex[1]);
_write_uint(writer, instrux->Vex3.Vex[2]);
_end_array(writer);
_write_uint(writer, "op", instrux->Vex3.op);
_write_uint(writer, "m", static_cast<uint8_t>(instrux->Vex3.m));
_write_uint(writer, "b", static_cast<uint8_t>(instrux->Vex3.b));
_write_uint(writer, "x", static_cast<uint8_t>(instrux->Vex3.x));
_write_uint(writer, "r", static_cast<uint8_t>(instrux->Vex3.r));
_write_uint(writer, "p", static_cast<uint8_t>(instrux->Vex3.p));
_write_uint(writer, "l", static_cast<uint8_t>(instrux->Vex3.l));
_write_uint(writer, "v", static_cast<uint8_t>(instrux->Vex3.v));
_write_uint(writer, "w", static_cast<uint8_t>(instrux->Vex3.w));
_end_object(writer);
}
static void _write_xop(Writer<StringBuffer> &writer, const INSTRUX *instrux)
{
if (!instrux->HasXop)
return;
_start_object(writer, "xop");
_start_array(writer, "value");
_write_uint(writer, instrux->Xop.Xop[0]);
_write_uint(writer, instrux->Xop.Xop[1]);
_write_uint(writer, instrux->Xop.Xop[2]);
_end_array(writer);
_write_uint(writer, "op", instrux->Xop.op);
_write_uint(writer, "m", static_cast<uint8_t>(instrux->Xop.m));
_write_uint(writer, "b", static_cast<uint8_t>(instrux->Xop.b));
_write_uint(writer, "x", static_cast<uint8_t>(instrux->Xop.x));
_write_uint(writer, "r", static_cast<uint8_t>(instrux->Xop.r));
_write_uint(writer, "p", static_cast<uint8_t>(instrux->Xop.p));
_write_uint(writer, "l", static_cast<uint8_t>(instrux->Xop.l));
_write_uint(writer, "v", static_cast<uint8_t>(instrux->Xop.v));
_write_uint(writer, "w", static_cast<uint8_t>(instrux->Xop.w));
_end_object(writer);
}
static void _write_evex(Writer<StringBuffer> &writer, const INSTRUX *instrux)
{
if (!instrux->HasEvex)
return;
_start_object(writer, "evex");
_start_array(writer, "value");
_write_uint(writer, instrux->Evex.Evex[0]);
_write_uint(writer, instrux->Evex.Evex[1]);
_write_uint(writer, instrux->Evex.Evex[2]);
_write_uint(writer, instrux->Evex.Evex[3]);
_end_array(writer);
_write_uint(writer, "op", instrux->Evex.op);
_write_uint(writer, "m", static_cast<uint8_t>(instrux->Evex.m));
_write_uint(writer, "zero", static_cast<uint8_t>(instrux->Evex.zero));
_write_uint(writer, "rp", static_cast<uint8_t>(instrux->Evex.rp));
_write_uint(writer, "b", static_cast<uint8_t>(instrux->Evex.b));
_write_uint(writer, "x", static_cast<uint8_t>(instrux->Evex.x));
_write_uint(writer, "r", static_cast<uint8_t>(instrux->Evex.r));
_write_uint(writer, "p", static_cast<uint8_t>(instrux->Evex.p));
_write_uint(writer, "one", static_cast<uint8_t>(instrux->Evex.one));
_write_uint(writer, "v", static_cast<uint8_t>(instrux->Evex.v));
_write_uint(writer, "w", static_cast<uint8_t>(instrux->Evex.w));
_write_uint(writer, "a", static_cast<uint8_t>(instrux->Evex.a));
_write_uint(writer, "vp", static_cast<uint8_t>(instrux->Evex.vp));
_write_uint(writer, "bm", static_cast<uint8_t>(instrux->Evex.bm));
_write_uint(writer, "l", static_cast<uint8_t>(instrux->Evex.l));
_write_uint(writer, "z", static_cast<uint8_t>(instrux->Evex.z));
_end_object(writer);
}
static void _write_exs(Writer<StringBuffer> &writer, const INSTRUX *instrux)
{
_start_object(writer, "exs");
_write_uint(writer, "w", static_cast<uint8_t>(instrux->Exs.w));
_write_uint(writer, "r", static_cast<uint8_t>(instrux->Exs.r));
_write_uint(writer, "x", static_cast<uint8_t>(instrux->Exs.x));
_write_uint(writer, "b", static_cast<uint8_t>(instrux->Exs.b));
_write_uint(writer, "rp", static_cast<uint8_t>(instrux->Exs.rp));
_write_uint(writer, "p", static_cast<uint8_t>(instrux->Exs.p));
_write_uint(writer, "m", static_cast<uint8_t>(instrux->Exs.m));
_write_uint(writer, "l", static_cast<uint8_t>(instrux->Exs.l));
_write_uint(writer, "v", static_cast<uint8_t>(instrux->Exs.v));
_write_uint(writer, "vp", static_cast<uint8_t>(instrux->Exs.vp));
_write_uint(writer, "bm", static_cast<uint8_t>(instrux->Exs.bm));
_write_uint(writer, "e", static_cast<uint8_t>(instrux->Exs.e));
_write_uint(writer, "z", static_cast<uint8_t>(instrux->Exs.z));
_write_uint(writer, "k", static_cast<uint8_t>(instrux->Exs.k));
_write_uint(writer, "s", static_cast<uint8_t>(instrux->Exs.s));
_end_object(writer);
}
static void _write_prefixes(Writer<StringBuffer> &writer, const INSTRUX *instrux)
{
_start_array(writer, "prefixes");
if (instrux->HasRex)
_write_string(writer, "rex");
if (instrux->HasVex)
_write_string(writer, "vex");
if (instrux->HasXop)
_write_string(writer, "xop");
if (instrux->HasEvex)
_write_string(writer, "evex");
if (instrux->HasMvex)
_write_string(writer, "mvex");
if (instrux->HasOpSize)
_write_string(writer, "op_size");
if (instrux->HasAddrSize)
_write_string(writer, "addr_size");
if (instrux->HasLock)
_write_string(writer, "lock");
if (instrux->HasRepnzXacquireBnd)
_write_string(writer, "repnz_xacquire_bnd");
if (instrux->HasRepRepzXrelease)
_write_string(writer, "rep_repz_xrelease");
if (instrux->HasSeg)
_write_string(writer, "seg");
_end_array(writer);
}
static void _write_chunks(Writer<StringBuffer> &writer, const INSTRUX *instrux)
{
_start_array(writer, "chunks");
if (instrux->HasModRm)
_write_string(writer, "mod_rm");
if (instrux->HasSib)
_write_string(writer, "sib");
if (instrux->HasDrex)
_write_string(writer, "drex");
if (instrux->HasDisp)
_write_string(writer, "disp");
if (instrux->HasAddr)
_write_string(writer, "addr");
if (instrux->HasMoffset)
_write_string(writer, "moffset");
if (instrux->HasImm1)
_write_string(writer, "imm1");
if (instrux->HasImm2)
_write_string(writer, "imm2");
if (instrux->HasImm3)
_write_string(writer, "imm3");
if (instrux->HasRelOffs)
_write_string(writer, "rel_offs");
if (instrux->HasSseImm)
_write_string(writer, "sse_imm");
if (instrux->HasCompDisp)
_write_string(writer, "comp_disp");
if (instrux->HasBroadcast)
_write_string(writer, "broadcast");
if (instrux->HasMask)
_write_string(writer, "mask");
if (instrux->HasZero)
_write_string(writer, "zero");
if (instrux->HasEr)
_write_string(writer, "er");
if (instrux->HasSae)
_write_string(writer, "sae");
if (instrux->SignDisp)
_write_string(writer, "sign_disp");
_end_array(writer);
}
static void _write_access(Writer<StringBuffer> &writer, const char *key, const uint8_t access)
{
_start_array(writer, key);
if (access & ND_ACCESS_READ)
_write_string(writer, "read");
if (access & ND_ACCESS_WRITE)
_write_string(writer, "write");
if (access & ND_ACCESS_COND_READ)
_write_string(writer, "cond_read");
if (access & ND_ACCESS_COND_WRITE)
_write_string(writer, "cond_write");
if (access == ND_ACCESS_NONE)
_write_string(writer, "none");
_end_array(writer);
}
static void _start_write_default_op(Writer<StringBuffer> &writer, const ND_OPERAND &op)
{
_start_object(writer);
_start_array(writer, "flags");
if (op.Flags.IsDefault)
_write_string(writer, "default");
if (op.Flags.SignExtendedOp1)
_write_string(writer, "sign_extended_op1");
if (op.Flags.SignExtendedDws)
_write_string(writer, "sign_extended_dws");
_end_array(writer);
_write_uint(writer, "size", op.Size);
_write_uint(writer, "raw_size", op.RawSize);
_write_access(writer, "access", op.Access.Access);
_start_object(writer, "decorator");
if (op.Decorator.HasMask)
_write_uint(writer, "mask", op.Decorator.Mask.Msk); // TODO: k0-k7
if (op.Decorator.HasZero)
_write_bool(writer, "zeroing", true);
if (op.Decorator.HasBroadcast) {
_start_object(writer, "broadcast");
_write_uint(writer, "count", op.Decorator.Broadcast.Count);
_write_uint(writer, "size", op.Decorator.Broadcast.Size);
_end_object(writer);
}
if (op.Decorator.HasEr)
_write_bool(writer, "er", true);
if (op.Decorator.HasSae)
_write_bool(writer, "sae", true);
_end_object(writer); // "decorator"
switch (op.Type) {
case ND_OP_NOT_PRESENT:
_write_string(writer, "type", "not_preset");
break;
case ND_OP_REG:
_write_string(writer, "type", "register");
break;
case ND_OP_MEM:
_write_string(writer, "type", "memory");
break;
case ND_OP_IMM:
_write_string(writer, "type", "immediate");
break;
case ND_OP_OFFS:
_write_string(writer, "type", "offset");
break;
case ND_OP_ADDR:
_write_string(writer, "type", "address");
break;
case ND_OP_CONST:
_write_string(writer, "type", "constant");
break;
case ND_OP_BANK:
_write_string(writer, "type", "bank");
break;
default:
_write_string(writer, "type", "<unknown>");
break;
}
// returns without closing the object
}
static void _write_op_reg(Writer<StringBuffer> &writer, const ND_OPERAND &op)
{
const auto& reg = op.Info.Register;
_write_uint(writer, "size", reg.Size);
_write_string(writer, "reg_type", reg_type_to_str(reg.Type));
_write_string(writer, "reg", reg_to_str(reg.Reg, reg.Type));
_write_uint(writer, "reg_id", reg.Reg);
_write_uint(writer, "count", reg.Count);
if (reg.IsHigh8)
_write_bool(writer, "is_high8", true);
if (reg.IsBlock)
_write_bool(writer, "is_block", true);
}
static void _write_op_mem(Writer<StringBuffer> &writer, const ND_OPERAND &op)
{
const auto& mem = op.Info.Memory;
_start_array(writer, "flags");
if (mem.IsRipRel)
_write_string(writer, "rip_rel");
if (mem.IsStack)
_write_string(writer, "stack");
if (mem.IsString)
_write_string(writer, "string");
if (mem.IsShadowStack)
_write_string(writer, "shadow_stack");
if (mem.IsDirect)
_write_string(writer, "direct");
if (mem.IsBitbase)
_write_string(writer, "bitbase");
if (mem.IsAG)
_write_string(writer, "ag");
if (mem.IsMib)
_write_string(writer, "mib");
if (mem.HasBroadcast)
_write_string(writer, "broadcast");
_end_array(writer);
if (mem.IsVsib) {
_start_object(writer, "vsib");
_write_uint(writer, "index_size", mem.Vsib.IndexSize);
_write_uint(writer, "elem_size", mem.Vsib.ElemSize);
_write_uint(writer, "elem_count", mem.Vsib.ElemCount);
_end_object(writer);
}
if (mem.HasSeg)
_write_uint(writer, "seg", mem.Seg);
if (mem.HasBase) {
_write_uint(writer, "base_size", mem.BaseSize);
_write_uint(writer, "base", mem.Base);
}
if (mem.HasIndex) {
_write_uint(writer, "index_size", mem.IndexSize);
_write_uint(writer, "index", mem.Index);
_write_uint(writer, "scale", mem.Scale);
}
if (mem.HasDisp || mem.HasCompDisp) {
if (mem.HasDisp)
_write_uint(writer, "disp_size", mem.DispSize);
if (mem.HasCompDisp)
_write_uint(writer, "comp_disp_size", mem.CompDispSize);
_write_uint(writer, "disp", mem.Disp);
}
}
static void _write_operands(Writer<StringBuffer> &writer, const INSTRUX *instrux)
{
_start_array(writer, "operands");
for (auto i = 0; i < instrux->OperandsCount; i++) {
const auto& op = instrux->Operands[i];
_start_write_default_op(writer, op);
_start_object(writer, "info");
switch (op.Type) {
case ND_OP_REG:
_write_op_reg(writer, op);
break;
case ND_OP_MEM:
_write_op_mem(writer, op);
break;
case ND_OP_IMM:
_write_uint64(writer, "imm", op.Info.Immediate.Imm);
break;
case ND_OP_OFFS:
_write_uint64(writer, "rel", op.Info.RelativeOffset.Rel);
break;
case ND_OP_ADDR:
_write_uint(writer, "base_seg", op.Info.Address.BaseSeg);
_write_uint64(writer, "offset", op.Info.Address.Offset);
break;
case ND_OP_CONST:
_write_uint64(writer, "const", op.Info.Constant.Const);
break;
case ND_OP_NOT_PRESENT:
case ND_OP_BANK:
break;
}
_end_object(writer); // "info"
_end_object(writer); // the one from _start_write_default_op
}
_end_array(writer);
}
static void _write_valid_modes(Writer<StringBuffer> &writer, const ND_VALID_MODES &modes)
{
_start_array(writer, "valid_modes");
if (modes.Ring0)
_write_string(writer, "ring0");
if (modes.Ring1)
_write_string(writer, "ring1");
if (modes.Ring2)
_write_string(writer, "ring2");
if (modes.Ring3)
_write_string(writer, "ring3");
if (modes.Real)
_write_string(writer, "real");
if (modes.V8086)
_write_string(writer, "v8086");
if (modes.Protected)
_write_string(writer, "protected");
if (modes.Compat)
_write_string(writer, "compatibility");
if (modes.Long)
_write_string(writer, "long");
if (modes.Smm)
_write_string(writer, "smm");
if (modes.Sgx)
_write_string(writer, "sgx");
if (modes.Tsx)
_write_string(writer, "tsx");
if (modes.VmxRoot)
_write_string(writer, "vmx_root");
if (modes.VmxNonRoot)
_write_string(writer, "vmx_non_root");
if (modes.VmxOff)
_write_string(writer, "vmx_off");
_end_array(writer);
}
static void _write_valid_prefixes(Writer<StringBuffer> &writer, const ND_VALID_PREFIXES &prefixes)
{
_start_array(writer, "valid_prefixes");
if (prefixes.Rep)
_write_string(writer, "rep");
if (prefixes.RepCond)
_write_string(writer, "rep_cond");
if (prefixes.Lock)
_write_string(writer, "lock");
if (prefixes.Hle)
_write_string(writer, "hle");
if (prefixes.Xacquire)
_write_string(writer, "xacquire");
if (prefixes.Xrelease)
_write_string(writer, "xrelease");
if (prefixes.Bnd)
_write_string(writer, "bnd");
if (prefixes.Bhint)
_write_string(writer, "bhint");
if (prefixes.HleNoLock)
_write_string(writer, "hle_no_lock");
if (prefixes.Dnt)
_write_string(writer, "dnt");
_end_array(writer);
}
static void _write_valid_decorators(Writer<StringBuffer> &writer, const ND_VALID_DECORATORS &decorators)
{
_start_array(writer, "valid_decorators");
if (decorators.Er)
_write_string(writer, "er");
if (decorators.Sae)
_write_string(writer, "Sae");
if (decorators.Zero)
_write_string(writer, "Zero");
if (decorators.Mask)
_write_string(writer, "mask");
if (decorators.Broadcast)
_write_string(writer, "broadcast");
_end_array(writer);
}
static void _write_cpuid_flag(Writer<StringBuffer> &writer, const ND_CPUID_FLAG &cpuid_flag)
{
if (0 == cpuid_flag.Flag)
return;
_start_object(writer, "cpuid_flag");
_write_uint64(writer, "flag", cpuid_flag.Flag);
_write_uint(writer, "leaf", cpuid_flag.Leaf);
_write_uint(writer, "sub_leaf", static_cast<uint32_t>(cpuid_flag.SubLeaf));
_write_uint(writer, "reg", static_cast<uint8_t>(cpuid_flag.Reg));
_write_uint(writer, "bit", static_cast<uint8_t>(cpuid_flag.Bit));
_end_object(writer);
}
static void _write_rflags(Writer<StringBuffer> &writer, const ND_RFLAGS &rflags, const char *key)
{
_start_array(writer, key);
if (rflags.CF)
_write_string(writer, "cf");
if (rflags.PF)
_write_string(writer, "pf");
if (rflags.AF)
_write_string(writer, "af");
if (rflags.ZF)
_write_string(writer, "zf");
if (rflags.SF)
_write_string(writer, "sf");
if (rflags.TF)
_write_string(writer, "tf");
if (rflags.IF)
_write_string(writer, "if");
if (rflags.DF)
_write_string(writer, "df");
if (rflags.OF)
_write_string(writer, "of");
if (rflags.IOPL)
_write_string(writer, "iopl");
if (rflags.NT)
_write_string(writer, "nt");
if (rflags.RF)
_write_string(writer, "rf");
if (rflags.VM)
_write_string(writer, "vm");
if (rflags.AC)
_write_string(writer, "ac");
if (rflags.VIF)
_write_string(writer, "vif");
if (rflags.VIP)
_write_string(writer, "vip");
if (rflags.ID)
_write_string(writer, "id");
_end_array(writer);
}
static void _write_flags_access(Writer<StringBuffer> &writer, INSTRUX *instrux)
{
if (ND_ACCESS_NONE == instrux->FlagsAccess.RegAccess)
return;
_start_object(writer, "flags_access");
_write_access(writer, "access", instrux->FlagsAccess.RegAccess);
if ((instrux->FlagsAccess.RegAccess & ND_ACCESS_ANY_READ) && instrux->FlagsAccess.Tested.Raw)
_write_rflags(writer, instrux->FlagsAccess.Tested, "tested");
if ((instrux->FlagsAccess.RegAccess & ND_ACCESS_ANY_WRITE) && instrux->FlagsAccess.Modified.Raw)
_write_rflags(writer, instrux->FlagsAccess.Modified, "modified");
if (instrux->FlagsAccess.Set.Raw)
_write_rflags(writer, instrux->FlagsAccess.Set, "set");
if (instrux->FlagsAccess.Cleared.Raw)
_write_rflags(writer, instrux->FlagsAccess.Cleared, "cleared");
if (instrux->FlagsAccess.Undefined.Raw)
_write_rflags(writer, instrux->FlagsAccess.Undefined, "undefined");
_end_object(writer);
}
StringBuffer instrux_to_json(INSTRUX *instrux, size_t rip, bool text_only /* = false */)
{
char text[ND_MIN_BUF_SIZE];
auto status = NdToText(instrux, rip, sizeof(text), text);
if (!ND_SUCCESS(status))
text[0] = 0;
auto s = StringBuffer {nullptr, 4096};
auto writer = Writer<StringBuffer> {s, nullptr};
_start_object(writer);
_write_string(writer, "text", text);
if (text_only) {
_end_object(writer);
return s;
}
_write_uint(writer, "def_code", _disasm_size_to_int(instrux->DefCode));
_write_uint(writer, "def_data", _disasm_size_to_int(instrux->DefData));
_write_uint(writer, "def_stack", _disasm_size_to_int(instrux->DefStack));
_write_string(writer, "enc_mode", enc_mode_to_str(instrux->EncMode));
_write_uint(writer, "addr_mode", _disasm_size_to_int(instrux->AddrMode));
_write_uint(writer, "op_mode", _disasm_size_to_int(instrux->OpMode));
_write_uint(writer, "ef_op_mode", _disasm_size_to_int(instrux->EfOpMode));
_write_uint(writer, "vec_mode", _disasm_size_to_int(instrux->VecMode) * 8);
_write_uint(writer, "ef_vec_mnode", _disasm_size_to_int(instrux->EfVecMode) * 8);
_write_rex(writer, instrux);
_write_modrm(writer, instrux);
_write_sib(writer, instrux);
_write_drex(writer, instrux);
_write_vex2(writer, instrux);
_write_vex3(writer, instrux);
_write_xop(writer, instrux);
_write_evex(writer, instrux);
if (instrux->Rep)
_write_uint(writer, "rep", instrux->Rep);
if (instrux->Seg)
_write_uint(writer, "seg", instrux->Seg);
_write_uint(writer, "stack_words", instrux->StackWords);
_write_exs(writer, instrux);
_write_prefixes(writer, instrux);
_write_chunks(writer, instrux);
if (instrux->IsRepeated)
_write_bool(writer, "is_repeated", true);
if (instrux->IsXacquireEnabled)
_write_bool(writer, "is_xacquire_enabled", true);
if (instrux->IsXreleaseEnabled)
_write_bool(writer, "is_xrelease_enabled", true);
if (instrux->IsRipRelative)
_write_bool(writer, "is_rip_relative", true);
if (instrux->IsCetTracked)
_write_bool(writer, "is_cet_tracked", true);
if (instrux->HasMandatory66)
_write_bool(writer, "mandatory_66", true);
if (instrux->HasMandatoryF2)
_write_bool(writer, "mandatory_f2", true);
if (instrux->HasMandatoryF3)
_write_bool(writer, "mandatory_f3", true);
_write_uint(writer, "length", instrux->Length);
_write_uint(writer, "word_length", static_cast<uint32_t>(instrux->WordLength));
_write_uint(writer, "pref_length", static_cast<uint32_t>(instrux->PrefLength));
_start_object(writer, "address");
_write_uint(writer, "ip", instrux->Address.Ip);
_write_uint(writer, "cs", instrux->Address.Cs);
_end_object(writer);
_write_uint(writer, "op_offset", static_cast<uint8_t>(instrux->OpOffset));
_write_uint(writer, "main_op_offset", static_cast<uint8_t>(instrux->MainOpOffset));
if (instrux->HasAddr) {
_start_object(writer, "addr");
_write_uint(writer, "len", static_cast<uint8_t>(instrux->AddrLength));
_write_uint(writer, "offset", static_cast<uint8_t>(instrux->AddrOffset));
_end_object(writer);
}
if (instrux->HasMoffset) {
_start_object(writer, "moffset");
_write_uint64(writer, "value", instrux->Moffset);
_write_uint(writer, "len", static_cast<uint8_t>(instrux->MoffsetLength));
_write_uint(writer, "offset", static_cast<uint8_t>(instrux->MoffsetOffset));
_end_object(writer);
};
if (instrux->HasDisp) {
_start_object(writer, "displacement");
_write_uint(writer, "value", instrux->Displacement);
_write_uint(writer, "len", static_cast<uint8_t>(instrux->DispLength));
_write_uint(writer, "offset", static_cast<uint8_t>(instrux->DispOffset));
_end_object(writer);
}
if (instrux->HasRelOffs) {
_start_object(writer, "relative_offset");
_write_uint(writer, "value", instrux->RelativeOffset);
_write_uint(writer, "len", static_cast<uint8_t>(instrux->RelOffsLength));
_write_uint(writer, "offset", static_cast<uint8_t>(instrux->RelOffsOffset));
_end_object(writer);
}
if (instrux->HasImm1) {
_start_object(writer, "immediate1");
_write_uint64(writer, "value", instrux->Immediate1);
_write_uint(writer, "len", static_cast<uint8_t>(instrux->Imm1Length));
_write_uint(writer, "offset", static_cast<uint8_t>(instrux->Imm1Offset));
_end_object(writer);
}
if (instrux->HasImm2) {
_start_object(writer, "immediate2");
_write_uint(writer, "value", instrux->Immediate2);
_write_uint(writer, "len", static_cast<uint8_t>(instrux->Imm2Length));
_write_uint(writer, "offset", static_cast<uint8_t>(instrux->Imm2Offset));
_end_object(writer);
}
if (instrux->HasImm3) {
_start_object(writer, "immediate3");
_write_uint(writer, "value", instrux->Immediate3);
_write_uint(writer, "len", static_cast<uint8_t>(instrux->Imm3Length));
_write_uint(writer, "offset", static_cast<uint8_t>(instrux->Imm3Offset));
_end_object(writer);
}
if (instrux->HasSseImm) {
_start_object(writer, "sse_immediate");
_write_uint(writer, "value", instrux->SseImmediate);
_write_uint(writer, "offset", static_cast<uint8_t>(instrux->SseImmOffset));
_end_object(writer);
}
_write_uint(writer, "sse_condition", instrux->SseCondition);
_write_uint(writer, "condition", instrux->Condition);
_write_uint(writer, "operands_count", instrux->OperandsCount);
_write_uint(writer, "exp_operands_count", instrux->ExpOperandsCount);
_write_uint(writer, "operands_encoding_map", instrux->OperandsEncodingMap);
_write_operands(writer, instrux);
_write_access(writer, "rip_access", instrux->RipAccess);
_write_access(writer, "memory_access", instrux->MemoryAccess);
_write_access(writer, "stack_access", instrux->StackAccess);
_write_flags_access(writer, instrux);
_write_uint(writer, "attributes", instrux->Attributes);
_write_string(writer, "class", ins_class_to_str(instrux->Iclass));
_write_string(writer, "category", ins_cat_to_str(instrux->Category));
_write_string(writer, "set", ins_set_to_str(instrux->IsaSet));
_write_cpuid_flag(writer, instrux->CpuidFlag);
_write_valid_modes(writer, instrux->ValidModes);
_write_valid_prefixes(writer, instrux->ValidPrefixes);
_write_valid_decorators(writer, instrux->ValidDecorators);
_write_string(writer, "mnemonic", instrux->Mnemonic);
_start_array(writer, "opcode_bytes");
for (int i = 0; i < instrux->OpLength; i++)
_write_uint(writer, instrux->OpCodeBytes[i]);
_end_array(writer);
_write_uint(writer, "primary_opcode", instrux->PrimaryOpCode);
_start_array(writer, "bytes");
for (int i = 0; i < instrux->Length; i++)
_write_uint(writer, instrux->InstructionBytes[i]);
_end_array(writer);
_end_object(writer);
return s;
}
StringBuffer byte_to_json(uint8_t byte, size_t rip)
{
auto s = StringBuffer {nullptr, 64};
auto writer = Writer<StringBuffer> {s, nullptr};
_start_object(writer);
_write_uint(writer, "byte", byte);
_write_uint(writer, "length", 1);
_write_uint64(writer, "rip", rip);
_end_object(writer);
return s;
}
const char *json_to_string(StringBuffer &j)
{
return j.GetString();
}