diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2016-01-30 17:23:16 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2016-01-30 17:23:16 (GMT) |
commit | 792b330c1bbe573a591687d25e14d4cd1eccd3c6 (patch) | |
tree | 9a3e0955205c0221ea5db03b1f3a4d56846efed2 | |
parent | c922b6b9c841a97dd948755658cff07b2c6762ff (diff) |
Introduced a format switch to distinguish different kinds of definitions.
-rw-r--r-- | ChangeLog | 35 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | src/arch/arm/v7/opdefs/Makefile.am | 37 | ||||
-rw-r--r-- | tools/d2c/Makefile.am | 3 | ||||
-rw-r--r-- | tools/d2c/bits/manager.c | 14 | ||||
-rw-r--r-- | tools/d2c/coder.c | 248 | ||||
-rw-r--r-- | tools/d2c/coder.h | 18 | ||||
-rw-r--r-- | tools/d2c/d2c.mk | 37 | ||||
-rwxr-xr-x | tools/d2c/d2c_genmakefile.sh | 60 | ||||
-rw-r--r-- | tools/d2c/format/Makefile.am | 31 | ||||
-rw-r--r-- | tools/d2c/format/decl.h | 37 | ||||
-rw-r--r-- | tools/d2c/format/grammar.y | 107 | ||||
-rw-r--r-- | tools/d2c/format/manager.c | 145 | ||||
-rw-r--r-- | tools/d2c/format/manager.h | 50 | ||||
-rw-r--r-- | tools/d2c/format/tokens.l | 26 | ||||
-rw-r--r-- | tools/d2c/grammar.y | 79 | ||||
-rw-r--r-- | tools/d2c/pproc.c | 26 | ||||
-rw-r--r-- | tools/d2c/pproc.h | 3 | ||||
-rw-r--r-- | tools/d2c/spec.c | 134 | ||||
-rw-r--r-- | tools/d2c/spec.h | 7 | ||||
-rw-r--r-- | tools/d2c/tokens.l | 110 |
21 files changed, 1055 insertions, 153 deletions
@@ -1,5 +1,40 @@ 16-01-30 Cyrille Bagard <nocbos@gmail.com> + * configure.ac: + Add the new Makefile from the 'tools/d2c/format' directory. + + * src/arch/arm/v7/opdefs/Makefile.am: + Update the Makefile definition. + + * tools/d2c/Makefile.am: + Add the 'format/libd2cformat.la' archive into d2c_LDADD and + format into SUBDIRS. + + * tools/d2c/bits/manager.c: + * tools/d2c/coder.c: + * tools/d2c/coder.h: + * tools/d2c/d2c.mk: + * tools/d2c/d2c_genmakefile.sh: + Introduce a format switch to distinguish different kinds of definitions. + + * tools/d2c/format/Makefile.am: + * tools/d2c/format/decl.h: + * tools/d2c/format/grammar.y: + * tools/d2c/format/manager.c: + * tools/d2c/format/manager.h: + * tools/d2c/format/tokens.l: + New entries: handle a '@format' keyword. + + * tools/d2c/grammar.y: + * tools/d2c/pproc.c: + * tools/d2c/pproc.h: + * tools/d2c/spec.c: + * tools/d2c/spec.h: + * tools/d2c/tokens.l: + Introduce a format switch to distinguish different kinds of definitions. + +16-01-30 Cyrille Bagard <nocbos@gmail.com> + * src/arch/dalvik/instruction-int.h: * src/arch/dalvik/instruction.c: * src/arch/dalvik/instruction.h: diff --git a/configure.ac b/configure.ac index 1d61cc8..948d612 100644 --- a/configure.ac +++ b/configure.ac @@ -362,6 +362,7 @@ AC_CONFIG_FILES([Makefile tools/d2c/args/Makefile tools/d2c/bits/Makefile tools/d2c/conv/Makefile + tools/d2c/format/Makefile tools/d2c/hooks/Makefile tools/d2c/rules/Makefile tools/d2c/syntax/Makefile diff --git a/src/arch/arm/v7/opdefs/Makefile.am b/src/arch/arm/v7/opdefs/Makefile.am index 5483f92..607b27f 100644 --- a/src/arch/arm/v7/opdefs/Makefile.am +++ b/src/arch/arm/v7/opdefs/Makefile.am @@ -5,6 +5,8 @@ include ../../../../../tools/d2c/d2c.mk D2C_BIN = ../../../../../tools/d2c/d2c GEN_BIN = ../../../../../tools/d2c/d2c_genmakefile.sh +D2C_TYPE = raw + D2C_OUTDIR = $(PWD)/.. D2C_ARCH = armv7 @@ -23,6 +25,25 @@ D2C_MACROS = \ -M SignExtend=sign_extend_armv7_imm \ -M SetInsFlag=g_arch_instruction_set_flag + +FIXED_C_INCLUDES = \ + \n\#include \"..\/helpers.h\" \ + \n\#include \"..\/instruction.h\" \ + \n\#include \"..\/fetch.h\" \ + \n\#include \"..\/post.h\" \ + \n\#include \"..\/..\/instruction.h\" \ + \n\#include \"..\/..\/link.h\" \ + \n\#include \"..\/..\/..\/link.h\" \ + \n\#include \"..\/..\/..\/..\/common\/bconst.h\" \ + \n\n + +FIXED_H_INCLUDES = \ + \n\#include \<stdint.h\> \ + \n \ + \n\#include \"..\/..\/..\/instruction.h\" \ + \n\n + + ARMV7_DEFS = \ adc_A881.d \ adc_A882.d \ @@ -101,25 +122,11 @@ ARMV7_DEFS = \ subs_B9320.d -all: $(ARMV7_DEFS:.d=.g) fmk.done fix_includes_in_c_templates fix_includes_in_h_templates untabify_disass +all: $(ARMV7_DEFS:.d=.g) fmk.done d2c_final_rules fmk.done: $(ARMV7_DEFS) $(GEN_BIN) ../opcodes/ ../opdefs/.gen ../../../../../tools/d2c/globalgen.mk arm thumb_32 thumb_16 touch $@ -fix_includes_in_c_templates: - @for f in `find .gen/ -name '*tmpl.c'`; do \ - if grep -q '##INCLUDES##' $$f; then \ - $(fix_verbose)sed -i 's/##INCLUDES##/\n#include "..\/helpers.h"\n#include "..\/instruction.h"\n#include "..\/fetch.h"\n#include "..\/post.h"\n#include "..\/..\/instruction.h"\n#include "..\/..\/link.h"\n#include "..\/..\/..\/link.h"\n#include "..\/..\/..\/..\/common\/bconst.h"\n\n/' $$f; \ - fi; \ - done - -fix_includes_in_h_templates: - @for f in `find .gen/ -name '*tmpl.h'`; do \ - if grep -q '##INCLUDES##' $$f; then \ - $(fix_verbose)sed -i 's/##INCLUDES##/#include\ <stdint.h>\n\n#include "..\/..\/..\/instruction.h"/' $$f ; \ - fi; \ - done - clean: rm -rf $(ARMV7_DEFS:.d=.g) .gen fmk.done diff --git a/tools/d2c/Makefile.am b/tools/d2c/Makefile.am index e89384f..dc4fdf8 100644 --- a/tools/d2c/Makefile.am +++ b/tools/d2c/Makefile.am @@ -33,6 +33,7 @@ d2c_SOURCES = \ d2c_LDADD = \ bits/libd2cbits.la \ conv/libd2cconv.la \ + format/libd2cformat.la \ hooks/libd2chooks.la \ rules/libd2crules.la \ syntax/libd2csyntax.la \ @@ -43,4 +44,4 @@ d2c_LDADD = \ CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h -SUBDIRS = args bits conv hooks rules syntax +SUBDIRS = args bits conv format hooks rules syntax diff --git a/tools/d2c/bits/manager.c b/tools/d2c/bits/manager.c index db6392d..cc2783b 100644 --- a/tools/d2c/bits/manager.c +++ b/tools/d2c/bits/manager.c @@ -282,9 +282,9 @@ raw_bitfield *find_named_field_in_bits(const coding_bits *bits, const char *name /****************************************************************************** * * -* Paramètres : spec = spécification servant de base à l'opération. * -* fd = descripteur d'un flux ouvert en écriture. * -* wide = taille des mots manipulés (en bits). * +* Paramètres : spec = spécification servant de base à l'opération. * +* fd = descripteur d'un flux ouvert en écriture. * +* wide = taille des mots manipulés (en bits). * * * * Description : Déclare les variables C associées aux champs de bits. * * * @@ -309,8 +309,8 @@ bool declare_used_bits_fields(const coding_bits *bits, int fd, unsigned int wide /****************************************************************************** * * -* Paramètres : spec = spécification servant de base à l'opération. * -* fd = descripteur d'un flux ouvert en écriture. * +* Paramètres : spec = spécification servant de base à l'opération. * +* fd = descripteur d'un flux ouvert en écriture. * * * * Description : Vérifie que les bits fixes correspondent au masque attendu. * * * @@ -353,8 +353,8 @@ bool check_bits_correctness(const coding_bits *bits, int fd) /****************************************************************************** * * -* Paramètres : spec = spécification servant de base à l'opération. * -* fd = descripteur d'un flux ouvert en écriture. * +* Paramètres : spec = spécification servant de base à l'opération. * +* fd = descripteur d'un flux ouvert en écriture. * * * * Description : Définit les variables C associées aux champs de bits. * * * diff --git a/tools/d2c/coder.c b/tools/d2c/coder.c index 83910aa..869461f 100644 --- a/tools/d2c/coder.c +++ b/tools/d2c/coder.c @@ -47,14 +47,18 @@ struct _rented_coder { const char *input; /* Fichier de définitions */ + InputOutputType type; /* Type des définitions (E/S) */ const char *outdir; /* Lieu d'enregistrement */ const char *arch; /* Architecture à traiter */ const char *header; /* En-tête pour les en-têtes */ + const char *const_prefix; /* Préfixe pour les opérandes */ pre_processor *pp; /* Pré-processeur avec macros */ char *copyright; /* Récupération des droits */ char *ins; /* Désignation humaine */ + char separator; /* Caractère de séparation */ + char *raw_details; /* Eventuels compléments bruts */ char *details; /* Eventuels compléments */ encoding_spec **specs; /* Définitions déjà en place */ @@ -89,6 +93,9 @@ static int create_code_file(const rented_coder *, const char *, const char *, co /* Ecrit une partie des fonctions issues des spécifications. */ static bool dump_all_matching_specs_in_coder(const rented_coder *, const string_exch *, int, int); +/* Ecrit une partie des fonctions issues des spécifications. */ +static bool dump_all_matching_specs_from_format(const rented_coder *, const string_exch *, int, int); + /* ---------------------------------------------------------------------------------- */ @@ -144,8 +151,11 @@ void delete_coder(rented_coder *coder) if (coder->ins != NULL) free(coder->ins); - if (coder->details != NULL) + if (coder->raw_details != NULL) + { + free(coder->raw_details); free(coder->details); + } for (i = 0; i < coder->specs_count; i++) delete_encoding_spec(coder->specs[i]); @@ -174,7 +184,15 @@ void delete_coder(rented_coder *coder) bool do_basic_checks_with_coder(const rented_coder *coder) { - return (coder->outdir != NULL && coder->arch != NULL && coder->header != NULL); + bool result; /* Validité à retourner */ + + result = coder->type != IOT_UNDEFINED && coder->outdir != NULL; + result &= coder->arch != NULL && coder->header != NULL; + + if (coder->type == IOT_FORMAT) + result &= (coder->const_prefix != NULL); + + return result; } @@ -220,6 +238,26 @@ void set_coder_input_file(rented_coder *coder, const char *input) /****************************************************************************** * * +* Paramètres : coder = gestion par la machine en remplacement de l'humain. * +* type = type de définition à attendre. * +* * +* Description : Spécifie le type de format à prendre en compte (E/S). * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void set_coder_input_type(rented_coder *coder, InputOutputType type) +{ + coder->type = type; + +} + + +/****************************************************************************** +* * * Paramètres : coder = gestion par la machine en remplacement de l'humain. * * outdir = répertoire de génération des fichiers. * * * @@ -280,6 +318,26 @@ void set_coder_header_base(rented_coder *coder, const char *header) /****************************************************************************** * * +* Paramètres : coder = gestion par la machine en remplacement de l'humain. * +* prefix = préfixe pour les types d'opérandes. * +* * +* Description : Définit le préfixe pour les opérandes chargées par format. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void set_coder_const_prefix(rented_coder *coder, const char *prefix) +{ + coder->const_prefix = prefix; + +} + + +/****************************************************************************** +* * * Paramètres : coder = gestion par la machine en remplacement de l'humain. * * * * Description : Fournit le pré-processeur du compilateur. * @@ -302,6 +360,7 @@ pre_processor *get_coder_pre_proc(const rented_coder *coder) * Paramètres : coder = gestion par la machine en remplacement de l'humain.* * copy = droits de copie en anglais. * * ins = désignation humaine de l'instruction. * +* sep = caractère de séparation avant les détails. * * details = compléments d'informations éventuels ou NULL. * * * * Description : Enregistre les contours d'une instruction d'assemblage. * @@ -312,11 +371,23 @@ pre_processor *get_coder_pre_proc(const rented_coder *coder) * * ******************************************************************************/ -void save_notes_for_coder(rented_coder *coder, char *copy, char *ins, const char *details) +void save_notes_for_coder(rented_coder *coder, char *copy, char *ins, char sep, const char *details) { coder->copyright = copy; coder->ins = make_string_lower(ins); - coder->details = (details != NULL ? make_callable(details, true) : strdup("")); + + coder->separator = sep; + + if (details != NULL) + { + coder->raw_details = strdup(details); + coder->details = make_callable(details, true); + } + else + { + coder->raw_details = strdup(""); + coder->details = strdup(""); + } } @@ -366,7 +437,8 @@ void push_encoding_spec(rented_coder *coder, char *prefix, unsigned int index) spec = coder->cur_spec; - define_encoding_spec_code_name(spec, prefix, index); + if (prefix != NULL) + define_encoding_spec_code_name(spec, prefix, index); coder->specs = (encoding_spec **)realloc(coder->specs, ++coder->specs_count * sizeof(encoding_spec *)); coder->specs[coder->specs_count - 1] = spec; @@ -494,9 +566,18 @@ static char *build_template_filename(const rented_coder *coder, const char *pref char *result; /* Chaîne construite à renvoyer*/ size_t length; /* Taille du nom de fichier */ - length = strlen(".gen") + 1 + strlen("template") + 1 + strlen(prefix) + 1 + strlen(name) + 3; - result = (char *)calloc(length, sizeof(char)); - snprintf(result, length, ".gen/%s.%s.tmpl.%c", prefix, name, ext); + if (prefix == NULL) + { + length = strlen(".gen") + 1 + strlen("template") + 1 + strlen(name) + 3; + result = (char *)calloc(length, sizeof(char)); + snprintf(result, length, ".gen/%s.tmpl.%c", name, ext); + } + else + { + length = strlen(".gen") + 1 + strlen("template") + 1 + strlen(prefix) + 1 + strlen(name) + 3; + result = (char *)calloc(length, sizeof(char)); + snprintf(result, length, ".gen/%s.%s.tmpl.%c", prefix, name, ext); + } return result; @@ -523,6 +604,7 @@ static bool create_template_file(const rented_coder *coder, const char *prefix, char *pathname; /* Chemin d'accès à constituer */ bool exist; /* Note une présence établie */ int fd; /* Flux ouvert pour création */ + const char *valid_prefix; /* Prefix vide au besoin */ char *uprefix; /* Préfixe en majuscule */ char *uname; /* Nom en majuscule */ @@ -545,11 +627,13 @@ static bool create_template_file(const rented_coder *coder, const char *prefix, if (fd != -1) { - write_owner_comments(coder, fd, prefix, name, ext); + valid_prefix = prefix != NULL ? prefix : ""; + + write_owner_comments(coder, fd, valid_prefix, name, ext); if (ext == 'h') { - uprefix = make_string_upper(strdup(prefix)); + uprefix = make_string_upper(strdup(valid_prefix)); uname = make_string_upper(strdup(name)); dprintf(fd, "#ifndef %s_%s%s_H\n", coder->header, uprefix, uname); @@ -568,7 +652,7 @@ static bool create_template_file(const rented_coder *coder, const char *prefix, } else { - dprintf(fd, "#include \"%sopcodes.h\"\n", prefix); + dprintf(fd, "#include \"%sopcodes.h\"\n", valid_prefix); dprintf(fd, "\n"); dprintf(fd, "##INCLUDES##\n"); @@ -611,9 +695,18 @@ static char *build_code_filename(const rented_coder *coder, const char *input, c point = strstr(orig, "."); if (point != NULL) *point = '\0'; - length = strlen(".gen") + 1 + strlen(orig) + 1 + strlen(prefix) + 1 + strlen(name) + 3; - result = (char *)calloc(length, sizeof(char)); - snprintf(result, length, ".gen/%s.%s.%s.%c", orig, prefix, name, ext); + if (prefix == NULL) + { + length = strlen(".gen") + 1 + strlen(orig) + 1 + strlen(name) + 3; + result = (char *)calloc(length, sizeof(char)); + snprintf(result, length, ".gen/%s.%s.%c", orig, name, ext); + } + else + { + length = strlen(".gen") + 1 + strlen(orig) + 1 + strlen(prefix) + 1 + strlen(name) + 3; + result = (char *)calloc(length, sizeof(char)); + snprintf(result, length, ".gen/%s.%s.%s.%c", orig, prefix, name, ext); + } free(orig); @@ -807,7 +900,22 @@ bool dump_all_routines_using_coder(const rented_coder *coder) /* Production de code... */ - result = dump_all_matching_specs_in_coder(coder, encoding, header_fd, code_fd); + switch (coder->type) + { + case IOT_UNDEFINED: + assert(false); + result = false; + break; + + case IOT_RAW: + result = dump_all_matching_specs_in_coder(coder, encoding, header_fd, code_fd); + break; + + case IOT_FORMAT: + result = dump_all_matching_specs_from_format(coder, encoding, header_fd, code_fd); + break; + + } close(header_fd); close(code_fd); @@ -899,7 +1007,7 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st dprintf(cfd, "*\n"); dprintf(cfd, " *\n"); - dprintf(cfd, "* Retour : Bilan de l'opération. *\n"); + dprintf(cfd, "* Retour : Instruction mise en place ou NULL en cas d'échec. *\n"); dprintf(cfd, "* *\n"); dprintf(cfd, "* Remarques : - *\n"); dprintf(cfd, "* *\n"); @@ -942,3 +1050,111 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st return result; } + + +/****************************************************************************** +* * +* Paramètres : coder = gestion par la machine en remplacement d'humain. * +* encoding = sélection de l'encodage à traiter. * +* hfd = flux ouvert en écriture pour les déclarations. * +* cfd = flux ouvert en écriture pour les définitions. * +* * +* Description : Ecrit une partie des fonctions issues des spécifications. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool dump_all_matching_specs_from_format(const rented_coder *coder, const string_exch *encoding, int hfd, int cfd) +{ + bool result; /* Bilan à retourner */ + char *keyword; /* Mot clef appelable en code */ + size_t maxlen; /* Taille à compléter */ + encoding_spec *spec; /* Définition à traiter */ + + keyword = make_callable(coder->ins, false); + + /* Désassemblage : déclaration */ + + dprintf(hfd, "/* Décode une instruction de type '%s'. */\n", coder->ins); + + if (encoding->dest == NULL) + dprintf(hfd, "GArchInstruction *%s_read_instr_%s%s", + coder->arch, keyword, coder->details); + else + dprintf(hfd, "GArchInstruction *%s_read_%sinstr_%s%s", + coder->arch, encoding->dest, keyword, coder->details); + + dprintf(hfd, "("); + dprintf(hfd, "const GArchProcessor *, GProcContext *, const GBinContent *, "); + dprintf(hfd, "vmpa2t *, GExeFormat *"); + dprintf(hfd, ");\n"); + + dprintf(hfd, "\n"); + + /* Désassemblage : définitions */ + + dprintf(cfd, "\n"); + + dprintf(cfd, "/******************************************************************************\n"); + dprintf(cfd, "* *\n"); + dprintf(cfd, "* Paramètres : proc = processeur de l'architecture d'exécution. *\n"); + dprintf(cfd, "* ctx = contexte associé à la phase de désassemblage. *\n"); + dprintf(cfd, "* content = flux de données à analyser. *\n"); + dprintf(cfd, "* pos = position courante dans ce flux. [OUT] *\n"); + dprintf(cfd, "* format = format du fichier contenant le code. *\n"); + dprintf(cfd, "* *\n"); + dprintf(cfd, "* Description : Décode une instruction de type '%s'.", coder->ins); + + maxlen = 28 - strlen(coder->ins); + + if (maxlen < 28) + dprintf(cfd, "%*s\n", (int)maxlen, "*"); + else + dprintf(cfd, "*\n"); + + dprintf(cfd, " *\n"); + dprintf(cfd, "* Retour : Instruction mise en place ou NULL en cas d'échec. *\n"); + dprintf(cfd, "* *\n"); + dprintf(cfd, "* Remarques : - *\n"); + dprintf(cfd, "* *\n"); + dprintf(cfd, "******************************************************************************/\n"); + + dprintf(cfd, "\n"); + + if (encoding->dest == NULL) + dprintf(cfd, "GArchInstruction *%s_read_instr_%s%s", + coder->arch, keyword, coder->details); + else + dprintf(cfd, "GArchInstruction *%s_read_%sinstr_%s%s", + coder->arch, encoding->dest, keyword, coder->details); + + dprintf(cfd, "("); + dprintf(cfd, "const GArchProcessor *proc, GProcContext *ctx, const GBinContent *content, "); + dprintf(cfd, "vmpa2t *pos, GExeFormat *format"); + dprintf(cfd, ")"); + + dprintf(cfd, "\n"); + dprintf(cfd, "{"); + dprintf(cfd, "\n"); + + assert(coder->specs_count == 1); + + spec = coder->specs[0]; + + assert(has_encoding_spec_prefix(spec, encoding->src)); + + result = write_encoding_spec_format_disass(spec, cfd, coder->arch, encoding->dest, + coder->ins, coder->separator, coder->raw_details, + coder->pp, coder->const_prefix); + + dprintf(cfd, "}\n"); + dprintf(cfd, "\n"); + + free(keyword); + + return result; + +} diff --git a/tools/d2c/coder.h b/tools/d2c/coder.h index d9f0f0e..7ba88bc 100644 --- a/tools/d2c/coder.h +++ b/tools/d2c/coder.h @@ -41,6 +41,16 @@ typedef struct _rented_coder rented_coder; /* -------------------------- CONSTRUCTION SELON COMMANDES -------------------------- */ +/* Type d'entrée/sortie attendues */ +typedef enum _InputOutputType +{ + IOT_UNDEFINED, /* Type non défini */ + IOT_RAW, /* Lecture de contenu brut */ + IOT_FORMAT /* Définition d'opérandes */ + +} InputOutputType; + + /* Débute la définition d'une fonction de désassemblage. */ rented_coder *create_coder(void); @@ -56,6 +66,9 @@ const char *get_coder_input_file(const rented_coder *); /* Spécifie le fichier de définition à prendre en entrée. */ void set_coder_input_file(rented_coder *, const char *); +/* Spécifie le type de format à prendre en compte (E/S). */ +void set_coder_input_type(rented_coder *, InputOutputType); + /* Spécifie le répertoire de base pour les sorties de code. */ void set_coder_output_directory(rented_coder *, const char *); @@ -65,11 +78,14 @@ void set_coder_arch(rented_coder *, const char *); /* Définit la base des protections des fichiers d'en-tête. */ void set_coder_header_base(rented_coder *, const char *); +/* Définit le préfixe pour les opérandes chargées par format. */ +void set_coder_const_prefix(rented_coder *, const char *); + /* Fournit le pré-processeur du compilateur. */ pre_processor *get_coder_pre_proc(const rented_coder *); /* Enregistre les contours d'une instruction d'assemblage. */ -void save_notes_for_coder(rented_coder *, char *, char *, const char *); +void save_notes_for_coder(rented_coder *, char *, char *, char, const char *); diff --git a/tools/d2c/d2c.mk b/tools/d2c/d2c.mk index b0b7b92..72269b7 100644 --- a/tools/d2c/d2c.mk +++ b/tools/d2c/d2c.mk @@ -9,19 +9,42 @@ fix_verbose = $(fix_verbose_@AM_V@) fix_verbose_ = $(fix_verbose_@AM_DEFAULT_V@) fix_verbose_0 = echo " FIX " `basename $$f`; -# D2C_BIN = -# D2C_OUTDIR = -# D2C_ARCH = -# D2C_HEADER = -# D2C_ENCODINGS = -# D2C_MACROS = + +# D2C_BIN = +# D2C_TYPE = +# D2C_OUTDIR = +# D2C_ARCH = +# D2C_HEADER = +# D2C_ENCODINGS = +# D2C_MACROS = +# D2C_PREFIX = + +# FIXED_C_INCLUDES = +# FIXED_H_INCLUDES = + SUFFIXES = .g .d.g: - $(d2c_verbose)$(D2C_BIN) -i $< -d $(D2C_OUTDIR) -a $(D2C_ARCH) -H $(D2C_HEADER) $(D2C_ENCODINGS) $(D2C_MACROS) + $(d2c_verbose)$(D2C_BIN) -i $< -t $(D2C_TYPE) -d $(D2C_OUTDIR) -a $(D2C_ARCH) -H $(D2C_HEADER) $(D2C_ENCODINGS) $(D2C_MACROS) -p $(D2C_PREFIX) @touch $@ +d2c_final_rules: fix_includes_in_c_templates fix_includes_in_h_templates untabify_disass + +fix_includes_in_c_templates: + for f in `find .gen/ -name '*tmpl.c'`; do \ + if grep -q '##INCLUDES##' $$f; then \ + $(fix_verbose)sed -i 's/##INCLUDES##/$(FIXED_C_INCLUDES)/' $$f; \ + fi; \ + done + +fix_includes_in_h_templates: + @for f in `find .gen/ -name '*tmpl.h'`; do \ + if grep -q '##INCLUDES##' $$f; then \ + $(fix_verbose)sed -i 's/##INCLUDES##/$(FIXED_H_INCLUDES)/' $$f ; \ + fi; \ + done + # Merci http://www.commandlinefu.com/commands/view/10276/grep-tab-t untabify_disass: @find .gen/ -name '*[ch]' -exec grep -q $$'\t' {} \; -exec sed -i 's/\t/ /g' {} \; diff --git a/tools/d2c/d2c_genmakefile.sh b/tools/d2c/d2c_genmakefile.sh index 2338b6d..7911d04 100755 --- a/tools/d2c/d2c_genmakefile.sh +++ b/tools/d2c/d2c_genmakefile.sh @@ -29,19 +29,31 @@ $echo >> ${MAKEFILE_TMP} $echo "include ${globalmk}" >> ${MAKEFILE_TMP} $echo >> ${MAKEFILE_TMP} -OPCODES=`find ${input} -name '*c' -and -not -name '*.tmpl.c' -exec basename {} \; | cut -d . -f 3 | sort | uniq` +if [ "$1" = "-" ]; then + OPCODES=`find ${input} -name '*c' -and -not -name '*.tmpl.c' -exec basename {} \; | cut -d. -f2 | sort | uniq` +else + OPCODES=`find ${input} -name '*c' -and -not -name '*.tmpl.c' -exec basename {} \; | cut -d. -f3 | sort | uniq` +fi # Génération des en-têtes de décodage for arch in $*; do - $echo -n "${arch}_HEADER_FILES =" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP} + if [ ${arch} = "-" ]; then + arch_name="" + arch_name_dotted="" + else + arch_name="${arch}_" + arch_name_dotted="${arch}_." + fi + + $echo -n "${arch_name}HEADER_FILES =" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP} has_header="" for op in $OPCODES; do - template="${input}/*${arch}_.${op}.c" + template="${input}/*.${arch_name_dotted}${op}.c" sources=`ls $template 2> /dev/null` @@ -62,8 +74,8 @@ do $echo >> ${MAKEFILE_TMP} $echo >> ${MAKEFILE_TMP} - $echo -n "${arch}_opcodes.h: " >> ${MAKEFILE_TMP} - $echo "\$(${arch}_HEADER_FILES)" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP} + $echo -n "${arch_name}opcodes.h: " >> ${MAKEFILE_TMP} + $echo "\$(${arch_name}HEADER_FILES)" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP} if [ -z "${has_header}" ]; then @@ -71,7 +83,7 @@ do else - $echo -e "\t\$(cini_verbose)cat ${input}/${arch}_.opcodes.tmpl.h > \$@" >> ${MAKEFILE_TMP} + $echo -e "\t\$(cini_verbose)cat ${input}/${arch_name_dotted}opcodes.tmpl.h > \$@" >> ${MAKEFILE_TMP} $echo -e "\t\$(cgen_verbose)cat \$^ >> \$@" >> ${MAKEFILE_TMP} $echo -e "\t\$(cfini_verbose)echo >> \$@" >> ${MAKEFILE_TMP} $echo -en "\t\$(cfini_verbose)echo \"#endif\t /* " >> ${MAKEFILE_TMP} @@ -93,7 +105,15 @@ for op in $OPCODES; do for arch in $*; do - template="${input}/*${arch}_.${op}.c" + if [ ${arch} = "-" ]; then + arch_name="" + arch_name_dotted="" + else + arch_name="${arch}_" + arch_name_dotted="${arch}_." + fi + + template="${input}/*.${arch_name_dotted}${op}.c" sources=`ls $template 2> /dev/null` @@ -101,7 +121,7 @@ do continue fi - $echo -n "${op}_${arch}_FILES =" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP} + $echo -n "${op}_${arch_name}FILES =" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP} for src in ${sources}; do @@ -112,13 +132,13 @@ do $echo >> ${MAKEFILE_TMP} $echo >> ${MAKEFILE_TMP} - $echo -n "${arch}_${op}.c: " >> ${MAKEFILE_TMP} - $echo -n "\$(${op}_${arch}_FILES)" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP} - $echo " ${arch}_opcodes.h" >> ${MAKEFILE_TMP} + $echo -n "${arch_name}${op}.c: " >> ${MAKEFILE_TMP} + $echo -n "\$(${op}_${arch_name}FILES)" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP} + $echo " ${arch_name}opcodes.h" >> ${MAKEFILE_TMP} - $echo -e "\t\$(cini_verbose)cat ${input}/${arch}_.${op}.tmpl.c > \$@" >> ${MAKEFILE_TMP} + $echo -e "\t\$(cini_verbose)cat ${input}/${arch_name_dotted}${op}.tmpl.c > \$@" >> ${MAKEFILE_TMP} $echo -ne "\t\$(cgen_verbose)cat \$(" >> ${MAKEFILE_TMP} - $echo -ne "${op}_${arch}_FILES" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP} + $echo -ne "${op}_${arch_name}FILES" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP} $echo -e ") >> \$@" >> ${MAKEFILE_TMP} $echo >> ${MAKEFILE_TMP} @@ -135,18 +155,26 @@ $echo -n "GENERATED_FILES =" >> ${MAKEFILE_TMP} for arch in $*; do + if [ ${arch} = "-" ]; then + arch_name="" + arch_name_dotted="" + else + arch_name="${arch}_" + arch_name_dotted="${arch}_." + fi + $echo -ne " \\" >> ${MAKEFILE_TMP} - $echo -ne "\n\t${arch}_opcodes.h" >> ${MAKEFILE_TMP} + $echo -ne "\n\t${arch_name}opcodes.h" >> ${MAKEFILE_TMP} for op in $OPCODES; do - template="${input}/*${arch}_.${op}.c" + template="${input}/*.${arch_name_dotted}${op}.c" sources=`ls $template 2> /dev/null` if [ ! -z "${sources}" ]; then $echo -ne " \\" >> ${MAKEFILE_TMP} - $echo -ne "\n\t${arch}_${op}.c" >> ${MAKEFILE_TMP} + $echo -ne "\n\t${arch_name}${op}.c" >> ${MAKEFILE_TMP} continue fi diff --git a/tools/d2c/format/Makefile.am b/tools/d2c/format/Makefile.am new file mode 100644 index 0000000..7afd98d --- /dev/null +++ b/tools/d2c/format/Makefile.am @@ -0,0 +1,31 @@ + +BUILT_SOURCES = grammar.h + + +# On évite d'utiliser les variables personnalisées de type *_la_[YL]FLAGS +# afin de conserver des noms de fichiers simples, ie sans le nom de la +# bibliothèque de sortie en préfixe. + +AM_YFLAGS = -v -d -p format_ + +AM_LFLAGS = -P format_ -o lex.yy.c --header-file=tokens.h \ + -Dyylval=format_lval -Dyyget_lineno=format_get_lineno \ + -Dyy_scan_string=format__scan_string \ + -Dyy_delete_buffer=format__delete_buffer + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) + + +noinst_LTLIBRARIES = libd2cformat.la + +.NOTPARALLEL: $(noinst_LTLIBRARIES) + +libd2cformat_la_SOURCES = \ + decl.h \ + manager.h manager.c \ + tokens.l \ + grammar.y + + +# Automake fait les choses à moitié +CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h diff --git a/tools/d2c/format/decl.h b/tools/d2c/format/decl.h new file mode 100644 index 0000000..0b7775a --- /dev/null +++ b/tools/d2c/format/decl.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * decl.h - déclarations de prototypes utiles + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +#ifndef _TOOLS_D2C_FORMAT_DECL_H +#define _TOOLS_D2C_FORMAT_DECL_H + + +#include "manager.h" + + + +/* Interprête des données relatives à une définition de format. */ +bool load_format_from_raw_line(operands_format *, const char *); + + + +#endif /* _TOOLS_D2C_BITS_DECL_H */ diff --git a/tools/d2c/format/grammar.y b/tools/d2c/format/grammar.y new file mode 100644 index 0000000..062d616 --- /dev/null +++ b/tools/d2c/format/grammar.y @@ -0,0 +1,107 @@ + +%{ + +#include "tokens.h" + + +/* Affiche un message d'erreur suite à l'analyse en échec. */ +static int yyerror(operands_format *, char *); + +%} + + +%code requires { + +#include "decl.h" + +} + + +%union { + + char *string; /* Chaîne de caractères */ + +} + + +%define api.pure full + +%parse-param { operands_format *format } + +%code provides { + +#define YY_DECL \ + int format_lex(YYSTYPE *yylvalp) + +YY_DECL; + +} + + +%token OPS_TYPE + +%type <string> OPS_TYPE + + + +%% + + +type : OPS_TYPE { set_operands_format_type(format, $1); } + + +%% + + +/****************************************************************************** +* * +* Paramètres : format = structure impliquée dans le processus. * +* msg = message d'erreur. * +* * +* Description : Affiche un message d'erreur suite à l'analyse en échec. * +* * +* Retour : 0 * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int yyerror(operands_format *format, char *msg) +{ + printf("bits yyerror line %d: %s\n", yyget_lineno(), msg); + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : format = structure à constituer à partir de données lues. * +* raw = données brutes à analyser. * +* * +* Description : Interprête des données relatives à une définition de format. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_format_from_raw_line(operands_format *format, const char *raw) +{ + bool result; /* Bilan à faire remonter */ + YY_BUFFER_STATE state; /* Support d'analyse */ + int status; /* Bilan de l'analyse */ + + state = yy_scan_string(raw); + + status = yyparse(format); + + result = (status == 0); + + yy_delete_buffer(state); + + return result; + +} diff --git a/tools/d2c/format/manager.c b/tools/d2c/format/manager.c new file mode 100644 index 0000000..070b70c --- /dev/null +++ b/tools/d2c/format/manager.c @@ -0,0 +1,145 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * manager.c - enregistrement de la définition des opérandes attendus + * + * Copyright (C) 2014 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 <http://www.gnu.org/licenses/>. + */ + + +#include "manager.h" + + +#include <malloc.h> + + +#include "../helpers.h" + + + +/* Mémorisation de la définition d'opérandes */ +struct _operands_format +{ + char *type; /* Définitions des opérandes */ + +}; + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée un nouveau gestionnaire de définitions d'opérandes. * +* * +* Retour : Nouvelle structure prête à emploi. * +* * +* Remarques : - * +* * +******************************************************************************/ + +operands_format *create_operands_format(void) +{ + operands_format *result; /* Définition vierge à renvoyer*/ + + result = (operands_format *)calloc(1, sizeof(operands_format)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = gestionnaire de définition d'opérandes à libérer. * +* * +* Description : Supprime de la mémoire un gestionnaire de définitions. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void delete_operands_format(operands_format *format) +{ + if (format->type != NULL) + free(format->type); + + free(format); + +} + + +/****************************************************************************** +* * +* Paramètres : format = gestionnaire de définition d'opérandes à traiter. * +* type = définitions des opérandes à charger. * +* * +* Description : Précise le type d'opérandes dont la définition est à charger.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void set_operands_format_type(operands_format *format, char *type) +{ + if (format->type != NULL) + free(format->type); + + format->type = make_string_upper(type); + +} + + +/****************************************************************************** +* * +* 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. * +* prefix = préfixe pour le type de définitions d'opérandes. * +* exit = exprime le besoin d'une voie de sortie. [OUT] * +* * +* Description : Définit le chargement des opérandes prévus par la définition.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool define_operands_loading(const operands_format *format, int fd, const char *arch, const char *prefix, bool *exit) +{ + if (format->type == NULL) + { + fprintf(stderr, "Error: no type defined for operands.\n"); + return false; + } + + *exit = true; + + dprintf(fd, "\tif (!%s_read_operands(result, format, content, pos, endian, %s%s))\n", + arch, prefix, format->type); + + dprintf(fd, "\t\tgoto bad_exit;\n"); + dprintf(fd, "\n"); + + return true; + +} diff --git a/tools/d2c/format/manager.h b/tools/d2c/format/manager.h new file mode 100644 index 0000000..4555710 --- /dev/null +++ b/tools/d2c/format/manager.h @@ -0,0 +1,50 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * manager.h - prototypes pour l'enregistrement de la définition des opérandes attendus + * + * Copyright (C) 2014 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 <http://www.gnu.org/licenses/>. + */ + + +#ifndef _TOOLS_D2C_FORMAT_MANAGER_H +#define _TOOLS_D2C_FORMAT_MANAGER_H + + +#include <stdbool.h> + + + +/* Mémorisation de la définition d'opérandes */ +typedef struct _operands_format operands_format; + + +/* Crée un nouveau gestionnaire de définitions d'opérandes. */ +operands_format *create_operands_format(void); + +/* Supprime de la mémoire un gestionnaire de définitions. */ +void delete_operands_format(operands_format *); + +/* Précise le type d'opérandes dont la définition est à charger. */ +void set_operands_format_type(operands_format *, char *); + +/* Définit le chargement des opérandes prévus par la définition. */ +bool define_operands_loading(const operands_format *, int, const char *, const char *, bool *); + + + +#endif /* _TOOLS_D2C_FORMAT_MANAGER_H */ diff --git a/tools/d2c/format/tokens.l b/tools/d2c/format/tokens.l new file mode 100644 index 0000000..12ca7f0 --- /dev/null +++ b/tools/d2c/format/tokens.l @@ -0,0 +1,26 @@ + +%top { + +#include "grammar.h" + +} + + +%option noyywrap +%option nounput +%option noinput +%option yylineno +%option noyy_top_state + +%x bsize + + +%% + + +" " { } + +[A-Za-z0-9_]* { yylvalp->string = strdup(yytext); return OPS_TYPE; } + + +%% diff --git a/tools/d2c/grammar.y b/tools/d2c/grammar.y index 986edd7..02b2671 100644 --- a/tools/d2c/grammar.y +++ b/tools/d2c/grammar.y @@ -30,11 +30,23 @@ static void *map_input_data(const char *, size_t *); #include "args/decl.h" #include "bits/decl.h" #include "conv/decl.h" +#include "format/decl.h" #include "hooks/decl.h" #include "rules/decl.h" #include "syntax/decl.h" +#define handle_coder_format(c, r) \ + ({ \ + encoding_spec *__spec; \ + operands_format *__format; \ + bool __status; \ + __spec = get_current_encoding_spec(c); \ + __format = get_format_in_encoding_spec(__spec); \ + __status = load_format_from_raw_line(__format, r); \ + if (!__status) YYABORT; \ + }) + #define handle_coder_bits(c, e, r) \ ({ \ encoding_spec *__spec; \ @@ -94,6 +106,7 @@ static void *map_input_data(const char *, size_t *); %union { + char character; /* Simple caractère isolé */ char *string; /* Chaîne de caractères #1 */ const char *cstring; /* Chaîne de caractères #2 */ @@ -124,12 +137,13 @@ YY_DECL; %token COPYRIGHT %token TITLE -%token INS_NAME INS_DETAILS +%token INS_NAME INS_SEP INS_DETAILS %token ENCODING %token TYPE NUMBER %token ENC_START ENC_END +%token FORMAT %token WORD HALF %token SYNTAX %token CONV @@ -140,6 +154,7 @@ YY_DECL; %type <string> COPYRIGHT INS_NAME +%type <character> INS_SEP %type <cstring> INS_DETAILS %type <string> TYPE @@ -153,14 +168,27 @@ YY_DECL; input : name encodings { if (!dump_all_routines_using_coder(coder)) YYABORT; } -name : COPYRIGHT TITLE INS_NAME { save_notes_for_coder(coder, $1, $3, NULL); } - | COPYRIGHT TITLE INS_NAME INS_DETAILS { save_notes_for_coder(coder, $1, $3, $4); } +name : COPYRIGHT TITLE INS_NAME { save_notes_for_coder(coder, $1, $3, '\0', NULL); } + | COPYRIGHT TITLE INS_NAME INS_SEP INS_DETAILS { save_notes_for_coder(coder, $1, $3, $4, $5); } encodings : /* empty */ | encoding encodings -encoding : ENCODING TYPE NUMBER content { push_encoding_spec(coder, $2, $3); } +encoding : ENCODING TYPE NUMBER format_content { push_encoding_spec(coder, $2, $3); } + | ENCODING format_content { push_encoding_spec(coder, NULL, -1); } + | ENCODING TYPE NUMBER content { push_encoding_spec(coder, $2, $3); } + + +/* Définitions à l'aide d'un format défini */ + +format_content : /* empty */ + | format format_content + +format : FORMAT RAW_LINE { handle_coder_format(coder, $2); } + + +/* Définitions à l'aide de données brutes */ content : /* empty */ @@ -170,7 +198,6 @@ content : /* empty */ | hooks content | rules content - bitfield : HALF RAW_LINE { handle_coder_bits(coder, 16, $2); } | WORD RAW_LINE { handle_coder_bits(coder, 32, $2); } @@ -225,7 +252,7 @@ static void show_usage(const char *argv0) { printf("\n"); - printf("Usage: %s [options] < file\n", argv0); + printf("Usage: %s [options]\n", argv0); printf("\n"); @@ -234,11 +261,14 @@ static void show_usage(const char *argv0) printf("\n"); printf("\t-h | --help\t\t\tDisplay this messsage.\n"); + printf("\t-i | --input <file>\t\tProvide the input file containing the description.\n"); + printf("\t-t | --type <raw|format>\tSet the type of the input file.\n"); printf("\t-d | --dir <string>\t\tSpecify the main output directory.\n"); printf("\t-a | --arch <string>\t\tDefine the archicture to handle.\n"); printf("\t-H | --header <string>\t\tSet the base of the #ifndef / #define game.\n"); - printf("\t-e | --encoding <string>\tDefine encoding prefixes for files.\n"); + printf("\t-e | --encoding <none|string>\tDefine encoding prefixes for files.\n"); printf("\t-m | --macro <string>\t\tRegister some conversion functions.\n"); + printf("\t-p | --prefix <string>\t\tDefine a prefix to format operand type constants (see -t).\n"); printf("\n"); @@ -333,11 +363,13 @@ int main(int argc, char **argv) { "help", no_argument, NULL, 'h' }, { "input", required_argument, NULL, 'i' }, + { "type", required_argument, NULL, 't' }, { "dir", required_argument, NULL, 'd' }, { "arch", required_argument, NULL, 'a' }, { "header", required_argument, NULL, 'H' }, { "encoding", required_argument, NULL, 'e' }, { "macro", required_argument, NULL, 'M' }, + { "prefix", required_argument, NULL, 'p' }, { NULL, 0, NULL, 0 } }; @@ -353,7 +385,7 @@ int main(int argc, char **argv) while (!has_error) { - ret = getopt_long(argc, argv, "hi:d:a:H:e:M:", long_options, &index); + ret = getopt_long(argc, argv, "hi:t:d:a:H:e:M:p:", long_options, &index); if (ret == -1) break; switch (ret) @@ -366,6 +398,13 @@ int main(int argc, char **argv) set_coder_input_file(coder, optarg); break; + case 't': + if (strcmp(optarg, "raw") == 0) + set_coder_input_type(coder, IOT_RAW); + else if (strcmp(optarg, "format") == 0) + set_coder_input_type(coder, IOT_FORMAT); + break; + case 'd': set_coder_output_directory(coder, optarg); break; @@ -380,13 +419,20 @@ int main(int argc, char **argv) case 'e': - sep = strchr(optarg, '='); - has_error = (sep == NULL); - - if (!has_error) + if (strcmp(optarg, "none") == 0) + register_empty_encoding(get_coder_pre_proc(coder)); + + else { - *sep = '\0'; - register_encoding(get_coder_pre_proc(coder), optarg, sep + 1); + sep = strchr(optarg, '='); + has_error = (sep == NULL); + + if (!has_error) + { + *sep = '\0'; + register_encoding(get_coder_pre_proc(coder), optarg, sep + 1); + } + } break; @@ -404,6 +450,10 @@ int main(int argc, char **argv) break; + case 'p': + set_coder_const_prefix(coder, optarg); + break; + } } @@ -412,6 +462,7 @@ int main(int argc, char **argv) { show_usage(argv[0]); result = (need_help ? EXIT_SUCCESS : EXIT_FAILURE); + printf("need help ? %d - result = %d vs %d\n", need_help, result, EXIT_SUCCESS); goto exit; } diff --git a/tools/d2c/pproc.c b/tools/d2c/pproc.c index 8644af5..fb72774 100644 --- a/tools/d2c/pproc.c +++ b/tools/d2c/pproc.c @@ -92,6 +92,32 @@ void delete_pre_processor(pre_processor *pp) /****************************************************************************** * * +* Paramètres : pp = pré-processeur dont le contenu est à compléter. * +* * +* Description : Enregistre une correspondance nule en matière d'encodage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void register_empty_encoding(pre_processor *pp) +{ + string_exch *encoding; /* Traduction à conserver */ + + pp->encodings = (string_exch *)realloc(pp->encodings, ++pp->encodings_count * sizeof(string_exch)); + + encoding = &pp->encodings[pp->encodings_count - 1]; + + encoding->src = NULL; + encoding->dest = NULL; + +} + + +/****************************************************************************** +* * * Paramètres : pp = pré-processeur dont le contenu est à compléter. * * src = chaîne à remplacer dans les définitions. * * dest = chaîne de remplacement. * diff --git a/tools/d2c/pproc.h b/tools/d2c/pproc.h index 2a7b6c8..a2812f8 100644 --- a/tools/d2c/pproc.h +++ b/tools/d2c/pproc.h @@ -47,6 +47,9 @@ pre_processor *create_pre_processor(void); /* Supprime de la mémoire un pré-processeur et ses macros. */ void delete_pre_processor(pre_processor *); +/* Enregistre une correspondance nule en matière d'encodage. */ +void register_empty_encoding(pre_processor *); + /* Enregistre une correspondance en matière d'encodage. */ void register_encoding(pre_processor *, const char *, const char *); diff --git a/tools/d2c/spec.c b/tools/d2c/spec.c index 30a412a..1692fd8 100644 --- a/tools/d2c/spec.c +++ b/tools/d2c/spec.c @@ -40,6 +40,8 @@ struct _encoding_spec 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 */ asm_syntax *syntax; /* Calligraphe d'assemblage */ conv_list *conversions; /* Conversions des données */ @@ -68,6 +70,8 @@ encoding_spec *create_encoding_spec(void) result = (encoding_spec *)calloc(1, sizeof(encoding_spec)); + result->format = create_operands_format(); + result->bits = create_coding_bits(); result->syntax = create_asm_syntax(); result->conversions = create_conv_list(); @@ -93,6 +97,8 @@ encoding_spec *create_encoding_spec(void) void delete_encoding_spec(encoding_spec *spec) { + delete_operands_format(spec->format); + delete_coding_bits(spec->bits); delete_asm_syntax(spec->syntax); delete_conv_list(spec->conversions); @@ -142,7 +148,37 @@ void define_encoding_spec_code_name(encoding_spec *spec, char *prefix, unsigned bool has_encoding_spec_prefix(const encoding_spec *spec, const char *prefix) { - return (strcmp(spec->prefix, prefix) == 0); + 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 : 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; } @@ -250,7 +286,6 @@ decoding_rules *get_rules_in_encoding_spec(const encoding_spec *spec) * subarch = sous-catégorie de cette même architecture. * * ins = désignation première de l'instruction manipulée. * * details = particularités de l'instruction. * -* keyword = nom clef de l'instruction utilisable dans du code. * * wide = taille des mots manipulés (en bits). * * pp = pré-processeur pour les échanges de chaînes. * * * @@ -380,3 +415,98 @@ bool write_encoding_spec_disass(const encoding_spec *spec, int fd, const char *a 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. * +* subarch = sous-catégorie de cette même architecture. * +* ins = désignation première de l'instruction manipulée. * +* sep = caractère de séparation avant les détails. * +* details = particularités de l'instruction. * +* pp = pré-processeur pour les échanges de chaînes. * +* 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 char *subarch, const char *ins, char sep, const char *details, const pre_processor *pp, const char *prefix) +{ + bool result; /* Bilan à retourner */ + bool quick_exit; /* Inclusion de sortie rapide ?*/ + bool bad_exit; /* Ajout d'une sortie d'échec ?*/ + const char *new_ins; /* Nouvelle définition de nom */ + + result = true; + + /* 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"); + + /* Création de l'instruction en elle-même */ + + new_ins = get_new_keyword_from_syntax_items(spec->syntax); + + if (new_ins != NULL) + dprintf(fd, "\tresult = g_%s_instruction_new(\"%s\");\n", arch, new_ins); + else + { + if (sep == '\0') + dprintf(fd, "\tresult = g_%s_instruction_new(\"%s\");\n", arch, ins); + else + dprintf(fd, "\tresult = g_%s_instruction_new(\"%s%c%s\");\n", arch, ins, sep, details); + } + + dprintf(fd, "\n"); + + /* Inscriptions des éventuelles fonctions ou propriété à lier */ + + result &= write_hook_functions(spec->hooks, fd); + + result &= write_decoding_rules(spec->rules, CAT_CHECKED_CALL, + fd, arch, subarch, spec->bits, spec->conversions, pp, &quick_exit); + + result &= write_decoding_rules(spec->rules, CAT_CALL, + fd, arch, subarch, spec->bits, spec->conversions, pp, &quick_exit); + + /* Création des opérandes */ + + dprintf(fd, "\tendian = g_arch_processor_get_endianness(G_ARCH_PROCESSOR(proc));\n"); + + dprintf(fd, "\n"); + + bad_exit = false; + + result &= define_operands_loading(spec->format, fd, arch, prefix, &bad_exit); + + /* Conclusion de la procédure */ + + 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"); + + } + + return result; + +} diff --git a/tools/d2c/spec.h b/tools/d2c/spec.h index e09aa49..8c62fc3 100644 --- a/tools/d2c/spec.h +++ b/tools/d2c/spec.h @@ -31,6 +31,7 @@ #include "pproc.h" #include "bits/manager.h" #include "conv/manager.h" +#include "format/manager.h" #include "hooks/manager.h" #include "rules/manager.h" #include "syntax/manager.h" @@ -53,6 +54,9 @@ void define_encoding_spec_code_name(encoding_spec *, char *, unsigned int); /* Indique si une spécification se range dans une catégorie. */ bool has_encoding_spec_prefix(const encoding_spec *, const char *); +/* Fournit le gestionnaire des définitions d'opérandes. */ +operands_format *get_format_in_encoding_spec(const encoding_spec *); + /* Fournit le gestionnaire des bits d'un encodage d'instruction. */ coding_bits *get_bits_in_encoding_spec(const encoding_spec *); @@ -71,6 +75,9 @@ decoding_rules *get_rules_in_encoding_spec(const encoding_spec *); /* Traduit en code une sous-fonction de désassemblage. */ bool write_encoding_spec_disass(const encoding_spec *, int, const char *, const char *, const char *, const char *, unsigned int, const pre_processor *); +/* Traduit en code une sous-fonction de désassemblage. */ +bool write_encoding_spec_format_disass(const encoding_spec *, int, const char *, const char *, const char *, char, const char *, const pre_processor *, const char *); + #endif /* _TOOLS_D2C_SPEC_H */ diff --git a/tools/d2c/tokens.l b/tools/d2c/tokens.l index e48d079..1e4b7b0 100644 --- a/tools/d2c/tokens.l +++ b/tools/d2c/tokens.l @@ -6,41 +6,19 @@ } - %{ - //typedef struct _rented_coder rented_coder; - - -//#include "d2c-d2c_gram.h" - -#include <ctype.h> -#include <string.h> - - #include "manual.h" - - %} + %option noyywrap %option nounput - //%option noinput %option yylineno %option stack %option noyy_top_state - //%option reentrant - //%option bison-bridge - -/* %option bison-bridge */ -/* %option bison-locations */ -/* %option ecs */ -/* %option nodefault */ -/* %option noyywrap */ -/* %option reentrant */ - %x comments @@ -52,81 +30,65 @@ %x raw_line - %% -[ \t\n]+ { } - -"/*" { BEGIN(comments); } -<comments>"*/" { BEGIN(INITIAL); } -<comments>[^*\n] { } -<comments>"Copyright"[^\n]* { yylvalp->string = strdup(yytext); return COPYRIGHT; } -<comments>"*" { } -<comments>"\n" { } - - -"@title" { BEGIN(ins_name); return TITLE; } - -<ins_name>[ ][A-Za-z-]+ { yylvalp->string = strdup(yytext + 1); BEGIN(try_details); return INS_NAME; } -<try_details>[ ,/] { BEGIN(ins_details); } -<try_details>[\n] { BEGIN(INITIAL); } - -<ins_details>[^\n]* { yylvalp->cstring = yytext; return INS_DETAILS; } -<ins_details>[\n] { BEGIN(INITIAL); } - - - -"@encoding" { BEGIN(encoding); return ENCODING; } - -<encoding>[ ] { } -<encoding>"(" { BEGIN(encoding_type); } - -<encoding_type>[A-Za-z] { yylvalp->string = strdup(yytext); return TYPE; } -<encoding_type>[0-9]+ { yylvalp->integer = atoi(yytext); return NUMBER; } -<encoding_type>")" { BEGIN(encoding); } - -<encoding>"{" { BEGIN(encoding_content); } -<encoding_content>[ \t\n]+ { } -<encoding_content>"}" { BEGIN(INITIAL); } - - - -<encoding_content>"@half " { yy_push_state(raw_line); return HALF; } -<encoding_content>"@word " { yy_push_state(raw_line); return WORD; } - - -<raw_line>[^\n]+ { yylvalp->cstring = yytext; return RAW_LINE; } -<raw_line>"\n" { yy_pop_state(); } +[ \t\n]+ { } +"/*" { BEGIN(comments); } +<comments>"*/" { BEGIN(INITIAL); } +<comments>[^*\n] { } +<comments>"Copyright"[^\n]* { yylvalp->string = strdup(yytext); return COPYRIGHT; } +<comments>"*" { } +<comments>"\n" { } +"@title" { BEGIN(ins_name); return TITLE; } -<encoding_content>"@syntax " { yy_push_state(raw_line); return SYNTAX; } +<ins_name>[ ][A-Za-z-]+ { yylvalp->string = strdup(yytext + 1); BEGIN(try_details); return INS_NAME; } +<try_details>[ ,/-] { BEGIN(ins_details); yylvalp->character = yytext[0]; return INS_SEP; } +<try_details>[\n] { BEGIN(INITIAL); } +<ins_details>[^\n]* { yylvalp->cstring = yytext; return INS_DETAILS; } +<ins_details>[\n] { BEGIN(INITIAL); } +"@encoding" { BEGIN(encoding); return ENCODING; } -<encoding_content>"@conv" { return CONV; } +<encoding>[ ] { } +<encoding>"(" { BEGIN(encoding_type); } +<encoding_type>[A-Za-z] { yylvalp->string = strdup(yytext); return TYPE; } +<encoding_type>[0-9]+ { yylvalp->integer = atoi(yytext); return NUMBER; } +<encoding_type>")" { BEGIN(encoding); } +<encoding>"{" { BEGIN(encoding_content); } +<encoding_content>[ \t\n]+ { } +<encoding_content>"}" { BEGIN(INITIAL); } -<encoding_content>"{" { - read_block(temp); - yylvalp->cstring = temp; return RAW_BLOCK; - } +<encoding_content>"@format" { yy_push_state(raw_line); return FORMAT; } +<encoding_content>"@half" { yy_push_state(raw_line); return HALF; } +<encoding_content>"@word" { yy_push_state(raw_line); return WORD; } +<encoding_content>"@syntax" { yy_push_state(raw_line); return SYNTAX; } +<encoding_content>"@conv" { return CONV; } +<encoding_content>"@hooks" { return HOOKS; } +<encoding_content>"@rules" { return RULES; } -<encoding_content>"@hooks" { return HOOKS; } +<raw_line>[^\n]+ { yylvalp->cstring = yytext; return RAW_LINE; } +<raw_line>"\n" { yy_pop_state(); } -<encoding_content>"@rules" { return RULES; } +<encoding_content>"{" { + read_block(temp); + yylvalp->cstring = temp; return RAW_BLOCK; + } %% |