From 33d49eb64654fc5dc5f617ce02ae3fffb6a75adb Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Wed, 4 May 2016 09:09:28 +0200 Subject: Created special instructions for real undefined behaviors. --- ChangeLog | 17 +++ src/arch/Makefile.am | 1 + src/arch/arm/v7/arm.c | 34 ++--- src/arch/arm/v7/thumb_32.c | 10 +- src/arch/raw.c | 12 +- src/arch/raw.h | 4 +- src/arch/undefined.c | 319 +++++++++++++++++++++++++++++++++++++++++++++ src/arch/undefined.h | 73 +++++++++++ 8 files changed, 434 insertions(+), 36 deletions(-) create mode 100644 src/arch/undefined.c create mode 100644 src/arch/undefined.h diff --git a/ChangeLog b/ChangeLog index 4334226..87bf638 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +16-05-04 Cyrille Bagard + + * src/arch/Makefile.am: + Add the 'undefined.[ch]' files to libarch_la_SOURCES. + + * src/arch/arm/v7/arm.c: + * src/arch/arm/v7/thumb_32.c: + Update code. + + * src/arch/raw.c: + * src/arch/raw.h: + Typo. + + * src/arch/undefined.c: + * src/arch/undefined.h: + Create special instructions for real undefined behaviors. + 16-05-03 Cyrille Bagard * src/glibext/gbufferline.c: diff --git a/src/arch/Makefile.am b/src/arch/Makefile.am index 82d63c9..f7508f4 100644 --- a/src/arch/Makefile.am +++ b/src/arch/Makefile.am @@ -19,6 +19,7 @@ libarch_la_SOURCES = \ register.h register.c \ target.h target.c \ translate.h \ + undefined.h undefined.c \ vmpa.h vmpa.c # libarch_la_LIBADD = \ diff --git a/src/arch/arm/v7/arm.c b/src/arch/arm/v7/arm.c index b536770..542d521 100644 --- a/src/arch/arm/v7/arm.c +++ b/src/arch/arm/v7/arm.c @@ -30,6 +30,7 @@ #include "opcodes/arm_opcodes.h" #include "opcodes/opcodes_tmp_arm.h" +#include "../../undefined.h" #include "../../../common/bconst.h" @@ -2074,8 +2075,7 @@ static GArchInstruction *process_armv7_arm_coprocessor_instructions_and_supervis op = (raw >> 4) & 0x1; if ((op1 & b111110) == b000000) - /* UNDEFINED */ - assert(false); + result = g_undef_instruction_new(IBS_UNDEFINED); else if ((op1 & b110000) == b110000) result = armv7_read_arm_instr_svc_previously_swi(raw); @@ -2249,23 +2249,20 @@ static GArchInstruction *process_armv7_arm_memory_hints_advanced_simd_instructio assert(false); else if ((op1 & b1110111) == b1000001) - /* (treat as NOP */ - assert(false); + result = g_undef_instruction_new(IBS_NOP); else if ((op1 & b1110111) == b1000101) result = armv7_read_arm_instr_pli_immediate_literal(raw); else if ((op1 & b1110011) == b1000011) - /* UNPREDICTABLE */ - assert(false); + result = g_undef_instruction_new(IBS_UNPREDICTABLE); else if ((op1 & b1110111) == b1010101) { if (rn != b1111) result = armv7_read_arm_instr_pld_pldw_immediate(raw); else - /* UNPREDICTABLE */ - assert(false); + result = g_undef_instruction_new(IBS_UNPREDICTABLE); } @@ -2279,21 +2276,18 @@ static GArchInstruction *process_armv7_arm_memory_hints_advanced_simd_instructio } else if (op1 == b1010011) - /* UNPREDICTABLE */ - assert(false); + result = g_undef_instruction_new(IBS_UNPREDICTABLE); else if (op1 == b1010111) { if (op2 == b0000) - /* UNPREDICTABLE */ - assert(false); + result = g_undef_instruction_new(IBS_UNPREDICTABLE); else if (op2 == b0001) result = armv7_read_arm_instr_clrex(raw); else if ((op2 & b1110) == b0010) - /* UNPREDICTABLE */ - assert(false); + result = g_undef_instruction_new(IBS_UNPREDICTABLE); else if (op2 == b0100) result = armv7_read_arm_instr_dsb(raw); @@ -2305,22 +2299,18 @@ static GArchInstruction *process_armv7_arm_memory_hints_advanced_simd_instructio result = armv7_read_arm_instr_isb(raw); else if (op2 == b0111) - /* UNPREDICTABLE */ - assert(false); + result = g_undef_instruction_new(IBS_UNPREDICTABLE); else if ((op2 & b1000) == b1000) - /* UNPREDICTABLE */ - assert(false); + result = g_undef_instruction_new(IBS_UNPREDICTABLE); } else if ((op1 & b1111011) == b1011011) - /* UNPREDICTABLE */ - assert(false); + result = g_undef_instruction_new(IBS_UNPREDICTABLE); else if ((op1 & b1110111) == b1100001 && (op2 & b0001) == b0000) - /* (treat as NOP */ - assert(false); + result = g_undef_instruction_new(IBS_NOP); else if ((op1 & b1110111) == b1100101 && (op2 & b0001) == b0000) result = armv7_read_arm_instr_pli_register(raw); diff --git a/src/arch/arm/v7/thumb_32.c b/src/arch/arm/v7/thumb_32.c index c1e3f3c..9dbad13 100644 --- a/src/arch/arm/v7/thumb_32.c +++ b/src/arch/arm/v7/thumb_32.c @@ -30,6 +30,7 @@ #include "opcodes/thumb_32_opcodes.h" #include "opcodes/opcodes_tmp_thumb_32.h" +#include "../../undefined.h" #include "../../../common/bconst.h" @@ -177,10 +178,8 @@ GArchInstruction *process_armv7_thumb_32_instruction_set_encoding(uint32_t raw) else if ((op2 & b1100111) == b0000101) result = process_armv7_thumb_32_load_word(raw); - /* - else if ((op2 & b00xx111) == b00xx111) - undefined; - */ + else if ((op2 & b1100111) == b0000111) + result = g_undef_instruction_new(IBS_UNDEFINED); else if ((op2 & b1110001) == b0010000) /* Advanced SIMD element or structure load/store instructions on page A7-275 */ @@ -2213,8 +2212,7 @@ static GArchInstruction *process_armv7_thumb_32_coprocessor_advanced_simd_and_fl op = (raw >> 4) & 0x1; if ((op1 & b111110) == b000000) - /* UNDEFINED */ - assert(false); + result = g_undef_instruction_new(IBS_UNDEFINED); else if ((op1 & b110000) == b110000) /* Advanced SIMD data-processing instructions on page A7-261 */ diff --git a/src/arch/raw.c b/src/arch/raw.c index 0dfb566..dff0c27 100644 --- a/src/arch/raw.c +++ b/src/arch/raw.c @@ -41,7 +41,7 @@ /* ------------------------- INSTRUCTION INCONNUE / DONNEES ------------------------- */ -/* Définition générique d'une instruction d'architecture inconnue (instance) */ +/* Définition générique d'une instruction brute d'architecture (instance) */ struct _GRawInstruction { GArchInstruction parent; /* A laisser en premier */ @@ -51,7 +51,7 @@ struct _GRawInstruction }; -/* Définition générique d'une instruction d'architecture inconnue (classe) */ +/* Définition générique d'une instruction brute d'architecture (classe) */ struct _GRawInstructionClass { GArchInstructionClass parent; /* A laisser en premier */ @@ -59,10 +59,10 @@ struct _GRawInstructionClass }; -/* Initialise la classe générique des opérandes. */ +/* Initialise la classe des instructions brutes d'architecture. */ static void g_raw_instruction_class_init(GRawInstructionClass *); -/* Initialise une instance d'opérande d'architecture. */ +/* Initialise une instance d'instruction brute d'architecture. */ static void g_raw_instruction_init(GRawInstruction *); /* Supprime toutes les références externes. */ @@ -95,7 +95,7 @@ G_DEFINE_TYPE(GRawInstruction, g_raw_instruction, G_TYPE_ARCH_INSTRUCTION); * * * Paramètres : klass = classe à initialiser. * * * -* Description : Initialise la classe générique des opérandes. * +* Description : Initialise la classe des instructions brutes d'architecture. * * * * Retour : - * * * @@ -126,7 +126,7 @@ static void g_raw_instruction_class_init(GRawInstructionClass *klass) * * * Paramètres : instr = instance à initialiser. * * * -* Description : Initialise une instance d'instruction d'architecture. * +* Description : Initialise une instance d'instruction brute d'architecture. * * * * Retour : - * * * diff --git a/src/arch/raw.h b/src/arch/raw.h index b40b411..18205ed 100644 --- a/src/arch/raw.h +++ b/src/arch/raw.h @@ -42,10 +42,10 @@ #define G_RAW_INSTRUCTION_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_raw_instruction_get_type(), GRawInstructionIface)) -/* Définition générique d'une instruction d'architecture inconnue (instance) */ +/* Définition générique d'une instruction brute d'architecture (instance) */ typedef struct _GRawInstruction GRawInstruction; -/* Définition générique d'une instruction d'architecture inconnue (classe) */ +/* Définition générique d'une instruction brute d'architecture (classe) */ typedef struct _GRawInstructionClass GRawInstructionClass; diff --git a/src/arch/undefined.c b/src/arch/undefined.c new file mode 100644 index 0000000..251f1a6 --- /dev/null +++ b/src/arch/undefined.c @@ -0,0 +1,319 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * undefined.c - instructions au comportement non défini + * + * Copyright (C) 2016 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * 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 "undefined.h" + + +#include + + +#include + + +#include "instruction-int.h" + + + +/* Définition générique d'une instruction au comportement non défini (instance) */ +struct _GUndefInstruction +{ + GArchInstruction parent; /* A laisser en premier */ + + InstrBehaviorStatus status; /* Conséquences réelles */ + +}; + +/* Définition générique d'une instruction au comportement non défini (classe) */ +struct _GUndefInstructionClass +{ + GArchInstructionClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des instructions non définies. */ +static void g_undef_instruction_class_init(GUndefInstructionClass *); + +/* Initialise une instance d'instruction non définie. */ +static void g_undef_instruction_init(GUndefInstruction *); + +/* Supprime toutes les références externes. */ +static void g_undef_instruction_dispose(GUndefInstruction *); + +/* Procède à la libération totale de la mémoire. */ +static void g_undef_instruction_finalize(GUndefInstruction *); + +/* Indique l'encodage d'une instruction de façon détaillée. */ +static const char *g_undef_instruction_get_encoding(const GUndefInstruction *); + +/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ +static GBufferLine *g_undef_instruction_print(const GUndefInstruction *, GCodeBuffer *, MemoryDataSize, const GBinContent *, AsmSyntax); + +/* Reconstruit le cache complet d'une désignation d'instruction. */ +static void g_undef_instruction_build_keyword(const GUndefInstruction *, AsmSyntax); + + + +/* ---------------------------------------------------------------------------------- */ +/* INSTRUCTION INCONNUE / DONNEES */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une instruction au comportement non défini. */ +G_DEFINE_TYPE(GUndefInstruction, g_undef_instruction, G_TYPE_ARCH_INSTRUCTION); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des instructions non définies. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_undef_instruction_class_init(GUndefInstructionClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GArchInstructionClass *instr; /* Encore une autre vision... */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_undef_instruction_dispose; + object->finalize = (GObjectFinalizeFunc)g_undef_instruction_finalize; + + instr = G_ARCH_INSTRUCTION_CLASS(klass); + + instr->get_encoding = (get_instruction_encoding_fc)g_undef_instruction_get_encoding; + instr->print = (print_instruction_fc)g_undef_instruction_print; + instr->build_key = (build_instruction_keyword_fc)g_undef_instruction_build_keyword; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instance à initialiser. * +* * +* Description : Initialise une instance d'instruction non définie. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_undef_instruction_init(GUndefInstruction *instr) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_undef_instruction_dispose(GUndefInstruction *instr) +{ + G_OBJECT_CLASS(g_undef_instruction_parent_class)->dispose(G_OBJECT(instr)); + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_undef_instruction_finalize(GUndefInstruction *instr) +{ + G_OBJECT_CLASS(g_undef_instruction_parent_class)->finalize(G_OBJECT(instr)); + +} + + +/****************************************************************************** +* * +* Paramètres : status = état réel du CPU après le passage de l'instruction. * +* * +* Description : Crée une instruction au comportement nominalement indéfini. * +* * +* Retour : Instruction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *g_undef_instruction_new(InstrBehaviorStatus status) +{ + GArchInstruction *result; /* Instruction à retourner */ + + result = g_object_new(G_TYPE_UNDEF_INSTRUCTION, NULL); + + G_UNDEF_INSTRUCTION(result)->status = status; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction quelconque à consulter. * +* * +* Description : Indique l'encodage d'une instruction de façon détaillée. * +* * +* Retour : Description humaine de l'encodage utilisé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static const char *g_undef_instruction_get_encoding(const GUndefInstruction *instr) +{ + const char *result; /* Description à retourner */ + + result = _("Undefined"); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'assemblage à représenter. * +* buffer = espace où placer ledit contenu. * +* msize = taille idéale des positions et adresses; * +* content = contenu binaire global à venir lire. * +* syntax = type de représentation demandée. * +* * +* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBufferLine *g_undef_instruction_print(const GUndefInstruction *instr, GCodeBuffer *buffer, MemoryDataSize msize, const GBinContent *content, AsmSyntax syntax) +{ + GBufferLine *result; /* Ligne de destination */ + GArchInstruction *base; /* Version de base */ + const char *key; /* Mot clef principal */ + size_t klen; /* Taille de ce mot clef */ + + base = G_ARCH_INSTRUCTION(instr); + + result = g_code_buffer_prepare_new_line(buffer, &base->range); + + g_buffer_line_add_flag(result, BLF_HAS_CODE); + + g_buffer_line_fill_for_instr(result, msize/* TODO ! */, msize, content, base->max_displayed_len); + + /* Instruction proprement dite */ + + key = g_arch_instruction_get_keyword(base, syntax); + klen = strlen(key); + + g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, key, klen, RTT_ERROR); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction à traiter. * +* format = format du binaire manipulé. * +* syntax = type de représentation demandée. * +* * +* Description : Reconstruit le cache complet d'une désignation d'instruction.* +* * +* Retour : Mot clef de bas niveau. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_undef_instruction_build_keyword(const GUndefInstruction *instr, AsmSyntax syntax) +{ + switch (instr->status) + { + case IBS_NOP: + G_ARCH_INSTRUCTION(instr)->cached_keyword = strdup("nop"); + break; + + case IBS_UNDEFINED: + G_ARCH_INSTRUCTION(instr)->cached_keyword = strdup("undefined"); + break; + + case IBS_UNPREDICTABLE: + G_ARCH_INSTRUCTION(instr)->cached_keyword = strdup("unpredictable"); + break; + + default: + assert(false); + break; + + } + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction à consulter. * +* * +* Description : Indique le type de conséquences réél de l'instruction. * +* * +* Retour : Etat réel du CPU après l'exécution de l'instruction. * +* * +* Remarques : - * +* * +******************************************************************************/ + +InstrBehaviorStatus g_undef_instruction_get_status(const GUndefInstruction *instr) +{ + return instr->status; + +} diff --git a/src/arch/undefined.h b/src/arch/undefined.h new file mode 100644 index 0000000..5ea8120 --- /dev/null +++ b/src/arch/undefined.h @@ -0,0 +1,73 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * undefined.h - prototypes pour les instructions au comportement non défini + * + * Copyright (C) 2016 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * 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 . + */ + + +#ifndef _ARCH_UNDEFINED_H +#define _ARCH_UNDEFINED_H + + +#include + + +#include "instruction.h" +#include "vmpa.h" + + + +#define G_TYPE_UNDEF_INSTRUCTION g_undef_instruction_get_type() +#define G_UNDEF_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_undef_instruction_get_type(), GUndefInstruction)) +#define G_IS_UNDEF_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_undef_instruction_get_type())) +#define G_UNDEF_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_UNDEF_INSTRUCTION, GUndefInstructionClass)) +#define G_IS_UNDEF_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_UNDEF_INSTRUCTION)) +#define G_UNDEF_INSTRUCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_UNDEF_INSTRUCTION, GUndefInstructionClass)) + + +/* Définition générique d'une instruction au comportement non défini (instance) */ +typedef struct _GUndefInstruction GUndefInstruction; + +/* Définition générique d'une instruction au comportement non défini (classe) */ +typedef struct _GUndefInstructionClass GUndefInstructionClass; + + +/* Etat précis de l'instruction */ +typedef enum _InstrBehaviorStatus +{ + IBS_NOP, + IBS_UNDEFINED, + IBS_UNPREDICTABLE, + + +} InstrBehaviorStatus; + + +/* Indique le type défini pour une instruction au comportement non défini. */ +GType g_undef_instruction_get_type(void); + +/* Crée une instruction au comportement nominalement indéfini. */ +GArchInstruction *g_undef_instruction_new(InstrBehaviorStatus); + +/* Indique le type de conséquences réél de l'instruction. */ +InstrBehaviorStatus g_undef_instruction_get_status(const GUndefInstruction *); + + + +#endif /* _ARCH_UNDEFINED_H */ -- cgit v0.11.2-87-g4458