diff options
33 files changed, 552 insertions, 103 deletions
| @@ -1,3 +1,58 @@ +15-03-18  Cyrille Bagard <nocbos@gmail.com> + +	* src/analysis/disass/area.c: +	Ensure symbols exist where instructions are marked as first instructions +	of a routine. + +	* src/analysis/disass/disassembler.c: +	* src/analysis/disass/limit.c: +	Compute limits for all routines according to existing symbols. + +	* src/arch/arm/v7/opdefs/b_A8818.d: +	* src/arch/arm/v7/opdefs/bl_A8825.d: +	* src/arch/arm/v7/opdefs/blx_A8826.d: +	* src/arch/arm/v7/opdefs/bx_A8827.d: +	* src/arch/arm/v7/opdefs/ldr_A8862.d: +	* src/arch/arm/v7/opdefs/ldr_A8863.d: +	* src/arch/arm/v7/opdefs/ldr_A8864.d: +	* src/arch/arm/v7/opdefs/ldr_A8865.d: +	* src/arch/arm/v7/opdefs/ldrb_A8867.d: +	* src/arch/arm/v7/opdefs/Makefile.am: +	* src/arch/arm/v7/opdefs/pop_A88131.d: +	* src/arch/arm/v7/opdefs/push_A88133.d: +	* src/arch/arm/v7/opdefs/str_A88204.d: +	Update all rules calls and define a new one for instruction flags. + +	* src/arch/arm/v7/post.c: +	Update symbol types: they are STP_CODE_LABEL, not STP_ROUTINE. + +	* src/arch/instruction.c: +	* src/arch/instruction.h: +	* src/arch/instruction-int.h: +	Define generic instruction flags. + +	* src/format/format.c: +	Collect routines when symbols are added. + +	* src/format/symbol.c: +	* src/format/symbol.h: +	Update code for the new 'STP_CODE_LABEL' type. + +	* tools/d2c/args.c: +	* tools/d2c/args.h: +	Allow constants unknown by d2c to be used: gcc will recognize them. + +	* tools/d2c/d2c_gram.y: +	* tools/d2c/d2c_tok.l: +	Handle binary as well as hex values for conditions. Update code. + +	* tools/d2c/qckcall.c: +	* tools/d2c/qckcall.h: +	* tools/d2c/rules.c: +	* tools/d2c/rules.h: +	* tools/d2c/spec.c: +	Allow to call routines with or without return code. +  15-03-13  Cyrille Bagard <nocbos@gmail.com>  	* src/analysis/disass/area.c: diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c index 916918e..90738be 100644 --- a/src/analysis/disass/area.c +++ b/src/analysis/disass/area.c @@ -71,6 +71,11 @@ static bool mark_range_in_mem_area_as_processed(mem_area *, phys_t, phys_t, GArc +/* S'assure de la présence d'un début de routine à un point. */ +static void update_address_as_routine(GBinFormat *, const vmpa2t *); + + +  /* Procède au désassemblage d'un contenu binaire non exécutable. */  static void load_data_from_mem_area(mem_area *, mem_area *, size_t, const GLoadedBinary *, GProcContext *, const vmpa2t *, status_blob_info *); @@ -377,6 +382,70 @@ static bool mark_range_in_mem_area_as_processed(mem_area *area, phys_t start, ph + + + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : format = format binaire en cours de traitement.              * +*                addr   = adresse d'une instruction présentée comme première. * +*                                                                             * +*  Description : S'assure de la présence d'un début de routine à un point.    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void update_address_as_routine(GBinFormat *format, const vmpa2t *addr) +{ +    GBinSymbol *symbol;                     /* Symbole présent ou créé     */ +    phys_t offset;                          /* Décallage trouvé            */ +    bool found;                             /* Détection de symbole        */ +    SymbolType sym_type;                    /* Type de symbole en place    */ +    bool wrong_type;                        /* Analyse plus fine de ce type*/ +    mrange_t range;                         /* Etendue du symbole à créer  */ +    VMPA_BUFFER(loc);                       /* Traduction de l'adresse     */ +    char name[5 + VMPA_MAX_LEN];            /* Nom de symbole nouveau      */ +    GBinRoutine *routine;                   /* Nouvelle routine trouvée    */ + +    found = g_binary_format_resolve_symbol(format, addr, &symbol, &offset); + +    if (found) +    { +        sym_type = g_binary_symbol_get_target_type(symbol); +        wrong_type = (sym_type != STP_ROUTINE && sym_type != STP_ENTRY_POINT); +    } + +    if (!found || (found && offset == 0 && wrong_type)) +    { +        init_mrange(&range, addr, 0); + +        vmpa2_virt_to_string(addr, MDS_UNDEFINED, loc, NULL); +        snprintf(name, sizeof(name), "ZZZ_%s", loc + 2); + +        routine = g_binary_routine_new(); +        g_binary_routine_set_name(routine, strdup(name)); + +        g_binary_routine_set_range(routine, &range); + +        if (!found) +        { +            symbol = g_binary_symbol_new(STP_ROUTINE, NULL, ~0); +            g_binary_symbol_attach_routine(symbol, routine); +            g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol); +        } +        else _g_binary_symbol_attach_routine(symbol, routine, STP_ROUTINE); + +    } + +} + +  /******************************************************************************  *                                                                             *  *  Paramètres  : area   = aire représentant à contenu à parcourir.            * @@ -489,6 +558,11 @@ bool load_code_from_mem_area(mem_area **list, size_t *count, size_t *index, cons          g_arch_instruction_set_range(instr, &range); +        /* Enregistrement d'un éventuel début de routine */ + +        if (g_arch_instruction_get_flags(instr) & AIF_ROUTINE_START) +            update_address_as_routine(format, &prev); +          /* Eventuel renvoi vers d'autres adresses */          g_arch_instruction_call_hook(instr, IPH_LINK, ctx, format); diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c index 37e6996..4b976c3 100644 --- a/src/analysis/disass/disassembler.c +++ b/src/analysis/disass/disassembler.c @@ -29,7 +29,7 @@  #include <string.h> -#include <i18n.h>   ///// +#include <i18n.h>  #include "fetch.h" @@ -299,6 +299,27 @@ G_BIN_FORMAT(g_loaded_binary_get_format(disass->binary) +    /* Troisième  étape */ + +    routines = g_binary_format_get_routines(G_BIN_FORMAT(disass->format), &routines_count); + + + + +    //id = gtk_extended_status_bar_push(statusbar, _("Finding remaining limits..."), true); + +    //qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_rcompare); + +    limit_all_routines(disass->format, routines, routines_count, statusbar, id); + +    //gtk_extended_status_bar_remove(statusbar, id); + +    //run_plugins_on_binary(disass->binary, PGA_BINARY_BOUNDED, true); + + + + +      /* Septième étape */      //id = gtk_extended_status_bar_push(statusbar, _("Printing disassembled code..."), true); diff --git a/src/analysis/disass/limit.c b/src/analysis/disass/limit.c index bb2c865..3810978 100644 --- a/src/analysis/disass/limit.c +++ b/src/analysis/disass/limit.c @@ -128,4 +128,29 @@ void limit_all_routines(GExeFormat *format, GBinRoutine **routines, size_t count      if (exe_ranges != NULL)          free(exe_ranges); + + + +    do +    { +        const mrange_t *_range; +        vmpa2t _end; + +        printf("LIMIT == %zu routines\n", count); + +        for (i = 0; i < count; i++) +        { +            _range = g_binary_routine_get_range(routines[i]); +            compute_mrange_end_addr(_range, &_end); + +            printf(" <LIMIT> 0x%08x <-> 0x%08x '%s'\n", +                   (unsigned int)((get_mrange_addr(_range))->virtual), +                   (unsigned int)_end.virtual, +                   g_binary_routine_to_string(routines[i])); + +        } + +    } while (0); + +  } diff --git a/src/arch/arm/v7/opdefs/Makefile.am b/src/arch/arm/v7/opdefs/Makefile.am index 45d4932..318e20b 100644 --- a/src/arch/arm/v7/opdefs/Makefile.am +++ b/src/arch/arm/v7/opdefs/Makefile.am @@ -21,7 +21,8 @@ D2C_MACROS =											\      -M Condition=g_arm_instruction_set_cond				\      -M Register=translate_armv7_register				\      -M "ExpandImmC32=g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, " \ -    -M SignExtend=sign_extend_armv7_imm +    -M SignExtend=sign_extend_armv7_imm					\ +    -M SetInsFlag=g_arch_instruction_set_flag  ARMV7_DEFS = 							\  	adc_A881.d							\ diff --git a/src/arch/arm/v7/opdefs/b_A8818.d b/src/arch/arm/v7/opdefs/b_A8818.d index 5d696a3..50bdda9 100644 --- a/src/arch/arm/v7/opdefs/b_A8818.d +++ b/src/arch/arm/v7/opdefs/b_A8818.d @@ -47,7 +47,7 @@          //if cond == '1110' then UNDEFINED;          //if cond == '1111' then SEE SVC; -        call DefineAsReturn(1) +        chk_call DefineAsReturn(1)      } @@ -75,7 +75,7 @@      @rules {          //if InITBlock() && !LastInITBlock() then UNPREDICTABLE; -        call DefineAsReturn(1) +        chk_call DefineAsReturn(1)      } @@ -105,7 +105,7 @@          //if cond<3:1> == '111' then SEE "Related encodings";          //if InITBlock() then UNPREDICTABLE; -        call DefineAsReturn(1) +        chk_call DefineAsReturn(1)      } @@ -135,7 +135,7 @@      @rules {          //if InITBlock() && !LastInITBlock() then UNPREDICTABLE; -        call DefineAsReturn(1) +        chk_call DefineAsReturn(1)      } @@ -163,7 +163,7 @@      @rules { -        call DefineAsReturn(1) +        chk_call DefineAsReturn(1)      } diff --git a/src/arch/arm/v7/opdefs/bl_A8825.d b/src/arch/arm/v7/opdefs/bl_A8825.d index c5de31e..63922dd 100644 --- a/src/arch/arm/v7/opdefs/bl_A8825.d +++ b/src/arch/arm/v7/opdefs/bl_A8825.d @@ -46,7 +46,7 @@      @rules { -        //call DefineAsReturn(1) +        //chk_call DefineAsReturn(1)      } @@ -75,7 +75,7 @@      @rules { -        //call DefineAsReturn(1) +        //chk_call DefineAsReturn(1)      } @@ -102,7 +102,7 @@      @rules { -        //call DefineAsReturn(1) +        //chk_call DefineAsReturn(1)      } @@ -129,7 +129,7 @@      @rules { -        //call DefineAsReturn(1) +        //chk_call DefineAsReturn(1)      } diff --git a/src/arch/arm/v7/opdefs/blx_A8826.d b/src/arch/arm/v7/opdefs/blx_A8826.d index 12c55ad..c972af2 100644 --- a/src/arch/arm/v7/opdefs/blx_A8826.d +++ b/src/arch/arm/v7/opdefs/blx_A8826.d @@ -39,7 +39,7 @@          //if m == 15 then UNPREDICTABLE;          //if InITBlock() && !LastInITBlock() then UNPREDICTABLE; -        //call DefineAsReturn(1) +        //chk_call DefineAsReturn(1)      } @@ -61,7 +61,7 @@      @rules {          //if m == 15 then UNPREDICTABLE; -        //call DefineAsReturn(1) +        //chk_call DefineAsReturn(1)      } diff --git a/src/arch/arm/v7/opdefs/bx_A8827.d b/src/arch/arm/v7/opdefs/bx_A8827.d index dd06901..4856885 100644 --- a/src/arch/arm/v7/opdefs/bx_A8827.d +++ b/src/arch/arm/v7/opdefs/bx_A8827.d @@ -44,7 +44,7 @@      @rules { -        call DefineAsReturn(1) +        chk_call DefineAsReturn(1)      } @@ -71,7 +71,7 @@      @rules { -        call DefineAsReturn(1) +        chk_call DefineAsReturn(1)      } diff --git a/src/arch/arm/v7/opdefs/ldr_A8862.d b/src/arch/arm/v7/opdefs/ldr_A8862.d index ecb530b..49d5c3a 100644 --- a/src/arch/arm/v7/opdefs/ldr_A8862.d +++ b/src/arch/arm/v7/opdefs/ldr_A8862.d @@ -76,7 +76,7 @@          //if Rn == '1111' then SEE LDR (literal);          //if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; -        if (Rt == '1111'); call DefineAsReturn(1) +        if (Rt == '1111'); chk_call DefineAsReturn(1)      } @@ -104,7 +104,7 @@          //if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;          //if P == '0' && W == '0' then UNDEFINED;          //if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE; -        if (Rt == '1111'); call DefineAsReturn(1) +        if (Rt == '1111'); chk_call DefineAsReturn(1)      } @@ -133,7 +133,7 @@          //if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;          //if P == '0' && W == '0' then UNDEFINED;          //if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE; -        if (Rt == '1111'); call DefineAsReturn(1) +        if (Rt == '1111'); chk_call DefineAsReturn(1)      } diff --git a/src/arch/arm/v7/opdefs/ldr_A8863.d b/src/arch/arm/v7/opdefs/ldr_A8863.d index 39b9079..2360e3a 100644 --- a/src/arch/arm/v7/opdefs/ldr_A8863.d +++ b/src/arch/arm/v7/opdefs/ldr_A8863.d @@ -46,7 +46,7 @@          //t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);          //index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');          //if wback && n == t then UNPREDICTABLE; -        if (Rt == '1111'); call DefineAsReturn(1) +        if (Rt == '1111'); chk_call DefineAsReturn(1)      } @@ -76,7 +76,7 @@          //t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);          //index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');          //if wback && n == t then UNPREDICTABLE; -        if (Rt == '1111'); call DefineAsReturn(1) +        if (Rt == '1111'); chk_call DefineAsReturn(1)      } diff --git a/src/arch/arm/v7/opdefs/ldr_A8864.d b/src/arch/arm/v7/opdefs/ldr_A8864.d index 3fbc0e3..c5b0dd0 100644 --- a/src/arch/arm/v7/opdefs/ldr_A8864.d +++ b/src/arch/arm/v7/opdefs/ldr_A8864.d @@ -70,7 +70,7 @@      @rules {          //if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; -        if (Rt == '1111'); call DefineAsReturn(1) +        if (Rt == '1111'); chk_call DefineAsReturn(1)      } @@ -101,7 +101,7 @@      @rules {          //if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; -        if (Rt == '1111'); call DefineAsReturn(1) +        if (Rt == '1111'); chk_call DefineAsReturn(1)      } diff --git a/src/arch/arm/v7/opdefs/ldr_A8865.d b/src/arch/arm/v7/opdefs/ldr_A8865.d index 56a09fb..e8d255b 100644 --- a/src/arch/arm/v7/opdefs/ldr_A8865.d +++ b/src/arch/arm/v7/opdefs/ldr_A8865.d @@ -67,7 +67,7 @@          //if Rn == '1111' then SEE LDR (literal);          //if m IN {13,15} then UNPREDICTABLE;          //if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; -        if (Rt == '1111'); call DefineAsReturn(1) +        if (Rt == '1111'); chk_call DefineAsReturn(1)      } diff --git a/src/arch/arm/v7/opdefs/ldrb_A8867.d b/src/arch/arm/v7/opdefs/ldrb_A8867.d index 52a50cb..2114330 100644 --- a/src/arch/arm/v7/opdefs/ldrb_A8867.d +++ b/src/arch/arm/v7/opdefs/ldrb_A8867.d @@ -60,7 +60,7 @@          //if Rt == '1111' then SEE PLD;          //if Rn == '1111' then SEE LDRB (literal);          //if t == 13 then UNPREDICTABLE; -        if (Rt == '1111'); call DefineAsReturn(1) +        if (Rt == '1111'); chk_call DefineAsReturn(1)      } @@ -88,7 +88,7 @@          //if P == '1' && U == '1' && W == '0' then SEE LDRBT;          //if P == '0' && W == '0' then UNDEFINED;          //if t == 13 || (t == 15 && W == '1') || (wback && n == t) then UNPREDICTABLE; -        if (Rt == '1111'); call DefineAsReturn(1) +        if (Rt == '1111'); chk_call DefineAsReturn(1)      } @@ -117,7 +117,7 @@          //if P == '1' && U == '1' && W == '0' then SEE LDRBT;          //if P == '0' && W == '0' then UNDEFINED;          //if t == 13 || (t == 15 && W == '1') || (wback && n == t) then UNPREDICTABLE; -        if (Rt == '1111'); call DefineAsReturn(1) +        if (Rt == '1111'); chk_call DefineAsReturn(1)      } diff --git a/src/arch/arm/v7/opdefs/pop_A88131.d b/src/arch/arm/v7/opdefs/pop_A88131.d index 329b705..2663e1b 100644 --- a/src/arch/arm/v7/opdefs/pop_A88131.d +++ b/src/arch/arm/v7/opdefs/pop_A88131.d @@ -48,7 +48,7 @@      @word 1 1 1 0 1 0 0 0 1 0 1 1 1 1 0 1 P(1) M(1) 0 register_list(13) -    @syntax "push.W" <registers> +    @syntax "pop.W" <registers>      @conv { @@ -69,7 +69,7 @@      @word 1 1 1 1 1 0 0 0 0 1 0 1 1 1 0 1 Rt(4) 1 0 1 1 0 0 0 0 0 1 0 0 -    @syntax "push.W" <registers> +    @syntax "pop.W" <registers>      @conv { diff --git a/src/arch/arm/v7/opdefs/push_A88133.d b/src/arch/arm/v7/opdefs/push_A88133.d index 0526a56..2ba7293 100644 --- a/src/arch/arm/v7/opdefs/push_A88133.d +++ b/src/arch/arm/v7/opdefs/push_A88133.d @@ -39,6 +39,8 @@          //if BitCount(registers) < 1 then UNPREDICTABLE; +        if (M == '1'); call SetInsFlag(AIF_ROUTINE_START); +      }  } @@ -59,6 +61,8 @@          //if BitCount(registers) < 2 then UNPREDICTABLE; +        if (M == '1'); call SetInsFlag(AIF_ROUTINE_START); +      }  } @@ -80,6 +84,8 @@          //if t IN {13,15} then UNPREDICTABLE +        if (Rt == '1110'); call SetInsFlag(AIF_ROUTINE_START); +      }  } @@ -101,6 +107,8 @@          //if BitCount(register_list) < 2 then SEE STMDB / STMFD; +        if (register_list & 0x4000); call SetInsFlag(AIF_ROUTINE_START); +      }  } @@ -123,6 +131,8 @@          //if t == 13 then UNPREDICTABLE; +        if (Rt == '1110'); call SetInsFlag(AIF_ROUTINE_START); +      }  } diff --git a/src/arch/arm/v7/opdefs/str_A88204.d b/src/arch/arm/v7/opdefs/str_A88204.d index d4e9377..2712e1b 100644 --- a/src/arch/arm/v7/opdefs/str_A88204.d +++ b/src/arch/arm/v7/opdefs/str_A88204.d @@ -43,7 +43,7 @@          //if P == '0' && W == '1' then SEE STRT;          //if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 == '000000000100' then SEE PUSH;          //if wback && (n == 15 || n == t) then UNPREDICTABLE; -        if (Rt == '1111'); call DefineAsReturn(1) +        if (Rt == '1111'); chk_call DefineAsReturn(1)      } @@ -70,7 +70,7 @@          //if P == '0' && W == '1' then SEE STRT;          //if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 == '000000000100' then SEE PUSH;          //if wback && (n == 15 || n == t) then UNPREDICTABLE; -        if (Rt == '1111'); call DefineAsReturn(1) +        if (Rt == '1111'); chk_call DefineAsReturn(1)      } diff --git a/src/arch/arm/v7/post.c b/src/arch/arm/v7/post.c index dfeb720..e6a6c2e 100644 --- a/src/arch/arm/v7/post.c +++ b/src/arch/arm/v7/post.c @@ -77,7 +77,7 @@ void post_process_branch_instructions(GArchInstruction *instr, GProcContext *con              g_binary_routine_set_range(routine, &trange); -            symbol = g_binary_symbol_new(STP_ROUTINE, NULL, ~0); +            symbol = g_binary_symbol_new(STP_CODE_LABEL, NULL, ~0);              g_binary_symbol_attach_routine(symbol, routine);              g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol); @@ -203,7 +203,7 @@ void post_process_comp_and_branch_instructions(GArchInstruction *instr, GProcCon              g_binary_routine_set_range(routine, &trange); -            symbol = g_binary_symbol_new(STP_ROUTINE, NULL, ~0); +            symbol = g_binary_symbol_new(STP_CODE_LABEL, NULL, ~0);              g_binary_symbol_attach_routine(symbol, routine);              g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol); @@ -285,7 +285,7 @@ void post_process_ldr_instructions(GArchInstruction *instr, GProcContext *contex              g_binary_routine_set_range(routine, &trange); -            symbol = g_binary_symbol_new(STP_ROUTINE, NULL, ~0); +            symbol = g_binary_symbol_new(STP_CODE_LABEL, NULL, ~0);              g_binary_symbol_attach_routine(symbol, routine);              g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol); diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h index de9c70d..bb45f72 100644 --- a/src/arch/instruction-int.h +++ b/src/arch/instruction-int.h @@ -55,6 +55,7 @@ struct _GArchInstruction      const char *suffix;                     /* Complément au nom affiché   */      char *cached_keyword;                   /* Désignation complète        */ +    ArchInstrFlag flags;                    /* Informations complémentaires*/      instr_hook_fc hooks[IPH_COUNT];         /* Traitements complémentaires */      mrange_t range;                         /* Emplacement en mémoire      */ diff --git a/src/arch/instruction.c b/src/arch/instruction.c index aced77e..0bcc739 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -151,7 +151,7 @@ static void g_arch_instruction_finalize(GArchInstruction *instr)  /******************************************************************************  *                                                                             *  *  Paramètres  : instr  = instruction quelconque à modifier.                  * -*                suffix =  chaîne de caractères fournie en complément.        * +*                suffix = chaîne de caractères fournie en complément.         *  *                                                                             *  *  Description : Etend la désignation d'un nom d'instruction.                 *  *                                                                             * @@ -171,6 +171,45 @@ void g_arch_instruction_append_suffix(GArchInstruction *instr, const char *suffi  /******************************************************************************  *                                                                             *  *  Paramètres  : instr = instruction quelconque à modifier.                   * +*                flag  = drapeau d'information complémentaire à planter.      * +*                                                                             * +*  Description : Ajoute une information complémentaire à une instruction.     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_arch_instruction_set_flag(GArchInstruction *instr, ArchInstrFlag flag) +{ +    instr->flags |= flag; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : instr = instruction quelconque à modifier.                   * +*                                                                             * +*  Description : Fournit les informations complémentaires d'une instruction.  * +*                                                                             * +*  Retour      : Eventuels drapeaux d'information complémentaire à plantés.   * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *instr) +{ +    return instr->flags; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : instr = instruction quelconque à modifier.                   *  *                type  = type de procédure à mémoriser.                       *  *                hook  = fonction à appeler sur commande.                     *  *                                                                             * diff --git a/src/arch/instruction.h b/src/arch/instruction.h index 12cfbb9..9251a34 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -62,6 +62,20 @@ GType g_arch_instruction_get_type(void);  /* Etend la désignation d'un nom d'instruction. */  void g_arch_instruction_append_suffix(GArchInstruction *, const char *); +/* Drapeaux pour informations complémentaires */ +typedef enum _ArchInstrFlag +{ +    AIF_NONE            = (0 << 0),         /* Aucune information          */ +    AIF_ROUTINE_START   = (1 << 0)          /* Début de routine            */ + +} ArchInstrFlag; + +/* Ajoute une information complémentaire à une instruction. */ +void g_arch_instruction_set_flag(GArchInstruction *, ArchInstrFlag); + +/* Fournit les informations complémentaires d'une instruction. */ +ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *); +  /**   * La définition de "GBinFormat", utile aux traitements complémentaires, ne peut   * se faire en incluant le fichier d'en-tête "../format/format.h", pour cause diff --git a/src/format/format.c b/src/format/format.c index 2808b67..2093469 100644 --- a/src/format/format.c +++ b/src/format/format.c @@ -192,11 +192,28 @@ void g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol)      format->symbols[format->symbols_count - 1] = symbol; -  	qsort(format->symbols, format->symbols_count,  		  sizeof(GBinSymbol *), (__compar_fn_t)g_binary_symbol_cmp); +    switch (g_binary_symbol_get_target_type(symbol)) +    { +        case STP_ROUTINE: +        case STP_ENTRY_POINT: + +            format->routines = (GBinRoutine **)realloc(format->routines, +                                                       ++format->routines_count * sizeof(GBinRoutine *)); + +            format->routines[format->routines_count - 1] = g_binary_symbol_get_routine(symbol); +             +            qsort(format->routines, format->routines_count, +                  sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_compare); +            break; + +        default: +            break; + +    }  } diff --git a/src/format/symbol.c b/src/format/symbol.c index d360591..c867b68 100644 --- a/src/format/symbol.c +++ b/src/format/symbol.c @@ -228,6 +228,7 @@ const char *g_binary_symbol_to_string(const GBinSymbol *symbol)      {          case STP_ROUTINE:          case STP_ENTRY_POINT: +        case STP_CODE_LABEL:              result = g_binary_routine_get_name(symbol->extra.routine);              break; @@ -292,6 +293,7 @@ const char *g_binary_symbol_get_label(const GBinSymbol *symbol)      {          case STP_ROUTINE:          case STP_ENTRY_POINT: +        case STP_CODE_LABEL:              result = g_binary_routine_get_name(symbol->extra.routine);              break; @@ -344,6 +346,7 @@ void g_binary_symbol_fix_range(GBinSymbol *symbol, const vmpa2t *full)          case STP_ROUTINE:          case STP_ENTRY_POINT: +        case STP_CODE_LABEL:              routine = g_binary_symbol_get_routine(symbol); @@ -392,6 +395,7 @@ const mrange_t *g_binary_symbol_get_range(const GBinSymbol *symbol)          case STP_ROUTINE:          case STP_ENTRY_POINT: +        case STP_CODE_LABEL:              result = g_binary_routine_get_range(symbol->extra.routine);              break; @@ -431,6 +435,7 @@ void g_binary_symbol_set_alt_name(GBinSymbol *symbol, char *alt)  *                                                                             *  *  Paramètres  : symbol  = symbole à venir consulter.                         *  *                routine = prototype de la fonction représentée.              * +*                type    = (nouveau) type du symbole attaché.                 *  *                                                                             *  *  Description : Attache la routine associée au symbole.                      *  *                                                                             * @@ -440,8 +445,13 @@ void g_binary_symbol_set_alt_name(GBinSymbol *symbol, char *alt)  *                                                                             *  ******************************************************************************/ -void g_binary_symbol_attach_routine(GBinSymbol *symbol, GBinRoutine *routine) +void _g_binary_symbol_attach_routine(GBinSymbol *symbol, GBinRoutine *routine, SymbolType type)  { +    if (symbol->extra.routine != NULL) +        g_object_unref(G_OBJECT(symbol->extra.routine)); + +    symbol->type = type; +      symbol->extra.routine = routine;  } @@ -449,6 +459,26 @@ void g_binary_symbol_attach_routine(GBinSymbol *symbol, GBinRoutine *routine)  /******************************************************************************  *                                                                             * +*  Paramètres  : symbol  = symbole à venir consulter.                         * +*                routine = prototype de la fonction représentée.              * +*                                                                             * +*  Description : Attache la routine associée au symbole.                      * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_binary_symbol_attach_routine(GBinSymbol *symbol, GBinRoutine *routine) +{ +    _g_binary_symbol_attach_routine(symbol, routine, symbol->type); + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : symbol = symbole à venir manipuler.                          *  *                instr  = représentation du symbole associé.                  *  *                                                                             * diff --git a/src/format/symbol.h b/src/format/symbol.h index fafc55f..49cde56 100644 --- a/src/format/symbol.h +++ b/src/format/symbol.h @@ -39,6 +39,7 @@ typedef enum _SymbolType  {      STP_DATA,                               /* Données brutes              */      STP_ROUTINE,                            /* Simple morceau de code      */ +    STP_CODE_LABEL,                         /* Renvoi au sein de code      */      STP_OBJECT,                             /* Objet quelconque            */      STP_FUNCTION,                           /* Simple morceau de code      */      STP_ENTRY_POINT,                        /* Morceau de code en entrée   */ @@ -99,6 +100,9 @@ const mrange_t *g_binary_symbol_get_range(const GBinSymbol *);  void g_binary_symbol_set_alt_name(GBinSymbol *, char *);  /* Attache la routine associée au symbole. */ +void _g_binary_symbol_attach_routine(GBinSymbol *, GBinRoutine *, SymbolType); + +/* Attache la routine associée au symbole. */  void g_binary_symbol_attach_routine(GBinSymbol *, GBinRoutine *);  /* Attache l'instruction associée au symbole. */ diff --git a/tools/d2c/args.c b/tools/d2c/args.c index 616873b..1a2c287 100644 --- a/tools/d2c/args.c +++ b/tools/d2c/args.c @@ -73,7 +73,12 @@ struct _arg_expr_t      union      {          /* CET_NAME */ -        char *name;                         /* Désignation de variable     */ +        struct +        { +            char *original;                 /* Désignation non transformée */ +            char *name;                     /* Désignation de variable     */ + +        };          /* CET_NUMBER */          unsigned long number;               /* Valeur durablement définie  */ @@ -83,6 +88,7 @@ struct _arg_expr_t          {              char **comp_items;              /* Elements à agréger          */              size_t comp_count;              /* Quantité de ces éléments    */ +          };          /* CET_UNARY */ @@ -156,6 +162,7 @@ arg_expr_t *build_arg_expr_from_name(char *name)      result->type = CET_NAME; +    result->original = strdup(name);      result->name = make_string_lower(name);      return result; @@ -327,6 +334,7 @@ void delete_arg_expr(arg_expr_t *expr)      switch (expr->type)      {          case CET_NAME: +            free(expr->original);              free(expr->name);              break; @@ -392,6 +400,11 @@ bool compute_arg_expr_size(const arg_expr_t *expr, const coding_bits *bits, cons                      result = compute_conv_func_size(func, bits, list, size);              } +            /** +             * On autorise le passage de constante inconnue par d2c mais valable pour gcc. +             */ +            else result = true; +              break;          case CET_COMPOSED: @@ -590,7 +603,8 @@ bool ensure_arg_expr_content_fully_marked(arg_expr_t *expr, const coding_bits *b          switch (sub->type)          {              case CET_NAME: -                result = mark_by_name(bits, lst, sub->name); +                /* result = */mark_by_name(bits, lst, sub->name); +                result = true;                  break;              case CET_COMPOSED: @@ -678,7 +692,8 @@ bool ensure_arg_expr_content_fully_declared(arg_expr_t *expr, int fd, const codi          switch (sub->type)          {              case CET_NAME: -                result = declare_by_name(f, bits, lst, *wide, sub->name); +                /* result = */declare_by_name(f, bits, lst, *wide, sub->name); +                result = true;                  break;              case CET_COMPOSED: @@ -762,7 +777,8 @@ bool ensure_arg_expr_content_fully_defined(arg_expr_t *expr, int fd, const char          switch (sub->type)          {              case CET_NAME: -                result = define_by_name(f, bits, lst, info, sub->name); +                /* result = */define_by_name(f, bits, lst, info, sub->name); +                result = true;                  break;              case CET_COMPOSED: @@ -824,7 +840,7 @@ bool define_arg_expr(const arg_expr_t *expr, int fd, const coding_bits *bits, co          case CET_NAME:              if (!find_var_by_name(bits, list, expr->name, &field, &func)) -                result = false; +                dprintf(fd, "%s", expr->original);              else              { @@ -926,6 +942,9 @@ bool define_arg_expr(const arg_expr_t *expr, int fd, const coding_bits *bits, co              switch (expr->bin_op)              { +                case CBO_AND: +                    dprintf(fd, " & "); +                    break;                  case CBO_EOR:                      dprintf(fd, " ^ ");                      break; diff --git a/tools/d2c/args.h b/tools/d2c/args.h index 0ad022e..d5855f4 100644 --- a/tools/d2c/args.h +++ b/tools/d2c/args.h @@ -49,6 +49,7 @@ typedef enum _ConvUnaryOperation  /* Types d'opérations binaires */  typedef enum _ConvBinaryOperation  { +    CBO_AND,                                /* Et logique                  */      CBO_EOR,                                /* Ou exclusif (booléen)       */      CBO_COUNT diff --git a/tools/d2c/d2c_gram.y b/tools/d2c/d2c_gram.y index 9e1e034..5d83930 100644 --- a/tools/d2c/d2c_gram.y +++ b/tools/d2c/d2c_gram.y @@ -143,11 +143,11 @@ struct action_tmp  %token SYNTAX OPERAND_NAME OPERAND_INTERNAL OPERAND_VISIBLE -%token CONV EQ OP COMMA CP NOT EOR COLON +%token CONV EQ OP COMMA CP NOT AND_LOG EOR COLON  %token HOOKS -%token RULES IF EXPR_START EQUAL BINVAL IMMVAL EXPR_END AND THEN SEE CALL UNPREDICTABLE +%token RULES IF EXPR_START EQUAL BINVAL HEXVAL EXPR_END AND THEN SEE CALL CHK_CALL UNPREDICTABLE  %type <string> COPYRIGHT INS_NAME @@ -170,7 +170,7 @@ struct action_tmp  %type <string> arg_field  %type <expr> rule_cond -%type <string> BINVAL IMMVAL +%type <string> BINVAL HEXVAL  %type <raction> action @@ -248,7 +248,8 @@ arg_expr : NAME                                     { $$ = build_arg_expr_from_n  arg_expr_un_op : NOT { $$ = CUO_NOT; } -arg_expr_bin_op : EOR { $$ = CBO_EOR; } +arg_expr_bin_op : AND_LOG { $$ = CBO_AND; } +                | EOR { $$ = CBO_EOR; }  arg_composed : arg_field COLON arg_field    { $$ = build_composed_arg_expr($1, $3); }               | arg_composed COLON arg_field { $$ = extend_composed_arg_expr($1, $3); } @@ -273,14 +274,17 @@ rules_list : /* empty */  rule : IF EXPR_START rule_cond EXPR_END THEN action { add_conditional_rule_to_coder(coder, $3, &$6); }       | action                                       { add_conditional_rule_to_coder(coder, NULL, &$1); } -rule_cond : NAME EQUAL BINVAL   { $$ = build_simple_cond_expression($1, CCT_EQUAL, $3); } -          | NAME EQUAL IMMVAL   { $$ = build_simple_cond_expression($1, CCT_EQUAL, $3); } +rule_cond : NAME EQUAL BINVAL   { $$ = build_simple_cond_expression($1, CCT_EQUAL, $3, true); } +          | NAME EQUAL HEXVAL   { $$ = build_simple_cond_expression($1, CCT_EQUAL, $3, false); } +          | NAME AND_LOG BINVAL { $$ = build_simple_cond_expression($1, CCT_AND, $3, true); } +          | NAME AND_LOG HEXVAL { $$ = build_simple_cond_expression($1, CCT_AND, $3, false); }            | EXPR_START rule_cond EXPR_END AND EXPR_START rule_cond EXPR_END                                  { $$ = build_composed_cond_expression($2, COT_AND, $6); } -action : SEE INS_DETAILS          { $$.type = CAT_SEE; $$.details = make_callable($2, false); } -       | UNPREDICTABLE            { $$.type = CAT_UNPREDICTABLE; } -       | CALL NAME OP arg_list CP { $$.type = CAT_CALL; $$.callee = $2; $$.args = $4; } +action : SEE INS_DETAILS              { $$.type = CAT_SEE; $$.details = make_callable($2, false); } +       | UNPREDICTABLE                { $$.type = CAT_UNPREDICTABLE; } +       | CALL NAME OP arg_list CP     { $$.type = CAT_CALL; $$.callee = $2; $$.args = $4; } +       | CHK_CALL NAME OP arg_list CP { $$.type = CAT_CHECKED_CALL; $$.callee = $2; $$.args = $4; }  %% diff --git a/tools/d2c/d2c_tok.l b/tools/d2c/d2c_tok.l index 9689b59..08562ce 100644 --- a/tools/d2c/d2c_tok.l +++ b/tools/d2c/d2c_tok.l @@ -39,7 +39,7 @@ void free_flex_memory(void) ;  %x hooks_begin hooks_content -%x rules_begin rules_content rules_cond rules_cond_binval rules_action rules_action_see rules_action_call +%x rules_begin rules_content rules_cond rules_cond_binval rules_cond_hexval rules_action rules_action_see rules_action_call  %% @@ -84,9 +84,9 @@ void free_flex_memory(void) ;  <encoding_content>"@half"           { BEGIN(encoding_bits); return HALF; }  <encoding_content>"@word"           { BEGIN(encoding_bits); return WORD; } -<encoding_bits>" "                  { } -<encoding_bits>"\n"                 { BEGIN(encoding_content); } -<encoding_bits>[A-Za-z][A-Za-z0-9_]* { d2c_lval.string = strdup(yytext); return NAME; } +<encoding_bits>" "                     { } +<encoding_bits>"\n"                    { BEGIN(encoding_content); } +<encoding_bits>[A-Za-z_][A-Za-z0-9__]* { d2c_lval.string = strdup(yytext); return NAME; }  <encoding_bits>"("                  { BEGIN(encoding_bits_size); }  <encoding_bits_size>[0-9]+          { d2c_lval.integer = atoi(yytext); return SIZE; } @@ -135,8 +135,9 @@ void free_flex_memory(void) ; -<conv_arg>[A-Za-z][A-Za-z0-9_]*      { +<conv_arg>[A-Za-z_][A-Za-z0-9_]*    {                                        if (strcmp(yytext, "NOT") == 0) return NOT; +                                      else if (strcmp(yytext, "AND") == 0) return AND_LOG;                                        else if (strcmp(yytext, "EOR") == 0) return EOR;                                        else                                        { @@ -161,8 +162,9 @@ void free_flex_memory(void) ; -<arg>[A-Za-z][A-Za-z0-9_]*     { +<arg>[A-Za-z_][A-Za-z0-9_]*     {                                     if (strcmp(yytext, "NOT") == 0) return NOT; +                                   else if (strcmp(yytext, "AND") == 0) return AND_LOG;                                     else if (strcmp(yytext, "EOR") == 0) return EOR;                                     else                                     { @@ -203,18 +205,21 @@ void free_flex_memory(void) ;  <rules_content>"see "               { BEGIN(rules_action_see); return SEE; }  <rules_content>"unpredictable"      { return UNPREDICTABLE; }  <rules_content>"call"               { BEGIN(rules_action_call); return CALL; } +<rules_content>"chk_call"           { BEGIN(rules_action_call); return CHK_CALL; }  <rules_content>"if"                 { BEGIN(rules_cond); return IF; }  <rules_cond>[ ]+                    { }  <rules_cond>"("                     { return EXPR_START; } -<rules_cond>[A-Za-z][A-Za-z0-9]*    { d2c_lval.string = strdup(yytext); return NAME; } +<rules_cond>[A-Za-z_][A-Za-z0-9_]*  { d2c_lval.string = strdup(yytext); return NAME; }  <rules_cond>"=="                    { return EQUAL; }  <rules_cond>"'"                     { BEGIN(rules_cond_binval); }  <rules_cond_binval>[01][01]*        { d2c_lval.string = strdup(yytext); return BINVAL; }  <rules_cond_binval>"'"              { BEGIN(rules_cond); } -<rules_cond>[0-9][0-9]*             { d2c_lval.string = strdup(yytext); return IMMVAL; } +<rules_cond>"0x"                     { BEGIN(rules_cond_hexval); } +<rules_cond_hexval>[0-9a-f][0-9a-f]* { d2c_lval.string = strdup(yytext); BEGIN(rules_cond); return HEXVAL; }  <rules_cond>")"                     { return EXPR_END; }  <rules_cond>"&&"                    { return AND; } +<rules_cond>"&"                    { return AND_LOG; }  <rules_cond>";"                     { BEGIN(rules_action); return THEN; }  <rules_action>[ ]+                  { } @@ -224,11 +229,12 @@ void free_flex_memory(void) ;  <rules_action>"unpredictable"       { BEGIN(rules_content); return UNPREDICTABLE; } -<rules_action>"call"                    { BEGIN(rules_action_call); return CALL; } -<rules_action_call>[\t ]+               { } -<rules_action_call>[A-Za-z][A-Za-z0-9]* { d2c_lval.string = strdup(yytext); return NAME; } -<rules_action_call>"("                  { yy_push_state(arg); return OP; } -<rules_action_call>[\n]                 { BEGIN(rules_content); } +<rules_action>"call"                      { BEGIN(rules_action_call); return CALL; } +<rules_action>"chk_call"                  { BEGIN(rules_action_call); return CHK_CALL; } +<rules_action_call>[\t ]+                 { } +<rules_action_call>[A-Za-z_][A-Za-z0-9_]* { d2c_lval.string = strdup(yytext); return NAME; } +<rules_action_call>"("                    { yy_push_state(arg); return OP; } +<rules_action_call>[\n]                   { BEGIN(rules_content); }  %% diff --git a/tools/d2c/qckcall.c b/tools/d2c/qckcall.c index ce9a0b2..e2e87d2 100644 --- a/tools/d2c/qckcall.c +++ b/tools/d2c/qckcall.c @@ -34,44 +34,44 @@ +/* Prépare au besoin la définition d'une macro de transtypage. */ +static char *build_cast_if_needed(const char *); + + +  /******************************************************************************  *                                                                             * -*  Paramètres  : callee = fonction appelée à nomer.                           * -*                args   = précise si la conversion est la dernière.           * -*                fd     = descripteur d'un flux ouvert en écriture.           * -*                bits   = gestionnaire des bits d'encodage.                   * -*                list   = liste de l'ensemble des fonctions de conversion.    * -*                pp     = pré-processeur pour les échanges de chaînes.        * +*  Paramètres  : callee = fonction appelée à nommer.                          *  *                                                                             * -*  Description : Réalise un appel à une fonction liée à une instruction.      * +*  Description : Prépare au besoin la définition d'une macro de transtypage.  *  *                                                                             * -*  Retour      : Bilan de l'opération.                                        * +*  Retour      : Macro de transtypage à libérer après usage ou NULL.          *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -bool call_instr_func(const char *callee, const arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list, const pre_processor *pp) +static char *build_cast_if_needed(const char *callee)  { -    bool result;                            /* Bilan à remonter            */ +    char *result;                           /* Macro à retourner           */      regex_t preg;                           /* Expression régulière        */      int ret;                                /* Bilan d'une manipulation    */      regmatch_t pmatch[3];                   /* Correspondances de chaînes  */      size_t cmplen;                          /* Taille de comparaison       */ -    char *cast;                             /* Macro de transtypage        */ + +    result = NULL;      ret = regcomp(&preg, "(g_([a-z0-9]*)_instruction)", REG_EXTENDED);      if (ret != 0)      {          fprintf(stderr, "Internal error: bad regular expression.\n"); -        return false; +        return NULL;      }      ret = regexec(&preg, callee, sizeof(pmatch) / sizeof(regmatch_t), pmatch, 0);      if (ret == REG_NOMATCH)      {          fprintf(stderr, "Internal error: bad function for dealing wih instruction: '%s'.\n", callee); -        result = false;          goto cif_exit;      } @@ -82,29 +82,102 @@ bool call_instr_func(const char *callee, const arg_list_t *args, int fd, const c      cmplen = MAX(strlen("arch"), pmatch[2].rm_eo - pmatch[2].rm_so); -    if (strncmp("arch", &callee[pmatch[2].rm_so], cmplen) == 0) -        dprintf(fd, "\t\tif (!%s(instr, ", callee); +    if (strncmp("arch", &callee[pmatch[2].rm_so], cmplen) != 0) +    { +        result = strndup(&callee[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so); + +        result = make_string_upper(result); + +    } + + cif_exit: + +    regfree(&preg); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : callee = fonction appelée à nommer.                          * +*                args   = précise si la conversion est la dernière.           * +*                fd     = descripteur d'un flux ouvert en écriture.           * +*                bits   = gestionnaire des bits d'encodage.                   * +*                list   = liste de l'ensemble des fonctions de conversion.    * +*                pp     = pré-processeur pour les échanges de chaînes.        * +*                                                                             * +*  Description : Réalise un appel à une fonction liée à une instruction.      * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool call_instr_func(const char *callee, const arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list, const pre_processor *pp) +{ +    bool result;                            /* Bilan à remonter            */ +    char *cast;                             /* Macro de transtypage        */ + +    cast = build_cast_if_needed(callee); + +    if (cast == NULL) +        dprintf(fd, "\t\t%s(instr, ", callee);      else      { -        cast = strndup(&callee[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so); +        dprintf(fd, "\t\t%s(%s(instr), ", callee, cast); +        free(cast); +    } -        cast = make_string_upper(cast); +    result = define_arg_list(args, fd, bits, list); -        dprintf(fd, "\t\tif (!%s(%s(instr), ", callee, cast); +    dprintf(fd, ");\n"); -        free(cast); +    return result; +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : callee = fonction appelée à nommer.                          * +*                args   = précise si la conversion est la dernière.           * +*                fd     = descripteur d'un flux ouvert en écriture.           * +*                bits   = gestionnaire des bits d'encodage.                   * +*                list   = liste de l'ensemble des fonctions de conversion.    * +*                pp     = pré-processeur pour les échanges de chaînes.        * +*                                                                             * +*  Description : Réalise un appel à une fonction liée à une instruction.      * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool checked_call_instr_func(const char *callee, const arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list, const pre_processor *pp) +{ +    bool result;                            /* Bilan à remonter            */ +    char *cast;                             /* Macro de transtypage        */ + +    cast = build_cast_if_needed(callee); + +    if (cast == NULL) +        dprintf(fd, "\t\tif (!%s(instr, ", callee); + +    else +    { +        dprintf(fd, "\t\tif (!%s(%s(instr), ", callee, cast); +        free(cast);      }      result = define_arg_list(args, fd, bits, list);      dprintf(fd, "))\n"); - cif_exit: - -    regfree(&preg); -      return result;  } diff --git a/tools/d2c/qckcall.h b/tools/d2c/qckcall.h index 59d4adc..42aa3db 100644 --- a/tools/d2c/qckcall.h +++ b/tools/d2c/qckcall.h @@ -39,6 +39,9 @@  /* Réalise un appel à une fonction liée à une instruction. */  bool call_instr_func(const char *, const arg_list_t *, int, const coding_bits *, const conv_list *, const pre_processor *); +/* Réalise un appel à une fonction liée à une instruction. */ +bool checked_call_instr_func(const char *, const arg_list_t *, int, const coding_bits *, const conv_list *, const pre_processor *); +  #endif  /* _TOOLS_QCKCALL_H */ diff --git a/tools/d2c/rules.c b/tools/d2c/rules.c index 6f2e075..3101727 100644 --- a/tools/d2c/rules.c +++ b/tools/d2c/rules.c @@ -48,7 +48,9 @@ struct _cond_expr          {              char *variable;                 /* Variable manipulée          */              CondCompType comp;              /* Type de comparaison         */ -            char *bvalue;                   /* Valeur binaire comparée     */ +            char *value;                    /* Valeur binaire comparée     */ + +            bool is_binary;                 /* Binaire ou hexadécimal      */          } simple; @@ -101,9 +103,10 @@ struct _decoding_rules  /******************************************************************************  *                                                                             * -*  Paramètres  : variable = désignation de la variable à manipuler.           * -*                comp     = type de comparaison à utiliser.                   * -*                bvalue   = valeur binaire à comparer.                        * +*  Paramètres  : variable  = désignation de la variable à manipuler.          * +*                comp      = type de comparaison à utiliser.                  * +*                value     = valeur binaire à comparer.                       * +*                is_binary = indique la nature de la valeur transmise.        *  *                                                                             *  *  Description : Crée une expression conditionnelle simple.                   *  *                                                                             * @@ -113,7 +116,7 @@ struct _decoding_rules  *                                                                             *  ******************************************************************************/ -cond_expr *build_simple_cond_expression(char *variable, CondCompType comp, char *bvalue) +cond_expr *build_simple_cond_expression(char *variable, CondCompType comp, char *value, bool is_binary)  {      cond_expr *result;                      /* Structure à retourner       */ @@ -123,7 +126,9 @@ cond_expr *build_simple_cond_expression(char *variable, CondCompType comp, char      result->simple.variable = make_string_lower(variable);      result->simple.comp = comp; -    result->simple.bvalue = bvalue; +    result->simple.value = value; + +    result->simple.is_binary = is_binary;      return result; @@ -178,7 +183,7 @@ static void delete_cond_expr(cond_expr *expr)      if (expr->is_simple)      {          free(expr->simple.variable); -        free(expr->simple.bvalue); +        free(expr->simple.value);      }      else      { @@ -209,6 +214,7 @@ static bool write_cond_expr(const cond_expr *expr, int fd, const coding_bits *bi  {      bool result;                            /* Bilan à renvoyer            */      const raw_bitfield *bf;                 /* Champ de bits de définition */ +    unsigned int provided;                  /* Nombre de bits fournis      */      result = true; @@ -224,10 +230,15 @@ static bool write_cond_expr(const cond_expr *expr, int fd, const coding_bits *bi              goto wce_exit;          } -        if (get_raw_bitfield_length(bf) != strlen(expr->simple.bvalue)) +        if (expr->simple.is_binary) +            provided = strlen(expr->simple.value); +        else +            provided = 4 * strlen(expr->simple.value); + +        if (get_raw_bitfield_length(bf) != provided)          { -            fprintf(stderr, "Error: variable '%s' and provided value sizes do not match (%u vs %zu).\n", -                    expr->simple.variable, get_raw_bitfield_length(bf), strlen(expr->simple.bvalue)); +            fprintf(stderr, "Error: variable '%s' and provided value sizes do not match (%u vs %u).\n", +                    expr->simple.variable, get_raw_bitfield_length(bf), provided);              result = false;              goto wce_exit;          } @@ -242,9 +253,15 @@ static bool write_cond_expr(const cond_expr *expr, int fd, const coding_bits *bi              case CCT_DIFF:                  dprintf(fd, " != ");                  break; +            case CCT_AND: +                dprintf(fd, " & "); +                break;          } -        dprintf(fd, "b%s", expr->simple.bvalue); +        if (expr->simple.is_binary) +            dprintf(fd, "b%s", expr->simple.value); +        else +            dprintf(fd, "0x%s", expr->simple.value);      }      else @@ -339,6 +356,7 @@ void delete_decoding_rules(decoding_rules *rules)                  break;              case CAT_CALL: +            case CAT_CHECKED_CALL:                  free(rule->action.callee);                  delete_arg_list(rule->action.args);                  break; @@ -406,8 +424,9 @@ void register_conditional_rule(decoding_rules *rules, cond_expr *expr, const rul  bool write_decoding_rules(decoding_rules *rules, CondActionType filter, int fd, const char *arch, const char *subarch, const coding_bits *bits, const conv_list *list, const pre_processor *pp, bool *exit)  {      bool result;                            /* Bilan à remonter            */ -    const extra_rule *rule;                 /* Règle en cours d'écriture   */      size_t i;                               /* Boucle de parcours          */ +    const extra_rule *rule;                 /* Règle en cours d'écriture   */ +    bool multi_lines;                       /* Nécessite des accolades     */      const char *callable;                   /* Fonction à appeler          */      result = true; @@ -419,6 +438,18 @@ bool write_decoding_rules(decoding_rules *rules, CondActionType filter, int fd,          if (rule->action.type != filter)              continue; +        switch (rule->action.type) +        { +            case CAT_CALL: +                multi_lines = false; +                break; + +            default: +                multi_lines = true; +                break; + +        } +          if (rule->expr != NULL)          {              dprintf(fd, "\t\tif "); @@ -427,7 +458,9 @@ bool write_decoding_rules(decoding_rules *rules, CondActionType filter, int fd,              if (!result) break;              dprintf(fd, "\n"); -            dprintf(fd, "\t\t{\n"); + +            if (multi_lines) +                dprintf(fd, "\t\t{\n");          } @@ -460,6 +493,20 @@ bool write_decoding_rules(decoding_rules *rules, CondActionType filter, int fd,                  result = call_instr_func(callable, rule->action.args, fd, bits, list, pp); +                break; + +            case CAT_CHECKED_CALL: + +                callable = find_macro(pp, rule->action.callee); + +                if (callable == NULL) +                    callable = rule->action.callee; + +                if (rule->expr != NULL) +                    dprintf(fd, "\t"); + +                result = checked_call_instr_func(callable, rule->action.args, fd, bits, list, pp); +                  if (rule->expr != NULL)                      dprintf(fd, "\t"); @@ -470,7 +517,7 @@ bool write_decoding_rules(decoding_rules *rules, CondActionType filter, int fd,          } -        if (rule->expr != NULL) +        if (rule->expr != NULL && multi_lines)              dprintf(fd, "\t\t}\n");          dprintf(fd, "\n"); diff --git a/tools/d2c/rules.h b/tools/d2c/rules.h index 6344828..cac6a55 100644 --- a/tools/d2c/rules.h +++ b/tools/d2c/rules.h @@ -39,7 +39,8 @@  typedef enum _CondCompType  {      CCT_EQUAL,                              /* Egalité '=='                */ -    CCT_DIFF                                /* Différence '!='             */ +    CCT_DIFF,                               /* Différence '!='             */ +    CCT_AND                                 /* Et logique '&'              */  } CondCompType; @@ -56,7 +57,7 @@ typedef struct _cond_expr cond_expr;  /* Crée une expression conditionnelle simple. */ -cond_expr *build_simple_cond_expression(char *, CondCompType, char *); +cond_expr *build_simple_cond_expression(char *, CondCompType, char *, bool);  /* Crée une expression conditionnelle composée. */  cond_expr *build_composed_cond_expression(cond_expr *, CondOpType, cond_expr *); @@ -71,7 +72,8 @@ typedef enum _CondActionType  {      CAT_SEE,                                /* Renvoi vers une instruction */      CAT_UNPREDICTABLE,                      /* Cas de figure improbable    */ -    CAT_CALL                                /* Appel à une fonction C      */ +    CAT_CALL,                               /* Appel à une fonction C      */ +    CAT_CHECKED_CALL                        /* Appel à une fonction C      */  } CondActionType; diff --git a/tools/d2c/spec.c b/tools/d2c/spec.c index 9d4447d..7d65cab 100644 --- a/tools/d2c/spec.c +++ b/tools/d2c/spec.c @@ -324,6 +324,9 @@ bool write_encoding_spec_disass(const encoding_spec *spec, int fd, const char *a      result &= write_hook_functions(spec->hooks, fd); +    result &= write_decoding_rules(spec->rules, CAT_CHECKED_CALL, +                                   fd, arch, subarch, spec->bits, spec->conversions, pp, &exit); +      result &= write_decoding_rules(spec->rules, CAT_CALL,                                     fd, arch, subarch, spec->bits, spec->conversions, pp, &exit); | 
