Code Disassembly

Code Disassembly — Functions for code disassembly.

Synopsis


#include <jclass/bytecode.h>


#define     OP_LENGTH_UNPREDICTABLE
enum        OperandType;
enum        ArrayType;
typedef     TableSwitchOperand;
typedef     LookupSwitchOperand;
#define     MAX_LEGAL_OPCODE
const char* jclass_code_instruction_name    (uint8_t opcode);
uint8_t     jclass_code_instruction_ops     (uint8_t opcode);
uint8_t     jclass_code_instruction_ops_length
                                            (uint8_t opcode);
OperandType jclass_code_instruction_op_type (uint8_t opcode,
                                             int operand_number,
                                             int is_wide);
int8_t      jclass_code_read_byte           (uint8_t *code,
                                             uint32_t *pc);
uint8_t     jclass_code_read_ubyte          (uint8_t *code,
                                             uint32_t *pc);
int16_t     jclass_code_read_short          (uint8_t *code,
                                             uint32_t *pc);
uint16_t    jclass_code_read_ushort         (uint8_t *code,
                                             uint32_t *pc);
int32_t     jclass_code_read_int            (uint8_t *code,
                                             uint32_t *pc);
TableSwitchOperand* jclass_code_read_tableswitch
                                            (uint8_t *code,
                                             uint32_t *pc);
LookupSwitchOperand* jclass_code_read_lookupswitch
                                            (uint8_t *code,
                                             uint32_t *pc);
void        jclass_code_lookupswitch_operand_free
                                            (LookupSwitchOperand *operand);
void        jclass_code_tableswitch_operand_free
                                            (TableSwitchOperand *operand);
#define     JCLASS_CODE_ALIGN_PC            (pc)
const char* jclass_code_array_name          (uint8_t array_number);

Description

Credits Information for the instructions was obtained from http://mrl.nyu.edu/~meyer/jvmref/ref-Java.html

Details

OP_LENGTH_UNPREDICTABLE

#define OP_LENGTH_UNPREDICTABLE	0x10

The length of the operands is unpredictable.


enum OperandType

typedef enum {
	OP_TYPE_NONE,
	OP_TYPE_BYTE,
	OP_TYPE_UNSIGNED_BYTE,
	OP_TYPE_BYTE_ARRAY_TYPE,
	OP_TYPE_BYTE_CONSTANT_INDEX,
	OP_TYPE_UNSIGNED_BYTE_USELESS,
	OP_TYPE_SHORT,
	OP_TYPE_UNSIGNED_SHORT,
	OP_TYPE_SHORT_OFFSET,
	OP_TYPE_SHORT_CLASS_INDEX,
	OP_TYPE_SHORT_METHOD_INDEX,
	OP_TYPE_SHORT_FIELD_INDEX,
	OP_TYPE_SHORT_CONSTANT_INDEX,
	OP_TYPE_INT,
	OP_TYPE_INT_OFFSET,
	OP_TYPE_INSTRUCTION,
	OP_TYPE_TABLESWITCH,
	OP_TYPE_LOOKUPSWITCH,
	OP_TYPE_ERROR
} OperandType;

Operand types.

OP_TYPE_NONENo operand.
OP_TYPE_BYTEThe operand is a signed byte.
OP_TYPE_UNSIGNED_BYTEThe operand is an unsigned byte.
OP_TYPE_BYTE_ARRAY_TYPEThe operand is an unsigned byte representing a primitive array type. Possible values are listed in the ArrayType enum. You can also use the jclass_code_array_name() function to get a string with the name.
OP_TYPE_BYTE_CONSTANT_INDEXThe operand is an unsigned byte index in the constant pool for a constant.
OP_TYPE_UNSIGNED_BYTE_USELESSThe operand is an unsigned byte which is useless. See the documentation for the invokeinterface instruction to see what I mean.
OP_TYPE_SHORTThe operand is a signed short integer.
OP_TYPE_UNSIGNED_SHORTThe operand is an unsigned short integer.
OP_TYPE_SHORT_OFFSETThe operand is a short offset from the pc of the instruction.
OP_TYPE_SHORT_CLASS_INDEXThe operand is a short integer which is the index of a class in the constant pool.
OP_TYPE_SHORT_METHOD_INDEXThe operand is a short integer which is the index of a method in the constant pool.
OP_TYPE_SHORT_FIELD_INDEXThe operand is a short integer which is the index of a field in the constant pool.
OP_TYPE_SHORT_CONSTANT_INDEXThe operand is a short integer which is the index of a constant in the constant pool.
OP_TYPE_INTThe operand is a 32-bit signed integer.
OP_TYPE_INT_OFFSETThe operand is a signed integer offset from the pc of th instruction.
OP_TYPE_INSTRUCTIONThe operand is an instruction (See wide instruction).
OP_TYPE_TABLESWITCHThe operand is a tableswitch. It is always aligned at a 4-byte boundary. The "page" or whatever you want to call it starts at the first byte of the code.
OP_TYPE_LOOKUPSWITCHThe operand is a lookupswitch. It is always aligned at a 4-byte boundary.
OP_TYPE_ERRORSome kind of error occured.

enum ArrayType

typedef enum {
	ARRAY_TYPE_BOOLEAN = 4,
	ARRAY_TYPE_CHAR,
	ARRAY_TYPE_FLOAT,
	ARRAY_TYPE_DOUBLE,
	ARRAY_TYPE_BYTE,
	ARRAY_TYPE_SHORT,
	ARRAY_TYPE_INT,
	ARRAY_TYPE_LONG
} ArrayType;

Primitive array type values. This enumeration is used in the newarray instruction to indicate the type of the primitive array. The operand is OP_TYPE_BYTE_ARRAY_TYPE.

ARRAY_TYPE_BOOLEANboolean array.
ARRAY_TYPE_CHARchar array.
ARRAY_TYPE_FLOATfloat array.
ARRAY_TYPE_DOUBLEdouble array.
ARRAY_TYPE_BYTEbyte array.
ARRAY_TYPE_SHORTshort array.
ARRAY_TYPE_INTint array.
ARRAY_TYPE_LONGlong array.

TableSwitchOperand

typedef struct {
	int32_t num_pairs;
	uint32_t default_target;
	int32_t low_value;
	uint32_t* target;
} TableSwitchOperand;

Operand for the tableswitch instruction.


LookupSwitchOperand

typedef struct {
	int32_t num_pairs;
	uint32_t default_target;
	uint32_t* value;
	uint32_t* target;
} LookupSwitchOperand;

Operand for the lookupswitch instruction.


MAX_LEGAL_OPCODE

#define MAX_LEGAL_OPCODE 201

The maximum legal opcode for an instruction.


jclass_code_instruction_name ()

const char* jclass_code_instruction_name    (uint8_t opcode);

Gives the name of the instruction with the given opcode. The string returned is from an internal table so don't try to free it. If the opcode is illegal it returns NULL.

opcode : The opcode for the instruction.
Returns : A constant string with the mnemonic for the instruction.

jclass_code_instruction_ops ()

uint8_t     jclass_code_instruction_ops     (uint8_t opcode);

Gives the number of the operands for the instruction. If the opcode is illegal it returns 0.

opcode : The opcode for the instruction.
Returns : The number of operands.

jclass_code_instruction_ops_length ()

uint8_t     jclass_code_instruction_ops_length
                                            (uint8_t opcode);

Gives the length of the operands for the instruction in bytes. If the instruction is widened multiply this number by 2. If the opcode is illegal it returns 0. If the length cannot be predicted it returns OP_LENGTH_UNPREDICTABLE.

opcode : The opcode for the instruction.
Returns : The length of the operands in bytes.

jclass_code_instruction_op_type ()

OperandType jclass_code_instruction_op_type (uint8_t opcode,
                                             int operand_number,
                                             int is_wide);

Gives the type of the given operand. If an inconsistency is detected such as asking for the wide form of an instruction that does not have one it returns OP_TYPE_ERROR.

opcode : The opcode for the instruction.
operand_number : The number of the operand (starting from 0) to get its type.
is_wide : Set to 1 if the instruction is widened, 0 otherwise.
Returns : An OperandType enum for the type of the operand.

jclass_code_read_byte ()

int8_t      jclass_code_read_byte           (uint8_t *code,
                                             uint32_t *pc);

Reads a signed byte operand and increments the pc by the length of the operand.

code : The code array.
pc : A pointer to the PC counter.
Returns : The signed byte at the current pc.

jclass_code_read_ubyte ()

uint8_t     jclass_code_read_ubyte          (uint8_t *code,
                                             uint32_t *pc);

Reads an unsigned byte operand and increments the pc by the length of the operand.

code : The code array.
pc : A pointer to the PC counter.
Returns : The unsigned byte at the current pc.

jclass_code_read_short ()

int16_t     jclass_code_read_short          (uint8_t *code,
                                             uint32_t *pc);

Reads a short operand and increments the pc by the length of the operand.

code : The code array.
pc : A pointer to the PC counter.
Returns : The short at the current pc.

jclass_code_read_ushort ()

uint16_t    jclass_code_read_ushort         (uint8_t *code,
                                             uint32_t *pc);

Reads an unsigned short operand and increments the pc by the length of the operand.

code : The code array.
pc : A pointer to the PC.
Returns : The unsigned short at the current pc.

jclass_code_read_int ()

int32_t     jclass_code_read_int            (uint8_t *code,
                                             uint32_t *pc);

Reads an integer operand and increments the pc by the length of the operand.

code : The code array.
pc : A pointer to the program counter.
Returns : The integer at the current pc.

jclass_code_read_tableswitch ()

TableSwitchOperand* jclass_code_read_tableswitch
                                            (uint8_t *code,
                                             uint32_t *pc);

Reads a tableswitch operand and increments the pc by the length of the operand.

code : The code array.
pc : A pointer to the PC.
Returns : A TableSwitch structure allocated with malloc.

jclass_code_read_lookupswitch ()

LookupSwitchOperand* jclass_code_read_lookupswitch
                                            (uint8_t *code,
                                             uint32_t *pc);

Reads a lookupswitch operand and increments the pc by the length of the operand.

code : The code array.
pc : A pointer to the PC.
Returns : A newly created LookupSwitch structure.

jclass_code_lookupswitch_operand_free ()

void        jclass_code_lookupswitch_operand_free
                                            (LookupSwitchOperand *operand);

Frees a LookupSwitch operand.

operand : The LookupSwitch operand to free.

jclass_code_tableswitch_operand_free ()

void        jclass_code_tableswitch_operand_free
                                            (TableSwitchOperand *operand);

Frees a TableSwitch operand.

operand : The TableSwitch operand to free.

JCLASS_CODE_ALIGN_PC()

#define JCLASS_CODE_ALIGN_PC(pc) (((pc) % 4) ? (((pc) + 4) - ((pc) % 4)) : (pc))

Aligns the PC at a 4-byte boundary. Useful for tableswitch and lookupswitch.

Example 1. Read a tableswitch operand


pc = JCLASS_CODE_ALIGN_PC(pc);
					
/* get default target offset */
default_target = jclass_code_read_int(code->code, &pc);
/* low */
low = jclass_code_read_int(code->code, &pc);
/* high */
high = jclass_code_read_int(code->code, &pc);

/* store the targets in an array */
target = (uint32*) malloc(sizeof(uint32) * ((high - low) + 1));
for(count = 0; count < (high - low) + 1; count++)
	target[count] = instruction_pc + jclass_code_read_int(code->code, &pc);


pc :The current pc.

jclass_code_array_name ()

const char* jclass_code_array_name          (uint8_t array_number);

Gives the name of the array type given a OP_TYPE_BYTE_ARRAY_TYPE operand.

array_number : The OP_TYPE_BYTE_ARRAY_TYPE operand.
Returns : A constant string you should not modify.