/* OpenIDA - Outil d'analyse de fichiers binaires
* processor.c - gestion de l'architecture x86
*
* Copyright (C) 2008 Cyrille Bagard
*
* This file is part of OpenIDA.
*
* OpenIDA 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; either version 3 of the License, or
* (at your option) any later version.
*
* OpenIDA 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 Foobar. If not, see .
*/
#include "processor.h"
#include
#include
#include "../processor-int.h"
#include "instruction.h"
#include "opcodes.h"
#include "operand.h"
typedef asm_x86_instr * (* read_instr) (const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
/* Carte d'identité d'un opcode */
typedef struct _x86_opcode
{
X86Prefix prefix; /* Préfixe(s) eventuel(s) */
uint8_t opcode; /* Opcode seul */
uint8_t op_ext; /* Extension de l'opcode */
bool has_op_ext; /* Ext. à prendre en compte ? */
const char *name; /* Désignation humaine */
read_instr read; /* Décodage de l'instruction */
} x86_opcode;
#define EXT_OPCODE_MASK 0x38
#define register_opcode(target, _opcode, _name, _read) \
do { \
target.prefix = X86_PRE_NONE; \
target.opcode = _opcode; \
target.has_op_ext = false; \
target.name = _name; \
target.read = _read; \
} while (0)
#define register_opcode_1632(target, _opcode, _name, _read) \
do { \
target.prefix = X86_PRE_OPSIZE; \
target.opcode = _opcode; \
target.has_op_ext = false; \
target.name = _name; \
target.read = _read; \
} while (0)
#define register_opcode_with_ext(target, _opcode, _ext, _name, _read) \
do { \
target.prefix = X86_PRE_NONE; \
target.opcode = _opcode; \
target.op_ext = _ext << 3; \
target.has_op_ext = true; \
target.name = _name; \
target.read = _read; \
} while (0)
#define register_opcode_1632_with_ext(target, _opcode, _ext, _name, _read) \
do { \
target.prefix = X86_PRE_OPSIZE; \
target.opcode = _opcode; \
target.op_ext = _ext << 3; \
target.has_op_ext = true; \
target.name = _name; \
target.read = _read; \
} while (0)
#define register_2b_opcode_1632(target, _opcode, _name, _read) \
do { \
target.prefix = X86_PRE_ESCAPE | X86_PRE_OPSIZE; \
target.opcode = _opcode; \
target.has_op_ext = false; \
target.name = _name; \
target.read = _read; \
} while (0)
/* Définition générique d'une architecture */
struct _asm_x86_processor
{
asm_processor base; /* A laisser en premier... */
AsmOperandSize operand_size; /* Taille par défaut */
x86_opcode opcodes[X86_OP_COUNT]; /* Liste des opcodes supportés */
};
/* Enregistre toutes les instructions reconnues pour x86. */
void x86_register_instructions(asm_x86_processor *);
/* Décode une instruction dans un flux de données. */
asm_instr *x86_fetch_instruction(const asm_x86_processor *, const uint8_t *, off_t *, off_t, uint64_t);
/* Traduit une instruction en version humainement lisible. */
void x86_print_instruction(const asm_x86_processor *, const exe_format *, const asm_x86_instr *, char *, size_t, AsmSyntax);
/******************************************************************************
* *
* Paramètres : - *
* *
* Description : Crée le support de l'architecture x86. *
* *
* Retour : Architecture mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
asm_processor *create_x86_processor(void)
{
asm_x86_processor *result; /* Architecture à retourner */
result = (asm_x86_processor *)calloc(1, sizeof(asm_x86_processor));
result->operand_size = AOS_32_BITS;
x86_register_instructions(result);
ASM_PROCESSOR(result)->fetch_instr = (fetch_instruction)x86_fetch_instruction;
ASM_PROCESSOR(result)->print_instr = (print_instruction)x86_print_instruction;
return ASM_PROCESSOR(result);
}
/******************************************************************************
* *
* Paramètres : proc = architecture visée par la consultation. *
* *
* Description : Fournit la taille courante des opérandes pour x86. *
* *
* Retour : Taille d'opérande (16 ou 32 bits). *
* *
* Remarques : - *
* *
******************************************************************************/
AsmOperandSize get_x86_current_operand_size(const asm_x86_processor *proc)
{
return proc->operand_size;
}
/******************************************************************************
* *
* Paramètres : proc = architecture visée par la consultation. *
* data = flux de données à analyser. *
* pos = position courante dans ce flux. [OUT] *
* *
* Description : Fournit la taille supplantée des opérandes pour x86. *
* *
* Retour : Taille d'opérande (16 ou 32 bits). *
* *
* Remarques : - *
* *
******************************************************************************/
AsmOperandSize switch_x86_operand_size_if_needed(const asm_x86_processor *proc, const uint8_t *data, off_t *pos)
{
AsmOperandSize result; /* Taille à renvoyer */
if (data[*pos] == 0x66)
{
result = (proc->operand_size == AOS_32_BITS ? AOS_16_BITS : AOS_32_BITS);
(*pos)++;
}
else result = proc->operand_size;
return result;
}
/******************************************************************************
* *
* Paramètres : proc = architecture visée par la procédure. *
* *
* Description : Enregistre toutes les instructions reconnues pour x86. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void x86_register_instructions(asm_x86_processor *proc)
{
register_opcode(proc->opcodes[X86_OP_ADD_RM8_R8], 0x00, "add", x86_read_instr_add_rm8_r8);
register_opcode(proc->opcodes[X86_OP_ADD_RM1632_R1632], 0x01, "add", x86_read_instr_add_rm1632_r1632);
register_opcode_1632(proc->opcodes[X86_OP_SUB_R1632_RM1632], 0x29, "sub", x86_read_instr_sub_r1632_from_rm1632);
register_opcode(proc->opcodes[X86_OP_SUB_AL_IMM8], 0x2c, "sub", x86_read_instr_sub_al_with_imm8);
register_opcode_1632(proc->opcodes[X86_OP_SUB_E_AX_IMM1632], 0x2d, "sub", x86_read_instr_sub_e_ax_with_imm1632);
register_opcode(proc->opcodes[X86_OP_XOR_RM8_R8], 0x30, "xor", x86_read_instr_xor_rm8_with_r8);
register_opcode_1632(proc->opcodes[X86_OP_XOR_RM1632_R1632], 0x31, "xor", x86_read_instr_xor_rm1632_with_r1632);
register_opcode(proc->opcodes[X86_OP_XOR_R8_RM8], 0x32, "xor", x86_read_instr_xor_r8_with_rm8);
register_opcode_1632(proc->opcodes[X86_OP_XOR_R1632_RM1632], 0x33, "xor", x86_read_instr_xor_r1632_with_rm1632);
register_opcode(proc->opcodes[X86_OP_XOR_AL_IMM8], 0x34, "xor", x86_read_instr_xor_al_with_imm8);
register_opcode_1632(proc->opcodes[X86_OP_XOR_E_AX_IMM1632], 0x35, "xor", x86_read_instr_xor_e_ax_with_imm1632);
register_opcode_1632(proc->opcodes[X86_OP_CMP_RM1632_R1632], 0x39, "cmp", x86_read_instr_cmp_rm1632_with_r1632);
register_opcode_1632(proc->opcodes[X86_OP_INC_E_AX], 0x40, "inc", x86_read_instr_inc_r1632);
register_opcode_1632(proc->opcodes[X86_OP_INC_E_CX], 0x41, "inc", x86_read_instr_inc_r1632);
register_opcode_1632(proc->opcodes[X86_OP_INC_E_DX], 0x42, "inc", x86_read_instr_inc_r1632);
register_opcode_1632(proc->opcodes[X86_OP_INC_E_BX], 0x43, "inc", x86_read_instr_inc_r1632);
register_opcode_1632(proc->opcodes[X86_OP_INC_E_SP], 0x44, "inc", x86_read_instr_inc_r1632);
register_opcode_1632(proc->opcodes[X86_OP_INC_E_BP], 0x45, "inc", x86_read_instr_inc_r1632);
register_opcode_1632(proc->opcodes[X86_OP_INC_E_SI], 0x46, "inc", x86_read_instr_inc_r1632);
register_opcode_1632(proc->opcodes[X86_OP_INC_E_DI], 0x47, "inc", x86_read_instr_inc_r1632);
register_opcode_1632(proc->opcodes[X86_OP_DEC_E_AX], 0x48, "dec", x86_read_instr_dec_r1632);
register_opcode_1632(proc->opcodes[X86_OP_DEC_E_CX], 0x49, "dec", x86_read_instr_dec_r1632);
register_opcode_1632(proc->opcodes[X86_OP_DEC_E_DX], 0x4a, "dec", x86_read_instr_dec_r1632);
register_opcode_1632(proc->opcodes[X86_OP_DEC_E_BX], 0x4b, "dec", x86_read_instr_dec_r1632);
register_opcode_1632(proc->opcodes[X86_OP_DEC_E_SP], 0x4c, "dec", x86_read_instr_dec_r1632);
register_opcode_1632(proc->opcodes[X86_OP_DEC_E_BP], 0x4d, "dec", x86_read_instr_dec_r1632);
register_opcode_1632(proc->opcodes[X86_OP_DEC_E_SI], 0x4e, "dec", x86_read_instr_dec_r1632);
register_opcode_1632(proc->opcodes[X86_OP_DEC_E_DI], 0x4f, "dec", x86_read_instr_dec_r1632);
register_opcode_1632(proc->opcodes[X86_OP_PUSH_E_AX], 0x50, "push", x86_read_instr_push_r1632);
register_opcode_1632(proc->opcodes[X86_OP_PUSH_E_CX], 0x51, "push", x86_read_instr_push_r1632);
register_opcode_1632(proc->opcodes[X86_OP_PUSH_E_DX], 0x52, "push", x86_read_instr_push_r1632);
register_opcode_1632(proc->opcodes[X86_OP_PUSH_E_BX], 0x53, "push", x86_read_instr_push_r1632);
register_opcode_1632(proc->opcodes[X86_OP_PUSH_E_SP], 0x54, "push", x86_read_instr_push_r1632);
register_opcode_1632(proc->opcodes[X86_OP_PUSH_E_BP], 0x55, "push", x86_read_instr_push_r1632);
register_opcode_1632(proc->opcodes[X86_OP_PUSH_E_SI], 0x56, "push", x86_read_instr_push_r1632);
register_opcode_1632(proc->opcodes[X86_OP_PUSH_E_DI], 0x57, "push", x86_read_instr_push_r1632);
register_opcode_1632(proc->opcodes[X86_OP_POP_E_AX], 0x58, "pop", x86_read_instr_pop_r1632);
register_opcode_1632(proc->opcodes[X86_OP_POP_E_CX], 0x59, "pop", x86_read_instr_pop_r1632);
register_opcode_1632(proc->opcodes[X86_OP_POP_E_DX], 0x5a, "pop", x86_read_instr_pop_r1632);
register_opcode_1632(proc->opcodes[X86_OP_POP_E_BX], 0x5b, "pop", x86_read_instr_pop_r1632);
register_opcode_1632(proc->opcodes[X86_OP_POP_E_SP], 0x5c, "pop", x86_read_instr_pop_r1632);
register_opcode_1632(proc->opcodes[X86_OP_POP_E_BP], 0x5d, "pop", x86_read_instr_pop_r1632);
register_opcode_1632(proc->opcodes[X86_OP_POP_E_SI], 0x5e, "pop", x86_read_instr_pop_r1632);
register_opcode_1632(proc->opcodes[X86_OP_POP_E_DI], 0x5f, "pop", x86_read_instr_pop_r1632);
register_opcode_1632(proc->opcodes[X86_OP_PUSH_IMM1632], 0x68, "push", x86_read_instr_push_imm1632);
register_opcode(proc->opcodes[X86_OP_JB_REL8], 0x72, "jb", x86_read_instr_jb_rel8);
register_opcode(proc->opcodes[X86_OP_JNB_REL8], 0x73, "jnb", x86_read_instr_jnb_rel8);
register_opcode(proc->opcodes[X86_OP_JE_8], 0x74, "je", x86_read_instr_je_8);
register_opcode(proc->opcodes[X86_OP_JNE_8], 0x75, "jne", x86_read_instr_jne_8);
register_opcode_with_ext(proc->opcodes[X86_OP_XOR_RM8_IMM8], 0x80, 6, "xor", x86_read_instr_xor_rm8_with_imm8);
register_opcode_with_ext(proc->opcodes[X86_OP_CMP_RM8_IMM8], 0x80, 7, "cmp", x86_read_instr_cmp_rm8_with_imm8);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_ADD_RM1632_IMM1632], 0x81, 0, "add", x86_read_instr_add_rm1632_imm1632);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_OR_RM1632_IMM1632], 0x81, 1, "or", x86_read_instr_or_rm1632_imm1632);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_ADC_RM1632_IMM1632], 0x81, 2, "adc", x86_read_instr_adc_rm1632_imm1632);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_SBB_RM1632_IMM1632], 0x81, 3, "sbb", x86_read_instr_sbb_rm1632_imm1632);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_AND_RM1632_IMM1632], 0x81, 4, "and", x86_read_instr_and_rm1632_imm1632);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_SUB_RM1632_IMM1632], 0x81, 5, "sub", x86_read_instr_sub_rm1632_imm1632);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_XOR_RM1632_IMM1632], 0x81, 6, "xor", x86_read_instr_xor_rm1632_imm1632);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_CMP_RM1632_IMM1632], 0x81, 7, "cmp", x86_read_instr_cmp_rm1632_imm1632);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_ADD_RM1632_IMM8], 0x83, 0, "add", x86_read_instr_add_imm8_to_rm1632);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_OR_RM1632_IMM8], 0x83, 1, "or", x86_read_instr_or_rm1632_with_imm8);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_ADC_RM1632_IMM8], 0x83, 2, "adc", x86_read_instr_adc_imm8_to_rm1632);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_SBB_RM1632_IMM8], 0x83, 3, "sbb", x86_read_instr_sbb_rm1632_with_imm8);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_AND_RM1632_IMM8], 0x83, 4, "and", x86_read_instr_and_rm1632_with_imm8);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_SUB_RM1632_IMM8], 0x83, 5, "sub", x86_read_instr_sub_imm8_from_rm1632);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_XOR_RM1632_IMM8], 0x83, 6, "xor", x86_read_instr_xor_rm1632_with_imm8);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_CMP_RM1632_IMM8], 0x83, 7, "cmp", x86_read_instr_cmp_rm1632_with_imm8);
register_opcode(proc->opcodes[X86_OP_TEST_RM8_R8], 0x84, "test", x86_read_instr_test_rm8_with_r8);
register_opcode_1632(proc->opcodes[X86_OP_TEST_RM1632_R1632], 0x85, "test", x86_read_instr_test_rm1632_with_r1632);
register_opcode(proc->opcodes[X86_OP_MOV_RM8_R8], 0x88, "mov", x86_read_instr_mov_rm8_r8);
register_opcode_1632(proc->opcodes[X86_OP_MOV_RM1632_R1632], 0x89, "mov", x86_read_instr_mov_r1632_to_rm1632);
register_opcode_1632(proc->opcodes[X86_OP_MOV_R1632_RM1632], 0x8b, "mov", x86_read_instr_mov_rm1632_to_r1632);
register_opcode_1632(proc->opcodes[X86_OP_LEA], 0x8d, "lea", x86_read_instr_lea);
register_opcode(proc->opcodes[X86_OP_NOP], 0x90, "nop", x86_read_instr_nop);
register_opcode(proc->opcodes[X86_OP_MOV_MOFFS_TO_AL], 0xa0, "mov", x86_read_instr_mov_moffs8_to_al);
register_opcode_1632(proc->opcodes[X86_OP_MOV_MOFFS_TO_E_AX], 0xa1, "mov", x86_read_instr_mov_moffs1632_to_e_ax);
register_opcode(proc->opcodes[X86_OP_MOV_AL_TO_MOFFS], 0xa2, "mov", x86_read_instr_mov_al_to_moffs8);
register_opcode_1632(proc->opcodes[X86_OP_MOV_E_AX_TO_MOFFS], 0xa3, "mov", x86_read_instr_mov_e_ax_to_moffs1632);
register_opcode(proc->opcodes[X86_OP_TEST_AL], 0xa8, "test", x86_read_instr_test_al);
register_opcode_1632(proc->opcodes[X86_OP_TEST_E_AX], 0xa9, "test", x86_read_instr_test_e_ax);
register_opcode_1632(proc->opcodes[X86_OP_MOV_E_AX], 0xb8, "mov", x86_read_instr_mov_imm1632_to_r1632);
register_opcode_1632(proc->opcodes[X86_OP_MOV_E_CX], 0xb9, "mov", x86_read_instr_mov_imm1632_to_r1632);
register_opcode_1632(proc->opcodes[X86_OP_MOV_E_DX], 0xba, "mov", x86_read_instr_mov_imm1632_to_r1632);
register_opcode_1632(proc->opcodes[X86_OP_MOV_E_BX], 0xbb, "mov", x86_read_instr_mov_imm1632_to_r1632);
register_opcode_1632(proc->opcodes[X86_OP_MOV_E_SP], 0xbc, "mov", x86_read_instr_mov_imm1632_to_r1632);
register_opcode_1632(proc->opcodes[X86_OP_MOV_E_BP], 0xbd, "mov", x86_read_instr_mov_imm1632_to_r1632);
register_opcode_1632(proc->opcodes[X86_OP_MOV_E_SI], 0xbe, "mov", x86_read_instr_mov_imm1632_to_r1632);
register_opcode_1632(proc->opcodes[X86_OP_MOV_E_DI], 0xbf, "mov", x86_read_instr_mov_imm1632_to_r1632);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_ROL_RM1632_IMM8], 0xc1, 0, "rol", x86_read_instr_rol_rm1632_imm8);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_ROR_RM1632_IMM8], 0xc1, 1, "ror", x86_read_instr_ror_rm1632_imm8);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_RCL_RM1632_IMM8], 0xc1, 2, "rcl", x86_read_instr_rcl_rm1632_imm8);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_RCR_RM1632_IMM8], 0xc1, 3, "rcr", x86_read_instr_rcr_rm1632_imm8);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_SHL_RM1632_IMM8], 0xc1, 4, "shl", x86_read_instr_shl_rm1632_imm8);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_SHR_RM1632_IMM8], 0xc1, 5, "shr", x86_read_instr_shr_rm1632_imm8);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_SAL_RM1632_IMM8], 0xc1, 6, "sal", x86_read_instr_sal_rm1632_imm8);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_SAR_RM1632_IMM8], 0xc1, 7, "sar", x86_read_instr_sar_rm1632_imm8);
register_opcode(proc->opcodes[X86_OP_RET], 0xc3, "ret", x86_read_instr_ret);
register_opcode(proc->opcodes[X86_OP_MOV_IMM8_TO_RM8], 0xc6, "mov", x86_read_instr_mov_imm8_to_rm8);
register_opcode_1632(proc->opcodes[X86_OP_MOV_IMM1632_TO_RM1632], 0xc7, "mov", x86_read_instr_mov_imm1632_to_rm1632);
register_opcode(proc->opcodes[X86_OP_LEAVE], 0xc9, "leave", x86_read_instr_leave);
register_opcode(proc->opcodes[X86_OP_INT], 0xcd, "int", x86_read_instr_int);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_SHL_RM1632_CL], 0xd3, 4, "shl", x86_read_instr_shl_rm1632_cl);
register_opcode_1632(proc->opcodes[X86_OP_CALL_REL1632], 0xe8, "call", x86_read_instr_call_rel1632);
register_opcode_1632(proc->opcodes[X86_OP_JMP_REL1632], 0xe9, "jmp", x86_read_instr_jmp_rel1632);
register_opcode(proc->opcodes[X86_OP_JMP_8], 0xeb, "jmp", x86_read_instr_jmp_8);
register_opcode(proc->opcodes[X86_OP_HLT], 0xf4, "hlt", x86_read_instr_hlt);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_NOT_RM1632], 0xf7, 7, "not", x86_read_instr_not_rm1632);
register_opcode(proc->opcodes[X86_OP_CLD], 0xfc, "cld", x86_read_instr_cld);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_CALL_RM1632], 0xff, 2, "call", x86_read_instr_call_rm1632);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_JMP_RM1632], 0xff, 4, "jmp", x86_read_instr_jmp_rm1632);
register_opcode_1632_with_ext(proc->opcodes[X86_OP_PUSH_RM1632], 0xff, 6, "push", x86_read_instr_push_rm1632);
register_2b_opcode_1632(proc->opcodes[X86_OP_MOVZX_R1632_RM8], 0xb6, "movzx", x86_read_instr_movzx_r1632_rm8);
register_2b_opcode_1632(proc->opcodes[X86_OP_MOVSX_R1632_RM8], 0xbe, "movsx", x86_read_instr_movsx_r1632_rm8);
}
/******************************************************************************
* *
* Paramètres : proc = architecture visée par la procédure. *
* data = flux de données à analyser. *
* pos = position courante dans ce flux. [OUT] *
* len = taille totale des données à analyser. *
* offset = adresse virtuelle de l'instruction. *
* *
* Description : Décode une instruction dans un flux de données. *
* *
* Retour : Instruction mise en place ou NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
asm_instr *x86_fetch_instruction(const asm_x86_processor *proc, const uint8_t *data, off_t *pos, off_t len, uint64_t offset)
{
asm_x86_instr *result; /* Résultat à faire remonter */
X86Prefix prefix; /* Préfixe détecté */
off_t k; /* Itération sur le contenu */
X86Opcodes i; /* Boucle de parcours */
result = NULL;
prefix = X86_PRE_NONE;
for (k = *pos; k < len; k++)
switch (data[k])
{
case 0x66:
prefix |= X86_PRE_OPSIZE;
break;
case 0x0f:
prefix |= X86_PRE_ESCAPE;
break;
default:
goto found_instr;
break;
}
/* Contenu binaire tronqué */
return NULL;
found_instr:
for (i = 0; i < X86_OP_COUNT; i++)
{
if ((prefix & proc->opcodes[i].prefix) != prefix) continue;
if (data[k] != proc->opcodes[i].opcode) continue;
result = proc->opcodes[i].read(data, pos, len, offset, proc);
if (result != NULL) result->type = i;
break;
}
return ASM_INSTRUCTION(result);
}
/******************************************************************************
* *
* Paramètres : proc = architecture visée par la procédure. *
* format = format du binaire manipulé. *
* instr = instruction à traiter. *
* buffer = tampon de sortie mis à disposition. [OUT] *
* len = taille de ce tampon. *
* syntax = type de représentation demandée. *
* *
* Description : Traduit une instruction en version humainement lisible. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void x86_print_instruction(const asm_x86_processor *proc, const exe_format *format, const asm_x86_instr *instr, char *buffer, size_t len, AsmSyntax syntax)
{
size_t i; /* Boucle de parcours */
char opbuffer[3][256]; /* Tampon pour les textes */
char *label; /* Etiquette de symbole */
SymbolType symtype; /* Type de symbole */
uint64_t offset; /* Décallage final constaté */
size_t oplen; /* Taille de description */
/* Impression des opérandes */
for (i = 0; i < ASM_INSTRUCTION(instr)->operands_count; i++)
switch (ASM_OPERAND(ASM_INSTRUCTION(instr)->operands[i])->type)
{
case AOT_NONE:
print_db_operand(ASM_OPERAND(ASM_INSTRUCTION(instr)->operands[i]), opbuffer[i], 256, syntax);
break;
case AOT_IMM:
print_imm_operand(ASM_OPERAND(ASM_INSTRUCTION(instr)->operands[i]), opbuffer[i], 256, syntax);
offset = ASM_OPERAND(ASM_INSTRUCTION(instr)->operands[i])->unsigned_imm.val32; /* FIXME !!! */
if (ASM_OPERAND(ASM_INSTRUCTION(instr)->operands[i])->size == proc->operand_size
&& resolve_exe_symbol(format, &label, &symtype, &offset))
{
oplen = strlen(opbuffer[i]);
switch (symtype)
{
case STP_SECTION:
if (offset == 0) snprintf(&opbuffer[i][oplen], 256 - oplen, " <%s>", label);
else snprintf(&opbuffer[i][oplen], 256 - oplen, " <%s+0x%llx>", label, offset);
break;
case STP_STRING:
label = escape_crlf_bin_string(label);
snprintf(&opbuffer[i][oplen], 256 - oplen, " \"%s\"", label);
break;
}
free(label);
}
break;
case AOT_REG:
x86_print_reg_operand(ASM_INSTRUCTION(instr)->operands[i], opbuffer[i], 256, syntax);
break;
case AOT_MEM:
break;
case AOT_MOFFS:
x86_print_moffs_operand(ASM_INSTRUCTION(instr)->operands[i], opbuffer[i], 256, syntax);
break;
}
/* Impression globale finale */
if (ASM_INSTRUCTION(instr)->type == AIT_DB)
snprintf(buffer, len, "db\t%s", opbuffer[0]);
else
switch (ASM_INSTRUCTION(instr)->operands_count)
{
case 0:
snprintf(buffer, len, "%s", proc->opcodes[instr->type].name);
break;
case 1:
snprintf(buffer, len, "%s\t%s", proc->opcodes[instr->type].name, opbuffer[0]);
break;
case 2:
switch (syntax)
{
case ASX_INTEL:
snprintf(buffer, len, "%s\t%s, %s", proc->opcodes[instr->type].name, opbuffer[0], opbuffer[1]);
break;
case ASX_ATT:
snprintf(buffer, len, "%s\t%s, %s", proc->opcodes[instr->type].name, opbuffer[1], opbuffer[0]);
break;
}
break;
}
}