summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog34
-rw-r--r--src/arch/dalvik/dop_aget.c6
-rw-r--r--src/arch/dalvik/dop_aput.c6
-rw-r--r--src/arch/dalvik/dop_arithm.c14
-rw-r--r--src/arch/dalvik/dop_array.c4
-rw-r--r--src/arch/dalvik/dop_const.c4
-rw-r--r--src/arch/dalvik/dop_invoke.c6
-rw-r--r--src/arch/dalvik/operand.c30
-rw-r--r--src/arch/dalvik/register.c29
-rw-r--r--src/arch/dalvik/register.h3
-rw-r--r--src/arch/operand-int.h5
-rw-r--r--src/arch/operand.c27
-rw-r--r--src/arch/operand.h3
-rw-r--r--src/decomp/context.c55
-rw-r--r--src/decomp/context.h5
-rw-r--r--src/decomp/expr/pseudo.c30
-rw-r--r--src/decomp/expr/pseudo.h3
-rw-r--r--src/glibext/Makefile.am1
-rw-r--r--src/glibext/gnhash.c52
-rw-r--r--src/glibext/gnhash.h37
20 files changed, 329 insertions, 25 deletions
diff --git a/ChangeLog b/ChangeLog
index 36113dc..aca1f7a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,37 @@
+10-11-12 Cyrille Bagard <nocbos@gmail.com>
+
+ * src/arch/dalvik/dop_aget.c:
+ * src/arch/dalvik/dop_aput.c:
+ * src/arch/dalvik/dop_arithm.c:
+ * src/arch/dalvik/dop_array.c:
+ * src/arch/dalvik/dop_const.c:
+ * src/arch/dalvik/dop_invoke.c:
+ Update code using pseudo registers.
+
+ * src/arch/dalvik/operand.c:
+ * src/arch/dalvik/register.c:
+ * src/arch/dalvik/register.h:
+ * src/arch/operand.c:
+ * src/arch/operand.h:
+ * src/arch/operand-int.h:
+ Add comparison methods to operands for being able to use them as keys
+ with the GLib maps.
+
+ * src/decomp/context.c:
+ * src/decomp/context.h:
+ Properly register pseudo registers.
+
+ * src/decomp/expr/pseudo.c:
+ * src/decomp/expr/pseudo.h:
+ Change the display of theses registers by using an index.
+
+ * src/glibext/gnhash.c:
+ * src/glibext/gnhash.h:
+ New entries: provide a new hash function for the GLib.
+
+ * src/glibext/Makefile.am:
+ Add the gnhash.[ch] files to libglibext_la_SOURCES.
+
10-11-11 Cyrille Bagard <nocbos@gmail.com>
* configure.ac:
diff --git a/src/arch/dalvik/dop_aget.c b/src/arch/dalvik/dop_aget.c
index 77e6ef2..5ea57cc 100644
--- a/src/arch/dalvik/dop_aget.c
+++ b/src/arch/dalvik/dop_aget.c
@@ -52,13 +52,13 @@ GDecInstruction *dalvik_decomp_instr_aget(const GArchInstruction *instr, GDecCon
GDecInstruction *access; /* Représentation de l'accès */
operand = g_arch_instruction_get_operand(instr, 0);
- content = g_pseudo_register_new();
+ content = g_dec_context_convert_register(ctx, operand);
operand = g_arch_instruction_get_operand(instr, 1);
- array = g_pseudo_register_new();
+ array = g_dec_context_convert_register(ctx, operand);
operand = g_arch_instruction_get_operand(instr, 2);
- index = g_pseudo_register_new();
+ index = g_dec_context_convert_register(ctx, operand);
access = g_array_access_new(G_DEC_EXPRESSION(array), G_DEC_EXPRESSION(index));
result = g_assign_expression_new(G_DEC_EXPRESSION(content), G_DEC_EXPRESSION(access));
diff --git a/src/arch/dalvik/dop_aput.c b/src/arch/dalvik/dop_aput.c
index 2e4527e..3b75667 100644
--- a/src/arch/dalvik/dop_aput.c
+++ b/src/arch/dalvik/dop_aput.c
@@ -52,13 +52,13 @@ GDecInstruction *dalvik_decomp_instr_aput(const GArchInstruction *instr, GDecCon
GDecInstruction *access; /* Représentation de l'accès */
operand = g_arch_instruction_get_operand(instr, 0);
- content = g_pseudo_register_new();
+ content = g_dec_context_convert_register(ctx, operand);
operand = g_arch_instruction_get_operand(instr, 1);
- array = g_pseudo_register_new();
+ array = g_dec_context_convert_register(ctx, operand);
operand = g_arch_instruction_get_operand(instr, 2);
- index = g_pseudo_register_new();
+ index = g_dec_context_convert_register(ctx, operand);
access = g_array_access_new(G_DEC_EXPRESSION(array), G_DEC_EXPRESSION(index));
result = g_assign_expression_new(G_DEC_EXPRESSION(access), G_DEC_EXPRESSION(content));
diff --git a/src/arch/dalvik/dop_arithm.c b/src/arch/dalvik/dop_arithm.c
index 388f906..7657f99 100644
--- a/src/arch/dalvik/dop_arithm.c
+++ b/src/arch/dalvik/dop_arithm.c
@@ -51,7 +51,6 @@ GDecInstruction *dalvik_decomp_instr_arithm_2addr(const GArchInstruction *instr,
GArchOperand *operand; /* Opérande de l'instruction */
GDecInstruction *dest; /* Enregistrement du résultat */
GDecInstruction *op1; /* Premier opérande utilisé */
- GDecInstruction *op2; /* Second opérande utilisé */
GDecInstruction *arithm; /* Opération arithmétique */
switch (g_dalvik_instruction_get_opcode(G_DALVIK_INSTRUCTION(instr)))
@@ -84,15 +83,12 @@ GDecInstruction *dalvik_decomp_instr_arithm_2addr(const GArchInstruction *instr,
}
operand = g_arch_instruction_get_operand(instr, 0);
- dest = g_pseudo_register_new();
+ dest = g_dec_context_convert_register(ctx, operand);
operand = g_arch_instruction_get_operand(instr, 1);
- op1 = g_pseudo_register_new();
-
- operand = g_arch_instruction_get_operand(instr, 2);
- op2 = g_pseudo_register_new();
+ op1 = g_dec_context_convert_register(ctx, operand);
- arithm = g_arithm_expression_new(G_DEC_EXPRESSION(op1), type, G_DEC_EXPRESSION(op2));
+ arithm = g_arithm_expression_new(G_DEC_EXPRESSION(dest), type, G_DEC_EXPRESSION(op1));
result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(arithm));
return result;
@@ -159,10 +155,10 @@ GDecInstruction *dalvik_decomp_instr_arithm_lit(const GArchInstruction *instr, G
}
operand = g_arch_instruction_get_operand(instr, 0);
- dest = g_pseudo_register_new();
+ dest = g_dec_context_convert_register(ctx, operand);
operand = g_arch_instruction_get_operand(instr, 1);
- op1 = g_pseudo_register_new();
+ op1 = g_dec_context_convert_register(ctx, operand);
operand = g_arch_instruction_get_operand(instr, 2);
op2 = g_imm_expression_new(G_IMM_OPERAND(operand));
diff --git a/src/arch/dalvik/dop_array.c b/src/arch/dalvik/dop_array.c
index 035b3eb..fa9f94f 100644
--- a/src/arch/dalvik/dop_array.c
+++ b/src/arch/dalvik/dop_array.c
@@ -60,11 +60,11 @@ GDecInstruction *dalvik_decomp_instr_array_length(const GArchInstruction *instr,
operand = g_arch_instruction_get_operand(instr, 1);
- reg = g_pseudo_register_new();
+ reg = g_dec_context_convert_register(ctx, operand);
len = g_dalvik_alength_new(G_DEC_EXPRESSION(reg));
operand = g_arch_instruction_get_operand(instr, 0);
- reg = g_pseudo_register_new();
+ reg = g_dec_context_convert_register(ctx, operand);
result = g_assign_expression_new(G_DEC_EXPRESSION(reg), G_DEC_EXPRESSION(len));
diff --git a/src/arch/dalvik/dop_const.c b/src/arch/dalvik/dop_const.c
index eab7acd..ea88089 100644
--- a/src/arch/dalvik/dop_const.c
+++ b/src/arch/dalvik/dop_const.c
@@ -59,8 +59,8 @@ GDecInstruction *dalvik_decomp_instr_const(const GArchInstruction *instr, GDecCo
- operand = g_arch_instruction_get_operand(instr, 1);
- reg = g_pseudo_register_new();
+ operand = g_arch_instruction_get_operand(instr, 0);
+ reg = g_dec_context_convert_register(ctx, operand);
operand = g_arch_instruction_get_operand(instr, 1);
imm = g_imm_expression_new(G_IMM_OPERAND(operand));
diff --git a/src/arch/dalvik/dop_invoke.c b/src/arch/dalvik/dop_invoke.c
index e4fa1fb..6fdca06 100644
--- a/src/arch/dalvik/dop_invoke.c
+++ b/src/arch/dalvik/dop_invoke.c
@@ -117,7 +117,7 @@ GDecInstruction *dalvik_decomp_instr_invoke_virtual(const GArchInstruction *inst
//GDecInstruction *g_routine_call_new(GBinRoutine *routine, bool is_object)
/*
operand = g_arch_instruction_get_operand(instr, 1);
- reg = g_pseudo_register_new();
+ reg = g_dec_context_convert_register(ctx, operand);
operand = g_arch_instruction_get_operand(instr, 1);
imm = g_imm_expression_new(G_IMM_OPERAND(operand));
@@ -141,8 +141,8 @@ GDecInstruction *dalvik_decomp_instr_invoke_virtual(const GArchInstruction *inst
{
case DOP_MOVE_RESULT:
- operand = g_arch_instruction_get_operand(instr, 0);
- reg = g_pseudo_register_new();
+ operand = g_arch_instruction_get_operand(iter, 0);
+ reg = g_dec_context_convert_register(ctx, operand);
result = g_assign_expression_new(G_DEC_EXPRESSION(reg), G_DEC_EXPRESSION(result));
diff --git a/src/arch/dalvik/operand.c b/src/arch/dalvik/operand.c
index 9c4a2c2..3227184 100644
--- a/src/arch/dalvik/operand.c
+++ b/src/arch/dalvik/operand.c
@@ -87,6 +87,9 @@ static void g_dalvik_register_operand_class_init(GDalvikRegisterOperandClass *);
/* Initialise une instance d'opérande de registre Dalvik. */
static void g_dalvik_register_operand_init(GDalvikRegisterOperand *);
+/* Compare un opérande avec un autre. */
+static bool g_dalvik_register_operand_compare(const GDalvikRegisterOperand *, const GDalvikRegisterOperand *);
+
/* Ajoute du texte simple à un fichier ouvert en écriture. */
static void g_dalvik_register_operand_add_text(const GDalvikRegisterOperand *, GRenderingOptions *, MainRendering, FILE *);
@@ -325,13 +328,18 @@ static void g_dalvik_register_operand_class_init(GDalvikRegisterOperandClass *kl
static void g_dalvik_register_operand_init(GDalvikRegisterOperand *operand)
{
- GContentExporter *parent; /* Instance parente */
+ GContentExporter *parent; /* Instance parente #1 */
+ GArchOperand *arch; /* Instance parente #2 */
parent = G_CONTENT_EXPORTER(operand);
parent->add_text = (add_text_fc)g_dalvik_register_operand_add_text;
parent->export_buffer = (export_buffer_fc)g_dalvik_register_operand_to_buffer;
+ arch = G_ARCH_OPERAND(operand);
+
+ arch->compare = (operand_compare_fc)g_dalvik_register_operand_compare;
+
}
@@ -400,6 +408,26 @@ GArchOperand *g_dalvik_register_operand_new(const bin_t *data, off_t *pos, off_t
/******************************************************************************
* *
+* Paramètres : a = premier opérande à consulter. *
+* b = second opérande à consulter. *
+* *
+* Description : Compare un opérande avec un autre. *
+* *
+* Retour : Bilan de la comparaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_dalvik_register_operand_compare(const GDalvikRegisterOperand *a, const GDalvikRegisterOperand *b)
+{
+ return g_dalvik_register_compare(a->reg, b->reg);
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : operand = opérande à transcrire. *
* options = options de rendu. *
* rendering = support effectif final des lignes de code. *
diff --git a/src/arch/dalvik/register.c b/src/arch/dalvik/register.c
index fc7757d..dd5a512 100644
--- a/src/arch/dalvik/register.c
+++ b/src/arch/dalvik/register.c
@@ -134,6 +134,35 @@ GDalvikRegister *g_dalvik_register_new(uint16_t index)
}
+/******************************************************************************
+* *
+* Paramètres : a = premier opérande à consulter. *
+* b = second opérande à consulter. *
+* *
+* Description : Compare un registre avec un autre. *
+* *
+* Retour : Bilan de la comparaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_dalvik_register_compare(const GDalvikRegister *a, const GDalvikRegister *b)
+{
+ /* FIXME : GCC (Debian 4.4.5-4) trouble ? */
+
+ if (a == NULL)
+ printf("Alerte :: %hd & %hd\n", a->index, b->index);
+
+ /*
+ printf("Compare :: %p & %p\n", a, b);
+ printf("Compare :: %hd & %hd\n", a->index, b->index);
+ */
+
+ return (a->index == b->index);
+
+}
+
/******************************************************************************
* *
diff --git a/src/arch/dalvik/register.h b/src/arch/dalvik/register.h
index 5ac5617..7767a9b 100644
--- a/src/arch/dalvik/register.h
+++ b/src/arch/dalvik/register.h
@@ -54,6 +54,9 @@ GType g_dalvik_register_get_type(void);
/* Crée une réprésentation de registre Dalvik. */
GDalvikRegister *g_dalvik_register_new(uint16_t);
+/* Compare un registre avec un autre. */
+bool g_dalvik_register_compare(const GDalvikRegister *, const GDalvikRegister *);
+
/* Indique si le registre correspond à ebp ou similaire. */
bool g_dalvik_register_is_base_pointer(const GDalvikRegister *);
diff --git a/src/arch/operand-int.h b/src/arch/operand-int.h
index f21b995..51f392b 100644
--- a/src/arch/operand-int.h
+++ b/src/arch/operand-int.h
@@ -30,17 +30,22 @@
+/* Compare un opérande avec un autre. */
+typedef bool (* operand_compare_fc) (const GArchOperand *, const GArchOperand *);
+
/* Traduit un opérande en version humainement lisible. */
typedef char * (* get_operand_text_fc) (const GArchOperand *, const GExeFormat *, AsmSyntax);
/* Traduit un opérande en version humainement lisible. */
typedef void (* operand_print_fc) (const GArchOperand *, GBufferLine *, AsmSyntax);
+
/* Définition générique d'un opérande d'architecture (instance) */
struct _GArchOperand
{
GContentExporter parent; /* A laisser en premier */
+ operand_compare_fc compare; /* Comparaison d'opérandes */
get_operand_text_fc get_text; /* Texte humain équivalent */
operand_print_fc print; /* Texte humain équivalent */
diff --git a/src/arch/operand.c b/src/arch/operand.c
index 16fc073..f3aecb6 100644
--- a/src/arch/operand.c
+++ b/src/arch/operand.c
@@ -117,3 +117,30 @@ void g_arch_operand_print(const GArchOperand *operand, GBufferLine *line, AsmSyn
return operand->print(operand, line, syntax);
}
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier opérande à consulter. *
+* b = second opérande à consulter. *
+* *
+* Description : Compare un opérande avec un autre. *
+* *
+* Retour : Bilan de la comparaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_arch_operand_compare(const GArchOperand *a, const GArchOperand *b)
+{
+ bool result; /* Bilan à faire remonter */
+
+ result = (G_OBJECT_TYPE(G_OBJECT(a)) == G_OBJECT_TYPE(G_OBJECT(b)));
+
+ if (result)
+ result = a->compare(a, b);
+
+ return result;
+
+}
diff --git a/src/arch/operand.h b/src/arch/operand.h
index 3745a80..d22235e 100644
--- a/src/arch/operand.h
+++ b/src/arch/operand.h
@@ -55,6 +55,9 @@ char *g_arch_operand_get_text(const GArchOperand *, const GExeFormat *, AsmSynta
/* Traduit un opérande en version humainement lisible. */
void g_arch_operand_print(const GArchOperand *, GBufferLine *, AsmSyntax);
+/* Compare un opérande avec un autre. */
+bool g_arch_operand_compare(const GArchOperand *, const GArchOperand *);
+
#endif /* _ARCH_OPERAND_H */
diff --git a/src/decomp/context.c b/src/decomp/context.c
index 7fe6937..6440c56 100644
--- a/src/decomp/context.c
+++ b/src/decomp/context.c
@@ -24,6 +24,14 @@
#include "context.h"
+#include <malloc.h>
+
+
+#include "expr/pseudo.h"
+#include "../arch/operand.h"
+#include "../glibext/gnhash.h"
+
+
/* Définition d'une context décompilée (instance) */
struct _GDecContext
@@ -32,6 +40,12 @@ struct _GDecContext
vmpa_t max; /* Première adresse à écarter */
+ GHashTable *machine; /* Correspondance reg./pseudo */
+ GHashTable *ssa; /* Remplacement des pseudos */
+
+ GDecInstruction **pseudos; /* Liste des pseudos-registre */
+ size_t count; /* Taille de cette liste */
+
};
@@ -87,6 +101,8 @@ static void g_dec_context_class_init(GDecContextClass *klass)
static void g_dec_context_init(GDecContext *ctx)
{
+ ctx->machine = g_hash_table_new(g_constant_hash, (GEqualFunc)g_arch_operand_compare);
+ ctx->ssa = g_hash_table_new(NULL, NULL);
}
@@ -151,3 +167,42 @@ void g_dec_context_set_max_address(GDecContext *ctx, vmpa_t max)
ctx->max = max;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : ctx = instance à consulter, voire mettre à jour. *
+* operand = opérande représentant un registre quelconque. *
+* *
+* Description : Convertit un registre machine en un pseudo-registre. *
+* *
+* Retour : Pseudo-registre, existant ou non, prêt à emploi. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDecInstruction *g_dec_context_convert_register(GDecContext *ctx, gpointer operand)
+{
+ GDecInstruction *result; /* Instance à retourner */
+ gpointer *found; /* Pseudo-registre trouvé */
+
+ found = g_hash_table_lookup(ctx->machine, operand);
+
+ if (found != NULL) result = G_DEC_INSTRUCTION(found);
+ else
+ {
+ result = g_pseudo_register_new();
+ g_pseudo_register_set_index(G_PSEUDO_REGISTER(result), ctx->count);
+
+ g_hash_table_insert(ctx->machine, operand, result);
+
+ ctx->pseudos = (GDecInstruction **)realloc(ctx->pseudos,
+ ++ctx->count * sizeof(GDecInstruction *));
+ ctx->pseudos[ctx->count - 1] = result;
+
+ }
+
+ return result;
+
+}
diff --git a/src/decomp/context.h b/src/decomp/context.h
index 76105e6..926a372 100644
--- a/src/decomp/context.h
+++ b/src/decomp/context.h
@@ -28,7 +28,7 @@
#include <glib-object.h>
-#include "expr/pseudo.h"
+#include "instruction.h"
#include "../arch/archbase.h"
@@ -61,6 +61,9 @@ vmpa_t g_dec_context_get_max_address(const GDecContext *);
/* Définit l'adresse où la décompilation n'est plus souhaitée. */
void g_dec_context_set_max_address(GDecContext *, vmpa_t);
+/* Convertit un registre machine en un pseudo-registre. */
+GDecInstruction *g_dec_context_convert_register(GDecContext *, gpointer);
+
#endif /* _DECOMP_CONTEXT_H */
diff --git a/src/decomp/expr/pseudo.c b/src/decomp/expr/pseudo.c
index 393f32c..abfcd4d 100644
--- a/src/decomp/expr/pseudo.c
+++ b/src/decomp/expr/pseudo.c
@@ -24,6 +24,10 @@
#include "pseudo.h"
+#include <stdio.h>
+#include <string.h>
+
+
#include "../expression-int.h"
@@ -33,6 +37,8 @@ struct _GPseudoRegister
{
GDecExpression parent; /* A laisser en premier */
+ size_t index; /* Position dans l'ensemble */
+
};
@@ -141,8 +147,30 @@ GDecInstruction *g_pseudo_register_new(void)
static void g_pseudo_register_print(const GPseudoRegister *reg, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
{
+ char label[32];
+
+ snprintf(label, 32, "var%d", reg->index);
+
+ g_buffer_line_insert_text(line, BLC_ASSEMBLY, label, strlen(label), RTT_RAW);
- g_buffer_line_insert_text(line, BLC_ASSEMBLY, "varX", 4, RTT_RAW);
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : reg = expression représentant un pseudo-registre à traiter.*
+* index = indice à associer au pseudo-registre. *
+* *
+* Description : Définit un indice unique pour un pseudo-registre donné. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+void g_pseudo_register_set_index(GPseudoRegister *reg, size_t index)
+{
+ reg->index = index;
}
diff --git a/src/decomp/expr/pseudo.h b/src/decomp/expr/pseudo.h
index 9734625..95612a9 100644
--- a/src/decomp/expr/pseudo.h
+++ b/src/decomp/expr/pseudo.h
@@ -54,6 +54,9 @@ GType g_pseudo_register_get_type(void);
/* Assigne le contenu d'une expression dans une autre. */
GDecInstruction *g_pseudo_register_new(void);
+/* Définit un indice unique pour un pseudo-registre donné. */
+void g_pseudo_register_set_index(GPseudoRegister *, size_t);
+
#endif /* _DECOMP_EXPR_PSEUDO_H */
diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am
index 1e21b58..2365190 100644
--- a/src/glibext/Makefile.am
+++ b/src/glibext/Makefile.am
@@ -7,6 +7,7 @@ libglibext_la_SOURCES = \
gbufferline.h gbufferline.c \
gbuffersegment.h gbuffersegment.c \
gcodebuffer.h gcodebuffer.c \
+ gnhash.h gnhash.c \
proto.h
libglibext_la_LDFLAGS =
diff --git a/src/glibext/gnhash.c b/src/glibext/gnhash.c
new file mode 100644
index 0000000..cdd4dd1
--- /dev/null
+++ b/src/glibext/gnhash.c
@@ -0,0 +1,52 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * gnhash.c - nouvelle fonction offrant une empreinte constante
+ *
+ * Copyright (C) 2010 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * 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 "gnhash.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : v = pointeur quelconque. *
+* *
+* Description : Convertit un pointeur en une empreinte constante. *
+* *
+* Retour : 2. *
+* *
+* Remarques : L'algorithme actuel (12/11/10) de la GLib impose qu'une *
+* même empreinte impose une même clef. Deux clefs distinctes, *
+* pourtant égales, ont deux empreintes distinctes, donc on *
+* définit une seule empreinte possible. Pas terrible, mais *
+* cela répond au besoin (association simple clef <-> valeur). *
+* *
+******************************************************************************/
+
+guint g_constant_hash(gconstpointer v)
+{
+ /**
+ * La valeur doit être supérieure à 1 pour ne
+ * pas être totalement inéfficace.
+ */
+ return 2;
+
+}
diff --git a/src/glibext/gnhash.h b/src/glibext/gnhash.h
new file mode 100644
index 0000000..4c49357
--- /dev/null
+++ b/src/glibext/gnhash.h
@@ -0,0 +1,37 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * gnhash.h - prototype pour une nouvelle fonction offrant une empreinte constante
+ *
+ * Copyright (C) 2010 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * 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 _GLIBEXT_GNHASH_H
+#define _GLIBEXT_GNHASH_H
+
+
+#include <glib-object.h>
+
+
+
+/* Convertit un pointeur en une empreinte constante. */
+guint g_constant_hash(gconstpointer);
+
+
+
+#endif /* _GLIBEXT_GNHASH_H */