summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2012-12-10 23:41:09 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2012-12-10 23:41:09 (GMT)
commit79ec14ee5c1cea5c4ad345a7047b47b9205fc29e (patch)
tree0596bb4b7910964ef96c3705c80ec5dba677eeb0
parent42420cfa1f406a5f0a9f062b258ece72098635b5 (diff)
Took care of Dalvik switch cases.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@299 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
-rw-r--r--ChangeLog32
-rw-r--r--plugins/androhelpers/Makefile.am3
-rw-r--r--plugins/androhelpers/androhelpers.c13
-rw-r--r--plugins/androhelpers/params.c3
-rw-r--r--plugins/androhelpers/switch.c360
-rw-r--r--plugins/androhelpers/switch.h37
-rw-r--r--plugins/androhelpers/try_n_catch.c7
-rw-r--r--src/analysis/disass/links.c6
-rw-r--r--src/arch/instruction.h1
-rw-r--r--src/format/dex/dex-int.c273
-rwxr-xr-xsrc/format/dex/dex-int.h23
-rwxr-xr-xsrc/format/dex/dex_def.h109
-rw-r--r--src/gtkext/graph/layout.c1
13 files changed, 787 insertions, 81 deletions
diff --git a/ChangeLog b/ChangeLog
index 6733926..83e1f04 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,35 @@
+12-12-11 Cyrille Bagard <nocbos@gmail.com>
+
+ * plugins/androhelpers/androhelpers.c:
+ Check for Dex format and handle a new process.
+
+ * plugins/androhelpers/Makefile.am:
+ Add the 'switch.[ch]' files to libandrohelpers_la_SOURCES.
+
+ * plugins/androhelpers/params.c:
+ Remove the check of the processed format.
+
+ * plugins/androhelpers/switch.c:
+ * plugins/androhelpers/switch.h:
+ New entries: take care of Dalvik switch cases.
+
+ * plugins/androhelpers/try_n_catch.c:
+ Typo. Remove the check of the processed format.
+
+ * src/analysis/disass/links.c:
+ Update code for the new link.
+
+ * src/arch/instruction.h:
+ Create a new kind of link, for switch cases.
+
+ * src/format/dex/dex_def.h:
+ * src/format/dex/dex-int.c:
+ * src/format/dex/dex-int.h:
+ Support the data relative to Dalvik switches.
+
+ * src/gtkext/graph/layout.c:
+ Update code for the new link.
+
12-12-10 Cyrille Bagard <nocbos@gmail.com>
* src/glibext/gbufferline.c:
diff --git a/plugins/androhelpers/Makefile.am b/plugins/androhelpers/Makefile.am
index d5618d1..acf4a4e 100644
--- a/plugins/androhelpers/Makefile.am
+++ b/plugins/androhelpers/Makefile.am
@@ -4,7 +4,8 @@ lib_LTLIBRARIES = libandrohelpers.la
libandrohelpers_la_SOURCES = \
androhelpers.h androhelpers.c \
params.h params.c \
- try_n_catch.h try_n_catch.c
+ try_n_catch.h try_n_catch.c \
+ switch.h switch.c
libandrohelpers_la_LDFLAGS = -L../../src/.libs -L../../src/gui/.libs -lchrysagui \
-lchrysadisass -lchrysagtkext \
diff --git a/plugins/androhelpers/androhelpers.c b/plugins/androhelpers/androhelpers.c
index f7360f8..c61ce02 100644
--- a/plugins/androhelpers/androhelpers.c
+++ b/plugins/androhelpers/androhelpers.c
@@ -27,7 +27,11 @@
#include <string.h>
+#include <format/dex/dex.h>
+
+
#include "params.h"
+#include "switch.h"
#include "try_n_catch.h"
@@ -92,16 +96,25 @@ bool execute_action_on_binary(GPluginModule *plugin, GLoadedBinary *binary, Plug
{
bool result; /* Bilan à retourner */
+ if (!G_IS_DEX_FORMAT(g_loaded_binary_get_format(binary)))
+ return false;
+
result = true;
if (action == PGA_BINARY_DISASSEMBLED)
result &= replace_parameters(binary);
else if (action == PGA_BINARY_LINKED)
+ {
+ result &= extract_switch_info(binary, true);
result &= process_exception_handlers(binary, true);
+ }
else if (action == PGA_BINARY_PRINTED)
+ {
+ result &= extract_switch_info(binary, false);
result &= process_exception_handlers(binary, false);
+ }
return result;
diff --git a/plugins/androhelpers/params.c b/plugins/androhelpers/params.c
index bbd254a..5b47aef 100644
--- a/plugins/androhelpers/params.c
+++ b/plugins/androhelpers/params.c
@@ -189,9 +189,6 @@ bool replace_parameters(GLoadedBinary *binary)
size_t j; /* Boucle de parcours #2 */
GDexMethod *method; /* Méthode à parcourir */
- if (!G_IS_DEX_FORMAT(g_loaded_binary_get_format(binary)))
- return false;
-
instrs = g_loaded_binary_get_instructions(binary);
format = G_DEX_FORMAT(g_loaded_binary_get_format(binary));
diff --git a/plugins/androhelpers/switch.c b/plugins/androhelpers/switch.c
new file mode 100644
index 0000000..a6f6f5b
--- /dev/null
+++ b/plugins/androhelpers/switch.c
@@ -0,0 +1,360 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * switch.c - apport de précisions sur les aiguillages Dalvik
+ *
+ * Copyright (C) 2012 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 "switch.h"
+
+
+#include <string.h>
+
+
+#include <arch/dalvik/instruction.h>
+#include <arch/dalvik/instruction-def.h>
+#include <arch/dalvik/operands/target.h>
+#include <format/dex/dex-int.h>
+#include <../i18n.h>
+
+
+
+/* Récupère les détails d'un aiguillage. */
+static bool load_dex_switch(const GArchInstruction *, GArchInstruction *, const GDexFormat *, dex_switch *);
+
+/* Lie les instructions selon les cas d'un aiguillage. */
+static void link_all_switch_cases(GArchInstruction *, const dex_switch *, GArchInstruction *, vmpa_t, vmpa_t);
+
+/* Insère des indications dans le texte humainement lisibles. */
+static void mark_all_switch_cases(const GArchInstruction *, const dex_switch *, GArchInstruction *, const GLoadedBinary *, vmpa_t, vmpa_t);
+
+/* Recherche des aiguillages dans chaque instruction. */
+static void look_for_switch_instructions(const GDexMethod *, GArchInstruction *, const GLoadedBinary *, const GDexFormat *, bool);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = instruction d'aiguillage rencontrée. *
+* instrs = liste des instructions pour tout le binaire. *
+* format = format du binaire Dex. *
+* dswitch = détails de l'aiguillage à reconstituer. [OUT] *
+* *
+* Description : Récupère les détails d'un aiguillage. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool load_dex_switch(const GArchInstruction *instr, GArchInstruction *instrs, const GDexFormat *format, dex_switch *dswitch)
+{
+ bool result; /* Bilan à retourner */
+ GArchOperand *operand; /* Operande à manipuler */
+ const GImmOperand *imm; /* Valeur concrête */
+ vmpa_t addr; /* Adresse du corps des infos */
+ GArchInstruction *info; /* Corps des infos brutes */
+ off_t pos; /* Position dans le binaire */
+ uint32_t *targets; /* Cibles relatives à corriger */
+ uint16_t i; /* Boucle de parcours */
+
+ /* Récupération de l'opérande */
+
+ operand = g_arch_instruction_get_operand(instr, 1);
+
+ if (!G_IS_DALVIK_TARGET_OPERAND(operand))
+ return false;
+
+ imm = g_dalvik_target_operand_get_value(G_DALVIK_TARGET_OPERAND(operand));
+
+ if (!g_imm_operand_to_vmpa_t(imm, &addr))
+ return false;
+
+ /* Lecture des détails */
+
+ info = g_arch_instruction_find_by_address(instrs, addr, true);
+ if (info == NULL)
+ return false;
+
+ g_arch_instruction_get_location(info, &pos, NULL, NULL);
+
+ result = read_dex_switch(format, &pos, dswitch);
+
+ /* Ajustement relatif */
+
+ if (result)
+ {
+ g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
+ if (dswitch->packed.ident == DPO_PACKED_SWITCH)
+ targets = dswitch->packed.targets;
+ else
+ targets = dswitch->sparse.targets;
+
+ for (i = 0; i < dswitch->packed.size; i++)
+ targets[i] = ((uint32_t)addr) + targets[i] * sizeof(uint16_t);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = instruction d'aiguillage rencontrée. *
+* dswitch = détails de l'aiguillage à reconstituer. *
+* instrs = liste des instructions pour tout le binaire. *
+* start = début de la zone théoriquement couverte. *
+* end = fin de la zone théoriquement couverte. *
+* *
+* Description : Lie les instructions selon les cas d'un aiguillage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void link_all_switch_cases(GArchInstruction *instr, const dex_switch *dswitch, GArchInstruction *instrs, vmpa_t start, vmpa_t end)
+{
+ uint32_t *targets; /* Cibles relatives à corriger */
+ uint16_t i; /* Boucle de parcours */
+ GArchInstruction *next; /* Instruction suivante */
+
+ /* Valeurs définies */
+
+ if (dswitch->packed.ident == DPO_PACKED_SWITCH)
+ targets = dswitch->packed.targets;
+ else
+ targets = dswitch->sparse.targets;
+
+ for (i = 0; i < dswitch->packed.size; i++)
+ {
+ if (!(start <= targets[i] && targets[i] < end))
+ continue;
+
+ next = g_arch_instruction_find_by_address(instrs, (vmpa_t)targets[i], true);
+
+ if (next != NULL)
+ g_arch_instruction_link_with(instr, next, ILT_CASE_JUMP);
+
+ }
+
+ /* Cas du défaut */
+
+ next = g_arch_instruction_get_next_iter(instrs, instr, end);
+
+ if (next != NULL)
+ g_arch_instruction_link_with(instr, next, ILT_CASE_JUMP);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = instruction d'aiguillage rencontrée. *
+* dswitch = détails de l'aiguillage à reconstituer. *
+* instrs = liste des instructions pour tout le binaire. *
+* binary = représentation binaire à traiter. *
+* start = début de la zone théoriquement couverte. *
+* end = fin de la zone théoriquement couverte. *
+* *
+* Description : Insère des indications dans le texte humainement lisibles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void mark_all_switch_cases(const GArchInstruction *instr, const dex_switch *dswitch, GArchInstruction *instrs, const GLoadedBinary *binary, vmpa_t start, vmpa_t end)
+{
+ GCodeBuffer *buffer; /* Contenu textuel à modifier */
+ uint32_t *targets; /* Cibles relatives à corriger */
+ uint16_t i; /* Boucle de parcours */
+ uint16_t index; /* Véritable indice recalculé */
+ uint32_t value; /* Valeur à indiquer */
+ GBufferLine *line; /* Nouvelle ligne à compléter */
+ size_t len; /* Taille de la description */
+ char *fulldesc; /* Description complète */
+ GArchInstruction *next; /* Instruction suivante */
+ vmpa_t addr; /* Adresse de cette instruction*/
+
+ buffer = g_loaded_binary_get_disassembled_buffer(binary);
+
+ /* Valeurs définies */
+
+ if (dswitch->packed.ident == DPO_PACKED_SWITCH)
+ targets = dswitch->packed.targets;
+ else
+ targets = dswitch->sparse.targets;
+
+ for (i = dswitch->packed.size; i > 0; i--)
+ {
+ index = i - 1;
+
+ if (!(start <= targets[index] && targets[index] < end))
+ continue;
+
+ if (dswitch->packed.ident == DPO_PACKED_SWITCH)
+ value = dswitch->packed.first_key + index;
+ else
+ value = dswitch->sparse.keys[index];
+
+ line = g_code_buffer_insert_at(buffer, (vmpa_t)targets[index], true);
+ g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD);
+
+ len = strlen(_("; Case for value 0x%08x (%d)")) + 8 + strlen("4294967295U") /* UINT_MAX */;
+ fulldesc = (char *)calloc(len + 1, sizeof(char));
+ len = snprintf(fulldesc, len + 1, _("; Case for value 0x%08x (%d)"), value, value);
+
+ g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, fulldesc, len, RTT_INDICATION);
+
+ free(fulldesc);
+
+ }
+
+ /* Cas du défaut */
+
+ next = g_arch_instruction_get_next_iter(instrs, instr, end);
+
+ if (next != NULL)
+ {
+ g_arch_instruction_get_location(next, NULL, NULL, &addr);
+
+ line = g_code_buffer_insert_at(buffer, addr, true);
+ g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD);
+
+ fulldesc = _("; Default case");
+ g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD,
+ fulldesc, strlen(fulldesc), RTT_INDICATION);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : method = routine à venir parcourir. *
+* instrs = liste des instructions pour tout le binaire. *
+* binary = représentation binaire à traiter. *
+* format = format du binaire Dex. *
+* link = édition de liens ou impression de commentaires ? *
+* *
+* Description : Recherche des aiguillages dans chaque instruction. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void look_for_switch_instructions(const GDexMethod *method, GArchInstruction *instrs, const GLoadedBinary *binary, const GDexFormat *format, bool link)
+{
+ GBinRoutine *routine; /* Abstraction de la méthode */
+ vmpa_t start; /* Début de la zone couverte */
+ vmpa_t end; /* Fin de la zone couverte */
+ GArchInstruction *iter; /* Boucle de parcours */
+ DalvikOpcodes opcode; /* Type d'instruction Dalvik */
+ dex_switch dswitch; /* Infos d'aiguillage */
+
+ routine = g_dex_method_get_routine(method);
+
+ start = g_binary_routine_get_address(routine);
+ end = start + g_binary_routine_get_size(routine);
+
+ for (iter = g_arch_instruction_find_by_address(instrs, start, true);
+ iter != NULL;
+ iter = g_arch_instruction_get_next_iter(instrs, iter, end))
+ {
+ opcode = g_dalvik_instruction_get_opcode(G_DALVIK_INSTRUCTION(iter));
+
+ if (opcode != DOP_PACKED_SWITCH && opcode != DOP_SPARSE_SWITCH)
+ continue;
+
+ if (!load_dex_switch(iter, instrs, format, &dswitch))
+ continue;
+
+ if (link)
+ link_all_switch_cases(iter, &dswitch, instrs, start, end);
+ else
+ mark_all_switch_cases(iter, &dswitch, instrs, binary, start, end);
+
+ reset_dex_switch(&dswitch);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : binary = représentation binaire à traiter. *
+* link = édition de liens ou impression de commentaires ? *
+* *
+* Description : Traite les données binaires associées aux switchs. *
+* *
+* Retour : true si une action a été menée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool extract_switch_info(GLoadedBinary *binary, bool link)
+{
+ GArchInstruction *instrs; /* Instructions Dalvik */
+ GDexFormat *format; /* Format du binaire chargé */
+ size_t cls_count; /* Nombre de classes trouvées */
+ size_t i; /* Boucle de parcours #1 */
+ GDexClass *class; /* Classe à analyser */
+ size_t meth_count; /* Nombre de méthodes trouvées */
+ size_t j; /* Boucle de parcours #2 */
+ GDexMethod *method; /* Méthode à parcourir */
+
+ instrs = g_loaded_binary_get_instructions(binary);
+ format = G_DEX_FORMAT(g_loaded_binary_get_format(binary));
+
+ cls_count = g_dex_format_count_classes(format);
+ for (i = 0; i < cls_count; i++)
+ {
+ class = g_dex_format_get_class(format, i);
+
+ meth_count = g_dex_class_count_methods(class, false);
+ for (j = 0; j < meth_count; j++)
+ {
+ method = g_dex_class_get_method(class, false, j);
+ look_for_switch_instructions(method, instrs, binary, format, link);
+ }
+
+ meth_count = g_dex_class_count_methods(class, true);
+ for (j = 0; j < meth_count; j++)
+ {
+ method = g_dex_class_get_method(class, true, j);
+ look_for_switch_instructions(method, instrs, binary, format, link);
+ }
+
+ }
+
+ return true;
+
+}
diff --git a/plugins/androhelpers/switch.h b/plugins/androhelpers/switch.h
new file mode 100644
index 0000000..4d0754a
--- /dev/null
+++ b/plugins/androhelpers/switch.h
@@ -0,0 +1,37 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * switch.h - prototypes pour l'apport de précisions sur les aiguillages Dalvik
+ *
+ * Copyright (C) 2012 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 _PLUGINS_SWITCH_H
+#define _PLUGINS_SWITCH_H
+
+
+#include <analysis/binary.h>
+
+
+
+/* Traite les données binaires associées aux switchs. */
+bool extract_switch_info(GLoadedBinary *, bool);
+
+
+
+#endif /* _PLUGINS_SWITCH_H */
diff --git a/plugins/androhelpers/try_n_catch.c b/plugins/androhelpers/try_n_catch.c
index d2ab4a9..2543641 100644
--- a/plugins/androhelpers/try_n_catch.c
+++ b/plugins/androhelpers/try_n_catch.c
@@ -51,7 +51,7 @@ static bool check_covered_area(const try_item *, const GBinRoutine *);
/* Rattache les gestionnaires d'exception à leur code couvert. */
static void attach_caught_code(const GLoadedBinary *, const GBinRoutine *, const try_item *, const caught_exception *, size_t);
-/* Insère des indications dans le texte humainement lisible. */
+/* Insère des indications dans le texte humainement lisibles. */
static void mark_exception_handlers(const GLoadedBinary *, uleb128_t, caught_exception **, size_t *);
/* Construit des listes pointant sur les différentes gestions. */
@@ -172,7 +172,7 @@ static void attach_caught_code(const GLoadedBinary *binary, const GBinRoutine *r
* handlers = ensemble des groupes de gestionnaires. *
* count = liste des quantités de gestionnaires groupés. *
* *
-* Description : Insère des indications dans le texte humainement lisible. *
+* Description : Insère des indications dans le texte humainement lisibles. *
* *
* Retour : - *
* *
@@ -409,9 +409,6 @@ bool process_exception_handlers(GLoadedBinary *binary, bool link)
size_t j; /* Boucle de parcours #2 */
GDexMethod *method; /* Méthode à parcourir */
- if (!G_IS_DEX_FORMAT(g_loaded_binary_get_format(binary)))
- return false;
-
format = G_DEX_FORMAT(g_loaded_binary_get_format(binary));
cls_count = g_dex_format_count_classes(format);
diff --git a/src/analysis/disass/links.c b/src/analysis/disass/links.c
index 0ba3fc6..df0c77f 100644
--- a/src/analysis/disass/links.c
+++ b/src/analysis/disass/links.c
@@ -108,9 +108,9 @@ void establish_links_between_lines(GArchInstruction *list, GBinRoutine **routine
default:
/**
- * Note pour GCC : à ce stade du désassemblage, ILT_CATCH_EXCEPTION
- * ne peut être présente, car ne provenant que de greffons.
- * Pour ILT_EXEC_FLOW, sa seule insertion est ici, plus bas.
+ * Note pour GCC : à ce stade du désassemblage, ILT_CASE_JUMP et
+ * ILT_CATCH_EXCEPTION ne peuvent être présentes, car ne provenant
+ * que de greffons. Pour ILT_EXEC_FLOW, sa seule insertion est ici, plus bas.
*/
break;
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index ae0bd68..8963284 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -45,6 +45,7 @@ typedef enum _InstructionLinkType
ILT_NONE, /* Aucune instruction visée */
ILT_EXEC_FLOW, /* Raccord attendu entre blocs */
ILT_JUMP, /* Saut inconditionnel */
+ ILT_CASE_JUMP, /* Saut suite à aiguillage */
ILT_JUMP_IF_TRUE, /* Saut conditionnel (si vrai) */
ILT_JUMP_IF_FALSE, /* Saut conditionnel (si faux) */
ILT_CALL, /* Appel d'une fonction */
diff --git a/src/format/dex/dex-int.c b/src/format/dex/dex-int.c
index 200b01f..58211e5 100644
--- a/src/format/dex/dex-int.c
+++ b/src/format/dex/dex-int.c
@@ -27,11 +27,80 @@
#include <malloc.h>
+#include "../../arch/dalvik/instruction-def.h"
#include "../../common/endianness.h"
/* ---------------------------------------------------------------------------------- */
+/* DESCRIPTION DU FORMAT DALVIK */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* header = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une en-tête de programme DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_header(const GDexFormat *format, off_t *pos, dex_header *header)
+{
+ bool result; /* Bilan à retourner */
+ const bin_t *content; /* Contenu binaire à lire */
+ off_t length; /* Taille totale du contenu */
+ size_t i; /* Boucle de parcours */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+ length = G_BIN_FORMAT(format)->length;
+
+ for (i = 0; i < DEX_FILE_MAGIC_LEN && result; i++)
+ result = read_u8(&header->magic[i], content, pos, length, SRE_LITTLE);
+
+ result &= read_u32(&header->checksum, content, pos, length, SRE_LITTLE);
+
+ for (i = 0; i < 20 && result; i++)
+ result = read_u8(&header->signature[i], content, pos, length, SRE_LITTLE);
+
+ result &= read_u32(&header->file_size, content, pos, length, SRE_LITTLE);
+ result &= read_u32(&header->header_size, content, pos, length, SRE_LITTLE);
+
+ result &= read_u32(&header->endian_tag, content, pos, length, SRE_LITTLE);
+
+ result &= read_u32(&header->link_size, content, pos, length, SRE_LITTLE);
+ result &= read_u32(&header->link_off, content, pos, length, SRE_LITTLE);
+ result &= read_u32(&header->map_off, content, pos, length, SRE_LITTLE);
+ result &= read_u32(&header->string_ids_size, content, pos, length, SRE_LITTLE);
+ result &= read_u32(&header->string_ids_off, content, pos, length, SRE_LITTLE);
+ result &= read_u32(&header->type_ids_size, content, pos, length, SRE_LITTLE);
+ result &= read_u32(&header->type_ids_off, content, pos, length, SRE_LITTLE);
+ result &= read_u32(&header->proto_ids_size, content, pos, length, SRE_LITTLE);
+ result &= read_u32(&header->proto_ids_off, content, pos, length, SRE_LITTLE);
+ result &= read_u32(&header->field_ids_size, content, pos, length, SRE_LITTLE);
+ result &= read_u32(&header->field_ids_off, content, pos, length, SRE_LITTLE);
+ result &= read_u32(&header->method_ids_size, content, pos, length, SRE_LITTLE);
+ result &= read_u32(&header->method_ids_off, content, pos, length, SRE_LITTLE);
+ result &= read_u32(&header->class_defs_size, content, pos, length, SRE_LITTLE);
+ result &= read_u32(&header->class_defs_off, content, pos, length, SRE_LITTLE);
+ result &= read_u32(&header->data_size, content, pos, length, SRE_LITTLE);
+ result &= read_u32(&header->data_off, content, pos, length, SRE_LITTLE);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
/* ELEMENTS DE TABLE DES CONSTANTES */
/* ---------------------------------------------------------------------------------- */
@@ -840,18 +909,87 @@ void reset_dex_code_item(code_item *item)
+/* ---------------------------------------------------------------------------------- */
+/* AIGUILLAGES DIVERS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* packed = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'un contenu d'aiguillage compact. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_packed_switch(const GDexFormat *format, off_t *pos, packed_switch *packed)
+{
+ bool result; /* Bilan à retourner */
+ const bin_t *content; /* Contenu binaire à lire */
+ off_t length; /* Taille totale du contenu */
+ uint16_t i; /* Boucle de parcours */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+ length = G_BIN_FORMAT(format)->length;
+
+ packed->targets = NULL;
+
+ result &= read_u16(&packed->ident, content, pos, length, SRE_LITTLE);
+ result &= read_u16(&packed->size, content, pos, length, SRE_LITTLE);
+ result &= read_u32(&packed->first_key, content, pos, length, SRE_LITTLE);
+ if (result && packed->size > 0)
+ {
+ packed->targets = (uint32_t *)calloc(packed->size, sizeof(uint32_t));
+
+ for (i = 0; i < packed->size && result; i++)
+ result &= read_u32(&packed->targets[i], content, pos, length, SRE_LITTLE);
+
+ }
+
+ if (!result)
+ reset_dex_packed_switch(packed);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : packed = structure à nettoyer. *
+* *
+* Description : Supprime tous les éléments chargés en mémoire à la lecture. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+void reset_dex_packed_switch(packed_switch *packed)
+{
+ if (packed->targets != NULL)
+ free(packed->targets);
+}
/******************************************************************************
* *
* Paramètres : format = informations chargées à consulter. *
* pos = position de début de lecture. [OUT] *
-* header = structure lue à retourner. [OUT] *
+* sparse = structure lue à retourner. [OUT] *
* *
-* Description : Procède à la lecture d'une en-tête de programme DEX. *
+* Description : Procède à la lecture d'un contenu d'aiguillage dispersé. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -859,54 +997,131 @@ void reset_dex_code_item(code_item *item)
* *
******************************************************************************/
-bool read_dex_header(const GDexFormat *format, off_t *pos, dex_header *header)
+bool read_dex_sparse_switch(const GDexFormat *format, off_t *pos, sparse_switch *sparse)
{
bool result; /* Bilan à retourner */
const bin_t *content; /* Contenu binaire à lire */
off_t length; /* Taille totale du contenu */
- size_t i; /* Boucle de parcours */
+ uint16_t i; /* Boucle de parcours */
result = true;
content = G_BIN_FORMAT(format)->content;
length = G_BIN_FORMAT(format)->length;
- for (i = 0; i < DEX_FILE_MAGIC_LEN && result; i++)
- result = read_u8(&header->magic[i], content, pos, length, SRE_LITTLE);
+ sparse->keys = NULL;
+ sparse->targets = NULL;
- result &= read_u32(&header->checksum, content, pos, length, SRE_LITTLE);
+ result &= read_u16(&sparse->ident, content, pos, length, SRE_LITTLE);
+ result &= read_u16(&sparse->size, content, pos, length, SRE_LITTLE);
- for (i = 0; i < 20 && result; i++)
- result = read_u8(&header->signature[i], content, pos, length, SRE_LITTLE);
+ if (result && sparse->size > 0)
+ {
+ sparse->keys = (uint32_t *)calloc(sparse->size, sizeof(uint32_t));
+ sparse->targets = (uint32_t *)calloc(sparse->size, sizeof(uint32_t));
- result &= read_u32(&header->file_size, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->header_size, content, pos, length, SRE_LITTLE);
+ for (i = 0; i < sparse->size && result; i++)
+ result &= read_u32(&sparse->keys[i], content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->endian_tag, content, pos, length, SRE_LITTLE);
+ for (i = 0; i < sparse->size && result; i++)
+ result &= read_u32(&sparse->targets[i], content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->link_size, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->link_off, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->map_off, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->string_ids_size, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->string_ids_off, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->type_ids_size, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->type_ids_off, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->proto_ids_size, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->proto_ids_off, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->field_ids_size, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->field_ids_off, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->method_ids_size, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->method_ids_off, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->class_defs_size, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->class_defs_off, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->data_size, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->data_off, content, pos, length, SRE_LITTLE);
+ }
+
+ if (!result)
+ reset_dex_sparse_switch(sparse);
return result;
}
+/******************************************************************************
+* *
+* Paramètres : sparse = structure à nettoyer. *
+* *
+* Description : Supprime tous les éléments chargés en mémoire à la lecture. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void reset_dex_sparse_switch(sparse_switch *sparse)
+{
+ if (sparse->keys != NULL)
+ free(sparse->keys);
+
+ if (sparse->targets != NULL)
+ free(sparse->targets);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* dsxitch = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'un contenu d'aiguillage Dex interne. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_switch(const GDexFormat *format, off_t *pos, dex_switch *dswitch)
+{
+ bool result; /* Bilan à retourner */
+ const bin_t *content; /* Contenu binaire à lire */
+ off_t length; /* Taille totale du contenu */
+ uint16_t ident; /* Pseudo-code d'identification*/
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+ length = G_BIN_FORMAT(format)->length;
+
+ result &= read_u16(&ident, content, (off_t []) { *pos }, length, SRE_LITTLE);
+
+ if (result)
+ {
+ if (ident == DPO_PACKED_SWITCH)
+ result = read_dex_packed_switch(format, pos, (packed_switch *)dswitch);
+
+ else if (ident == DPO_SPARSE_SWITCH)
+ result = read_dex_sparse_switch(format, pos, (sparse_switch *)dswitch);
+
+ else
+ result = false;
+ }
+
+ return result;
+}
+
+/******************************************************************************
+* *
+* Paramètres : dswitch = structure à nettoyer. *
+* *
+* Description : Supprime tous les éléments chargés en mémoire à la lecture. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void reset_dex_switch(dex_switch *dswitch)
+{
+ if (dswitch->packed.ident == DPO_PACKED_SWITCH)
+ reset_dex_packed_switch((packed_switch *)dswitch);
+ else
+ reset_dex_sparse_switch((sparse_switch *)dswitch);
+
+}
diff --git a/src/format/dex/dex-int.h b/src/format/dex/dex-int.h
index 6a153c1..55a48b5 100755
--- a/src/format/dex/dex-int.h
+++ b/src/format/dex/dex-int.h
@@ -68,6 +68,13 @@ size_t g_dex_format_count_classes(const GDexFormat *);
GDexClass *g_dex_format_get_class(const GDexFormat *, size_t);
+/* -------------------------- DESCRIPTION DU FORMAT DALVIK -------------------------- */
+
+
+/* Procède à la lecture d'une en-tête de programme DEX. */
+bool read_dex_header(const GDexFormat *, off_t *, dex_header *);
+
+
/* ------------------------ ELEMENTS DE TABLE DES CONSTANTES ------------------------ */
@@ -147,14 +154,26 @@ void reset_dex_code_item(code_item *);
+/* ------------------------------- AIGUILLAGES DIVERS ------------------------------- */
-/* Procède à la lecture d'une en-tête de programme DEX. */
-bool read_dex_header(const GDexFormat *, off_t *, dex_header *);
+/* Procède à la lecture d'un contenu d'aiguillage compact. */
+bool read_dex_packed_switch(const GDexFormat *, off_t *, packed_switch *);
+
+/* Supprime tous les éléments chargés en mémoire à la lecture. */
+void reset_dex_packed_switch(packed_switch *);
+/* Procède à la lecture d'un contenu d'aiguillage dispersé. */
+bool read_dex_sparse_switch(const GDexFormat *, off_t *, sparse_switch *);
+/* Supprime tous les éléments chargés en mémoire à la lecture. */
+void reset_dex_sparse_switch(sparse_switch *);
+/* Procède à la lecture d'un contenu d'aiguillage Dex interne. */
+bool read_dex_switch(const GDexFormat *, off_t *, dex_switch *);
+/* Supprime tous les éléments chargés en mémoire à la lecture. */
+void reset_dex_switch(dex_switch *);
diff --git a/src/format/dex/dex_def.h b/src/format/dex/dex_def.h
index d21ac15..eee3574 100755
--- a/src/format/dex/dex_def.h
+++ b/src/format/dex/dex_def.h
@@ -29,6 +29,55 @@
+/* -------------------------- DESCRIPTION DU FORMAT DALVIK -------------------------- */
+
+
+/* Identifiant magique "dex\n035\0" */
+#define DEX_FILE_MAGIC "\x64\x65\x78\x0a\x30\x33\x35\x00"
+#define DEX_FILE_MAGIC_LEN 8
+
+/* Types de boutisme */
+#define ENDIAN_CONSTANT 0x12345678
+#define REVERSE_ENDIAN_CONSTANT 0x78563412
+
+/* Indice non valide */
+#define NO_INDEX 0xffffffff
+
+
+/* En-tête de tout programe Dex */
+typedef struct _dex_header
+{
+ uint8_t magic[DEX_FILE_MAGIC_LEN]; /* Valeur magique du format */
+
+ uint32_t checksum; /* Somme de contrôle adler32 */
+ uint8_t signature[20]; /* Emprunte SHA-1 du reste */
+ uint32_t file_size; /* Taille du fichier */
+ uint32_t header_size; /* Taille de cette en-tête */
+
+ uint32_t endian_tag; /* Boutisme du fichier */
+
+ uint32_t link_size; /* Taille de section 'liaisons'*/
+ uint32_t link_off; /* Position de ladite section */
+ uint32_t map_off; /* Position de la cartographie */
+ uint32_t string_ids_size; /* Nombre de chaînes de carac. */
+ uint32_t string_ids_off; /* Position de cette liste */
+ uint32_t type_ids_size; /* Nom d'identifiant de type */
+ uint32_t type_ids_off; /* Position de la liste */
+ uint32_t proto_ids_size; /* Nombre de prototypes */
+ uint32_t proto_ids_off; /* Position de la liste */
+ uint32_t field_ids_size; /* Nombre de champs */
+ uint32_t field_ids_off; /* Position de la liste */
+ uint32_t method_ids_size; /* Nombre de méthodes */
+ uint32_t method_ids_off; /* Position de la liste */
+ uint32_t class_defs_size; /* Nombre de classes déclarées */
+ uint32_t class_defs_off; /* Position de la liste */
+ uint32_t data_size; /* Taille des données */
+ uint32_t data_off; /* Début des données */
+
+} dex_header;
+
+
+
/* -------------------------- CONSTANTES POUR DEX DIVERSES -------------------------- */
@@ -240,52 +289,36 @@ typedef struct _code_item
-/* -------------------------- DESCRIPTION DU FORMAT DALVIK -------------------------- */
-
+/* ------------------------------- AIGUILLAGES DIVERS ------------------------------- */
-/* Identifiant magique "dex\n035\0" */
-#define DEX_FILE_MAGIC "\x64\x65\x78\x0a\x30\x33\x35\x00"
-#define DEX_FILE_MAGIC_LEN 8
-
-/* Types de boutisme */
-#define ENDIAN_CONSTANT 0x12345678
-#define REVERSE_ENDIAN_CONSTANT 0x78563412
-/* Indice non valide */
-#define NO_INDEX 0xffffffff
+/* Aiguillage compressé */
+typedef struct _packed_switch
+{
+ uint16_t ident; /* Pseudo-code d'identification*/
+ uint16_t size; /* Nombre d'entrées */
+ uint32_t first_key; /* Première et plus petite clef*/
+ uint32_t *targets; /* Cibles relatives */
+} packed_switch;
-/* En-tête de tout programe Dex */
-typedef struct _dex_header
+/* Aiguillage dispersé */
+typedef struct _sparse_switch
{
- uint8_t magic[DEX_FILE_MAGIC_LEN]; /* Valeur magique du format */
-
- uint32_t checksum; /* Somme de contrôle adler32 */
- uint8_t signature[20]; /* Emprunte SHA-1 du reste */
- uint32_t file_size; /* Taille du fichier */
- uint32_t header_size; /* Taille de cette en-tête */
+ uint16_t ident; /* Pseudo-code d'identification*/
+ uint16_t size; /* Nombre d'entrées */
+ uint32_t *keys; /* Clefs valeureuses */
+ uint32_t *targets; /* Cibles relatives */
- uint32_t endian_tag; /* Boutisme du fichier */
+} sparse_switch;
- uint32_t link_size; /* Taille de section 'liaisons'*/
- uint32_t link_off; /* Position de ladite section */
- uint32_t map_off; /* Position de la cartographie */
- uint32_t string_ids_size; /* Nombre de chaînes de carac. */
- uint32_t string_ids_off; /* Position de cette liste */
- uint32_t type_ids_size; /* Nom d'identifiant de type */
- uint32_t type_ids_off; /* Position de la liste */
- uint32_t proto_ids_size; /* Nombre de prototypes */
- uint32_t proto_ids_off; /* Position de la liste */
- uint32_t field_ids_size; /* Nombre de champs */
- uint32_t field_ids_off; /* Position de la liste */
- uint32_t method_ids_size; /* Nombre de méthodes */
- uint32_t method_ids_off; /* Position de la liste */
- uint32_t class_defs_size; /* Nombre de classes déclarées */
- uint32_t class_defs_off; /* Position de la liste */
- uint32_t data_size; /* Taille des données */
- uint32_t data_off; /* Début des données */
+/* Manipulation interne */
+typedef union _dex_switch
+{
+ packed_switch packed; /* Modèle compact */
+ sparse_switch sparse; /* Modèle dispersé */
-} dex_header;
+} dex_switch;
diff --git a/src/gtkext/graph/layout.c b/src/gtkext/graph/layout.c
index 3a2f4e3..45e3a82 100644
--- a/src/gtkext/graph/layout.c
+++ b/src/gtkext/graph/layout.c
@@ -169,6 +169,7 @@ static char *complete_graph_links(const GtkGraphView *view, GtkViewPanel **views
{
case ILT_EXEC_FLOW:
case ILT_JUMP:
+ case ILT_CASE_JUMP:
snprintf(cmd, LINKS_DESC_LEN,
"_%p:s -> _%p:n [ltail=cluster_%p, lhead=cluster_%p];\n",
views[i], views[k], views[i], views[k]);