Logo Search packages:      
Sourcecode: virtualbox-ose version File versions  Download package

dis.h

Go to the documentation of this file.
/** @file
 * DIS - The VirtualBox Disassembler.
 */

/*
 * Copyright (C) 2006-2007 innotek GmbH
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file 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,
 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
 * distribution. VirtualBox OSE is distributed in the hope that it will
 * be useful, but WITHOUT ANY WARRANTY of any kind.
 */

#ifndef ___VBox_disasm_h
#define ___VBox_disasm_h

#include <VBox/cdefs.h>
#include <VBox/types.h>
#include <VBox/cpum.h>
#include <VBox/disopcode.h>

#if defined(__L4ENV__)
#include <setjmp.h>
#endif

__BEGIN_DECLS


/** CPU mode flags (DISCPUSTATE::mode).
 * @{
 */
00035 typedef enum
{
    CPUMODE_16BIT = 1,
    CPUMODE_32BIT = 2,
    CPUMODE_64BIT = 3
} DISCPUMODE;
/** @} */

/** Prefix byte flags
 * @{
 */
00046 #define PREFIX_NONE                     0
/** non-default address size. */
00048 #define PREFIX_ADDRSIZE                 1
/** non-default operand size. */
00050 #define PREFIX_OPSIZE                   2
/** lock prefix. */
00052 #define PREFIX_LOCK                     4
/** segment prefix. */
00054 #define PREFIX_SEG                      8
/** rep(e) prefix (not a prefix, but we'll treat is as one). */
00056 #define PREFIX_REP                      16
/** rep(e) prefix (not a prefix, but we'll treat is as one). */
00058 #define PREFIX_REPNE                    32
/** @} */

/**
 * Operand type.
 */
00064 #define OPTYPE_INVALID               RT_BIT(0)
#define OPTYPE_HARMLESS              RT_BIT(1)
#define OPTYPE_CONTROLFLOW           RT_BIT(2)
#define OPTYPE_POTENTIALLY_DANGEROUS RT_BIT(3)
#define OPTYPE_DANGEROUS             RT_BIT(4)
#define OPTYPE_PORTIO                RT_BIT(5)
#define OPTYPE_PRIVILEGED            RT_BIT(6)
#define OPTYPE_PRIVILEGED_NOTRAP     RT_BIT(7)
#define OPTYPE_UNCOND_CONTROLFLOW    RT_BIT(8)
#define OPTYPE_RELATIVE_CONTROLFLOW  RT_BIT(9)
#define OPTYPE_COND_CONTROLFLOW      RT_BIT(10)
#define OPTYPE_INTERRUPT             RT_BIT(11)
#define OPTYPE_ILLEGAL               RT_BIT(12)
00077 #define OPTYPE_RRM_DANGEROUS         RT_BIT(14) /**< Some additional dangerouse ones when recompiling raw r0. */
00078 #define OPTYPE_RRM_DANGEROUS_16      RT_BIT(15) /**< Some additional dangerouse ones when recompiling 16-bit raw r0. */
#define OPTYPE_RRM_MASK              (OPTYPE_RRM_DANGEROUS | OPTYPE_RRM_DANGEROUS_16)
00080 #define OPTYPE_INHIBIT_IRQS          RT_BIT(16) /**< Will or can inhibit irqs (sti, pop ss, mov ss) */
#define OPTYPE_PORTIO_READ           RT_BIT(17)
#define OPTYPE_PORTIO_WRITE          RT_BIT(18)
#define OPTYPE_ALL                   (0xffffffff)

/** Parameter usage flags.
 * @{
 */
00088 #define USE_BASE                        RT_BIT(0)
#define USE_INDEX                       RT_BIT(1)
#define USE_SCALE                       RT_BIT(2)
#define USE_REG_GEN8                    RT_BIT(3)
#define USE_REG_GEN16                   RT_BIT(4)
#define USE_REG_GEN32                   RT_BIT(5)
#define USE_REG_FP                      RT_BIT(6)
#define USE_REG_MMX                     RT_BIT(7)
#define USE_REG_XMM                     RT_BIT(8)
#define USE_REG_CR                      RT_BIT(9)
#define USE_REG_DBG                     RT_BIT(10)
#define USE_REG_SEG                     RT_BIT(11)
#define USE_REG_TEST                    RT_BIT(12)
#define USE_DISPLACEMENT8               RT_BIT(13)
#define USE_DISPLACEMENT16              RT_BIT(14)
#define USE_DISPLACEMENT32              RT_BIT(15)
#define USE_IMMEDIATE8                  RT_BIT(16)
#define USE_IMMEDIATE8_REL              RT_BIT(17)
#define USE_IMMEDIATE16                 RT_BIT(18)
#define USE_IMMEDIATE16_REL             RT_BIT(19)
#define USE_IMMEDIATE32                 RT_BIT(20)
#define USE_IMMEDIATE32_REL             RT_BIT(21)
#define USE_IMMEDIATE64                 RT_BIT(22)
#define USE_IMMEDIATE_ADDR_0_32         RT_BIT(23)
#define USE_IMMEDIATE_ADDR_16_32        RT_BIT(24)
#define USE_IMMEDIATE_ADDR_0_16         RT_BIT(25)
#define USE_IMMEDIATE_ADDR_16_16        RT_BIT(26)
/** DS:ESI */
00116 #define USE_POINTER_DS_BASED            RT_BIT(27)
/** ES:EDI */
00118 #define USE_POINTER_ES_BASED            RT_BIT(28)
#define USE_IMMEDIATE16_SX8             RT_BIT(29)
#define USE_IMMEDIATE32_SX8             RT_BIT(30)

#define USE_IMMEDIATE                   (USE_IMMEDIATE8|USE_IMMEDIATE16|USE_IMMEDIATE32|USE_IMMEDIATE64|USE_IMMEDIATE8_REL|USE_IMMEDIATE16_REL|USE_IMMEDIATE32_REL|USE_IMMEDIATE_ADDR_0_32|USE_IMMEDIATE_ADDR_16_32|USE_IMMEDIATE_ADDR_0_16|USE_IMMEDIATE_ADDR_16_16|USE_IMMEDIATE16_SX8|USE_IMMEDIATE32_SX8)

/** @} */

/** index in {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"}
 * @{
 */
00129 #define USE_REG_EAX                     0
#define USE_REG_ECX                     1
#define USE_REG_EDX                     2
#define USE_REG_EBX                     3
#define USE_REG_ESP                     4
#define USE_REG_EBP                     5
#define USE_REG_ESI                     6
#define USE_REG_EDI                     7
/** @} */
/** index in {"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI"}
 * @{
 */
00141 #define USE_REG_AX                      0
#define USE_REG_CX                      1
#define USE_REG_DX                      2
#define USE_REG_BX                      3
#define USE_REG_SP                      4
#define USE_REG_BP                      5
#define USE_REG_SI                      6
#define USE_REG_DI                      7
/** @} */

/** index in {"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH"}
 * @{
 */
00154 #define USE_REG_AL                      0
#define USE_REG_CL                      1
#define USE_REG_DL                      2
#define USE_REG_BL                      3
#define USE_REG_AH                      4
#define USE_REG_CH                      5
#define USE_REG_DH                      6
#define USE_REG_BH                      7
/** @} */

/** index in {ES, CS, SS, DS, FS, GS}
 * @{
 */
00167 #define USE_REG_ES                      0
#define USE_REG_CS                      1
#define USE_REG_SS                      2
#define USE_REG_DS                      3
#define USE_REG_FS                      4
#define USE_REG_GS                      5
/** @} */

#define USE_REG_FP0                     0
#define USE_REG_FP1                     1
#define USE_REG_FP2                     2
#define USE_REG_FP3                     3
#define USE_REG_FP4                     4
#define USE_REG_FP5                     5
#define USE_REG_FP6                     6
#define USE_REG_FP7                     7

#define USE_REG_CR0                     0
#define USE_REG_CR1                     1
#define USE_REG_CR2                     2
#define USE_REG_CR3                     3
#define USE_REG_CR4                     4

#define USE_REG_DR0                     0
#define USE_REG_DR1                     1
#define USE_REG_DR2                     2
#define USE_REG_DR3                     3
#define USE_REG_DR4                     4
#define USE_REG_DR5                     5
#define USE_REG_DR6                     6
#define USE_REG_DR7                     7

#define USE_REG_MMX0                    0
#define USE_REG_MMX1                    1
#define USE_REG_MMX2                    2
#define USE_REG_MMX3                    3
#define USE_REG_MMX4                    4
#define USE_REG_MMX5                    5
#define USE_REG_MMX6                    6
#define USE_REG_MMX7                    7

#define USE_REG_XMM0                    0
#define USE_REG_XMM1                    1
#define USE_REG_XMM2                    2
#define USE_REG_XMM3                    3
#define USE_REG_XMM4                    4
#define USE_REG_XMM5                    5
#define USE_REG_XMM6                    6
#define USE_REG_XMM7                    7

/** Used by DISQueryParamVal & EMIQueryParamVal
 * @{
 */
00220 #define PARAM_VAL8             RT_BIT(0)
#define PARAM_VAL16            RT_BIT(1)
#define PARAM_VAL32            RT_BIT(2)
#define PARAM_VAL64            RT_BIT(3)
#define PARAM_VALFARPTR16      RT_BIT(4)
#define PARAM_VALFARPTR32      RT_BIT(5)

#define PARMTYPE_REGISTER      1
#define PARMTYPE_ADDRESS       2
#define PARMTYPE_IMMEDIATE     3

typedef struct
{
    uint32_t        type;
    uint32_t        flags;
    uint32_t        size;

    union
    {
        uint8_t     val8;
        uint16_t    val16;
        uint32_t    val32;
        uint64_t    val64;

        struct
        {
            uint16_t sel;
            uint32_t offset;
        } farptr;
    } val;

} OP_PARAMVAL;
/** Pointer to opcode parameter value. */
00253 typedef OP_PARAMVAL *POP_PARAMVAL;

typedef enum
{
    PARAM_DEST,
    PARAM_SOURCE
} PARAM_TYPE;

/** @} */

/**
 * Operand Parameter.
 */
00266 typedef struct _OP_PARAMETER
{
    int             param;
    uint64_t        parval;
    char            szParam[32];

    int32_t         disp8, disp16, disp32;

    uint32_t        flags;

    uint32_t        size;

    union
    {
        uint32_t    reg_gen8;
        uint32_t    reg_gen16;
        uint32_t    reg_gen32;
        /** ST(0) - ST(7) */
00284         uint32_t    reg_fp;
        /** MMX0 - MMX7 */
00286         uint32_t    reg_mmx;
        /** XMM0 - XMM7 */
00288         uint32_t    reg_xmm;
        /** {ES, CS, SS, DS, FS, GS} */
00290         uint32_t    reg_seg;
        /** TR0-TR7 (?) */
00292         uint32_t    reg_test;
        /** CR0-CR4 */
00294         uint32_t    reg_ctrl;
        /** DR0-DR7 */
00296         uint32_t    reg_dbg;
    } base;
    union
    {
        uint32_t    reg_gen;
    } index;

    /** 2, 4 or 8. */
00304     uint32_t scale;

} OP_PARAMETER;
/** Pointer to opcode parameter. */
00308 typedef OP_PARAMETER *POP_PARAMETER;
/** Pointer to opcode parameter. */
00310 typedef const OP_PARAMETER *PCOP_PARAMETER;


struct _OPCODE;
/** Pointer to opcode. */
00315 typedef struct _OPCODE *POPCODE;
/** Pointer to const opcode. */
00317 typedef const struct _OPCODE *PCOPCODE;

typedef DECLCALLBACK(int) FN_DIS_READBYTES(RTUINTPTR pSrc, uint8_t *pDest, uint32_t size, void *pvUserdata);
typedef FN_DIS_READBYTES *PFN_DIS_READBYTES;

/* forward decl */
struct _DISCPUSTATE;
/** Pointer to the disassembler CPU state. */
00325 typedef struct _DISCPUSTATE *PDISCPUSTATE;

/** Parser callback.
 * @remark no DECLCALLBACK() here because it's considered to be internal (really, I'm too lazy to update all the functions). */
00329 typedef unsigned FNDISPARSE(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu);
typedef FNDISPARSE *PFNDISPARSE;

typedef struct _DISCPUSTATE
{
    /* Global setting */
    uint32_t        mode;

    /* Per instruction prefix settings */
    uint32_t        prefix;
    /** segment prefix value. */
    uint32_t        prefix_seg;
    /** addressing mode (16 or 32 bits). (CPUMODE_*) */
    uint32_t        addrmode;
    /** operand mode (16 or 32 bits). (CPUMODE_*) */
    uint32_t        opmode;

    OP_PARAMETER    param1;
    OP_PARAMETER    param2;
    OP_PARAMETER    param3;

    /** ModRM byte. */
    uint32_t        ModRM;
    /** scalar, index, base byte. */
    uint32_t        SIB;

    int32_t         disp;

    /** First opcode byte of instruction. */
    uint8_t         opcode;
    /** Last prefix byte (for SSE2 extension tables) */
    uint8_t         lastprefix;
    RTUINTPTR       opaddr;
    uint32_t        opsize;
#ifndef DIS_CORE_ONLY
    /** Opcode format string for current instruction. */
    const char      *pszOpcode;
#endif

    /** Internal: pointer to disassembly function table */
    PFNDISPARSE    *pfnDisasmFnTable;
    /** Internal: instruction filter */
    uint32_t        uFilter;

    /** Pointer to the current instruction. */
    PCOPCODE        pCurInstr;

    void           *apvUserData[3];

    /** Optional read function */
    PFN_DIS_READBYTES pfnReadBytes;
#ifdef __L4ENV__
    jmp_buf *pJumpBuffer;
#endif /* __L4ENV__ */
} DISCPUSTATE;

/** Opcode. */
#pragma pack(4)
00387 typedef struct _OPCODE
{
#ifndef DIS_CORE_ONLY
    const char  *pszOpcode;
#endif
    uint8_t     idxParse1;
    uint8_t     idxParse2;
    uint8_t     idxParse3;
    uint16_t    opcode;
    uint16_t    param1;
    uint16_t    param2;
    uint16_t    param3;

    uint32_t    optype;
} OPCODE;
#pragma pack()


/**
 * Disassembles a code block.
 *
 * @returns VBox error code
 * @param   pCpu            Pointer to cpu structure which have DISCPUSTATE::mode
 *                          set correctly.
 * @param   pvCodeBlock     Pointer to the strunction to disassemble.
 * @param   cbMax           Maximum number of bytes to disassemble.
 * @param   pcbSize         Where to store the size of the instruction.
 *                          NULL is allowed.
 *
 *
 * @todo    Define output callback.
 * @todo    Using signed integers as sizes is a bit odd. There are still
 *          some GCC warnings about mixing signed and unsigend integers.
 * @todo    Need to extend this interface to include a code address so we
 *          can dissassemble GC code. Perhaps a new function is better...
 * @remark  cbMax isn't respected as a boundry. DISInstr() will read beyond cbMax.
 *          This means *pcbSize >= cbMax sometimes.
 */
DISDECL(int) DISBlock(PDISCPUSTATE pCpu, RTUINTPTR pvCodeBlock, unsigned cbMax, unsigned *pSize);

/**
 * Disassembles one instruction
 *
 * @returns VBox error code
 * @param   pCpu            Pointer to cpu structure which have DISCPUSTATE::mode
 *                          set correctly.
 * @param   pu8Instruction  Pointer to the instrunction to disassemble.
 * @param   u32EipOffset    Offset to add to instruction address to get the real virtual address
 * @param   pcbSize         Where to store the size of the instruction.
 *                          NULL is allowed.
 * @param   pszOutput       Storage for disassembled instruction
 *
 * @todo    Define output callback.
 */
DISDECL(int) DISInstr(PDISCPUSTATE pCpu, RTUINTPTR pu8Instruction, unsigned u32EipOffset, unsigned *pcbSize, char *pszOutput);

/**
 * Disassembles one instruction
 *
 * @returns VBox error code
 * @param   pCpu            Pointer to cpu structure which have DISCPUSTATE::mode
 *                          set correctly.
 * @param   pu8Instruction  Pointer to the strunction to disassemble.
 * @param   u32EipOffset    Offset to add to instruction address to get the real virtual address
 * @param   pcbSize         Where to store the size of the instruction.
 *                          NULL is allowed.
 * @param   pszOutput       Storage for disassembled instruction
 * @param   uFilter         Instruction type filter
 *
 * @todo    Define output callback.
 */
DISDECL(int) DISInstrEx(PDISCPUSTATE pCpu, RTUINTPTR pu8Instruction, uint32_t u32EipOffset, uint32_t *pcbSize,
                         char *pszOutput, unsigned uFilter);

/**
 * Parses one instruction.
 * The result is found in pCpu.
 *
 * @returns VBox error code
 * @param   pCpu            Pointer to cpu structure which has DISCPUSTATE::mode set correctly.
 * @param   InstructionAddr Pointer to the instruction to parse.
 * @param   pcbInstruction  Where to store the size of the instruction.
 *                          NULL is allowed.
 */
DISDECL(int) DISCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction);

/**
 * Parses one guest instruction.
 * * The result is found in pCpu and pcbInstruction.
 *
 * @returns VBox status code.
 * @param   InstructionAddr Address of the instruction to decode. What this means
 *                          is left to the pfnReadBytes function.
 * @param   CpuMode         The CPU mode. CPUMODE_32BIT, CPUMODE_16BIT, or CPUMODE_64BIT.
 * @param   pfnReadBytes    Callback for reading instruction bytes.
 * @param   pvUser          User argument for the instruction reader. (Ends up in dwUserData[0].)
 * @param   pCpu            Pointer to cpu structure. Will be initialized.
 * @param   pcbInstruction  Where to store the size of the instruction.
 *                          NULL is allowed.
 */
DISDECL(int) DISCoreOneEx(RTUINTPTR InstructionAddr, unsigned CpuMode, PFN_DIS_READBYTES pfnReadBytes, void *pvUser,
                          PDISCPUSTATE pCpu, unsigned *pcbInstruction);

DISDECL(int) DISGetParamSize(PDISCPUSTATE pCpu, POP_PARAMETER pParam);
DISDECL(int) DISDetectSegReg(PDISCPUSTATE pCpu, POP_PARAMETER pParam);
DISDECL(uint8_t) DISQuerySegPrefixByte(PDISCPUSTATE pCpu);

/**
 * Returns the value of the parameter in pParam
 *
 * @returns VBox error code
 * @param   pCtx            Exception structure pointer
 * @param   pCpu            Pointer to cpu structure which have DISCPUSTATE::mode
 *                          set correctly.
 * @param   pParam          Pointer to the parameter to parse
 * @param   pParamVal       Pointer to parameter value (OUT)
 * @param   parmtype        Parameter type
 *
 * @note    Currently doesn't handle FPU/XMM/MMX/3DNow! parameters correctly!!
 *
 */
DISDECL(int) DISQueryParamVal(PCPUMCTXCORE pCtx, PDISCPUSTATE pCpu, POP_PARAMETER pParam, POP_PARAMVAL pParamVal, PARAM_TYPE parmtype);

DISDECL(int) DISFetchReg8(PCPUMCTXCORE pCtx, uint32_t reg8, uint8_t *pVal);
DISDECL(int) DISFetchReg16(PCPUMCTXCORE pCtx, uint32_t reg16, uint16_t *pVal);
DISDECL(int) DISFetchReg32(PCPUMCTXCORE pCtx, uint32_t reg32, uint32_t *pVal);
DISDECL(int) DISFetchRegSeg(PCPUMCTXCORE pCtx, uint32_t sel, RTSEL *pVal);
DISDECL(int) DISFetchRegSegEx(PCPUMCTXCORE pCtx, uint32_t sel, RTSEL *pVal, CPUMSELREGHID **ppSelHidReg);
DISDECL(int) DISWriteReg8(PCPUMCTXCORE pRegFrame, uint32_t reg8, uint8_t val8);
DISDECL(int) DISWriteReg16(PCPUMCTXCORE pRegFrame, uint32_t reg32, uint16_t val16);
DISDECL(int) DISWriteReg32(PCPUMCTXCORE pRegFrame, uint32_t reg32, uint32_t val32);
DISDECL(int) DISWriteRegSeg(PCPUMCTXCORE pCtx, uint32_t sel, RTSEL val);

__END_DECLS

#endif


Generated by  Doxygen 1.6.0   Back to index