summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2015-01-24 11:19:32 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2015-01-24 11:19:32 (GMT)
commit141d2f0fbb2ce3b4ddf85383c55b891fd59dc598 (patch)
tree085fa1a20d77f86825e1a6f4215b1ffd8fd961e8
parent3df9f6dc8548b0562312036abfbfcf9850a81041 (diff)
Introduced conditional calls in instruction definition rules.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@459 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
-rw-r--r--ChangeLog82
-rw-r--r--src/analysis/disass/area.c116
-rw-r--r--src/analysis/disass/fetch.c17
-rw-r--r--src/arch/arm/v456/instruction.c2
-rw-r--r--src/arch/arm/v7/context.c48
-rw-r--r--src/arch/arm/v7/context.h15
-rw-r--r--src/arch/arm/v7/link.c242
-rw-r--r--src/arch/arm/v7/link.h33
-rw-r--r--src/arch/arm/v7/opdefs/Makefile.am1
-rw-r--r--src/arch/arm/v7/opdefs/b_A8818.d45
-rw-r--r--src/arch/arm/v7/opdefs/bl_A8825.d32
-rw-r--r--src/arch/arm/v7/opdefs/blx_A8826.d2
-rw-r--r--src/arch/arm/v7/opdefs/bx_A8827.d12
-rw-r--r--src/arch/arm/v7/opdefs/cbnz_A8829.d14
-rw-r--r--src/arch/arm/v7/opdefs/ldr_A8862.d3
-rw-r--r--src/arch/arm/v7/opdefs/ldr_A8863.d2
-rw-r--r--src/arch/arm/v7/opdefs/ldr_A8864.d32
-rw-r--r--src/arch/arm/v7/opdefs/ldr_A8865.d1
-rw-r--r--src/arch/arm/v7/opdefs/ldrb_A8867.d3
-rw-r--r--src/arch/arm/v7/post.c189
-rw-r--r--src/arch/arm/v7/post.h9
-rw-r--r--src/arch/arm/v7/processor.c7
-rw-r--r--src/arch/artificial.c23
-rw-r--r--src/arch/dalvik/instruction.c2
-rw-r--r--src/arch/instruction-int.h9
-rw-r--r--src/arch/instruction.c26
-rw-r--r--src/arch/instruction.h3
-rw-r--r--src/arch/x86/instruction.c2
-rw-r--r--tools/d2c/Makefile.am2
-rw-r--r--tools/d2c/args.c1161
-rw-r--r--tools/d2c/args.h131
-rw-r--r--tools/d2c/conv.c1209
-rw-r--r--tools/d2c/conv.h98
-rw-r--r--tools/d2c/d2c_gram.y69
-rw-r--r--tools/d2c/d2c_tok.l51
-rw-r--r--tools/d2c/qckcall.c110
-rw-r--r--tools/d2c/qckcall.h44
-rw-r--r--tools/d2c/rules.c96
-rw-r--r--tools/d2c/rules.h32
-rw-r--r--tools/d2c/spec.c13
40 files changed, 2598 insertions, 1390 deletions
diff --git a/ChangeLog b/ChangeLog
index f730ae1..68a0145 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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);