/* 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 "../processor-int.h" #include "instruction.h" #include "opcodes.h" #include typedef asm_x86_instr * (* read_instr) (const char *, off_t *, off_t); /* Carte d'identité d'un opcode */ typedef struct _x86_opcode { char opcode; /* Opcode + préfixe eventuel */ const char *name; /* Désignation humaine */ read_instr read; /* Décodage de l'instruction */ } x86_opcode; #define register_opcode(target, bin, n, func) \ do {\ target.opcode = bin; \ target.name = n; \ target.read = func; \ } while (0) /* Définition générique d'une architecture */ typedef struct _asm_x86_processor { asm_processor base; /* A laisser en premier... */ x86_opcode opcodes[X86_OP_COUNT]; /* Liste des opcodes supportés */ } asm_x86_processor; /* 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 char *, off_t *, off_t); /* Traduit une instruction en version humainement lisible. */ void x86_print_instruction(const asm_x86_processor *, 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)); x86_register_instructions(result); ASM_PROCESSOR(result)->fetch_instr = x86_fetch_instruction; ASM_PROCESSOR(result)->print_instr = x86_print_instruction; return ASM_PROCESSOR(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_INT], 0xcd, "int", read_instr_int); } /****************************************************************************** * * * 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. * * * * 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 char *data, off_t *pos, off_t len) { asm_x86_instr *result; /* Résultat à faire remonter */ X86Opcodes i; /* Boucle de parcours */ result = NULL; //printf("--------\n"); for (i = 0; i < X86_OP_COUNT; i++) { /* printf(" cmp :: 0x%02hhx vs 0x%02hhx ? %d\n", data[*pos], proc->opcodes[i].opcode, data[*pos] == proc->opcodes[i].opcode); */ if (data[*pos] == proc->opcodes[i].opcode) { result = proc->opcodes[i].read(data, pos, len); if (result != NULL) result->type = i; break; } } return ASM_INSTRUCTION(result); } /****************************************************************************** * * * Paramètres : proc = architecture visée par la procédure. * * 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 asm_x86_instr *instr, char *buffer, size_t len, AsmSyntax syntax) { if (ASM_INSTRUCTION(instr)->opcode == DB_OPCODE) snprintf(buffer, len, "db\t0x%02hhx", ASM_INSTRUCTION(instr)->operands[0].value.val8); else snprintf(buffer, len, "%s\t0x%02hhx", proc->opcodes[instr->type].name, ASM_INSTRUCTION(instr)->operands[0].value.val8); }