diff options
Diffstat (limited to 'tools/d2c/encoding.c')
-rw-r--r-- | tools/d2c/encoding.c | 573 |
1 files changed, 573 insertions, 0 deletions
diff --git a/tools/d2c/encoding.c b/tools/d2c/encoding.c new file mode 100644 index 0000000..052fc04 --- /dev/null +++ b/tools/d2c/encoding.c @@ -0,0 +1,573 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * encoding.c - représentation complète d'un encodage + * + * Copyright (C) 2014-2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 <http://www.gnu.org/licenses/>. + */ + + +#include "encoding.h" + + +#include <assert.h> +#include <malloc.h> +#include <regex.h> +#include <stdio.h> +#include <string.h> + + +#include "helpers.h" +#include "qckcall.h" + + + +/* Mémorisation d'un encodage complet */ +struct _encoding_spec +{ + char *prefix; /* Distinction principale */ + char *lprefix; /* Distinction en minuscules */ + unsigned int index; /* Distinction secondaire */ + + operands_format *format; /* Définition des opérandes */ + + coding_bits *bits; /* Encodage des bits associés */ + instr_hooks *hooks; /* Fonctions complémentaires */ + + encoding_syntax **syntaxes; /* Définitions déjà en place */ + size_t syntax_count; /* Nombre de ces définitions */ + +}; + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée un nouveau suivi de l'encodage d'une instruction. * +* * +* Retour : Nouvelle structure prête à emploi. * +* * +* Remarques : - * +* * +******************************************************************************/ + +encoding_spec *create_encoding_spec(void) +{ + encoding_spec *result; /* Définition vierge à renvoyer*/ + + result = (encoding_spec *)calloc(1, sizeof(encoding_spec)); + + result->format = create_operands_format(); + + result->bits = create_coding_bits(); + result->hooks = create_instr_hooks(); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : spec = spécification d'encodage à libérer de la mémoire. * +* * +* Description : Supprime de la mémoire un suivi d'encodage d'une instruction.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void delete_encoding_spec(encoding_spec *spec) +{ + size_t i; /* Boucle de parcours */ + + delete_operands_format(spec->format); + + delete_coding_bits(spec->bits); + delete_instr_hooks(spec->hooks); + + if (spec->syntaxes != NULL) + { + for (i = 0; i < spec->syntax_count; i++) + delete_encoding_syntax(spec->syntaxes[i]); + + free(spec->syntaxes); + + } + + free(spec); + +} + + +/****************************************************************************** +* * +* Paramètres : spec = spécification d'encodage à compléter. * +* prefix = distinction principale entre les définitions. * +* index = distinction secondaire entre les définitions. * +* * +* Description : Définit le nom de code d'une spécification d'encodage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void define_encoding_spec_code_name(encoding_spec *spec, char *prefix, unsigned int index) +{ + spec->prefix = prefix; + spec->lprefix = make_string_lower(strdup(prefix)); + spec->index = index; + +} + + +/****************************************************************************** +* * +* Paramètres : spec = spécification d'encodage à consulter. * +* prefix = distinction principale entre les définitions. * +* * +* Description : Indique si une spécification se range dans une catégorie. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool has_encoding_spec_prefix(const encoding_spec *spec, const char *prefix) +{ + bool result; /* Bilan à renvoyer */ + + if (spec->prefix == NULL && prefix == NULL) + result = true; + + else if (spec->prefix != NULL && prefix != NULL) + result = strcmp(spec->prefix, prefix) == 0; + + else + result = false; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : spec = spécification d'encodage à consulter. * +* * +* Description : Construit la distinction propre à un encodage. * +* * +* Retour : Distinction à libérer de la mémoire après usage. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *build_encoding_spec_prefix(const encoding_spec *spec) +{ + char *result; /* Chaîne à retourner */ + + asprintf(&result, "%s%u", spec->lprefix, spec->index); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : spec = spécification d'encodage à consulter. * +* * +* Description : Fournit le gestionnaire des définitions d'opérandes. * +* * +* Retour : Structure assurant la définition des opérandes. * +* * +* Remarques : - * +* * +******************************************************************************/ + +operands_format *get_format_in_encoding_spec(const encoding_spec *spec) +{ + return spec->format; + +} + + +/****************************************************************************** +* * +* Paramètres : spec = spécification d'encodage à consulter. * +* * +* Description : Fournit le gestionnaire des bits d'un encodage d'instruction.* +* * +* Retour : Structure assurant le suivi des bits. * +* * +* Remarques : - * +* * +******************************************************************************/ + +coding_bits *get_bits_in_encoding_spec(const encoding_spec *spec) +{ + return spec->bits; + +} + + +/****************************************************************************** +* * +* Paramètres : spec = spécification d'encodage à consulter. * +* * +* Description : Fournit la liste des fonctions à lier à une instruction. * +* * +* Retour : Structure assurant la gestion des fonctions de conversion. * +* * +* Remarques : - * +* * +******************************************************************************/ + +instr_hooks *get_hooks_in_encoding_spec(const encoding_spec *spec) +{ + return spec->hooks; + +} + + +/****************************************************************************** +* * +* Paramètres : spec = spécification d'encodage à étendre. * +* * +* Description : Enregistre une définition de syntaxe supplémentaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void push_new_encoding_syntax(encoding_spec *spec) +{ + encoding_syntax *syntax; /* Définition à compléter */ + + syntax = create_encoding_syntax(); + + spec->syntaxes = realloc(spec->syntaxes, ++spec->syntax_count * sizeof(encoding_syntax *)); + spec->syntaxes[spec->syntax_count - 1] = syntax; + +} + + +/****************************************************************************** +* * +* Paramètres : spec = spécification d'encodage à consulter. * +* * +* Description : Fournit un lien vers la définition de syntaxe courante. * +* * +* Retour : Définition en cours d'édition. * +* * +* Remarques : - * +* * +******************************************************************************/ + +encoding_syntax *get_current_encoding_syntax(const encoding_spec *spec) +{ + encoding_syntax *result; /* Définition à retourner */ + + if (spec->syntax_count == 0) + result = NULL; + + else + result = spec->syntaxes[spec->syntax_count - 1]; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : spec = spécification servant de base à l'opération. * +* fd = descripteur d'un flux ouvert en écriture. * +* arch = architecture visée par l'opération. * +* id = identifiant unique attribué à l'instruction. * +* pp = pré-processeur pour les échanges de chaînes. * +* * +* Description : Traduit en code une sous-fonction de désassemblage. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool write_encoding_spec_raw_disass(const encoding_spec *spec, int fd, const char *arch, const instr_id *id, const pre_processor *pp) +{ + bool result; /* Bilan à retourner */ + bool openbar; /* Syntaxe unique par défaut ? */ + disass_assert *dassert; /* Eventuelles conditions */ + size_t i; /* Boucle de parcours */ + + + + + + + bool op_decl; /* Suivi des déclaration #1 */ + bool imm_decl; /* Suivi des déclaration #2 */ + + bool bad_exit; /* Ajout d'une sortie d'échec ?*/ + bool quick_exit; /* Inclusion de sortie rapide ?*/ + + + + char *encoding_fc; /* Spécification d'encodage */ + char *cast; /* Conversion vers le format */ + + + + /*************** + * + * + * REAL ONE + * + * + * + **********************/ + + + + + result = true; + + /* Détermination de la forme du code */ + + openbar = (spec->syntax_count == 1); + + if (openbar) + { + dassert = get_assertions_for_encoding_syntax(spec->syntaxes[0]); + openbar = is_disass_assert_empty(dassert); + } + + else + { + for (i = 0; i < spec->syntax_count && result; i++) + { + dassert = get_assertions_for_encoding_syntax(spec->syntaxes[0]); + + if (is_disass_assert_empty(dassert)) + { + fprintf(stderr, "The syntax definition #%zu has no entry conditions!\n", i); + result = false; + } + + } + + } + + if (!result) + goto wesrd_exit; + + /* Déclarations préalables */ + + dprintf(fd, "\tGArchInstruction *result; /* Instruction créée à renvoyer*/\n"); + + for (i = 0; i < spec->syntax_count && result; i++) + result = mark_syntax_items(spec->syntaxes[i], spec->bits); + + if (!result) + goto wesrd_exit; + + result = declare_used_bits_fields(spec->bits, fd); + if (!result) goto wesrd_exit; + + if (openbar) + { + result = declare_encoding_syntax(spec->syntaxes[0], fd, spec->bits); + if (!result) goto wesrd_exit; + } + + dprintf(fd, "\n"); + + result = declare_hook_functions(spec->hooks, fd); + if (!result) goto wesrd_exit; + + /* Vérification que le décodage est possible */ + + result &= check_bits_correctness(spec->bits, fd); + if (!result) goto wesrd_exit; + + dprintf(fd, "\n"); + + /* Définition des champs bruts */ + + result = define_used_bits_fields(spec->bits, fd); + if (!result) goto wesrd_exit; + + for (i = 0; i < spec->syntax_count && result; i++) + result = write_encoding_syntax(spec->syntaxes[i], fd, arch, spec->bits, openbar, &bad_exit); + + if (!result) + goto wesrd_exit; + + /* Encodage en dernier lieu */ + + asprintf(&encoding_fc, "g_%s_instruction_set_encoding", arch); + + cast = build_cast_if_needed(encoding_fc); + + dprintf(fd, "\t%s(%s(result), \"%s\");\n", encoding_fc, cast, spec->prefix); + + free(cast); + + free(encoding_fc); + + dprintf(fd, "\n"); + + /* Inscriptions des éventuelles fonctions ou propriété à lier */ + + result = write_hook_functions(spec->hooks, fd); + if (!result) goto wesrd_exit; + + /* Conclusion globale */ + + dprintf(fd, "\treturn result;\n"); + + dprintf(fd, "\n"); + + if (bad_exit) + { + dprintf(fd, " bad_exit:\n"); + dprintf(fd, "\n"); + + dprintf(fd, "\tg_object_unref(G_OBJECT(result));\n"); + dprintf(fd, "\treturn NULL;\n"); + + dprintf(fd, "\n"); + + } + + wesrd_exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : spec = spécification servant de base à l'opération. * +* fd = descripteur d'un flux ouvert en écriture. * +* arch = architecture visée par l'opération. * +* id = identifiant unique attribué à l'instruction. * +* prefix = préfixe pour le type de définitions d'opérandes. * +* * +* Description : Traduit en code une sous-fonction de désassemblage. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool write_encoding_spec_format_disass(const encoding_spec *spec, int fd, const char *arch, const instr_id *id, const char *prefix) +{ + bool result; /* Bilan à retourner */ + unsigned int iid; /* Identifiant unique attribué */ + bool bad_exit; /* Ajout d'une sortie d'échec ?*/ + conv_list *conversions; /* Conversions de la syntaxe */ + decoding_rules *rules; /* Règles de la syntaxe */ + + /* Déclarations préalables */ + + dprintf(fd, "\tGArchInstruction *result; /* Instruction créée à renvoyer*/\n"); + dprintf(fd, "\tSourceEndian endian; /* Boutisme lié au binaire */\n"); + + dprintf(fd, "\n"); + + result = declare_hook_functions(spec->hooks, fd); + if (!result) goto wesfd_exit; + + /* Création de l'instruction en elle-même */ + + iid = get_instruction_id_value(id); + + dprintf(fd, "\tresult = g_%s_instruction_new(0x%x);\n", arch, iid); + + dprintf(fd, "\n"); + + /* Inscriptions des éventuelles fonctions ou propriété à lier */ + + result = write_hook_functions(spec->hooks, fd); + if (!result) goto wesfd_exit; + + bad_exit = false; + + assert(spec->syntax_count <= 1); + + if (spec->syntax_count > 0) + { + conversions = get_conversions_in_encoding_syntax(spec->syntaxes[0]); + rules = get_rules_in_encoding_syntax(spec->syntaxes[0]); + + result = write_decoding_rules(rules, CAT_CHECKED_CALL, fd, arch, spec->bits, conversions, "", &bad_exit); + if (!result) goto wesfd_exit; + + result = write_decoding_rules(rules, CAT_CALL, fd, arch, spec->bits, conversions, "", &bad_exit); + if (!result) goto wesfd_exit; + + } + + /* Création des opérandes */ + + dprintf(fd, "\tendian = g_arch_processor_get_endianness(proc);\n"); + + dprintf(fd, "\n"); + + result = define_operands_loading(spec->format, fd, arch, prefix, &bad_exit); + if (!result) goto wesfd_exit; + + /* Conclusion de la procédure */ + + dprintf(fd, "\treturn result;\n"); + + dprintf(fd, "\n"); + + if (bad_exit) + { + if (bad_exit) + dprintf(fd, " bad_exit:\n"); + + dprintf(fd, "\n"); + + dprintf(fd, "\tg_object_unref(G_OBJECT(result));\n"); + dprintf(fd, "\treturn NULL;\n"); + + dprintf(fd, "\n"); + + } + + wesfd_exit: + + return result; + +} |