blob: 636afdfdd31fcdba5d7636d186604d7ec984e664 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Alexander V. Astapchuk
*/
/**
* @file
* @brief Disassembler for JVMTI interface declaration.
*/
#if !defined(__JVMTI_DASM_H_INCLUDED__)
#define __JVMTI_DASM_H_INCLUDED__
#include "open/types.h"
#include "vm_core_types.h"
#include "jni_types.h"
#include <assert.h>
class InstructionDisassembler {
public:
/**
* Type of instruction.
*/
enum Type {
OPCODEERROR = 0,
UNKNOWN,
OTHER=UNKNOWN,
RELATIVE_JUMP,
RELATIVE_COND_JUMP,
RELATIVE_CALL,
INDIRECT_JUMP,
INDIRECT_CALL,
RET
};
/**
* General-purpose registers set.
*/
enum Register {
DISASM_REG_NONE,
#ifdef HYX86
DISASM_REG_EAX, DISASM_REG_EBX, DISASM_REG_ECX, DISASM_REG_EDX,
DISASM_REG_ESI, DISASM_REG_EDI, DISASM_REG_EBP, DISASM_REG_ESP
#elif defined HYX86_64
DISASM_REG_RAX, DISASM_REG_RBX, DISASM_REG_RCX, DISASM_REG_RDX,
DISASM_REG_RSI, DISASM_REG_RDI, DISASM_REG_RSP, DISASM_REG_RBP,
DISASM_REG_R8 , DISASM_REG_R9 , DISASM_REG_R10, DISASM_REG_R11,
DISASM_REG_R12, DISASM_REG_R13, DISASM_REG_R14, DISASM_REG_R15
#endif
};
/**
* Kind of operand
* @see Opnd
*/
enum Kind {
/// Operand represents a constant
Kind_Imm,
/// Operand is memory reference
Kind_Mem,
/// Operand is register
Kind_Reg
};
/**
* Describes an argument of instruction.
*/
struct Opnd {
Opnd()
{
kind = Kind_Imm;
base = index = reg = DISASM_REG_NONE;
scale = 0;
disp = 0;
}
Kind kind;
Register base;
Register index;
unsigned scale;
union {
int disp;
Register reg;
int imm;
};
};
/**
* @brief Enum of possible condtions for conditional jump-s.
*
* @note To simplify decoding, the current order of the enum constants
* exactly matches the order of ConditionalMnemonic constants
* in #EncoderBase. Reordering of this constants requires some
* changes in InstructionDisassembler::disasm.
*/
enum CondJumpType
{
JUMP_OVERFLOW=0,
JUMP_NOT_OVERFLOW=1,
JUMP_BELOW=2, JUMP_NOT_ABOVE_OR_EQUAL=JUMP_BELOW, JUMP_CARRY=JUMP_BELOW,
JUMP_NOT_BELOW=3, JUMP_ABOVE_OR_EQUAL=JUMP_NOT_BELOW, JUMP_NOT_CARRY=JUMP_NOT_BELOW,
JUMP_ZERO=4, JUMP_EQUAL=JUMP_ZERO,
JUMP_NOT_ZERO=5, JUMP_NOT_EQUAL=JUMP_NOT_ZERO,
JUMP_BELOW_OR_EQUAL=6, JUMP_NOT_ABOVE=JUMP_BELOW_OR_EQUAL,
JUMP_NOT_BELOW_OR_EQUAL=7, JUMP_ABOVE=JUMP_NOT_BELOW_OR_EQUAL,
JUMP_SIGN=8,
JUMP_NOT_SIGN=9,
JUMP_PARITY=10, JUMP_PARITY_EVEN=JUMP_PARITY,
JUMP_NOT_PARITY=11, JUMP_PARITY_ODD=JUMP_NOT_PARITY,
JUMP_LESS=12, JUMP_NOT_GREATER_OR_EQUAL=JUMP_LESS,
JUMP_NOT_LESS=13, JUMP_GREATER_OR_EQUAL=JUMP_NOT_LESS,
JUMP_LESS_OR_EQUAL=14, JUMP_NOT_GREATER=JUMP_LESS_OR_EQUAL,
JUMP_NOT_LESS_OR_EQUAL=15, JUMP_GREATER=JUMP_NOT_LESS_OR_EQUAL,
CondJumpType_Count = 16
};
InstructionDisassembler(void) :
m_type(OPCODEERROR), m_target(0), m_len(0),
m_cond_jump_type(JUMP_OVERFLOW), m_argc(0)
{
}
InstructionDisassembler(NativeCodePtr address) :
m_type(OPCODEERROR), m_target(0), m_len(0),
m_cond_jump_type(JUMP_OVERFLOW), m_argc(0)
{
disasm(address, this);
}
InstructionDisassembler(InstructionDisassembler &d)
{
m_type = d.m_type;
m_target = d.m_target;
m_len = d.m_len;
m_cond_jump_type = d.m_cond_jump_type;
m_argc = d.m_argc;
m_opnds[0] = d.m_opnds[0];
m_opnds[1] = d.m_opnds[1];
m_opnds[2] = d.m_opnds[2];
}
/**
* @brief Returns type of underlying instruction.
*/
Type get_type(void) const
{
return m_type;
}
/**
* @brief Returns length (in bytes) of underlying instruction.
*
* The size includes instruction's prefixes, if any.
*/
jint get_length_with_prefix(void) const
{
assert(get_type() != OPCODEERROR);
return m_len;
}
/**
* @brief Returns absolute address of target, if applicable.
*
* For instructions other than relative JMP, CALL and conditional jumps,
* the value is undefined.
*/
NativeCodePtr get_jump_target_address(void) const
{
assert(get_type() == RELATIVE_JUMP ||
get_type() == RELATIVE_COND_JUMP ||
get_type() == RELATIVE_CALL);
return m_target;
}
/**
* @brief Returns type of conditional jump.
*
* @note For instructions other than conditional jump, the value is
* undefined.
*/
CondJumpType get_cond_jump_type(void) const
{
assert(get_type() == RELATIVE_COND_JUMP);
return m_cond_jump_type;
}
/**
* Returns number of operands of the instruction.
*/
unsigned get_operands_count(void) const
{
return m_argc;
}
/**
* Returns \c i-th operand.
*/
const Opnd& get_opnd(unsigned i) const
{
assert(i<get_operands_count());
return m_opnds[i];
}
/**
* Calculates and returns address of target basing on the decoded
* arguments and provided register context.
*
* Works for both indirect and direct branches.
*
* @note Only valid for branch instructions like JMPs, CALLs, etc.
*/
NativeCodePtr get_target_address_from_context(const Registers* pregs) const;
/**
* Returns the appropriate register value for the register operand reg
*/
const char* get_reg_value(Register reg, const Registers* pcontext) const;
private:
/**
* @brief Performs disassembling, fills out InstructionDisassembler's
* fields.
*
* If it's impossible (for any reason) to decode an instruction, then
* type is set to OPCODEERROR and other fields' values are undefined.
*/
static void disasm(const NativeCodePtr addr,
InstructionDisassembler * pidi);
/**
* @brief Type of instruction.
*/
Type m_type;
/**
* @brief Absolute address of target, if applicable.
*/
NativeCodePtr m_target;
/**
* @brief Length of the instruction, in bytes.
*/
unsigned m_len;
/**
* @brief Type of conditional jump.
*/
CondJumpType m_cond_jump_type;
/**
* @brief Number of arguments of the instruction.
*/
unsigned m_argc;
/**
* @brief Arguments of the instruction.
*/
Opnd m_opnds[3];
};
#endif // __JVMTI_DASM_H_INCLUDED__