diff options
40 files changed, 2598 insertions, 1390 deletions
@@ -1,3 +1,85 @@ +15-01-24 Cyrille Bagard <nocbos@gmail.com> + + * src/analysis/disass/area.c: + Try to better follow the execution flow. + + * src/analysis/disass/fetch.c: + Add some extra entry points. They are fixed, so this needs to be improved. + + * src/arch/arm/v456/instruction.c: + Disable some old code. + + * src/arch/arm/v7/context.c: + * src/arch/arm/v7/context.h: + Provide a way to create new drop points and memorize their encodings. + + * src/arch/arm/v7/link.c: + * src/arch/arm/v7/link.h: + Handle more instructions: b, cb[n]z and ldr. + + * 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/cbnz_A8829.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: + Update hooks and rules. + + * src/arch/arm/v7/opdefs/Makefile.am: + Register the 'DefineAsReturn' macro in D2C_MACROS. + + * src/arch/arm/v7/post.c: + * src/arch/arm/v7/post.h: + Handle more instructions: b, cb[n]z and ldr. + + * src/arch/arm/v7/processor.c: + Do not create a dummy instruction when decoding failed anymore. + + * src/arch/artificial.c: + Remove the old 'g_db_instruction_is_return()' function. + + * src/arch/dalvik/instruction.c: + Disable some old code. + + * src/arch/instruction.c: + * src/arch/instruction.h: + * src/arch/instruction-int.h: + Change the way an instruction gives information about its 'return'-like + behavior property. + + * src/arch/x86/instruction.c: + Disable some old code. + + * tools/d2c/args.c: + * tools/d2c/args.h: + New entries: handle expressions used as call arguments. + + * tools/d2c/conv.c: + * tools/d2c/conv.h: + Update code by using new arguments. + + * tools/d2c/d2c_gram.y: + * tools/d2c/d2c_tok.l: + Introduce conditional calls in instruction definition rules. + + * tools/d2c/Makefile.am: + Add the new 'args.[ch]' and 'qckcall.[ch]' files into d2c_SOURCES. + + * tools/d2c/qckcall.c: + * tools/d2c/qckcall.h: + New entries: provide a way to call functions and manage associated casts. + + * tools/d2c/rules.c: + * tools/d2c/rules.h: + Introduce conditional calls in instruction definition rules. + + * tools/d2c/spec.c: + Update code. + 15-01-18 Cyrille Bagard <nocbos@gmail.com> * src/arch/arm/v7/opdefs/Makefile.am: diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c index 8c46eb0..7e3a9a8 100644 --- a/src/analysis/disass/area.c +++ b/src/analysis/disass/area.c @@ -28,8 +28,6 @@ - - /* Zone mémoire bien bornée */ typedef struct _mem_area { @@ -49,10 +47,6 @@ typedef struct _mem_area } mem_area; - - - - /* Initialise une aire de données à partir d'une adresse donnée. */ static void init_mem_area_from_addr(mem_area *, const vmpa2t *, phys_t); @@ -381,6 +375,14 @@ void load_code_from_mem_area(mem_area *area, mem_area *list, size_t count, const //printf(" [%p] CODE start @ %u (len=%u)\n", area, (unsigned int)diff, (unsigned int)alen); + + + printf(" START @ 0x%08x\n", (unsigned int)get_virt_addr(&pos)); + + + bin_length = (get_phy_addr(get_mrange_addr(&area->range)) + alen); + + for (i = diff; i < alen; i += diff) { //il y a eu un point d'entrée... -> STOP @@ -418,6 +420,26 @@ void load_code_from_mem_area(mem_area *area, mem_area *list, size_t count, const assert(!is_range_blank_in_mem_areas(list, count, &range)); + + + + printf(" --disass-- '%s' @ 0x%08x (break=%d)\n", + g_arch_instruction_get_keyword(instr, 0), + (unsigned int)get_virt_addr(&prev), + g_arch_instruction_is_return(instr)); + + + + + if (g_arch_instruction_is_return(instr)) + printf("BREAK @ 0x%08x\n", (unsigned int)get_virt_addr(&prev)); + + //continue; + + /* Rupture du flot d'exécution ? */ + if (g_arch_instruction_is_return(instr)) + break; + } @@ -485,8 +507,9 @@ static void load_data_from_mem_area(mem_area *area, mem_area *list, size_t count advance_vmpa(&pos, diff); /* - printf(" [%p] DATA start @ 0x%08x -> %u (len=%u)\n", - area, (unsigned int)get_phy_addr(&pos), (unsigned int)diff, (unsigned int)alen); + printf(" [%p] DATA start @ 0x%08x -> %u (len=%u) => 0x%08x <-> 0x%08x\n", + area, (unsigned int)get_phy_addr(&pos), (unsigned int)diff, (unsigned int)alen, + (unsigned int)get_virt_addr(&pos), (unsigned int)(get_virt_addr(&pos) + alen)); */ for (i = diff; i < alen; i += diff) @@ -496,7 +519,7 @@ static void load_data_from_mem_area(mem_area *area, mem_area *list, size_t count copy_vmpa(&prev, &pos); instr = NULL; - + /* if (instr == NULL && (i + 4) <= alen) { init_mrange(&range, &pos, 4); @@ -505,7 +528,7 @@ static void load_data_from_mem_area(mem_area *area, mem_area *list, size_t count instr = g_raw_instruction_new_array(bin_data, MDS_32_BITS, 1, &pos, bin_length, endianness); } - + */ if (instr == NULL && (i + 2) <= alen) { copy_vmpa(&pos, &prev); @@ -525,10 +548,29 @@ static void load_data_from_mem_area(mem_area *area, mem_area *list, size_t count instr = g_raw_instruction_new_array(bin_data, MDS_8_BITS, 1, &pos, bin_length, endianness); else { - printf(" break !! 0x%08x\n", - (unsigned int)get_phy_addr(&pos)); - assert(0); - break; + /** + * On rencontre ici un morceau déjà traité. + * On recherche donc la fin de cette partie à sauter, si elle existe. + */ + + ////////////// + return; + + + + for (i++; i < alen; i++) + { + advance_vmpa(&pos, 1); + init_mrange(&range, &pos, 1); + + if (is_range_blank_in_mem_areas(list, count, &range)) + break; + + } + + diff = 0; + continue; + } } @@ -551,6 +593,12 @@ static void load_data_from_mem_area(mem_area *area, mem_area *list, size_t count assert(!is_range_blank_in_mem_areas(list, count, &range)); + + + if (area->exec) break; + + + } } @@ -579,11 +627,14 @@ static void fill_mem_area(mem_area *area, mem_area *list, size_t count, const GL phys_t i; /* Boucle de parcours */ vmpa2t start; /* Adresse de départ de combles*/ - /* - printf(" === FILLING | 0x%08x (%u)...\n", + bool on = true; + + + printf(" === FILLING | 0x%08x // 0x%08x <-> 0x%08x...\n", (unsigned int)get_phy_addr(get_mrange_addr(&area->range)), - (unsigned int)get_phy_addr(get_mrange_addr(&area->range))); - */ + (unsigned int)get_virt_addr(get_mrange_addr(&area->range)), + (unsigned int)(get_virt_addr(get_mrange_addr(&area->range)) + get_mrange_length(&area->range))); + /* Les symboles se doivent d'être indépendants ! */ if (area->has_sym) return; @@ -597,14 +648,29 @@ static void fill_mem_area(mem_area *area, mem_area *list, size_t count, const GL copy_vmpa(&start, get_mrange_addr(&area->range)); advance_vmpa(&start, i); - if (area->exec) + if (area->exec && get_virt_addr(&start) % 4 == 0) + { load_code_from_mem_area(area, list, count, binary, ctx, &start, info); + if (!is_range_blank_in_mem_area(area, i, 1, NULL)) + { + printf(" --filled-- @ 0x%08x\n", (unsigned int)get_virt_addr(&start)); + on = false; + } + else + printf(" --fill failed-- @ 0x%08x\n", (unsigned int)get_virt_addr(&start)); + + + } + if (is_range_blank_in_mem_area(area, i, 1, NULL)) load_data_from_mem_area(area, list, count, binary, ctx, &start, info); } + + else on = true; + if (is_range_blank_in_mem_area(area, i, 1, NULL)) printf(" [%p] error with %u\n", area, (unsigned int)i); @@ -1134,6 +1200,18 @@ static bool handle_bytes_map_in_mem_area(mem_area *list, size_t count, const mra else { + + printf("BUG_ON | off=%u remaining=%u length=%u\n", + (unsigned int)offset, + (unsigned int)remaining, + (unsigned int)get_mrange_length(&area->range)); + + printf("BUG_ON @ 0x%08x + %d\n", + (unsigned int)get_virt_addr(get_mrange_addr(range)), + (int)get_mrange_length(range) + ); + + assert(0); /* Traitement de la fin de la première aire */ diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c index 2e9eb81..ffc653a 100644 --- a/src/analysis/disass/fetch.c +++ b/src/analysis/disass/fetch.c @@ -58,6 +58,8 @@ static void follow_execution_flow(const GLoadedBinary *binary, GProcContext *ctx vmpa2t addr; /* Conversion en pleine adresse*/ mem_area *area; /* Zone de désassemblage */ + printf("-- follow 0x%08x\n", (unsigned int)virt); + g_proc_context_push_drop_point(ctx, virt); while (g_proc_context_has_drop_points(ctx)) @@ -65,10 +67,20 @@ static void follow_execution_flow(const GLoadedBinary *binary, GProcContext *ctx virt = g_proc_context_pop_drop_point(ctx); init_vmpa(&addr, VMPA_NO_PHYSICAL, virt); + + + printf(" ++ point 0x%08x\n", (unsigned int)virt); + + area = find_memory_area_by_addr(areas, count, &addr); load_code_from_mem_area(area, areas, count, binary, ctx, &addr, info); + + + printf(" ++\n"); + + } } @@ -128,6 +140,9 @@ GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, GtkExt virt = g_binary_format_get_entry_point(format); + follow_execution_flow(binary, ctx, areas, count, info, 0x84c5); + follow_execution_flow(binary, ctx, areas, count, info, 0x8a65); + follow_execution_flow(binary, ctx, areas, count, info, virt); /* Symboles exécutables présents et passés à travers les mailles */ @@ -147,6 +162,8 @@ GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, GtkExt } + printf(" ------------------------------------------- follow done\n"); + done = get_current_progessive_status(info); fini_progessive_status(info); diff --git a/src/arch/arm/v456/instruction.c b/src/arch/arm/v456/instruction.c index b5df0f8..4fc78a2 100644 --- a/src/arch/arm/v456/instruction.c +++ b/src/arch/arm/v456/instruction.c @@ -399,7 +399,7 @@ static void g_dalvik_instruction_init(GDalvikInstruction *instr) parent->get_rw_regs = (get_instruction_rw_regs_fc)g_dalvik_instruction_get_rw_registers; parent->get_text = (get_instruction_text_fc)dalvik_get_instruction_text; parent->get_link = (get_instruction_link_fc)dalvik_get_instruction_link; - parent->is_return = (is_instruction_return_fc)dalvik_instruction_is_return; + //parent->is_return = (is_instruction_return_fc)dalvik_instruction_is_return; parent->decomp = (decomp_instr_fc)dalvik_instruction_decompile; } diff --git a/src/arch/arm/v7/context.c b/src/arch/arm/v7/context.c index 41ffd29..c29794d 100644 --- a/src/arch/arm/v7/context.c +++ b/src/arch/arm/v7/context.c @@ -24,6 +24,9 @@ #include "context.h" +#include <assert.h> + + #include "../context-int.h" @@ -208,7 +211,7 @@ static void g_armv7_context_push_drop_point(GArmV7Context *ctx, virt_t addr) { - printf("PUSH v7 !!\n"); + printf("PUSH v7 !! 0x%08x\n", addr); @@ -224,6 +227,47 @@ static void g_armv7_context_push_drop_point(GArmV7Context *ctx, virt_t addr) } +/****************************************************************************** +* * +* Paramètres : ctx = contexte de désassemblage à compléter. * +* addr = adresse d'un nouveau point de départ à traiter. * +* * +* Description : Ajoute une adresse virtuelle comme point de départ de code. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_armv7_context_push_drop_point_ext(GArmV7Context *ctx, virt_t addr, ArmV7InstrSet marker) +{ + + + printf("PUSH v7 !! 0x%08x\n", (unsigned int)addr); + + + + if (addr & 0x1) + { + addr -= 0x1; + assert(marker == AV7IS_THUMB); + } + + + g_armv7_context_define_encoding(ctx, addr, marker); + + G_PROC_CONTEXT_CLASS(g_armv7_context_parent_class)->push_point(G_PROC_CONTEXT(ctx), addr); + +} + + + + + + + + /****************************************************************************** @@ -242,6 +286,8 @@ static void g_armv7_context_push_drop_point(GArmV7Context *ctx, virt_t addr) void g_armv7_context_define_encoding(GArmV7Context *ctx, virt_t addr, ArmV7InstrSet marker) { + printf(" --encoding-- @ 0x%08llx -> %d\n", (unsigned long long)addr, (int)marker); + _g_arm_context_define_encoding(G_ARM_CONTEXT(ctx), addr, marker); } diff --git a/src/arch/arm/v7/context.h b/src/arch/arm/v7/context.h index 65b5302..a4d99d6 100644 --- a/src/arch/arm/v7/context.h +++ b/src/arch/arm/v7/context.h @@ -79,4 +79,19 @@ ArmV7InstrSet g_armv7_context_find_encoding(GArmV7Context *, virt_t); + + + + + + + + +void g_armv7_context_push_drop_point_ext(GArmV7Context *ctx, virt_t addr, ArmV7InstrSet marker); + + + + + + #endif /* _ARCH_ARM_V7_CONTEXT_H */ diff --git a/src/arch/arm/v7/link.c b/src/arch/arm/v7/link.c index fff0944..c1f83ac 100644 --- a/src/arch/arm/v7/link.c +++ b/src/arch/arm/v7/link.c @@ -25,6 +25,7 @@ #include <assert.h> +#include <operands/offset.h> @@ -43,6 +44,54 @@ * * ******************************************************************************/ +void handle_links_with_instruction_b_with_orig(GArchInstruction *instr, GArmV7Context *context, GBinFormat *format, ArmV7InstrSet iset) +{ + const mrange_t *range; /* Emplacementt d'instruction */ + virt_t pc; /* Position dans l'exécution */ + GArchOperand *op; /* Opérande numérique en place */ + int32_t offset; /* Décallage encodé en dur */ + virt_t target; /* Adresse virtuelle visée */ + + range = g_arch_instruction_get_range(instr); + + pc = get_virt_addr(get_mrange_addr(range)); + + pc += get_mrange_length(range); + + op = g_arch_instruction_get_operand(instr, 0); + + if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_SIGNED, &offset)) + g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset); + + else assert(0); + + printf("1... 0x%x (0x%x) + 0x%x\n", + (unsigned int)get_virt_addr(get_mrange_addr(range)), + (unsigned int)pc, (unsigned int)offset); + + target = pc + offset; + + //g_armv7_context_define_encoding(context, target, iset); + g_armv7_context_push_drop_point_ext(context, target, iset); + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* context = contexte associé à la phase de désassemblage. * +* format = acès aux données du binaire d'origine. * +* iset = type de jeu d'instructions courant à faire suivre. * +* * +* Description : Complète un désassemblage accompli pour une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + void handle_links_with_instruction_bl_with_orig(GArchInstruction *instr, GArmV7Context *context, GBinFormat *format, ArmV7InstrSet iset) { const mrange_t *range; /* Emplacementt d'instruction */ @@ -69,9 +118,18 @@ void handle_links_with_instruction_bl_with_orig(GArchInstruction *instr, GArmV7C if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_SIGNED, &offset)) g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset); + else assert(0); + + printf("2... 0x%x (0x%x) + 0x%x\n", + (unsigned int)get_virt_addr(get_mrange_addr(range)), + (unsigned int)pc, (unsigned int)offset); + + + target = pc + offset; - g_armv7_context_define_encoding(context, target, iset); + //g_armv7_context_define_encoding(context, target, iset); + g_armv7_context_push_drop_point_ext(context, target, iset); } @@ -118,8 +176,188 @@ void handle_links_with_instruction_blx_with_dest(GArchInstruction *instr, GArmV7 if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_SIGNED, &offset)) g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset); + else assert(0); + + printf("3... 0x%x (0x%x) + 0x%x\n", + (unsigned int)get_virt_addr(get_mrange_addr(range)), + (unsigned int)pc, (unsigned int)offset); + + + target = pc + offset; - g_armv7_context_define_encoding(context, target, iset); + //g_armv7_context_define_encoding(context, target, iset); + g_armv7_context_push_drop_point_ext(context, target, iset); + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* context = contexte associé à la phase de désassemblage. * +* format = acès aux données du binaire d'origine. * +* * +* Description : Complète un désassemblage accompli pour une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void handle_links_with_instruction_cb_n_z(GArchInstruction *instr, GArmV7Context *context, GBinFormat *format) +{ + const mrange_t *range; /* Emplacementt d'instruction */ + virt_t pc; /* Position dans l'exécution */ + GArchOperand *op; /* Opérande numérique en place */ + uint32_t offset; /* Décallage encodé en dur */ + virt_t target; /* Adresse virtuelle visée */ + + range = g_arch_instruction_get_range(instr); + + pc = get_virt_addr(get_mrange_addr(range)); + + + printf("PC :: 0x%08x\n", (unsigned int)pc); + + + /** + * En mode Thumb, pc a pour valeur l'adresse courante plus 4. + */ + + pc += 4; + + op = g_arch_instruction_get_operand(instr, 1); + + if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &offset)) + g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset); + + else assert(0); + + target = pc + offset; + + //g_armv7_context_define_encoding(context, target, AV7IS_THUMB); + g_armv7_context_push_drop_point_ext(context, target, AV7IS_THUMB); + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* context = contexte associé à la phase de désassemblage. * +* format = acès aux données du binaire d'origine. * +* iset = type de jeu d'instructions courant à inverser. * +* * +* Description : Complète un désassemblage accompli pour une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void handle_links_with_instruction_ldr_literal_with_orig(GArchInstruction *instr, GArmV7Context *context, GBinFormat *format, ArmV7InstrSet iset) +{ + const mrange_t *range; /* Emplacementt d'instruction */ + phys_t phys_pc; /* Position dans l'exécution */ + GArchOperand *op; /* Opérande de surcouche */ + GArchOperand *sub_op; /* Opérande numérique en place */ + + + uint32_t offset; /* Décallage encodé en dur */ + bool ret; /* Bilan d'une récupération */ + + + off_t val_offset; /* Position de valeur à lire */ + + + + off_t length; /* Taille des données à lire */ + const bin_t *data; /* Données binaires à lire */ + + + uint32_t target; /* Adresse virtuelle visée */ + GArchOperand *new; /* Instruction de ciblage */ + + /* Récupération de l'adresse visée par le chargement */ + + range = g_arch_instruction_get_range(instr); + + phys_pc = get_phy_addr(get_mrange_addr(range)); + + phys_pc &= ~3; + //phys_pc = (phys_pc + 3) & ~3; + + printf(">>>>>>> @pc @ 0x%08x\n", (unsigned int)phys_pc); + + + switch (iset) + { + case AV7IS_ARM: + phys_pc += 8; + break; + case AV7IS_THUMB: + phys_pc += 4; + break; + default: + assert(0); + break; + } + + op = g_arch_instruction_get_operand(instr, 1); + assert(G_IS_ARMV7_OFFSET_OPERAND(op)); + + sub_op = g_armv7_offset_operand_get_value(G_ARMV7_OFFSET_OPERAND(op)); + + ret = g_imm_operand_get_value(G_IMM_OPERAND(sub_op), MDS_32_BITS_UNSIGNED, &offset); + if (!ret) + { + assert(0); + return; + } + + /* Lecture de la valeur vers laquelle renvoyer */ + + if (g_armv7_offset_operand_is_positive(G_ARMV7_OFFSET_OPERAND(op))) + val_offset = phys_pc + offset; + else + val_offset = phys_pc - offset; + + + data = g_binary_format_get_content(format, &length); + + + printf(">>>>>>> @reading @ 0x%08x (0x%x)\n", (unsigned int)val_offset, offset); + + + ret = read_u32(&target, data, &val_offset, length, SRE_LITTLE /* FIXME */); + if (!ret) return; + + + printf(">>>>>>> @got target :: 0x%08x\n", (unsigned int)target); + + + //g_imm_operand_set_value(G_IMM_OPERAND(sub_op), MDS_32_BITS_UNSIGNED, target); + + + new = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, target); + g_arch_instruction_replace_operand(instr, new, op); + + + + + //exit(0); + + + + //target = pc + offset; + + //g_armv7_context_define_encoding(context, target, AV7IS_THUMB); + g_armv7_context_push_drop_point_ext(context, target, AV7IS_THUMB); + + + //exit(0); } diff --git a/src/arch/arm/v7/link.h b/src/arch/arm/v7/link.h index ef71bd6..87bef54 100644 --- a/src/arch/arm/v7/link.h +++ b/src/arch/arm/v7/link.h @@ -32,6 +32,21 @@ /* Complète un désassemblage accompli pour une instruction. */ +void handle_links_with_instruction_b_with_orig(GArchInstruction *, GArmV7Context *, GBinFormat *, ArmV7InstrSet); + + +static inline void handle_links_with_instruction_b_from_arm(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt) +{ + handle_links_with_instruction_b_with_orig(ins, ctx, fmt, AV7IS_THUMB); +} + +static inline void handle_links_with_instruction_b_from_thumb(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt) +{ + handle_links_with_instruction_b_with_orig(ins, ctx, fmt, AV7IS_ARM); +} + + +/* Complète un désassemblage accompli pour une instruction. */ void handle_links_with_instruction_bl_with_orig(GArchInstruction *, GArmV7Context *, GBinFormat *, ArmV7InstrSet); @@ -61,5 +76,23 @@ static inline void handle_links_with_instruction_blx_from_thumb(GArchInstruction } +/* Complète un désassemblage accompli pour une instruction. */ +void handle_links_with_instruction_cb_n_z(GArchInstruction *, GArmV7Context *, GBinFormat *); + +/* Complète un désassemblage accompli pour une instruction. */ +void handle_links_with_instruction_ldr_literal_with_orig(GArchInstruction *, GArmV7Context *, GBinFormat *, ArmV7InstrSet); + + +static inline void handle_links_with_instruction_ldr_literal_from_arm(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt) +{ + handle_links_with_instruction_ldr_literal_with_orig(ins, ctx, fmt, AV7IS_ARM); +} + +static inline void handle_links_with_instruction_ldr_literal_from_thumb(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt) +{ + handle_links_with_instruction_ldr_literal_with_orig(ins, ctx, fmt, AV7IS_THUMB); +} + + #endif /* _ARCH_ARM_V7_LINK_H */ diff --git a/src/arch/arm/v7/opdefs/Makefile.am b/src/arch/arm/v7/opdefs/Makefile.am index 0966e2e..fa42230 100644 --- a/src/arch/arm/v7/opdefs/Makefile.am +++ b/src/arch/arm/v7/opdefs/Makefile.am @@ -16,6 +16,7 @@ D2C_ENCODINGS = \ -e T=thumb_32_ D2C_MACROS = \ + -M DefineAsReturn=g_arch_instruction_define_as_return \ -M SetFlags=g_armv7_instruction_define_setflags \ -M Condition=g_arm_instruction_set_cond \ -M Register=translate_armv7_register \ diff --git a/src/arch/arm/v7/opdefs/b_A8818.d b/src/arch/arm/v7/opdefs/b_A8818.d index 50600d4..5d696a3 100644 --- a/src/arch/arm/v7/opdefs/b_A8818.d +++ b/src/arch/arm/v7/opdefs/b_A8818.d @@ -36,10 +36,18 @@ } + @hooks { + + link = handle_links_with_instruction_b_from_thumb + post = post_process_branch_instructions + + } + @rules { //if cond == '1110' then UNDEFINED; //if cond == '1111' then SEE SVC; + call DefineAsReturn(1) } @@ -57,9 +65,17 @@ } + @hooks { + + link = handle_links_with_instruction_b_from_thumb + post = post_process_branch_instructions + + } + @rules { //if InITBlock() && !LastInITBlock() then UNPREDICTABLE; + call DefineAsReturn(1) } @@ -78,10 +94,18 @@ } + @hooks { + + link = handle_links_with_instruction_b_from_thumb + post = post_process_branch_instructions + + } + @rules { //if cond<3:1> == '111' then SEE "Related encodings"; //if InITBlock() then UNPREDICTABLE; + call DefineAsReturn(1) } @@ -101,9 +125,17 @@ } + @hooks { + + link = handle_links_with_instruction_b_from_thumb + post = post_process_branch_instructions + + } + @rules { //if InITBlock() && !LastInITBlock() then UNPREDICTABLE; + call DefineAsReturn(1) } @@ -122,4 +154,17 @@ } + @hooks { + + link = handle_links_with_instruction_b_from_arm + post = post_process_branch_instructions + + } + + @rules { + + call DefineAsReturn(1) + + } + } diff --git a/src/arch/arm/v7/opdefs/bl_A8825.d b/src/arch/arm/v7/opdefs/bl_A8825.d index 96c782f..c5de31e 100644 --- a/src/arch/arm/v7/opdefs/bl_A8825.d +++ b/src/arch/arm/v7/opdefs/bl_A8825.d @@ -40,7 +40,13 @@ @hooks { link = handle_links_with_instruction_bl_from_thumb - post = post_process_branch_instructions + post = post_process_branch_and_link_instructions + + } + + @rules { + + //call DefineAsReturn(1) } @@ -63,7 +69,13 @@ @hooks { link = handle_links_with_instruction_blx_from_thumb - post = post_process_branch_instructions + post = post_process_branch_and_link_instructions + + } + + @rules { + + //call DefineAsReturn(1) } @@ -84,7 +96,13 @@ @hooks { link = handle_links_with_instruction_bl_from_arm - post = post_process_branch_instructions + post = post_process_branch_and_link_instructions + + } + + @rules { + + //call DefineAsReturn(1) } @@ -105,7 +123,13 @@ @hooks { link = handle_links_with_instruction_blx_from_arm - post = post_process_branch_instructions + post = post_process_branch_and_link_instructions + + } + + @rules { + + //call DefineAsReturn(1) } diff --git a/src/arch/arm/v7/opdefs/blx_A8826.d b/src/arch/arm/v7/opdefs/blx_A8826.d index 178515a..12c55ad 100644 --- a/src/arch/arm/v7/opdefs/blx_A8826.d +++ b/src/arch/arm/v7/opdefs/blx_A8826.d @@ -39,6 +39,7 @@ //if m == 15 then UNPREDICTABLE; //if InITBlock() && !LastInITBlock() then UNPREDICTABLE; + //call DefineAsReturn(1) } @@ -60,6 +61,7 @@ @rules { //if m == 15 then UNPREDICTABLE; + //call DefineAsReturn(1) } diff --git a/src/arch/arm/v7/opdefs/bx_A8827.d b/src/arch/arm/v7/opdefs/bx_A8827.d index 45ccfd5..b8ab6f8 100644 --- a/src/arch/arm/v7/opdefs/bx_A8827.d +++ b/src/arch/arm/v7/opdefs/bx_A8827.d @@ -36,6 +36,12 @@ } + @rules { + + call DefineAsReturn(1) + + } + } @encoding(A1) { @@ -51,4 +57,10 @@ } + @rules { + + call DefineAsReturn(1) + + } + } diff --git a/src/arch/arm/v7/opdefs/cbnz_A8829.d b/src/arch/arm/v7/opdefs/cbnz_A8829.d index 9ecf141..93a8d1f 100644 --- a/src/arch/arm/v7/opdefs/cbnz_A8829.d +++ b/src/arch/arm/v7/opdefs/cbnz_A8829.d @@ -36,6 +36,13 @@ } + @hooks { + + link = handle_links_with_instruction_cb_n_z + post = post_process_comp_and_branch_instructions + + } + } @encoding(t12) { @@ -51,4 +58,11 @@ } + @hooks { + + link = handle_links_with_instruction_cb_n_z + post = post_process_comp_and_branch_instructions + + } + } diff --git a/src/arch/arm/v7/opdefs/ldr_A8862.d b/src/arch/arm/v7/opdefs/ldr_A8862.d index 7799fce..ecb530b 100644 --- a/src/arch/arm/v7/opdefs/ldr_A8862.d +++ b/src/arch/arm/v7/opdefs/ldr_A8862.d @@ -76,6 +76,7 @@ //if Rn == '1111' then SEE LDR (literal); //if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; + if (Rt == '1111'); call DefineAsReturn(1) } @@ -103,6 +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) } @@ -131,6 +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) } diff --git a/src/arch/arm/v7/opdefs/ldr_A8863.d b/src/arch/arm/v7/opdefs/ldr_A8863.d index 2526671..0158c3d 100644 --- a/src/arch/arm/v7/opdefs/ldr_A8863.d +++ b/src/arch/arm/v7/opdefs/ldr_A8863.d @@ -46,6 +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) } @@ -75,6 +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) } diff --git a/src/arch/arm/v7/opdefs/ldr_A8864.d b/src/arch/arm/v7/opdefs/ldr_A8864.d index acb6f94..3fbc0e3 100644 --- a/src/arch/arm/v7/opdefs/ldr_A8864.d +++ b/src/arch/arm/v7/opdefs/ldr_A8864.d @@ -37,6 +37,13 @@ } + @hooks { + + link = handle_links_with_instruction_ldr_literal_from_thumb + post = post_process_ldr_instructions + + } + } @encoding(T2) { @@ -53,9 +60,17 @@ } + @hooks { + + link = handle_links_with_instruction_ldr_literal_from_thumb + post = post_process_ldr_instructions + + } + @rules { //if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; + if (Rt == '1111'); call DefineAsReturn(1) } @@ -65,14 +80,29 @@ @word cond(4) 0 1 0 1 U(1) 0 0 1 1 1 1 1 Rt(4) imm12(12) - @syntax <Rgt> <label> + @syntax {c} <Rgt> <label> @conv { + c = Condition(cond) Rgt = Register(Rt) imm32 = ZeroExtend(imm12, 12, 32) label = MakeAccessOffset(U, imm32) } + @hooks { + + link = handle_links_with_instruction_ldr_literal_from_arm + post = post_process_ldr_instructions + + } + + @rules { + + //if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; + if (Rt == '1111'); call DefineAsReturn(1) + + } + } diff --git a/src/arch/arm/v7/opdefs/ldr_A8865.d b/src/arch/arm/v7/opdefs/ldr_A8865.d index 11a8932..56a09fb 100644 --- a/src/arch/arm/v7/opdefs/ldr_A8865.d +++ b/src/arch/arm/v7/opdefs/ldr_A8865.d @@ -67,6 +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) } diff --git a/src/arch/arm/v7/opdefs/ldrb_A8867.d b/src/arch/arm/v7/opdefs/ldrb_A8867.d index 8097fd0..52a50cb 100644 --- a/src/arch/arm/v7/opdefs/ldrb_A8867.d +++ b/src/arch/arm/v7/opdefs/ldrb_A8867.d @@ -60,6 +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) } @@ -87,6 +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) } @@ -115,6 +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) } diff --git a/src/arch/arm/v7/post.c b/src/arch/arm/v7/post.c index f85fc91..8895740 100644 --- a/src/arch/arm/v7/post.c +++ b/src/arch/arm/v7/post.c @@ -89,3 +89,192 @@ void post_process_branch_instructions(GArchInstruction *instr, GProcContext *con } } + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* context = contexte associé à la phase de désassemblage. * +* format = accès aux données du binaire d'origine. * +* * +* Description : Complète un désassemblage accompli pour une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void post_process_branch_and_link_instructions(GArchInstruction *instr, GProcContext *context, GBinFormat *format) +{ + GArchOperand *op; /* Opérande numérique en place */ + uint32_t addr; /* Adresse visée par le saut */ + GArchOperand *new; /* Instruction de ciblage */ + vmpa2t target; + mrange_t trange; + VMPA_BUFFER(loc); + char name[5 + VMPA_MAX_LEN]; + GBinRoutine *routine; /* Nouvelle routine trouvée */ + GBinSymbol *symbol; /* Nouveau symbole construit */ + + op = g_arch_instruction_get_operand(instr, 0); + + if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &addr)) + { + new = g_target_operand_new(MDS_32_BITS_UNSIGNED, addr); + + if (!g_target_operand_resolve(G_TARGET_OPERAND(new), format)) + { + init_vmpa(&target, VMPA_NO_PHYSICAL, addr); + init_mrange(&trange, &target, 0); + + vmpa2_virt_to_string(&target, MDS_32_BITS, loc, NULL); + snprintf(name, sizeof(name), "sub_%s", loc + 2); + + routine = g_binary_routine_new(); + g_binary_routine_set_name(routine, strdup(name)); + //routine = try_to_demangle_routine(name); + + g_binary_routine_set_range(routine, &trange); + + 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); + + + + g_target_operand_resolve(G_TARGET_OPERAND(new), format); + + } + + g_arch_instruction_replace_operand(instr, new, op); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* context = contexte associé à la phase de désassemblage. * +* format = accès aux données du binaire d'origine. * +* * +* Description : Complète un désassemblage accompli pour une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void post_process_comp_and_branch_instructions(GArchInstruction *instr, GProcContext *context, GBinFormat *format) +{ + GArchOperand *op; /* Opérande numérique en place */ + uint32_t addr; /* Adresse visée par le saut */ + GArchOperand *new; /* Instruction de ciblage */ + vmpa2t target; + mrange_t trange; + VMPA_BUFFER(loc); + char name[5 + VMPA_MAX_LEN]; + GBinRoutine *routine; /* Nouvelle routine trouvée */ + GBinSymbol *symbol; /* Nouveau symbole construit */ + + op = g_arch_instruction_get_operand(instr, 1); + + if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &addr)) + { + new = g_target_operand_new(MDS_32_BITS_UNSIGNED, addr); + + if (!g_target_operand_resolve(G_TARGET_OPERAND(new), format)) + { + init_vmpa(&target, VMPA_NO_PHYSICAL, addr); + init_mrange(&trange, &target, 0); + + vmpa2_virt_to_string(&target, MDS_32_BITS, loc, NULL); + snprintf(name, sizeof(name), "loc_%s", loc + 2); + + routine = g_binary_routine_new(); + g_binary_routine_set_name(routine, strdup(name)); + //routine = try_to_demangle_routine(name); + + g_binary_routine_set_range(routine, &trange); + + 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); + + + + g_target_operand_resolve(G_TARGET_OPERAND(new), format); + + } + + g_arch_instruction_replace_operand(instr, new, op); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* context = contexte associé à la phase de désassemblage. * +* format = accès aux données du binaire d'origine. * +* * +* Description : Complète un désassemblage accompli pour une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void post_process_ldr_instructions(GArchInstruction *instr, GProcContext *context, GBinFormat *format) +{ + GArchOperand *op; /* Opérande numérique en place */ + uint32_t addr; /* Adresse visée par le saut */ + GArchOperand *new; /* Instruction de ciblage */ + vmpa2t target; + mrange_t trange; + VMPA_BUFFER(loc); + char name[5 + VMPA_MAX_LEN]; + GBinRoutine *routine; /* Nouvelle routine trouvée */ + GBinSymbol *symbol; /* Nouveau symbole construit */ + + op = g_arch_instruction_get_operand(instr, 1); + + if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &addr)) + { + new = g_target_operand_new(MDS_32_BITS_UNSIGNED, addr); + + if (!g_target_operand_resolve(G_TARGET_OPERAND(new), format)) + { + init_vmpa(&target, VMPA_NO_PHYSICAL, addr); + init_mrange(&trange, &target, 0); + + vmpa2_virt_to_string(&target, MDS_32_BITS, loc, NULL); + snprintf(name, sizeof(name), "loc_%s", loc + 2); + + routine = g_binary_routine_new(); + g_binary_routine_set_name(routine, strdup(name)); + //routine = try_to_demangle_routine(name); + + g_binary_routine_set_range(routine, &trange); + + 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); + + + + g_target_operand_resolve(G_TARGET_OPERAND(new), format); + + } + + g_arch_instruction_replace_operand(instr, new, op); + + } + +} diff --git a/src/arch/arm/v7/post.h b/src/arch/arm/v7/post.h index dec51b2..79dcaa8 100644 --- a/src/arch/arm/v7/post.h +++ b/src/arch/arm/v7/post.h @@ -33,6 +33,15 @@ /* Complète un désassemblage accompli pour une instruction. */ void post_process_branch_instructions(GArchInstruction *, GProcContext *, GBinFormat *); +/* Complète un désassemblage accompli pour une instruction. */ +void post_process_branch_and_link_instructions(GArchInstruction *, GProcContext *, GBinFormat *); + +/* Complète un désassemblage accompli pour une instruction. */ +void post_process_comp_and_branch_instructions(GArchInstruction *, GProcContext *, GBinFormat *); + +/* Complète un désassemblage accompli pour une instruction. */ +void post_process_ldr_instructions(GArchInstruction *, GProcContext *, GBinFormat *); + #endif /* _ARCH_ARM_V7_POST_H */ diff --git a/src/arch/arm/v7/processor.c b/src/arch/arm/v7/processor.c index d83c36d..3464214 100644 --- a/src/arch/arm/v7/processor.c +++ b/src/arch/arm/v7/processor.c @@ -231,8 +231,7 @@ static GArmV7Context *g_armv7_processor_get_context(const GArmV7Processor *proc) * Remarques : - * * * ******************************************************************************/ -#include "link.h" -#include "post.h" + static GArchInstruction *g_armv7_processor_disassemble(const GArmV7Processor *proc, GArmV7Context *ctx, const bin_t *data, vmpa2t *pos, phys_t end) { GArchInstruction *result; /* Instruction à renvoyer */ @@ -297,11 +296,11 @@ static GArchInstruction *g_armv7_processor_disassemble(const GArmV7Processor *pr if (result != NULL) advance_vmpa(pos, diff); - + /* else result = g_raw_instruction_new_array(data, MDS_32_BITS, 1, pos, end, G_ARCH_PROCESSOR(proc)->endianness); - + */ return result; } diff --git a/src/arch/artificial.c b/src/arch/artificial.c index 9b84226..d2b2117 100644 --- a/src/arch/artificial.c +++ b/src/arch/artificial.c @@ -72,9 +72,6 @@ static void g_db_instruction_build_keyword(const GDbInstruction *, AsmSyntax); /* Informe sur une éventuelle référence à une autre instruction. */ static InstructionLinkType g_db_instruction_get_link(const GDbInstruction *, vmpa_t *); -/* Indique si l'instruction correspond à un retour de fonction. */ -static bool g_db_instruction_is_return(const GDbInstruction *); - /* ---------------------------------------------------------------------------------- */ @@ -134,7 +131,6 @@ static void g_db_instruction_init(GDbInstruction *instr) parent = G_ARCH_INSTRUCTION(instr); parent->get_link = (get_instruction_link_fc)g_db_instruction_get_link; - parent->is_return = (is_instruction_return_fc)g_db_instruction_is_return; } @@ -271,25 +267,6 @@ static InstructionLinkType g_db_instruction_get_link(const GDbInstruction *instr } -/****************************************************************************** -* * -* Paramètres : instr = instruction à consulter. * -* * -* Description : Indique si l'instruction correspond à un retour de fonction. * -* * -* Retour : true si l'instruction est un 'return' quelconque ou false. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_db_instruction_is_return(const GDbInstruction *instr) -{ - return false; - -} - - #ifdef DEBUG /****************************************************************************** diff --git a/src/arch/dalvik/instruction.c b/src/arch/dalvik/instruction.c index 98e29dd..ac1efdc 100644 --- a/src/arch/dalvik/instruction.c +++ b/src/arch/dalvik/instruction.c @@ -398,7 +398,7 @@ static void g_dalvik_instruction_init(GDalvikInstruction *instr) parent->get_rw_regs = (get_instruction_rw_regs_fc)g_dalvik_instruction_get_rw_registers; parent->get_link = (get_instruction_link_fc)dalvik_get_instruction_link; - parent->is_return = (is_instruction_return_fc)dalvik_instruction_is_return; + //parent->is_return = (is_instruction_return_fc)dalvik_instruction_is_return; parent->decomp = (decomp_instr_fc)dalvik_instruction_decompile; } diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h index 5bdcedb..de9c70d 100644 --- a/src/arch/instruction-int.h +++ b/src/arch/instruction-int.h @@ -44,9 +44,6 @@ typedef void (* build_instruction_keyword_fc) (const GArchInstruction *, AsmSynt /* Informe sur une éventuelle référence à une autre instruction. */ typedef InstructionLinkType (* get_instruction_link_fc) (const GArchInstruction *, vmpa_t *); -/* Indique si l'instruction correspond à un retour de fonction. */ -typedef bool (* is_instruction_return_fc) (const GArchInstruction *); - /* Définition générique d'une instruction d'architecture (instance) */ struct _GArchInstruction @@ -71,8 +68,6 @@ struct _GArchInstruction vmpa_t address; /* Position associée */ /* ------- %< ----------- */ - - GArchOperand **operands; /* Liste des opérandes */ size_t operands_count; /* Nbre. d'opérandes utilisées */ @@ -88,9 +83,11 @@ struct _GArchInstruction //print_instruction_fc print; /* Imprime l'ensemble */ //get_instruction_keyword_fc get_key; /* Texte humain équivalent */ get_instruction_link_fc get_link; /* Référence à une instruction */ - is_instruction_return_fc is_return; /* Retour de fonction ou pas ? */ + //is_instruction_return_fc is_return; /* Retour de fonction ou pas ? */ decomp_instr_fc decomp; /* Procédure de décompilation */ + bool is_return; /* Retour de fonction ou pas ? */ + }; diff --git a/src/arch/instruction.c b/src/arch/instruction.c index 598da6d..67fd184 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -105,6 +105,8 @@ static void g_arch_instruction_init(GArchInstruction *instr) { DL_LIST_ITEM_INIT(&instr->flow); + instr->is_return = false; + } @@ -475,6 +477,28 @@ InstructionLinkType g_arch_instruction_get_link(const GArchInstruction *instr, v /****************************************************************************** * * +* Paramètres : instr = instruction à consulter. * +* status = statut de l'instruction vis à vis du flot. * +* * +* Description : Précise si l'instruction correspond à un retour de fonction. * +* * +* Retour : true (pour respecter le prototypage depuis les fichiers D). * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_arch_instruction_define_as_return(GArchInstruction *instr, bool status) +{ + instr->is_return = status; + + return true; + +} + + +/****************************************************************************** +* * * Paramètres : instr = instruction à consulter. * * * * Description : Indique si l'instruction correspond à un retour de fonction. * @@ -487,7 +511,7 @@ InstructionLinkType g_arch_instruction_get_link(const GArchInstruction *instr, v bool g_arch_instruction_is_return(const GArchInstruction *instr) { - return instr->is_return(instr); + return instr->is_return; } diff --git a/src/arch/instruction.h b/src/arch/instruction.h index eb31865..02bb9b7 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -156,6 +156,9 @@ typedef union _link_extra_info /* Informe sur une éventuelle référence à une autre instruction. */ InstructionLinkType g_arch_instruction_get_link(const GArchInstruction *, vmpa_t *); +/* Précise si l'instruction correspond à un retour de fonction. */ +bool g_arch_instruction_define_as_return(GArchInstruction *, bool); + /* Indique si l'instruction correspond à un retour de fonction. */ bool g_arch_instruction_is_return(const GArchInstruction *instr); diff --git a/src/arch/x86/instruction.c b/src/arch/x86/instruction.c index 0450d96..c26a995 100644 --- a/src/arch/x86/instruction.c +++ b/src/arch/x86/instruction.c @@ -496,7 +496,7 @@ static void g_x86_instruction_init(GX86Instruction *instr) //parent->get_text = (get_instruction_text_fc)x86_get_instruction_text; parent->get_link = (get_instruction_link_fc)x86_get_instruction_link; - parent->is_return = (is_instruction_return_fc)x86_instruction_is_return; + //parent->is_return = (is_instruction_return_fc)x86_instruction_is_return; } diff --git a/tools/d2c/Makefile.am b/tools/d2c/Makefile.am index e997beb..63ca5fe 100644 --- a/tools/d2c/Makefile.am +++ b/tools/d2c/Makefile.am @@ -7,6 +7,7 @@ bin_PROGRAMS = d2c d2c_SOURCES = \ + args.h args.c \ bits.h bits.c \ coder.h coder.c \ conv.h conv.c \ @@ -15,6 +16,7 @@ d2c_SOURCES = \ helpers.h helpers.c \ hooks.h hooks.c \ pproc.h pproc.c \ + qckcall.h qckcall.c \ rules.h rules.c \ spec.h spec.c \ syntax.h syntax.c diff --git a/tools/d2c/args.c b/tools/d2c/args.c new file mode 100644 index 0000000..616873b --- /dev/null +++ b/tools/d2c/args.c @@ -0,0 +1,1161 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * args.c - gestion des arguments dans leur ensemble + * + * Copyright (C) 2015 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 "args.h" + + +#include <assert.h> +#include <malloc.h> +#include <string.h> + + +#include "conv.h" +#include "helpers.h" + + + +/* +#include <assert.h> +#include <ctype.h> + +#include <regex.h> +#include <stdbool.h> +#include <sys/param.h> + + +*/ + + + + +/* Types d'expressions représentés */ +typedef enum _ConvExprType +{ + CET_NAME, /* Désignation de variable */ + CET_NUMBER, /* Valeur codée en dur */ + CET_COMPOSED, /* Agrégat de champs divers */ + CET_UNARY, /* Opération unaire */ + CET_BINARY, /* Opération binaire */ + + CET_COUNT + +} ConvExprType; + + +/* Représentation d'une expression de conversion */ +struct _arg_expr_t +{ + ConvExprType type; + + bool declared; /* Expression déjà déclarée ? */ + bool defined; /* Expression déjà définie ? */ + + union + { + /* CET_NAME */ + char *name; /* Désignation de variable */ + + /* CET_NUMBER */ + unsigned long number; /* Valeur durablement définie */ + + /* CET_COMPOSED */ + struct + { + char **comp_items; /* Elements à agréger */ + size_t comp_count; /* Quantité de ces éléments */ + }; + + /* CET_UNARY */ + struct + { + arg_expr_t *un_expr; /* Expression à traiter */ + ConvUnaryOperation un_op; /* Type d'opération à mener */ + + }; + + /* CET_BINARY */ + struct + { + arg_expr_t *bin_expr1; /* Expression à traiter */ + arg_expr_t *bin_expr2; /* Expression à traiter */ + ConvBinaryOperation bin_op; /* Type d'opération à mener */ + + }; + + }; + +}; + + +/* Visite une expression en traitant en premier ses composantes. */ +typedef bool (* visit_expr_fc) (arg_expr_t *, int, const coding_bits *, const conv_list *, void *); + +/* Visite une expression en traitant en premier ses composantes. */ +static bool visit_arg_expr(arg_expr_t *, visit_expr_fc, int, const coding_bits *, const conv_list *, void *); + +/* Retrouve si elle existe une variable manipulée. */ +static bool find_var_by_name(const coding_bits *, const conv_list *, const char *, raw_bitfield **, conv_func **); + + + +/* ----------------------- MANIPULATION DE LISTES D'ARGUMENTS ----------------------- */ + + +/* Liste d'expressions utilisées en arguments de conversion */ +struct _arg_list_t +{ + arg_expr_t **items; /* Liste d'expressions */ + size_t count; /* Taille de cette liste */ + +}; + + + +/* ---------------------------------------------------------------------------------- */ +/* REPRESENTATION D'UN ARGUMENT */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : name = désignation d'une variable quelconque. * +* * +* Description : Référence une variable en tant qu'expression de conversion. * +* * +* Retour : Nouvelle expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +arg_expr_t *build_arg_expr_from_name(char *name) +{ + arg_expr_t *result; /* Structure à retourner */ + + result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t)); + + result->type = CET_NAME; + + result->name = make_string_lower(name); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : number = valeur à conserver dans sa forme brute. * +* * +* Description : Conserve une valeur en tant qu'expression de conversion. * +* * +* Retour : Nouvelle expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +arg_expr_t *build_arg_expr_from_number(unsigned long number) +{ + arg_expr_t *result; /* Structure à retourner */ + + result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t)); + + result->type = CET_NUMBER; + + result->number = number; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item1 = premier élément à agréger. * +* item2 = second élément à agréger. * +* * +* Description : Construit une base d'expression de conversion composée. * +* * +* Retour : Nouvelle expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +arg_expr_t *build_composed_arg_expr(char *item1, char *item2) +{ + arg_expr_t *result; /* Structure à retourner */ + + result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t)); + + result->type = CET_COMPOSED; + + result->comp_items = (char **)calloc(2, sizeof(char *)); + result->comp_count = 2; + + result->comp_items[0] = make_string_lower(item1); + result->comp_items[1] = make_string_lower(item2); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression déjà en place à compléter. * +* item = nouvel élément à agréger. * +* * +* Description : Etend une base d'expression de conversion composée. * +* * +* Retour : Expression en place et mise à jour. * +* * +* Remarques : - * +* * +******************************************************************************/ + +arg_expr_t *extend_composed_arg_expr(arg_expr_t *expr, char *item) +{ + assert(expr->type == CET_COMPOSED); + + expr->comp_items = (char **)realloc(expr->comp_items, ++expr->comp_count * sizeof(char *)); + + expr->comp_items[expr->comp_count - 1] = make_string_lower(item); + + return expr; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression à encapsuler. * +* op = opération unaire à associer à l'opération. * +* * +* Description : Traduit une opération unaire sur expression de conversion. * +* * +* Retour : Nouvelle expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +arg_expr_t *build_unary_arg_expr(arg_expr_t *expr, ConvUnaryOperation op) +{ + arg_expr_t *result; /* Structure à retourner */ + + result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t)); + + result->type = CET_UNARY; + + result->un_expr = expr; + result->un_op = op; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr1 = première expression à encapsuler. * +* expr2 = seconde expression à encapsuler. * +* op = opération binaire à associer à l'opération. * +* * +* Description : Traduit une opération binaire sur expression de conversion. * +* * +* Retour : Nouvelle expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +arg_expr_t *build_binary_arg_expr(arg_expr_t *expr1, arg_expr_t *expr2, ConvBinaryOperation op) +{ + arg_expr_t *result; /* Structure à retourner */ + + result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t)); + + result->type = CET_BINARY; + + result->bin_expr1 = expr1; + result->bin_expr2 = expr2; + result->bin_op = op; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression à libérer de la mémoire. * +* * +* Description : Supprime tous les éléments mis en place pour un argument. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void delete_arg_expr(arg_expr_t *expr) +{ + size_t i; /* Boucle de parcours */ + + switch (expr->type) + { + case CET_NAME: + free(expr->name); + break; + + case CET_COMPOSED: + for (i = 0; i < expr->comp_count; i++) + free(expr->comp_items[i]); + free(expr->comp_items); + break; + + case CET_UNARY: + delete_arg_expr(expr->un_expr); + break; + + case CET_BINARY: + delete_arg_expr(expr->bin_expr1); + delete_arg_expr(expr->bin_expr2); + break; + + default: + break; + + } + + free(expr); + +} + + +/****************************************************************************** +* * +* Paramètres : expr = première expression à consulter. * +* bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* size = taille déterminée avec précision. [OUT] * +* * +* Description : Détermine la taille en bits d'une expression donnée. * +* * +* Retour : true si la taille a pu être déterminée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool compute_arg_expr_size(const arg_expr_t *expr, const coding_bits *bits, const conv_list *list, unsigned int *size) +{ + bool result; /* Bilan à retourner */ + raw_bitfield *field; /* Eventuel champ brut associé */ + conv_func *func; /* Eventuelle fonction liée */ + size_t i; /* Boucle de parcours */ + unsigned int tmp; /* Stockage temporaire */ + + switch (expr->type) + { + case CET_NAME: + + result = find_var_by_name(bits, list, expr->name, &field, &func); + + if (result) + { + if (field != NULL) + *size = get_raw_bitfield_length(field); + else + result = compute_conv_func_size(func, bits, list, size); + } + + break; + + case CET_COMPOSED: + + result = true; + *size = 0; + + for (i = 0; i < expr->comp_count && result; i++) + { + if (isdigit(expr->comp_items[i][0])) + *size += strlen(expr->comp_items[i]); + + else + { + if (!find_var_by_name(bits, list, expr->comp_items[i], &field, &func)) + result = false; + + else + { + if (field != NULL) + *size += get_raw_bitfield_length(field); + else + { + result = compute_conv_func_size(func, bits, list, &tmp); + *size += tmp; + } + } + + } + + } + + break; + + case CET_UNARY: + result = compute_arg_expr_size(expr->un_expr, bits, list, size); + break; + + case CET_BINARY: + + result = compute_arg_expr_size(expr->bin_expr1, bits, list, &tmp); + + if (result) + result = compute_arg_expr_size(expr->bin_expr1, bits, list, size); + + if (tmp > *size) *size = tmp; + + break; + + default: + result = false; + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = première expression à encapsuler. * +* fd = descripteur d'un flux ouvert en écriture. * +* bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* data = éventuelle donnée à transmettre à chaque visite. * +* * +* Description : Visite une expression en traitant en premier ses composantes.* +* * +* Retour : Bilan des traitements effectués. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool visit_arg_expr(arg_expr_t *expr, visit_expr_fc visit, int fd, const coding_bits *bits, const conv_list *list, void *data) +{ + bool result; /* Bilan à retourner */ + + switch (expr->type) + { + case CET_UNARY: + result = visit_arg_expr(expr->un_expr, visit, fd, bits, list, data); + break; + + case CET_BINARY: + result = visit_arg_expr(expr->bin_expr1, visit, fd, bits, list, data); + result = visit_arg_expr(expr->bin_expr2, visit, fd, bits, list, data); + break; + + default: + result = true; + break; + + } + + result &= visit(expr, fd, bits, list, data); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* name = déssignation de la variable recherchée. * +* field = éventuel élement brut de décodage. * +* func = éventuelle fonction de conversion pour intermédiaire.* +* * +* Description : Retrouve si elle existe une variable manipulée. * +* * +* Retour : Bilan des recherches : trouvaille ou non ? * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool find_var_by_name(const coding_bits *bits, const conv_list *list, const char *name, raw_bitfield **field, conv_func **func) +{ + bool result; /* Bilan à retourner */ + raw_bitfield *cached_field; /* Champ, version cachée */ + conv_func *cached_func; /* Fonction, version cachée */ + + cached_field = find_named_field_in_bits(bits, name); + result = (cached_field != NULL); + + if (!result) + { + cached_func = find_named_conv_in_list(list, name); + result = (cached_func != NULL); + } + else + cached_func = NULL; + + if (field != NULL) *field = cached_field; + if (func != NULL) *func = cached_func; + + if (!result) + fprintf(stderr, "Variable '%s' not found!\n", name); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = première expression à encapsuler. * +* bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* * +* Description : S'assure du marquage des expressions pre-requises. * +* * +* Retour : Bilan des traitements effectués. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_arg_expr_content_fully_marked(arg_expr_t *expr, const coding_bits *bits, const conv_list *list) +{ + bool mark_sub_expr(arg_expr_t *sub, int dummy, const coding_bits *bts, const conv_list *lst, void *unused) + { + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + + bool mark_by_name(const coding_bits *_bts, const conv_list *_lst, const char *name) + { + bool found; /* Bilan d'opération à renvoyer*/ + raw_bitfield *field; /* Eventuel champ brut associé */ + conv_func *func; /* Eventuelle fonction liée */ + + found = find_var_by_name(bts, lst, name, &field, &func); + + if (found) + { + if (field != NULL) + mark_raw_bitfield_as_used(field); + else /*if (func != NULL) */ + mark_conv_func(func, bts, lst); + + printf(" VAR '%s' found (bf=%d fc=%d)\n", name, !!field, !!func); + + + } + else printf(" VAR '%s' not found...\n", name); + + return found; + + } + + /* Il est uniquement nécessaire de s'attacher aux références */ + switch (sub->type) + { + case CET_NAME: + result = mark_by_name(bits, lst, sub->name); + break; + + case CET_COMPOSED: + result = true; + for (i = 0; i < sub->comp_count && result; i++) + if (!isdigit(sub->comp_items[i][0])) + result = mark_by_name(bits, lst, sub->comp_items[i]); + break; + + default: + result = true; + break; + + } + + return result; + + } + + return visit_arg_expr(expr, (visit_expr_fc)mark_sub_expr, -1, bits, list, NULL); + +} + + +/****************************************************************************** +* * +* Paramètres : expr = première expression à encapsuler. * +* fd = descripteur d'un flux ouvert en écriture. * +* arch = architecture visée par l'opération globale. * +* bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* wide = taille des mots décodés. * +* * +* Description : S'assure de la déclaration des expressions pre-requises. * +* * +* Retour : Bilan des traitements effectués. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_arg_expr_content_fully_declared(arg_expr_t *expr, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide) +{ + bool declare_sub_expr(arg_expr_t *sub, int f, const coding_bits *bts, const conv_list *lst, unsigned int *wide) + { + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + + /* Si l'expression a déjà été définie lors d'un précédent besoin... */ + printf(" sub declared ? %d -- type = %d\n", sub->declared, sub->type); + if (sub->declared) return true; + + bool declare_by_name(int _f, const coding_bits *_bts, const conv_list *_lst, unsigned int _wide, const char *name) + { + bool found; /* Bilan d'opération à renvoyer*/ + conv_func *func; /* Eventuelle fonction liée */ + + found = find_var_by_name(bts, lst, name, NULL, &func); + + if (found && func != NULL) + { + printf("========= DECLARE for '%s'\n", name); + found = declare_conv_func(func, _f, _bts, _lst, _wide); + printf("========= END DECLARE for '%s'\n", name); + + /** + * Si on déclare les variables suivantes dans declare_conv_func(), + * elles seront également déclarées pour les fonctions de conversion + * racine à partir de declare_syntax_items(), ce qui ne convient pas + * car les appels racine servent directement d'arguments. + */ + + if (is_conv_func_expression(func)) + dprintf(_f, "\t\tuint%u_t val_%s; // Ho\n", _wide, name); + else + dprintf(_f, "\t\tGArchOperand *val_%s;;;;;\n", name); + + } + + return found; + + } + + /* Il est uniquement nécessaire de s'attacher aux références */ + switch (sub->type) + { + case CET_NAME: + result = declare_by_name(f, bits, lst, *wide, sub->name); + break; + + case CET_COMPOSED: + result = true; + for (i = 0; i < sub->comp_count && result; i++) + if (!isdigit(sub->comp_items[i][0])) + printf("... trying to declare... '%s'\n", sub->comp_items[i]); + for (i = 0; i < sub->comp_count && result; i++) + if (!isdigit(sub->comp_items[i][0])) + result = declare_by_name(f, bits, lst, *wide, sub->comp_items[i]); + break; + + default: + result = true; + break; + + } + + sub->declared = result; + + return result; + + } + + return visit_arg_expr(expr, (visit_expr_fc)declare_sub_expr, fd, bits, list, &wide); + +} + + +/****************************************************************************** +* * +* Paramètres : expr = première expression à encapsuler. * +* fd = descripteur d'un flux ouvert en écriture. * +* arch = architecture visée par l'opération globale. * +* 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 : S'assure de la définition des expressions pre-requises. * +* * +* Retour : Bilan des traitements effectués. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_arg_expr_content_fully_defined(arg_expr_t *expr, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp) +{ + typedef struct _def_info + { + const char *arch; + const pre_processor *pp; + + } def_info; + + def_info info; /* Transmissions au visiteur */ + + bool define_sub_expr(arg_expr_t *sub, int f, const coding_bits *bts, const conv_list *lst, def_info *info) + { + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + + /* Si l'expression a déjà été définie lors d'un précédent besoin... */ + if (sub->defined) return true; + + bool define_by_name(int _f, const coding_bits *_bts, const conv_list *_lst, def_info *_info, const char *name) + { + bool found; /* Bilan d'opération à renvoyer*/ + conv_func *func; /* Eventuelle fonction liée */ + + found = find_var_by_name(bts, lst, name, NULL, &func); + + if (found && func != NULL) + found = define_conv_func(func, false, false, _f, _info->arch, _bts, _lst, _info->pp); + + return found; + + } + + /* Il est uniquement nécessaire de s'attacher aux références */ + switch (sub->type) + { + case CET_NAME: + result = define_by_name(f, bits, lst, info, sub->name); + break; + + case CET_COMPOSED: + result = true; + for (i = 0; i < sub->comp_count && result; i++) + if (!isdigit(sub->comp_items[i][0])) + result = define_by_name(f, bits, lst, info, sub->comp_items[i]); + break; + + default: + result = true; + break; + + } + + sub->defined = result; + + return result; + + } + + info.arch = arch; + info.pp = pp; + + return visit_arg_expr(expr, (visit_expr_fc)define_sub_expr, fd, bits, list, &info); + +} + + +/****************************************************************************** +* * +* Paramètres : expr = première expression à encapsuler. * +* fd = descripteur d'un flux ouvert en écriture. * +* bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* * +* Description : Définit une expression utilisée dans une conversion. * +* * +* Retour : Bilan des traitements effectués. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool define_arg_expr(const arg_expr_t *expr, int fd, const coding_bits *bits, const conv_list *list) +{ + bool result; /* Bilan à retourner */ + raw_bitfield *field; /* Eventuel champ brut associé */ + conv_func *func; /* Eventuelle fonction liée */ + unsigned int max_size; /* Quantité de bits totale */ + size_t i; /* Boucle de parcours */ + const char *cname; /* Raccourci de confort */ + unsigned int used_size; /* Quantité de bits utilisée */ + + result = true; + + switch (expr->type) + { + case CET_NAME: + + if (!find_var_by_name(bits, list, expr->name, &field, &func)) + result = false; + + else + { + if (field != NULL) + dprintf(fd, "raw_%s", expr->name); + else + dprintf(fd, "val_%s", expr->name); + } + + break; + + case CET_NUMBER: + dprintf(fd, "%lu", expr->number); + break; + + case CET_COMPOSED: + + result = compute_arg_expr_size(expr, bits, list, &max_size); + + printf("MAX SIZE :: %u\n", max_size); + + for (i = 0; i < expr->comp_count && result; i++) + { + cname = expr->comp_items[i]; + + if (i > 0) + dprintf(fd, " | "); + + /* Constante binaire ? */ + if (isdigit(cname[0])) + { + max_size -= strlen(cname); + + if (max_size == 0) + dprintf(fd, "b%s", cname); + else + dprintf(fd, "b%s << %u", cname, max_size); + + } + + /* Ou variable définie ? */ + else + { + result = find_var_by_name(bits, list, cname, &field, &func); + + if (result) + { + if (field != NULL) + used_size = get_raw_bitfield_length(field); + else + /*result = */compute_conv_func_size(func, bits, list, &used_size); + + max_size -= used_size; + + if (field != NULL) + { + if (max_size == 0) + dprintf(fd, "raw_%s", cname); + else + dprintf(fd, "raw_%s << %u", cname, max_size); + } + else + { + if (max_size == 0) + dprintf(fd, "val_%s", cname); + else + dprintf(fd, "val_%s << %u", cname, max_size); + } + + } + + } + + } + + break; + + case CET_UNARY: + + switch (expr->un_op) + { + case CUO_NOT: + dprintf(fd, "!"); + break; + default: + result = false; + break; + } + + result &= define_arg_expr(expr->un_expr, fd, bits, list); + + break; + + case CET_BINARY: + + dprintf(fd, "("); + + result = define_arg_expr(expr->bin_expr1, fd, bits, list); + + switch (expr->bin_op) + { + case CBO_EOR: + dprintf(fd, " ^ "); + break; + default: + result = false; + break; + } + + result &= define_arg_expr(expr->bin_expr2, fd, bits, list); + + dprintf(fd, ")"); + + break; + + default: + result = false; + break; + + } + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* MANIPULATION DE LISTES D'ARGUMENTS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : expr = expression initial pour constituer une liste. * +* * +* Description : Crée une liste d'arguments de conversion. * +* * +* Retour : Nouvelle structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +arg_list_t *build_arg_list(arg_expr_t *expr) +{ + arg_list_t *result; /* Structure à retourner */ + + result = (arg_list_t *)calloc(1, sizeof(arg_list_t)); + + result->items = (arg_expr_t **)calloc(1, sizeof(arg_expr_t *)); + result->count = 1; + + result->items[0] = expr; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : list = liste d'expressions à supprimer de la mémoire. * +* * +* Description : Libère la mémoire occupée par une liste d'expressions. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void delete_arg_list(arg_list_t *list) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < list->count; i++) + delete_arg_expr(list->items[i]); + + if (list->items != NULL) + free(list->items); + + free(list); + +} + + +/****************************************************************************** +* * +* Paramètres : list = liste d'expressions à supprimer de la mémoire. [OUT] * +* expr = expression à ajouter à la liste courante. * +* * +* Description : Ajoute un élément à une liste d'arguments de conversion. * +* * +* Retour : Structure en place mise à jour. * +* * +* Remarques : - * +* * +******************************************************************************/ + +arg_list_t *extend_arg_list(arg_list_t *list, arg_expr_t *expr) +{ + list->items = (arg_expr_t **)realloc(list->items, ++list->count * sizeof(arg_expr_t *)); + + list->items[list->count - 1] = expr; + + return list; + +} + + +/****************************************************************************** +* * +* Paramètres : args = liste d'expressions à supprimer de la mémoire. * +* bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* * +* Description : S'assure du marquage des expressions pre-requises. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_arg_list_content_fully_marked(arg_list_t *args, const coding_bits *bits, const conv_list *list) +{ + bool result; /* Bilan à remonter */ + size_t i; /* Boucle de parcours */ + + result = true; + + for (i = 0; i < args->count && result; i++) + result = ensure_arg_expr_content_fully_marked(args->items[i], bits, list); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : args = liste d'expressions à supprimer de la mémoire. * +* fd = descripteur d'un flux ouvert en écriture. * +* bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* wide = taille des mots décodés. * +* * +* Description : S'assure de la déclaration des expressions pre-requises. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_arg_list_content_fully_declared(arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide) +{ + bool result; /* Bilan à remonter */ + size_t i; /* Boucle de parcours */ + + result = true; + + for (i = 0; i < args->count && result; i++) + result = ensure_arg_expr_content_fully_declared(args->items[i], fd, bits, list, wide); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : args = liste d'expressions à supprimer de la mémoire. * +* fd = descripteur d'un flux ouvert en écriture. * +* arch = architecture visée par l'opération globale. * +* 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 : S'assure de la définition des expressions pre-requises. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_arg_list_content_fully_defined(arg_list_t *args, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp) +{ + bool result; /* Bilan à remonter */ + size_t i; /* Boucle de parcours */ + + result = true; + + for (i = 0; i < args->count && result; i++) + result = ensure_arg_expr_content_fully_defined(args->items[i], fd, arch, bits, list, pp); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : args = liste d'expressions à supprimer de la mémoire. * +* fd = descripteur d'un flux ouvert en écriture. * +* bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* * +* Description : Définit les variables associées à un appel de fonction. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool define_arg_list(const arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list) +{ + bool result; /* Bilan à remonter */ + size_t i; /* Boucle de parcours */ + + result = true; + + for (i = 0; i < args->count && result; i++) + { + if (i > 0) dprintf(fd, ", "); + result = define_arg_expr(args->items[i], fd, bits, list); + } + + return result; + +} diff --git a/tools/d2c/args.h b/tools/d2c/args.h new file mode 100644 index 0000000..0ad022e --- /dev/null +++ b/tools/d2c/args.h @@ -0,0 +1,131 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * args.h - prototypes pour la gestion des arguments dans leur ensemble + * + * Copyright (C) 2015 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_ARGS_H +#define _TOOLS_ARGS_H + + +#include "bits.h" +#include "pproc.h" + + +/* Liste des fonctions de conversions présentes */ +typedef struct _conv_list conv_list; + + + +/* -------------------------- REPRESENTATION D'UN ARGUMENT -------------------------- */ + + +/* Types d'opérations unaires */ +typedef enum _ConvUnaryOperation +{ + CUO_NOT, /* NOT (booléen) */ + + CUO_COUNT + +} ConvUnaryOperation; + +/* Types d'opérations binaires */ +typedef enum _ConvBinaryOperation +{ + CBO_EOR, /* Ou exclusif (booléen) */ + + CBO_COUNT + +} ConvBinaryOperation; + + +/* Représentation d'une expression de conversion */ +typedef struct _arg_expr_t arg_expr_t; + + +/* Référence une variable en tant qu'expression de conversion. */ +arg_expr_t *build_arg_expr_from_name(char *); + +/* Conserve une valeur en tant qu'expression de conversion. */ +arg_expr_t *build_arg_expr_from_number(unsigned long ); + +/* Construit une base d'expression de conversion composée. */ +arg_expr_t *build_composed_arg_expr(char *, char *); + +/* Etend une base d'expression de conversion composée. */ +arg_expr_t *extend_composed_arg_expr(arg_expr_t *, char *); + +/* Traduit une opération unaire sur expression de conversion. */ +arg_expr_t *build_unary_arg_expr(arg_expr_t *, ConvUnaryOperation); + +/* Traduit une opération binaire sur expression de conversion. */ +arg_expr_t *build_binary_arg_expr(arg_expr_t *, arg_expr_t *, ConvBinaryOperation); + +/* Supprime tous les éléments mis en place pour un argument. */ +void delete_arg_expr(arg_expr_t *); + +/* Détermine la taille en bits d'une expression donnée. */ +bool compute_arg_expr_size(const arg_expr_t *, const coding_bits *, const conv_list *, unsigned int *); + +/* S'assure du marquage des expressions pre-requises. */ +bool ensure_arg_expr_content_fully_marked(arg_expr_t *, const coding_bits *, const conv_list *); + +/* S'assure de la déclaration des expressions pre-requises. */ +bool ensure_arg_expr_content_fully_declared(arg_expr_t *, int, const coding_bits *, const conv_list *, unsigned int); + +/* S'assure de la définition des expressions pre-requises. */ +bool ensure_arg_expr_content_fully_defined(arg_expr_t *, int, const char *, const coding_bits *, const conv_list *, const pre_processor *); + +/* Définit une expression utilisée dans une conversion. */ +bool define_arg_expr(const arg_expr_t *, int, const coding_bits *, const conv_list *); + + + +/* ----------------------- MANIPULATION DE LISTES D'ARGUMENTS ----------------------- */ + + +/* Liste d'expressions utilisées en arguments de conversion */ +typedef struct _arg_list_t arg_list_t; + + +/* Crée une liste d'arguments de conversion. */ +arg_list_t *build_arg_list(arg_expr_t *); + +/* Libère la mémoire occupée par une liste d'expressions. */ +void delete_arg_list(arg_list_t *); + +/* Ajoute un élément à une liste d'arguments de conversion. */ +arg_list_t *extend_arg_list(arg_list_t *, arg_expr_t *); + +/* S'assure du marquage des expressions pre-requises. */ +bool ensure_arg_list_content_fully_marked(arg_list_t *, const coding_bits *, const conv_list *); + +/* S'assure de la déclaration des expressions pre-requises. */ +bool ensure_arg_list_content_fully_declared(arg_list_t *, int, const coding_bits *, const conv_list *, unsigned int); + +/* S'assure de la définition des expressions pre-requises. */ +bool ensure_arg_list_content_fully_defined(arg_list_t *, int, const char *, const coding_bits *, const conv_list *, const pre_processor *); + +/* Définit les variables associées à un appel de fonction. */ +bool define_arg_list(const arg_list_t *, int, const coding_bits *, const conv_list *); + + + +#endif /* _TOOLS_ARGS_H */ diff --git a/tools/d2c/conv.c b/tools/d2c/conv.c index e103c93..9947593 100644 --- a/tools/d2c/conv.c +++ b/tools/d2c/conv.c @@ -27,127 +27,12 @@ #include <assert.h> #include <ctype.h> #include <malloc.h> -#include <regex.h> #include <stdbool.h> #include <string.h> -#include <sys/param.h> #include "helpers.h" - - - - - -/* Types d'expressions représentés */ -typedef enum _ConvExprType -{ - CET_NAME, /* Désignation de variable */ - CET_NUMBER, /* Valeur codée en dur */ - CET_COMPOSED, /* Agrégat de champs divers */ - CET_UNARY, /* Opération unaire */ - CET_BINARY, /* Opération binaire */ - - CET_COUNT - -} ConvExprType; - - -/* Représentation d'une expression de conversion */ -struct _conv_expr_t -{ - ConvExprType type; - - bool declared; /* Expression déjà déclarée ? */ - bool defined; /* Expression déjà définie ? */ - - union - { - /* CET_NAME */ - char *name; /* Désignation de variable */ - - /* CET_NUMBER */ - unsigned long number; /* Valeur durablement définie */ - - /* CET_COMPOSED */ - struct - { - char **comp_items; /* Elements à agréger */ - size_t comp_count; /* Quantité de ces éléments */ - }; - - /* CET_UNARY */ - struct - { - conv_expr_t *un_expr; /* Expression à traiter */ - ConvUnaryOperation un_op; /* Type d'opération à mener */ - - }; - - /* CET_BINARY */ - struct - { - conv_expr_t *bin_expr1; /* Expression à traiter */ - conv_expr_t *bin_expr2; /* Expression à traiter */ - ConvBinaryOperation bin_op; /* Type d'opération à mener */ - - }; - - }; - -}; - - -/* Visite une expression en traitant en premier ses composantes. */ -typedef bool (* visit_expr_fc) (conv_expr_t *, int, const coding_bits *, const conv_list *, void *); - - -/* Détermine la taille en bits d'une expression donnée. */ -static bool compute_conv_expr_size(const conv_expr_t *, const coding_bits *, const conv_list *, unsigned int *); - -/* Visite une expression en traitant en premier ses composantes. */ -static bool visit_conv_expr(conv_expr_t *, visit_expr_fc, int, const coding_bits *, const conv_list *, void *); - -/* Retrouve si elle existe une variable manipulée. */ -static bool find_var_by_name(const coding_bits *, const conv_list *, const char *, raw_bitfield **, conv_func **); - -/* S'assure du marquage des expressions pre-requises. */ -static bool ensure_conv_expr_content_fully_marked(conv_expr_t *, const coding_bits *, const conv_list *); - -/* S'assure de la déclaration des expressions pre-requises. */ -static bool ensure_conv_expr_content_fully_declared(conv_expr_t *, int, const coding_bits *, const conv_list *, unsigned int); - -/* S'assure de la définition des expressions pre-requises. */ -static bool ensure_conv_expr_content_fully_defined(conv_expr_t *, int, const char *, const coding_bits *, const conv_list *, const pre_processor *); - -/* Définit une expression utilisée dans une conversion. */ -static bool define_conv_expr(conv_expr_t *, int, const coding_bits *, const conv_list *); - - - -/* ------------------------ LISTES D'ARGUMENTS DE CONVERSION ------------------------ */ - - -/* Liste d'expressions utilisées en arguments de conversion */ -struct _conv_arg_list_t -{ - conv_expr_t **items; /* Liste d'expressions */ - size_t count; /* Taille de cette liste */ - -}; - - -/* S'assure du marquage des expressions pre-requises. */ -static bool ensure_arg_list_content_fully_marked(conv_arg_list_t *, const coding_bits *, const conv_list *); - -/* S'assure de la déclaration des expressions pre-requises. */ -static bool ensure_arg_list_content_fully_declared(conv_arg_list_t *, int, const coding_bits *, const conv_list *, unsigned int); - -/* S'assure de la définition des expressions pre-requises. */ -static bool ensure_arg_list_content_fully_defined(conv_arg_list_t *, int, const char *, const coding_bits *, const conv_list *, const pre_processor *); - -/* Définit les variables associées à un appel de fonction. */ -static bool define_arg_list(conv_arg_list_t *, int, const coding_bits *, const conv_list *); +#include "qckcall.h" @@ -166,12 +51,12 @@ struct _conv_func union { - conv_expr_t *expr; /* Valeur expressive directe */ + arg_expr_t *expr; /* Valeur expressive directe */ struct { char *name; /* Fonction de conversion */ - conv_arg_list_t *args; /* Liste des arguments */ + arg_list_t *args; /* Liste des arguments */ }; @@ -180,20 +65,6 @@ struct _conv_func }; -/* Détermine la taille en bits du résultat d'une fonction. */ -static bool compute_conv_func_size(const conv_func *, const coding_bits *, const conv_list *, unsigned int *); - - - - - - -#define delete_conv_expr(e) - - - - - /* ---------------------------- ENSEMBLES DE CONVERSIONS ---------------------------- */ @@ -208,986 +79,6 @@ struct _conv_list - - - - - - - - - -/****************************************************************************** -* * -* Paramètres : name = désignation d'une variable quelconque. * -* * -* Description : Référence une variable en tant qu'expression de conversion. * -* * -* Retour : Nouvelle expression mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -conv_expr_t *build_conv_expr_from_name(char *name) -{ - conv_expr_t *result; /* Structure à retourner */ - - result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t)); - - result->type = CET_NAME; - - result->name = make_string_lower(name); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : number = valeur à conserver dans sa forme brute. * -* * -* Description : Conserve une valeur en tant qu'expression de conversion. * -* * -* Retour : Nouvelle expression mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -conv_expr_t *build_conv_expr_from_number(unsigned long number) -{ - conv_expr_t *result; /* Structure à retourner */ - - result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t)); - - result->type = CET_NUMBER; - - result->number = number; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : item1 = premier élément à agréger. * -* item2 = second élément à agréger. * -* * -* Description : Construit une base d'expression de conversion composée. * -* * -* Retour : Nouvelle expression mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -conv_expr_t *build_composed_conv_expr(char *item1, char *item2) -{ - conv_expr_t *result; /* Structure à retourner */ - - result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t)); - - result->type = CET_COMPOSED; - - result->comp_items = (char **)calloc(2, sizeof(char *)); - result->comp_count = 2; - - result->comp_items[0] = make_string_lower(item1); - result->comp_items[1] = make_string_lower(item2); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : expr = expression déjà en place à compléter. * -* item = nouvel élément à agréger. * -* * -* Description : Etend une base d'expression de conversion composée. * -* * -* Retour : Expression en place et mise à jour. * -* * -* Remarques : - * -* * -******************************************************************************/ - -conv_expr_t *extend_composed_conv_expr(conv_expr_t *expr, char *item) -{ - assert(expr->type == CET_COMPOSED); - - expr->comp_items = (char **)realloc(expr->comp_items, ++expr->comp_count * sizeof(char *)); - - expr->comp_items[expr->comp_count - 1] = make_string_lower(item); - - return expr; - -} - - -/****************************************************************************** -* * -* Paramètres : expr = expression à encapsuler. * -* op = opération unaire à associer à l'opération. * -* * -* Description : Traduit une opération unaire sur expression de conversion. * -* * -* Retour : Nouvelle expression mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -conv_expr_t *build_unary_conv_expr(conv_expr_t *expr, ConvUnaryOperation op) -{ - conv_expr_t *result; /* Structure à retourner */ - - result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t)); - - result->type = CET_UNARY; - - result->un_expr = expr; - result->un_op = op; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : expr1 = première expression à encapsuler. * -* expr2 = seconde expression à encapsuler. * -* op = opération binaire à associer à l'opération. * -* * -* Description : Traduit une opération binaire sur expression de conversion. * -* * -* Retour : Nouvelle expression mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -conv_expr_t *build_binary_conv_expr(conv_expr_t *expr1, conv_expr_t *expr2, ConvBinaryOperation op) -{ - conv_expr_t *result; /* Structure à retourner */ - - result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t)); - - result->type = CET_BINARY; - - result->bin_expr1 = expr1; - result->bin_expr2 = expr2; - result->bin_op = op; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : expr = première expression à consulter. * -* bits = gestionnaire des bits d'encodage. * -* list = liste de l'ensemble des fonctions de conversion. * -* size = taille déterminée avec précision. [OUT] * -* * -* Description : Détermine la taille en bits d'une expression donnée. * -* * -* Retour : true si la taille a pu être déterminée, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool compute_conv_expr_size(const conv_expr_t *expr, const coding_bits *bits, const conv_list *list, unsigned int *size) -{ - bool result; /* Bilan à retourner */ - raw_bitfield *field; /* Eventuel champ brut associé */ - conv_func *func; /* Eventuelle fonction liée */ - size_t i; /* Boucle de parcours */ - unsigned int tmp; /* Stockage temporaire */ - - switch (expr->type) - { - case CET_NAME: - - result = find_var_by_name(bits, list, expr->name, &field, &func); - - if (result) - { - if (field != NULL) - *size = get_raw_bitfield_length(field); - else - result = compute_conv_func_size(func, bits, list, size); - } - - break; - - case CET_COMPOSED: - - result = true; - *size = 0; - - for (i = 0; i < expr->comp_count && result; i++) - { - if (isdigit(expr->comp_items[i][0])) - *size += strlen(expr->comp_items[i]); - - else - { - if (!find_var_by_name(bits, list, expr->comp_items[i], &field, &func)) - result = false; - - else - { - if (field != NULL) - *size += get_raw_bitfield_length(field); - else - { - result = compute_conv_func_size(func, bits, list, &tmp); - *size += tmp; - } - } - - } - - } - - break; - - case CET_UNARY: - result = compute_conv_expr_size(expr->un_expr, bits, list, size); - break; - - case CET_BINARY: - - result = compute_conv_expr_size(expr->bin_expr1, bits, list, &tmp); - - if (result) - result = compute_conv_expr_size(expr->bin_expr1, bits, list, size); - - if (tmp > *size) *size = tmp; - - break; - - default: - result = false; - break; - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : expr = première expression à encapsuler. * -* fd = descripteur d'un flux ouvert en écriture. * -* bits = gestionnaire des bits d'encodage. * -* list = liste de l'ensemble des fonctions de conversion. * -* data = éventuelle donnée à transmettre à chaque visite. * -* * -* Description : Visite une expression en traitant en premier ses composantes.* -* * -* Retour : Bilan des traitements effectués. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool visit_conv_expr(conv_expr_t *expr, visit_expr_fc visit, int fd, const coding_bits *bits, const conv_list *list, void *data) -{ - bool result; /* Bilan à retourner */ - - switch (expr->type) - { - case CET_UNARY: - result = visit_conv_expr(expr->un_expr, visit, fd, bits, list, data); - break; - - case CET_BINARY: - result = visit_conv_expr(expr->bin_expr1, visit, fd, bits, list, data); - result = visit_conv_expr(expr->bin_expr2, visit, fd, bits, list, data); - break; - - default: - result = true; - break; - - } - - result &= visit(expr, fd, bits, list, data); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : bits = gestionnaire des bits d'encodage. * -* list = liste de l'ensemble des fonctions de conversion. * -* name = déssignation de la variable recherchée. * -* field = éventuel élement brut de décodage. * -* func = éventuelle fonction de conversion pour intermédiaire.* -* * -* Description : Retrouve si elle existe une variable manipulée. * -* * -* Retour : Bilan des recherches : trouvaille ou non ? * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool find_var_by_name(const coding_bits *bits, const conv_list *list, const char *name, raw_bitfield **field, conv_func **func) -{ - bool result; /* Bilan à retourner */ - raw_bitfield *cached_field; /* Champ, version cachée */ - conv_func *cached_func; /* Fonction, version cachée */ - - cached_field = find_named_field_in_bits(bits, name); - result = (cached_field != NULL); - - if (!result) - { - cached_func = find_named_conv_in_list(list, name); - result = (cached_func != NULL); - } - else - cached_func = NULL; - - if (field != NULL) *field = cached_field; - if (func != NULL) *func = cached_func; - - if (!result) - fprintf(stderr, "Variable '%s' not found!\n", name); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : expr = première expression à encapsuler. * -* bits = gestionnaire des bits d'encodage. * -* list = liste de l'ensemble des fonctions de conversion. * -* * -* Description : S'assure du marquage des expressions pre-requises. * -* * -* Retour : Bilan des traitements effectués. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool ensure_conv_expr_content_fully_marked(conv_expr_t *expr, const coding_bits *bits, const conv_list *list) -{ - bool mark_sub_expr(conv_expr_t *sub, int dummy, const coding_bits *bts, const conv_list *lst, void *unused) - { - bool result; /* Bilan à retourner */ - size_t i; /* Boucle de parcours */ - - bool mark_by_name(const coding_bits *_bts, const conv_list *_lst, const char *name) - { - bool found; /* Bilan d'opération à renvoyer*/ - raw_bitfield *field; /* Eventuel champ brut associé */ - conv_func *func; /* Eventuelle fonction liée */ - - found = find_var_by_name(bts, lst, name, &field, &func); - - if (found) - { - if (field != NULL) - mark_raw_bitfield_as_used(field); - else /*if (func != NULL) */ - mark_conv_func(func, bts, lst); - - printf(" VAR '%s' found (bf=%d fc=%d)\n", name, !!field, !!func); - - - } - else printf(" VAR '%s' not found...\n", name); - - return found; - - } - - /* Il est uniquement nécessaire de s'attacher aux références */ - switch (sub->type) - { - case CET_NAME: - result = mark_by_name(bits, lst, sub->name); - break; - - case CET_COMPOSED: - result = true; - for (i = 0; i < sub->comp_count && result; i++) - if (!isdigit(sub->comp_items[i][0])) - result = mark_by_name(bits, lst, sub->comp_items[i]); - break; - - default: - result = true; - break; - - } - - return result; - - } - - return visit_conv_expr(expr, (visit_expr_fc)mark_sub_expr, -1, bits, list, NULL); - -} - - -/****************************************************************************** -* * -* Paramètres : expr = première expression à encapsuler. * -* fd = descripteur d'un flux ouvert en écriture. * -* arch = architecture visée par l'opération globale. * -* bits = gestionnaire des bits d'encodage. * -* list = liste de l'ensemble des fonctions de conversion. * -* wide = taille des mots décodés. * -* * -* Description : S'assure de la déclaration des expressions pre-requises. * -* * -* Retour : Bilan des traitements effectués. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool ensure_conv_expr_content_fully_declared(conv_expr_t *expr, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide) -{ - bool declare_sub_expr(conv_expr_t *sub, int f, const coding_bits *bts, const conv_list *lst, unsigned int *wide) - { - bool result; /* Bilan à retourner */ - size_t i; /* Boucle de parcours */ - - /* Si l'expression a déjà été définie lors d'un précédent besoin... */ - printf(" sub declared ? %d -- type = %d\n", sub->declared, sub->type); - if (sub->declared) return true; - - bool declare_by_name(int _f, const coding_bits *_bts, const conv_list *_lst, unsigned int _wide, const char *name) - { - bool found; /* Bilan d'opération à renvoyer*/ - conv_func *func; /* Eventuelle fonction liée */ - - found = find_var_by_name(bts, lst, name, NULL, &func); - - if (found && func != NULL) - { - if (func->is_expr) - dprintf(_f, "\t\tuint%u_t val_%s;\n", _wide, name); - else - dprintf(_f, "\t\tGArchOperand *val_%s;\n", name); - - printf("========= DECLARE for '%s'\n", name); - found = declare_conv_func(func, _f, _bts, _lst, _wide); - printf("========= END DECLARE for '%s'\n", name); - } - - return found; - - } - - /* Il est uniquement nécessaire de s'attacher aux références */ - switch (sub->type) - { - case CET_NAME: - result = declare_by_name(f, bits, lst, *wide, sub->name); - break; - - case CET_COMPOSED: - result = true; - for (i = 0; i < sub->comp_count && result; i++) - if (!isdigit(sub->comp_items[i][0])) - printf("... trying to declare... '%s'\n", sub->comp_items[i]); - for (i = 0; i < sub->comp_count && result; i++) - if (!isdigit(sub->comp_items[i][0])) - result = declare_by_name(f, bits, lst, *wide, sub->comp_items[i]); - break; - - default: - result = true; - break; - - } - - sub->declared = result; - - return result; - - } - - return visit_conv_expr(expr, (visit_expr_fc)declare_sub_expr, fd, bits, list, &wide); - -} - - -/****************************************************************************** -* * -* Paramètres : expr = première expression à encapsuler. * -* fd = descripteur d'un flux ouvert en écriture. * -* arch = architecture visée par l'opération globale. * -* 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 : S'assure de la définition des expressions pre-requises. * -* * -* Retour : Bilan des traitements effectués. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool ensure_conv_expr_content_fully_defined(conv_expr_t *expr, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp) -{ - typedef struct _def_info - { - const char *arch; - const pre_processor *pp; - - } def_info; - - def_info info; /* Transmissions au visiteur */ - - bool define_sub_expr(conv_expr_t *sub, int f, const coding_bits *bts, const conv_list *lst, def_info *info) - { - bool result; /* Bilan à retourner */ - size_t i; /* Boucle de parcours */ - - /* Si l'expression a déjà été définie lors d'un précédent besoin... */ - if (sub->defined) return true; - - bool define_by_name(int _f, const coding_bits *_bts, const conv_list *_lst, def_info *_info, const char *name) - { - bool found; /* Bilan d'opération à renvoyer*/ - conv_func *func; /* Eventuelle fonction liée */ - - found = find_var_by_name(bts, lst, name, NULL, &func); - - if (found && func != NULL) - found = define_conv_func(func, false, false, _f, _info->arch, _bts, _lst, _info->pp); - - return found; - - } - - /* Il est uniquement nécessaire de s'attacher aux références */ - switch (sub->type) - { - case CET_NAME: - result = define_by_name(f, bits, lst, info, sub->name); - break; - - case CET_COMPOSED: - result = true; - for (i = 0; i < sub->comp_count && result; i++) - if (!isdigit(sub->comp_items[i][0])) - result = define_by_name(f, bits, lst, info, sub->comp_items[i]); - break; - - default: - result = true; - break; - - } - - sub->defined = result; - - return result; - - } - - info.arch = arch; - info.pp = pp; - - return visit_conv_expr(expr, (visit_expr_fc)define_sub_expr, fd, bits, list, &info); - -} - - -/****************************************************************************** -* * -* Paramètres : expr = première expression à encapsuler. * -* fd = descripteur d'un flux ouvert en écriture. * -* bits = gestionnaire des bits d'encodage. * -* list = liste de l'ensemble des fonctions de conversion. * -* * -* Description : Définit une expression utilisée dans une conversion. * -* * -* Retour : Bilan des traitements effectués. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool define_conv_expr(conv_expr_t *expr, int fd, const coding_bits *bits, const conv_list *list) -{ - bool result; /* Bilan à retourner */ - raw_bitfield *field; /* Eventuel champ brut associé */ - conv_func *func; /* Eventuelle fonction liée */ - unsigned int max_size; /* Quantité de bits totale */ - size_t i; /* Boucle de parcours */ - const char *cname; /* Raccourci de confort */ - unsigned int used_size; /* Quantité de bits utilisée */ - - result = true; - - switch (expr->type) - { - case CET_NAME: - - if (!find_var_by_name(bits, list, expr->name, &field, &func)) - result = false; - - else - { - if (field != NULL) - dprintf(fd, "raw_%s", expr->name); - else - dprintf(fd, "val_%s", expr->name); - } - - break; - - case CET_NUMBER: - dprintf(fd, "%lu", expr->number); - break; - - case CET_COMPOSED: - - result = compute_conv_expr_size(expr, bits, list, &max_size); - - printf("MAX SIZE :: %u\n", max_size); - - for (i = 0; i < expr->comp_count && result; i++) - { - cname = expr->comp_items[i]; - - if (i > 0) - dprintf(fd, " | "); - - /* Constante binaire ? */ - if (isdigit(cname[0])) - { - max_size -= strlen(cname); - - if (max_size == 0) - dprintf(fd, "b%s", cname); - else - dprintf(fd, "b%s << %u", cname, max_size); - - } - - /* Ou variable définie ? */ - else - { - result = find_var_by_name(bits, list, cname, &field, &func); - - if (result) - { - if (field != NULL) - used_size = get_raw_bitfield_length(field); - else - /*result = */compute_conv_func_size(func, bits, list, &used_size); - - max_size -= used_size; - - if (field != NULL) - { - if (max_size == 0) - dprintf(fd, "raw_%s", cname); - else - dprintf(fd, "raw_%s << %u", cname, max_size); - } - else - { - if (max_size == 0) - dprintf(fd, "val_%s", cname); - else - dprintf(fd, "val_%s << %u", cname, max_size); - } - - } - - } - - } - - break; - - case CET_UNARY: - - switch (expr->un_op) - { - case CUO_NOT: - dprintf(fd, "!"); - break; - default: - result = false; - break; - } - - result &= define_conv_expr(expr->un_expr, fd, bits, list); - - break; - - case CET_BINARY: - - dprintf(fd, "("); - - result = define_conv_expr(expr->bin_expr1, fd, bits, list); - - switch (expr->bin_op) - { - case CBO_EOR: - dprintf(fd, " ^ "); - break; - default: - result = false; - break; - } - - result &= define_conv_expr(expr->bin_expr2, fd, bits, list); - - dprintf(fd, ")"); - - break; - - default: - result = false; - break; - - } - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* LISTES D'ARGUMENTS DE CONVERSION */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : expr = expression initial pour constituer une liste. * -* * -* Description : Crée une liste d'arguments de conversion. * -* * -* Retour : Nouvelle structure mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -conv_arg_list_t *build_conv_arg_list(conv_expr_t *expr) -{ - conv_arg_list_t *result; /* Structure à retourner */ - - result = (conv_arg_list_t *)calloc(1, sizeof(conv_arg_list_t)); - - result->items = (conv_expr_t **)calloc(1, sizeof(conv_expr_t *)); - result->count = 1; - - result->items[0] = expr; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : list = liste d'expressions à supprimer de la mémoire. * -* * -* Description : Libère la mémoire occupée par une liste d'expressions. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void delete_conv_arg_list(conv_arg_list_t *list) -{ - size_t i; /* Boucle de parcours */ - - for (i = 0; i < list->count; i++) - delete_conv_expr(list->items[i]); - - if (list->items != NULL) - free(list->items); - - free(list); - -} - - -/****************************************************************************** -* * -* Paramètres : list = liste d'expressions à supprimer de la mémoire. [OUT] * -* expr = expression à ajouter à la liste courante. * -* * -* Description : Ajoute un élément à une liste d'arguments de conversion. * -* * -* Retour : Structure en place mise à jour. * -* * -* Remarques : - * -* * -******************************************************************************/ - -conv_arg_list_t *extend_conv_arg_list(conv_arg_list_t *list, conv_expr_t *expr) -{ - list->items = (conv_expr_t **)realloc(list->items, ++list->count * sizeof(conv_expr_t *)); - - list->items[list->count - 1] = expr; - - return list; - -} - - -/****************************************************************************** -* * -* Paramètres : args = liste d'expressions à supprimer de la mémoire. * -* bits = gestionnaire des bits d'encodage. * -* list = liste de l'ensemble des fonctions de conversion. * -* * -* Description : S'assure du marquage des expressions pre-requises. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool ensure_arg_list_content_fully_marked(conv_arg_list_t *args, const coding_bits *bits, const conv_list *list) -{ - bool result; /* Bilan à remonter */ - size_t i; /* Boucle de parcours */ - - result = true; - - for (i = 0; i < args->count && result; i++) - result = ensure_conv_expr_content_fully_marked(args->items[i], bits, list); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : args = liste d'expressions à supprimer de la mémoire. * -* fd = descripteur d'un flux ouvert en écriture. * -* bits = gestionnaire des bits d'encodage. * -* list = liste de l'ensemble des fonctions de conversion. * -* wide = taille des mots décodés. * -* * -* Description : S'assure de la déclaration des expressions pre-requises. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool ensure_arg_list_content_fully_declared(conv_arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide) -{ - bool result; /* Bilan à remonter */ - size_t i; /* Boucle de parcours */ - - result = true; - - for (i = 0; i < args->count && result; i++) - result = ensure_conv_expr_content_fully_declared(args->items[i], fd, bits, list, wide); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : args = liste d'expressions à supprimer de la mémoire. * -* fd = descripteur d'un flux ouvert en écriture. * -* arch = architecture visée par l'opération globale. * -* 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 : S'assure de la définition des expressions pre-requises. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool ensure_arg_list_content_fully_defined(conv_arg_list_t *args, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp) -{ - bool result; /* Bilan à remonter */ - size_t i; /* Boucle de parcours */ - - result = true; - - for (i = 0; i < args->count && result; i++) - result = ensure_conv_expr_content_fully_defined(args->items[i], fd, arch, bits, list, pp); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : args = liste d'expressions à supprimer de la mémoire. * -* fd = descripteur d'un flux ouvert en écriture. * -* bits = gestionnaire des bits d'encodage. * -* list = liste de l'ensemble des fonctions de conversion. * -* * -* Description : Définit les variables associées à un appel de fonction. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool define_arg_list(conv_arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list) -{ - bool result; /* Bilan à remonter */ - size_t i; /* Boucle de parcours */ - - result = true; - - for (i = 0; i < args->count && result; i++) - { - if (i > 0) dprintf(fd, ", "); - result = define_conv_expr(args->items[i], fd, bits, list); - } - - return result; - -} - - - /* ---------------------------------------------------------------------------------- */ /* CONVERSION DES ARGUMENTS */ /* ---------------------------------------------------------------------------------- */ @@ -1206,7 +97,7 @@ static bool define_arg_list(conv_arg_list_t *args, int fd, const coding_bits *bi * * ******************************************************************************/ -conv_func *make_conv_from_expr(char *dest, conv_expr_t *expr) +conv_func *make_conv_from_expr(char *dest, arg_expr_t *expr) { conv_func *result; /* Conversion à retourner */ @@ -1236,7 +127,7 @@ conv_func *make_conv_from_expr(char *dest, conv_expr_t *expr) * * ******************************************************************************/ -conv_func *make_conv_from_func(char *dest, char *func, conv_arg_list_t *args) +conv_func *make_conv_from_func(char *dest, char *func, arg_list_t *args) { conv_func *result; /* Conversion à retourner */ @@ -1268,12 +159,12 @@ conv_func *make_conv_from_func(char *dest, char *func, conv_arg_list_t *args) void delete_conv_func(conv_func *func) { if (func->is_expr) - delete_conv_expr(func->expr); + delete_arg_expr(func->expr); else { free(func->name); - delete_conv_arg_list(func->args); + delete_arg_list(func->args); } free(func); @@ -1303,6 +194,25 @@ const char *get_conv_dest_name(const conv_func *func) /****************************************************************************** * * * Paramètres : func = fonction de conversion à consulter. * +* * +* Description : Indique la nature d'une conversion : fonction ou expression ?* +* * +* Retour : Indication sur la constitution interne de la conversion. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool is_conv_func_expression(const conv_func *func) +{ + return func->is_expr; + +} + + +/****************************************************************************** +* * +* Paramètres : func = fonction de conversion à consulter. * * bits = gestionnaire des bits d'encodage. * * list = liste de l'ensemble des fonctions de conversion. * * size = taille déterminée avec précision. [OUT] * @@ -1315,14 +225,14 @@ const char *get_conv_dest_name(const conv_func *func) * * ******************************************************************************/ -static bool compute_conv_func_size(const conv_func *func, const coding_bits *bits, const conv_list *list, unsigned int *size) +bool compute_conv_func_size(const conv_func *func, const coding_bits *bits, const conv_list *list, unsigned int *size) { bool result; /* Bilan à retourner */ result = func->is_expr; if (result) - result = compute_conv_expr_size(func->expr, bits, list, size); + result = compute_arg_expr_size(func->expr, bits, list, size); return result; @@ -1348,7 +258,7 @@ bool mark_conv_func(conv_func *func, const coding_bits *bits, const conv_list *l bool result; /* Bilan à remonter */ if (func->is_expr) - result = ensure_conv_expr_content_fully_marked(func->expr, bits, list); + result = ensure_arg_expr_content_fully_marked(func->expr, bits, list); else result = ensure_arg_list_content_fully_marked(func->args, bits, list); @@ -1378,11 +288,11 @@ bool declare_conv_func(conv_func *func, int fd, const coding_bits *bits, const c bool result; /* Bilan à remonter */ /* Si la fonction a déjà été définie lors d'un précédent besoin... */ - printf(" func declared ? %d\n", func->declared); if (func->declared) return true; if (func->is_expr) - result = ensure_conv_expr_content_fully_declared(func->expr, fd, bits, list, wide); + result = ensure_arg_expr_content_fully_declared(func->expr, fd, bits, list, wide); + else result = ensure_arg_list_content_fully_declared(func->args, fd, bits, list, wide); @@ -1416,17 +326,12 @@ bool define_conv_func(conv_func *func, bool last, bool internal, int fd, const c { bool result; /* Bilan à remonter */ const char *callable; /* Fonction à appeler */ - 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 */ /* Si la fonction a déjà été définie lors d'un précédent besoin... */ if (func->defined) return true; if (func->is_expr) - result = ensure_conv_expr_content_fully_defined(func->expr, fd, arch, bits, list, pp); + result = ensure_arg_expr_content_fully_defined(func->expr, fd, arch, bits, list, pp); else result = ensure_arg_list_content_fully_defined(func->args, fd, arch, bits, list, pp); @@ -1453,53 +358,7 @@ bool define_conv_func(conv_func *func, bool last, bool internal, int fd, const c { /* Si l'on doit manipuler une propriété d'instructon... */ if (internal) - { - ret = regcomp(&preg, "(g_([a-z0-9]*)_instruction)", REG_EXTENDED); - if (ret != 0) - { - fprintf(stderr, "Internal error: bad regular expression.\n"); - return false; - } - - ret = regexec(&preg, callable, sizeof(pmatch) / sizeof(regmatch_t), pmatch, 0); - if (ret == REG_NOMATCH) - { - fprintf(stderr, "Internal error: bad function for dealing wih instruction: '%s'.\n", callable); - result = false; - goto dcf_skip_internal; - } - - /** - * La variable de résultat est de type 'GArchInstruction', - * donc toute fonction différente de g_arch_instruction_*() attend un transtypage... - */ - - cmplen = MAX(strlen(arch), pmatch[2].rm_eo - pmatch[2].rm_so); - - if (strncmp("arch", &callable[pmatch[2].rm_so], cmplen) == 0) - dprintf(fd, "\t\tif (!%s(instr, ", callable); - - else - { - cast = strndup(&callable[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so); - - cast = make_string_upper(cast); - - dprintf(fd, "\t\tif (!%s(%s(instr), ", callable, cast); - - free(cast); - - } - - result &= define_arg_list(func->args, fd, bits, list); - - dprintf(fd, "))\n"); - - dcf_skip_internal: - - regfree(&preg); - - } + result = call_instr_func(callable, func->args, fd, bits, list, pp); /* Si on doit constituer un opérande à ajouter... */ else @@ -1523,7 +382,7 @@ bool define_conv_func(conv_func *func, bool last, bool internal, int fd, const c dprintf(fd, "\t\tval_%s = ", func->dest); if (func->is_expr) - result &= define_conv_expr(func->expr, fd, bits, list); + result &= define_arg_expr(func->expr, fd, bits, list); else { diff --git a/tools/d2c/conv.h b/tools/d2c/conv.h index acf007b..85c7578 100644 --- a/tools/d2c/conv.h +++ b/tools/d2c/conv.h @@ -25,88 +25,12 @@ #define _TOOLS_CONV_H -#include "bits.h" -#include "pproc.h" - - - - -/* Liste des fonctions de conversions présentes */ -typedef struct _conv_list conv_list; - - - - - - - -/* Types d'opérations unaires */ -typedef enum _ConvUnaryOperation -{ - CUO_NOT, /* NOT (booléen) */ - - CUO_COUNT - -} ConvUnaryOperation; - - - -/* Types d'opérations binaires */ -typedef enum _ConvBinaryOperation -{ - CBO_EOR, /* Ou exclusif (booléen) */ - - CBO_COUNT - -} ConvBinaryOperation; - - -/* Représentation d'une expression de conversion */ -typedef struct _conv_expr_t conv_expr_t; - - - -/* Référence une variable en tant qu'expression de conversion. */ -conv_expr_t *build_conv_expr_from_name(char *); +#include <stdbool.h> -/* Conserve une valeur en tant qu'expression de conversion. */ -conv_expr_t *build_conv_expr_from_number(unsigned long ); - -/* Construit une base d'expression de conversion composée. */ -conv_expr_t *build_composed_conv_expr(char *, char *); - -/* Etend une base d'expression de conversion composée. */ -conv_expr_t *extend_composed_conv_expr(conv_expr_t *, char *); - -/* Traduit une opération unaire sur expression de conversion. */ -conv_expr_t *build_unary_conv_expr(conv_expr_t *, ConvUnaryOperation); - -/* Traduit une opération binaire sur expression de conversion. */ -conv_expr_t *build_binary_conv_expr(conv_expr_t *, conv_expr_t *, ConvBinaryOperation); - - - - - - - - -/* ------------------------ LISTES D'ARGUMENTS DE CONVERSION ------------------------ */ - - -/* Liste d'expressions utilisées en arguments de conversion */ -typedef struct _conv_arg_list_t conv_arg_list_t; - - -/* Crée une liste d'arguments de conversion. */ -conv_arg_list_t *build_conv_arg_list(conv_expr_t *); - -/* Libère la mémoire occupée par une liste d'expressions. */ -void delete_conv_arg_list(conv_arg_list_t *); - -/* Ajoute un élément à une liste d'arguments de conversion. */ -conv_arg_list_t *extend_conv_arg_list(conv_arg_list_t *, conv_expr_t *); +#include "args.h" +#include "bits.h" +#include "pproc.h" @@ -118,10 +42,10 @@ typedef struct _conv_func conv_func; /* Définit une conversion à partir d'une simple expression. */ -conv_func *make_conv_from_expr(char *, conv_expr_t *); +conv_func *make_conv_from_expr(char *, arg_expr_t *); /* Définit une conversion à partir d'une function à appeler. */ -conv_func *make_conv_from_func(char *, char *, conv_arg_list_t *); +conv_func *make_conv_from_func(char *, char *, arg_list_t *); /* Libère de la mémoire une conversion enregistrée. */ void delete_conv_func(conv_func *); @@ -129,6 +53,12 @@ void delete_conv_func(conv_func *); /* Indique la variable de destination d'une conversion. */ const char *get_conv_dest_name(const conv_func *); +/* Indique la nature d'une conversion : fonction ou expression ? */ +bool is_conv_func_expression(const conv_func *); + +/* Détermine la taille en bits du résultat d'une fonction. */ +bool compute_conv_func_size(const conv_func *, const coding_bits *, const conv_list *, unsigned int *); + /* Marque les champs utilisés par une fonction de conversion. */ bool mark_conv_func(conv_func *, const coding_bits *, const conv_list *); @@ -143,6 +73,10 @@ bool define_conv_func(conv_func *, bool, bool, int, const char *, const coding_b /* ---------------------------- ENSEMBLES DE CONVERSIONS ---------------------------- */ +/* Liste des fonctions de conversions présentes */ +typedef struct _conv_list conv_list; + + /* Crée un nouvelle liste vierge de fonctions de conversion. */ conv_list *create_conv_list(void); diff --git a/tools/d2c/d2c_gram.y b/tools/d2c/d2c_gram.y index 12eff11..9e1e034 100644 --- a/tools/d2c/d2c_gram.y +++ b/tools/d2c/d2c_gram.y @@ -33,6 +33,7 @@ static void show_usage(const char *); #include "coder.h" #include "conv.h" +#include "helpers.h" struct action_tmp { @@ -95,13 +96,13 @@ struct action_tmp register_hook_function(__hooks, t, f); \ }) -#define add_conditional_rule_to_coder(c, e, a, d) \ +#define add_conditional_rule_to_coder(c, e, a) \ ({ \ encoding_spec *__spec; \ decoding_rules *__rules; \ __spec = get_current_encoding_spec(c); \ __rules = get_rules_in_encoding_spec(__spec); \ - register_conditional_rule(__rules, e, a, d); \ + register_conditional_rule(__rules, e, a); \ }) } @@ -115,15 +116,15 @@ struct action_tmp int integer; conv_func *subst; /* Fonction de conversion */ - conv_arg_list_t *conv_list; /* Liste d'arguments de conv. */ + arg_list_t *args; /* Liste d'arguments */ - conv_expr_t *conv; /* Expression de conversion */ + arg_expr_t *arg; /* Argument multi-usages */ ConvUnaryOperation un_op; /* Opération unaire */ ConvBinaryOperation bin_op; /* Opération bianire */ cond_expr *expr; /* Expression de déclenchement */ - struct action_tmp tmpa; /* Transfert temporaire */ + rule_action raction; /* Action et éléments associés */ } @@ -146,7 +147,7 @@ struct action_tmp %token HOOKS -%token RULES IF EXPR_START EQUAL BINVAL IMMVAL EXPR_END AND THEN SEE UNPREDICTABLE +%token RULES IF EXPR_START EQUAL BINVAL IMMVAL EXPR_END AND THEN SEE CALL UNPREDICTABLE %type <string> COPYRIGHT INS_NAME @@ -160,17 +161,17 @@ struct action_tmp %type <string> OPERAND_NAME OPERAND_INTERNAL OPERAND_VISIBLE - %type <subst> substitution -%type <conv_list> conv_arg_list -%type <conv> conv_expr conv_arg_composed -%type <un_op> conv_expr_un_op -%type <bin_op> conv_expr_bin_op -%type <string> conv_arg_field + +%type <args> arg_list +%type <arg> arg_expr arg_composed +%type <un_op> arg_expr_un_op +%type <bin_op> arg_expr_bin_op +%type <string> arg_field %type <expr> rule_cond %type <string> BINVAL IMMVAL -%type <tmpa> action +%type <raction> action %% @@ -231,28 +232,29 @@ conversions : CONV substitutions substitutions : /* empty */ | substitutions substitution { register_conversion_in_coder(coder, $2); } -substitution : NAME EQ conv_expr { $$ = make_conv_from_expr($1, $3); } - | NAME EQ NAME OP conv_arg_list CP { $$ = make_conv_from_func($1, $3, $5); } +substitution : NAME EQ arg_expr { $$ = make_conv_from_expr($1, $3); } + | NAME EQ NAME OP arg_list CP { $$ = make_conv_from_func($1, $3, $5); } + -conv_arg_list : conv_expr { $$ = build_conv_arg_list($1); } - | conv_arg_list COMMA conv_expr { $$ = extend_conv_arg_list($1, $3); printf("extend\n"); } +arg_list : arg_expr { $$ = build_arg_list($1); } + | arg_list COMMA arg_expr { $$ = extend_arg_list($1, $3); } -conv_expr : NAME { $$ = build_conv_expr_from_name($1); } - | NUMBER { $$ = build_conv_expr_from_number($1); } - | conv_arg_composed { $$ = $1; } - | OP conv_expr CP { $$ = $2; } - | conv_expr_un_op conv_expr { $$ = build_unary_conv_expr($2, $1); } - | OP conv_expr conv_expr_bin_op conv_expr CP { $$ = build_binary_conv_expr($2, $4, $3); } +arg_expr : NAME { $$ = build_arg_expr_from_name($1); } + | NUMBER { $$ = build_arg_expr_from_number($1); } + | arg_composed { $$ = $1; } + | OP arg_expr CP { $$ = $2; } + | arg_expr_un_op arg_expr { $$ = build_unary_arg_expr($2, $1); } + | OP arg_expr arg_expr_bin_op arg_expr CP { $$ = build_binary_arg_expr($2, $4, $3); } -conv_expr_un_op : NOT { $$ = CUO_NOT; } +arg_expr_un_op : NOT { $$ = CUO_NOT; } -conv_expr_bin_op : EOR { $$ = CBO_EOR; } +arg_expr_bin_op : EOR { $$ = CBO_EOR; } -conv_arg_composed : conv_arg_field COLON conv_arg_field { $$ = build_composed_conv_expr($1, $3); } - | conv_arg_composed COLON conv_arg_field { $$ = extend_composed_conv_expr($1, $3); } +arg_composed : arg_field COLON arg_field { $$ = build_composed_arg_expr($1, $3); } + | arg_composed COLON arg_field { $$ = extend_composed_arg_expr($1, $3); } -conv_arg_field : NAME { $$ = $1; printf(" composed::name '%s'\n", $1); } - | BINVAL { $$ = $1; printf(" composed::bin '%s'\n", $1); } +arg_field : NAME { $$ = $1; } + | BINVAL { $$ = $1; } hooks : HOOKS hookings @@ -268,16 +270,17 @@ rules : RULES rules_list rules_list : /* empty */ | rules_list rule -rule : IF EXPR_START rule_cond EXPR_END THEN action - { add_conditional_rule_to_coder(coder, $3, $6.action, $6.details); } +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); } | 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 { $$.action = CAT_SEE; $$.details = $2; } - | UNPREDICTABLE { $$.action = CAT_UNPREDICTABLE; $$.details = NULL; } +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; } %% diff --git a/tools/d2c/d2c_tok.l b/tools/d2c/d2c_tok.l index 8f54c8d..9689b59 100644 --- a/tools/d2c/d2c_tok.l +++ b/tools/d2c/d2c_tok.l @@ -19,7 +19,9 @@ void free_flex_memory(void) ; %option noyywrap %option nounput %option noinput -%option yylineno +%option yylineno +%option stack +%option noyy_top_state %x comments @@ -33,9 +35,11 @@ void free_flex_memory(void) ; %x conv_begin conv_content conv_arg conv_arg_binval +%x arg arg_binval + %x hooks_begin hooks_content -%x rules_begin rules_content rules_cond rules_cond_binval rules_action rules_action_see +%x rules_begin rules_content rules_cond rules_cond_binval rules_action rules_action_see rules_action_call %% @@ -127,6 +131,10 @@ void free_flex_memory(void) ; } <conv_content>"=" { return EQ; } <conv_content>"(" { BEGIN(conv_arg); return OP; } + + + + <conv_arg>[A-Za-z][A-Za-z0-9_]* { if (strcmp(yytext, "NOT") == 0) return NOT; else if (strcmp(yytext, "EOR") == 0) return EOR; @@ -147,6 +155,33 @@ void free_flex_memory(void) ; + + + + + + +<arg>[A-Za-z][A-Za-z0-9_]* { + if (strcmp(yytext, "NOT") == 0) return NOT; + else if (strcmp(yytext, "EOR") == 0) return EOR; + else + { + d2c_lval.string = strdup(yytext); + return NAME; + } + } +<arg>[0-9][0-9]* { d2c_lval.integer = atoi(yytext); return NUMBER; } +<arg>"'" { BEGIN(arg_binval); } +<arg_binval>[01][01]* { d2c_lval.string = strdup(yytext); return BINVAL; } +<arg_binval>"'" { BEGIN(arg); } +<arg>"," { return COMMA; } +<arg>":" { return COLON; } +<arg>[ ]+ { } +<arg>")" { yy_pop_state(); return CP; } + + + + <encoding_content>"@hooks" { BEGIN(hooks_begin); return HOOKS; } <hooks_begin>[ ]+ { } <hooks_begin>"{" { BEGIN(hooks_content); } @@ -165,6 +200,10 @@ void free_flex_memory(void) ; <rules_content>[ \t\n]+ { } <rules_content>"}" { BEGIN(encoding_content); } +<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>"if" { BEGIN(rules_cond); return IF; } <rules_cond>[ ]+ { } <rules_cond>"(" { return EXPR_START; } @@ -179,10 +218,18 @@ void free_flex_memory(void) ; <rules_cond>";" { BEGIN(rules_action); return THEN; } <rules_action>[ ]+ { } + <rules_action>"see " { BEGIN(rules_action_see); return SEE; } <rules_action_see>[^\n]* { d2c_lval.cstring = yytext; BEGIN(rules_content); return INS_DETAILS; } + <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); } + %% diff --git a/tools/d2c/qckcall.c b/tools/d2c/qckcall.c new file mode 100644 index 0000000..ce9a0b2 --- /dev/null +++ b/tools/d2c/qckcall.c @@ -0,0 +1,110 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * qckcall.c - appel rapide et facilité à une fonction C de Chrysalide + * + * Copyright (C) 2015 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 "qckcall.h" + + +#include <malloc.h> +#include <regex.h> +#include <string.h> +#include <sys/param.h> + + +#include "helpers.h" + + + +/****************************************************************************** +* * +* 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. * +* * +* 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 */ + 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 */ + + ret = regcomp(&preg, "(g_([a-z0-9]*)_instruction)", REG_EXTENDED); + if (ret != 0) + { + fprintf(stderr, "Internal error: bad regular expression.\n"); + return false; + } + + 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; + } + + /** + * La variable de résultat est de type 'GArchInstruction', + * donc toute fonction différente de g_arch_instruction_*() attend un transtypage... + */ + + 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); + + else + { + cast = strndup(&callee[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so); + + cast = make_string_upper(cast); + + 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 new file mode 100644 index 0000000..59d4adc --- /dev/null +++ b/tools/d2c/qckcall.h @@ -0,0 +1,44 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * qckcall.h - prototypes pour un appel rapide et facilité à une fonction C de Chrysalide + * + * Copyright (C) 2015 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_QCKCALL_H +#define _TOOLS_QCKCALL_H + + +#include <stdbool.h> + + + +#include "args.h" +#include "conv.h" +#include "bits.h" +#include "pproc.h" + + + +/* 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 *); + + + +#endif /* _TOOLS_QCKCALL_H */ diff --git a/tools/d2c/rules.c b/tools/d2c/rules.c index 73ec965..6f2e075 100644 --- a/tools/d2c/rules.c +++ b/tools/d2c/rules.c @@ -30,6 +30,7 @@ #include "helpers.h" +#include "qckcall.h" @@ -79,8 +80,7 @@ static bool write_cond_expr(const cond_expr *, int, const coding_bits *); typedef struct _extra_rule { cond_expr *expr; /* Expression de déclenchement */ - CondActionType action; /* Conséquence d'une validation*/ - char *details; /* Eventuel complément d'info. */ + rule_action action; /* Conséquence d'une validation*/ } extra_rule; @@ -320,12 +320,31 @@ decoding_rules *create_decoding_rules(void) void delete_decoding_rules(decoding_rules *rules) { size_t i; /* Boucle de parcours */ + extra_rule *rule; /* Règle à traiter */ for (i = 0; i < rules->extra_count; i++) { - delete_cond_expr(rules->extra[i].expr); - if (rules->extra[i].details) - free(rules->extra[i].details); + rule = &rules->extra[i]; + + if (rule->expr != NULL) + delete_cond_expr(rule->expr); + + switch (rule->action.type) + { + case CAT_SEE: + free(rule->action.details); + break; + + case CAT_UNPREDICTABLE: + break; + + case CAT_CALL: + free(rule->action.callee); + delete_arg_list(rule->action.args); + break; + + } + } if (rules->extra != NULL) @@ -341,7 +360,6 @@ void delete_decoding_rules(decoding_rules *rules) * Paramètres : rules = ensemble de règles à compléter. * * expr = représentation d'expression à conserver. * * action = conséquence associée à la règle. * -* details = éventuel complément d'informations. * * * * Description : Ajoute une règle complète à la définition d'un codage. * * * @@ -351,7 +369,7 @@ void delete_decoding_rules(decoding_rules *rules) * * ******************************************************************************/ -void register_conditional_rule(decoding_rules *rules, cond_expr *expr, CondActionType action, const char *details) +void register_conditional_rule(decoding_rules *rules, cond_expr *expr, const rule_action *action) { extra_rule *rule; /* Nouvelle prise en compte */ @@ -360,8 +378,7 @@ void register_conditional_rule(decoding_rules *rules, cond_expr *expr, CondActio rule = &rules->extra[rules->extra_count - 1]; rule->expr = expr; - rule->action = action; - rule->details = (details != NULL ? make_callable(details, false) : NULL); + rule->action = *action; } @@ -369,10 +386,13 @@ void register_conditional_rule(decoding_rules *rules, cond_expr *expr, CondActio /****************************************************************************** * * * Paramètres : rules = ensemble de règles à consulter. * +* filter = filtre sur les règles à effectivement imprimer. * * 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. * * bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* pp = pré-processeur pour les échanges de chaînes. * * exit = exprime le besoin d'une voie de sortie. [OUT] * * * * Description : Traduit en code les éventuelles règles présentes. * @@ -383,40 +403,39 @@ void register_conditional_rule(decoding_rules *rules, cond_expr *expr, CondActio * * ******************************************************************************/ -bool write_decoding_rules(decoding_rules *rules, int fd, const char *arch, const char *subarch, const coding_bits *bits, bool *exit) +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 char *callable; /* Fonction à appeler */ result = true; - *exit = false; - for (i = 0; i < rules->extra_count; i++) { rule = &rules->extra[i]; - dprintf(fd, "\t\tif "); + if (rule->action.type != filter) + continue; - result = write_cond_expr(rule->expr, fd, bits); - if (!result) break; + if (rule->expr != NULL) + { + dprintf(fd, "\t\tif "); - dprintf(fd, "\n"); - dprintf(fd, "\t\t{\n"); + result = write_cond_expr(rule->expr, fd, bits); + if (!result) break; - switch (rule->action) + dprintf(fd, "\n"); + dprintf(fd, "\t\t{\n"); + + } + + switch (rule->action.type) { case CAT_SEE: - if (rule->details == NULL) - { - fprintf(stderr, "Error: directive 'see' must provide additional details.\n"); - result = false; - goto wcsr_exit; - } - - dprintf(fd, "\t\t\tinstr = %s_read_%sinstr_%s", arch, subarch, rule->details); + dprintf(fd, "\t\t\tinstr = %s_read_%sinstr_%s", arch, subarch, rule->action.details); /* TODO : adapter les paramètres d'appel selon le 'coder' */ dprintf(fd, "(_raw);\n"); @@ -429,16 +448,35 @@ bool write_decoding_rules(decoding_rules *rules, int fd, const char *arch, const case CAT_UNPREDICTABLE: break; + case CAT_CALL: + + callable = find_macro(pp, rule->action.callee); + + if (callable == NULL) + callable = rule->action.callee; + + if (rule->expr != NULL) + dprintf(fd, "\t"); + + result = call_instr_func(callable, rule->action.args, fd, bits, list, pp); + + if (rule->expr != NULL) + dprintf(fd, "\t"); + + dprintf(fd, "\t\t\tgoto quick_exit;\n"); + + *exit = true; + break; + } - dprintf(fd, "\t\t}\n"); + if (rule->expr != NULL) + dprintf(fd, "\t\t}\n"); dprintf(fd, "\n"); } - wcsr_exit: - return result; } diff --git a/tools/d2c/rules.h b/tools/d2c/rules.h index af2cac5..6344828 100644 --- a/tools/d2c/rules.h +++ b/tools/d2c/rules.h @@ -25,7 +25,10 @@ #define _TOOLS_RULES_H +#include "args.h" #include "bits.h" +#include "conv.h" +#include "pproc.h" @@ -67,10 +70,33 @@ cond_expr *build_composed_cond_expression(cond_expr *, CondOpType, cond_expr *); typedef enum _CondActionType { CAT_SEE, /* Renvoi vers une instruction */ - CAT_UNPREDICTABLE /* Cas de figure improbable */ + CAT_UNPREDICTABLE, /* Cas de figure improbable */ + CAT_CALL /* Appel à une fonction C */ } CondActionType; +/* Définition d'une action de règle */ +typedef struct _rule_action +{ + CondActionType type; /* Conséquence d'une validation*/ + + union + { + /* CAT_SEE */ + char *details; /* Eventuel complément d'info. */ + + /* CAT_CALL */ + struct + { + char *callee; /* Fonction appelée */ + arg_list_t *args; /* Arguments à fournir */ + + }; + + }; + +} rule_action; + /* Règles de décodage supplémentaires */ typedef struct _decoding_rules decoding_rules; @@ -82,10 +108,10 @@ decoding_rules *create_decoding_rules(void); void delete_decoding_rules(decoding_rules *); /* Ajoute une règle complète à la définition d'un codage. */ -void register_conditional_rule(decoding_rules *, cond_expr *, CondActionType, const char *); +void register_conditional_rule(decoding_rules *, cond_expr *, const rule_action *); /* Traduit en code les éventuelles règles présentes. */ -bool write_decoding_rules(decoding_rules *, int, const char *, const char *, const coding_bits *, bool *); +bool write_decoding_rules(decoding_rules *, CondActionType, int, const char *, const char *, const coding_bits *, const conv_list *, const pre_processor *, bool *); diff --git a/tools/d2c/spec.c b/tools/d2c/spec.c index b56c6aa..9d4447d 100644 --- a/tools/d2c/spec.c +++ b/tools/d2c/spec.c @@ -304,7 +304,13 @@ bool write_encoding_spec_disass(const encoding_spec *spec, int fd, const char *a /* Inclusion des éventuelles règles */ - result &= write_decoding_rules(spec->rules, fd, arch, subarch, spec->bits, &exit); + exit = false; + + result &= write_decoding_rules(spec->rules, CAT_SEE, + fd, arch, subarch, spec->bits, spec->conversions, pp, &exit); + + result &= write_decoding_rules(spec->rules, CAT_UNPREDICTABLE, + fd, arch, subarch, spec->bits, spec->conversions, pp, &exit); /* Création de l'instruction en elle-même */ @@ -314,10 +320,13 @@ bool write_encoding_spec_disass(const encoding_spec *spec, int fd, const char *a dprintf(fd, "\n"); - /* Inscriptions des éventuelles fonctions à lier */ + /* Inscriptions des éventuelles fonctions ou propriété à lier */ result &= write_hook_functions(spec->hooks, fd); + result &= write_decoding_rules(spec->rules, CAT_CALL, + fd, arch, subarch, spec->bits, spec->conversions, pp, &exit); + /* Création des opérandes */ result &= define_syntax_items(spec->syntax, fd, arch, spec->bits, spec->conversions, pp); |