summaryrefslogtreecommitdiff
path: root/plugins/dex/dex-int.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2017-10-18 20:50:10 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2017-10-18 20:50:10 (GMT)
commitdce9d9cdfef1d37ef11a987a21f36e83b6b1944f (patch)
tree830623ade20e892954fcbddd3b7b05d09aac1dd7 /plugins/dex/dex-int.c
parent1e7c7de85438749d3faf7b76984b86a9c088fbc1 (diff)
Created plugins for the Dex and Dalvik support.
Diffstat (limited to 'plugins/dex/dex-int.c')
-rw-r--r--plugins/dex/dex-int.c1115
1 files changed, 1115 insertions, 0 deletions
diff --git a/plugins/dex/dex-int.c b/plugins/dex/dex-int.c
new file mode 100644
index 0000000..3f3eccb
--- /dev/null
+++ b/plugins/dex/dex-int.c
@@ -0,0 +1,1115 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * dex-int.c - structures internes du format DEX
+ *
+ * Copyright (C) 2010-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "dex-int.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+
+
+#include <i18n.h>
+
+
+#include <common/endianness.h>
+#include <plugins/dalvik/instruction-def.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, vmpa2t *pos, dex_header *header)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+ size_t i; /* Boucle de parcours */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ for (i = 0; i < DEX_FILE_MAGIC_LEN && result; i++)
+ result = g_binary_content_read_u8(content, pos, &header->magic[i]);
+
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->checksum);
+
+ for (i = 0; i < 20 && result; i++)
+ result = g_binary_content_read_u8(content, pos, &header->signature[i]);
+
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->file_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->header_size);
+
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->endian_tag);
+
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->link_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->link_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->map_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->string_ids_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->string_ids_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->type_ids_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->type_ids_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->proto_ids_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->proto_ids_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->field_ids_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->field_ids_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->method_ids_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->method_ids_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->class_defs_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->class_defs_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->data_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->data_off);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* ELEMENTS DE TABLE DES CONSTANTES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* str_id = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'un identifiant de chaîne DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_string_id_item(const GDexFormat *format, vmpa2t *pos, string_id_item *str_id)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &str_id->string_data_off);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* str_data = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture de proriétés de chaîne DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_string_data_item(const GDexFormat *format, vmpa2t *pos, string_data_item *str_data)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result = g_binary_content_read_uleb128(content, pos, &str_data->utf16_size);
+
+ if (result)
+ {
+ str_data->data = g_binary_content_get_raw_access(content, pos, str_data->utf16_size);
+ result = (str_data->data != NULL);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* item = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'un identifiant de type DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_type_id_item(const GDexFormat *format, vmpa2t *pos, type_id_item *item)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &item->descriptor_idx);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* proto_id = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une description de prototype. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_proto_id_item(const GDexFormat *format, vmpa2t *pos, proto_id_item *proto_id)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &proto_id->shorty_idx);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &proto_id->return_type_idx);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &proto_id->parameters_off);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* field_id = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une description de champ. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_field_id_item(const GDexFormat *format, vmpa2t *pos, field_id_item *field_id)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &field_id->class_idx);
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &field_id->type_idx);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &field_id->name_idx);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* meth_id = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une description de méthode. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_method_id_item(const GDexFormat *format, vmpa2t *pos, method_id_item *meth_id)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &meth_id->class_idx);
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &meth_id->proto_idx);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &meth_id->name_idx);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* class_def = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture des propriétés d'une classe DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_class_def_item(const GDexFormat *format, vmpa2t *pos, class_def_item *class_def)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->class_idx);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->access_flags);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->superclass_idx);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->interfaces_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->source_file_idx);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->annotations_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->class_data_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->static_values_off);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* DESCRIPTION DE CLASSES DEX */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* field = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'un champ quelconque DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_encoded_field(const GDexFormat *format, vmpa2t *pos, encoded_field *field)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result &= g_binary_content_read_uleb128(content, pos, &field->field_idx_diff);
+ result &= g_binary_content_read_uleb128(content, pos, &field->access_flags);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* method = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une méthode quelconque DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_encoded_method(const GDexFormat *format, vmpa2t *pos, encoded_method *method)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ copy_vmpa(&method->origin, pos);
+
+ result &= g_binary_content_read_uleb128(content, pos, &method->method_idx_diff);
+ result &= g_binary_content_read_uleb128(content, pos, &method->access_flags);
+ result &= g_binary_content_read_uleb128(content, pos, &method->code_off);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* item = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'un type DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_type_item(const GDexFormat *format, vmpa2t *pos, type_item *item)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->type_idx);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* list = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une liste de types DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_type_list(const GDexFormat *format, vmpa2t *pos, type_list *list)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &list->size);
+
+ list->list = (type_item *)g_binary_content_get_raw_access(content, pos, list->size * sizeof(type_item));
+ result &= (list->list != NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* item = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'un contenu de classe DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_class_data_item(const GDexFormat *format, vmpa2t *pos, class_data_item *item)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+ uleb128_t i; /* Boucle de parcours */
+
+ result = true;
+
+ item->static_fields = NULL;
+ item->instance_fields = NULL;
+ item->direct_methods = NULL;
+ item->virtual_methods = NULL;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result &= g_binary_content_read_uleb128(content, pos, &item->static_fields_size);
+ result &= g_binary_content_read_uleb128(content, pos, &item->instance_fields_size);
+ result &= g_binary_content_read_uleb128(content, pos, &item->direct_methods_size);
+ result &= g_binary_content_read_uleb128(content, pos, &item->virtual_methods_size);
+
+ if (result && item->static_fields_size > 0)
+ {
+ item->static_fields = (encoded_field *)calloc(item->static_fields_size, sizeof(encoded_field));
+ if (item->static_fields == NULL) item->static_fields_size = 0;
+
+ for (i = 0; i < item->static_fields_size && result; i++)
+ result = read_dex_encoded_field(format, pos, &item->static_fields[i]);
+
+ }
+
+ if (result && item->instance_fields_size > 0)
+ {
+ item->instance_fields = (encoded_field *)calloc(item->instance_fields_size, sizeof(encoded_field));
+ if (item->instance_fields == NULL) item->instance_fields_size = 0;
+
+ for (i = 0; i < item->instance_fields_size && result; i++)
+ result = read_dex_encoded_field(format, pos, &item->instance_fields[i]);
+
+ }
+
+ if (result && item->direct_methods_size > 0)
+ {
+ item->direct_methods = (encoded_method *)calloc(item->direct_methods_size, sizeof(encoded_method));
+ if (item->direct_methods == NULL) item->direct_methods_size = 0;
+
+ for (i = 0; i < item->direct_methods_size && result; i++)
+ result = read_dex_encoded_method(format, pos, &item->direct_methods[i]);
+
+ }
+
+ if (result && item->virtual_methods_size > 0)
+ {
+ item->virtual_methods = (encoded_method *)calloc(item->virtual_methods_size, sizeof(encoded_method));
+ if (item->virtual_methods == NULL) item->virtual_methods_size = 0;
+
+ for (i = 0; i < item->virtual_methods_size && result; i++)
+ result = read_dex_encoded_method(format, pos, &item->virtual_methods[i]);
+
+ }
+
+ if (!result)
+ reset_dex_class_data_item(item);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = structure à nettoyer. *
+* *
+* Description : Supprime tous les éléments chargés en mémoire à la lecture. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void reset_dex_class_data_item(class_data_item *item)
+{
+ if (item->static_fields != NULL)
+ free(item->static_fields);
+
+ if (item->instance_fields != NULL)
+ free(item->instance_fields);
+
+ if (item->direct_methods != NULL)
+ free(item->direct_methods);
+
+ if (item->virtual_methods != NULL)
+ free(item->virtual_methods);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* PORTION DE CODE EXECUTABLE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* pair = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une association exception <-> code. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_encoded_type_addr_pair(const GDexFormat *format, vmpa2t *pos, encoded_type_addr_pair *pair)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result &= g_binary_content_read_uleb128(content, pos, &pair->type_idx);
+ result &= g_binary_content_read_uleb128(content, pos, &pair->addr);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* handler = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une association exception <-> code. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_encoded_catch_handler(const GDexFormat *format, vmpa2t *pos, encoded_catch_handler *handler)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+ leb128_t count; /* Nombre de gestionnaires */
+ leb128_t i; /* Boucle de parcours */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ handler->offset = get_phy_addr(pos);
+
+ result &= g_binary_content_read_leb128(content, pos, &handler->size);
+
+ count = leb128_abs(handler->size);
+
+ if (count > 0 && result)
+ {
+ handler->handlers = (encoded_type_addr_pair *)calloc(count, sizeof(encoded_type_addr_pair));
+
+ for (i = 0; i < count && result; i++)
+ result &= read_dex_encoded_type_addr_pair(format, pos, &handler->handlers[i]);
+
+ }
+ else handler->handlers = NULL;
+
+ if (handler->size <= 0)
+ result &= g_binary_content_read_uleb128(content, pos, &handler->catch_all_addr);
+
+ else
+ handler->catch_all_addr = ULEB128_MAX;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : handler = structure à nettoyer. *
+* *
+* Description : Supprime tous les éléments chargés en mémoire à la lecture. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void reset_dex_encoded_catch_handler(encoded_catch_handler *handler)
+{
+ if (handler->handlers != NULL)
+ free(handler->handlers);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* list = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une association exception <-> code. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_encoded_catch_handler_list(const GDexFormat *format, vmpa2t *pos, encoded_catch_handler_list *list)
+{
+ bool result; /* Bilan à retourner */
+ off_t saved_off; /* Sauvegarde de position */
+ GBinContent *content; /* Contenu binaire à lire */
+ uleb128_t i; /* Boucle de parcours */
+
+ result = true;
+
+ saved_off = get_phy_addr(pos);
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result &= g_binary_content_read_uleb128(content, pos, &list->size);
+
+ if (list->size > 0 && result)
+ {
+ list->list = (encoded_catch_handler *)calloc(list->size, sizeof(encoded_catch_handler));
+
+ for (i = 0; i < list->size && result; i++)
+ {
+ result &= read_dex_encoded_catch_handler(format, pos, &list->list[i]);
+ if (result) list->list[i].offset -= saved_off;
+ }
+
+ }
+ else list->list = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = structure à nettoyer. *
+* *
+* Description : Supprime tous les éléments chargés en mémoire à la lecture. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void reset_dex_encoded_catch_handler_list(encoded_catch_handler_list *list)
+{
+ uleb128_t i; /* Boucle de parcours */
+
+ if (list->list != NULL)
+ {
+ for (i = 0; i < list->size; i++)
+ reset_dex_encoded_catch_handler(&list->list[i]);
+
+ free(list->list);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* item = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une association exception <-> code. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_try_item(const GDexFormat *format, vmpa2t *pos, try_item *item)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &item->start_addr);
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->insn_count);
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->handler_off);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* item = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une portion de code DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_code_item(const GDexFormat *format, vmpa2t *pos, code_item *item)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+ vmpa2t origin; /* Mémorisation d'une position */
+ uint16_t padding; /* Eventuel alignement */
+ uint16_t i; /* Boucle de parcours */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->registers_size);
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->ins_size);
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->outs_size);
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->tries_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &item->debug_info_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &item->insns_size);
+
+ item->insns = (uint16_t *)g_binary_content_get_raw_access(content, pos, item->insns_size * sizeof(uint16_t));
+ if (item->insns == NULL) goto rdci_bad_insns;
+
+ /* Padding ? */
+ if (item->tries_size > 0 && item->insns_size % 2 == 1)
+ {
+ copy_vmpa(&origin, pos);
+
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &padding);
+
+ if (padding != 0)
+ g_binary_format_add_error(G_BIN_FORMAT(format), BFE_SPECIFICATION, &origin,
+ _("Expected a null value as padding."));
+
+ }
+
+ if (item->tries_size > 0 && result)
+ {
+ assert(get_phy_addr(pos) % 4 == 0);
+
+ item->tries = (try_item *)calloc(item->tries_size, sizeof(try_item));
+ if (item->tries == NULL) goto rdci_bad_tries;
+
+ for (i = 0; i < item->tries_size && result; i++)
+ result &= read_dex_try_item(format, pos, &item->tries[i]);
+
+ if (result)
+ {
+ item->handlers = (encoded_catch_handler_list *)calloc(1, sizeof(encoded_catch_handler_list));
+ result &= read_dex_encoded_catch_handler_list(format, pos, item->handlers);
+ }
+
+ else
+ item->handlers = NULL;
+
+ }
+
+ else
+ {
+ item->tries = NULL;
+ item->handlers = NULL;
+ }
+
+ return result;
+
+ rdci_bad_insns:
+
+ item->tries = NULL;
+
+ rdci_bad_tries:
+
+ item->handlers = NULL;
+
+ return false;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = structure à nettoyer. *
+* *
+* Description : Supprime tous les éléments chargés en mémoire à la lecture. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void reset_dex_code_item(code_item *item)
+{
+ if (item->tries != NULL)
+ free(item->tries);
+
+ if (item->handlers != NULL)
+ {
+ reset_dex_encoded_catch_handler_list(item->handlers);
+ free(item->handlers);
+ }
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* 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, vmpa2t *pos, packed_switch *packed)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+ uint16_t i; /* Boucle de parcours */
+
+ result = true;
+
+ packed->targets = NULL;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &packed->ident);
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &packed->size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &packed->first_key);
+
+ if (result && packed->size > 0)
+ {
+ packed->targets = (uint32_t *)calloc(packed->size, sizeof(uint32_t));
+
+ for (i = 0; i < packed->size && result; i++)
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &packed->targets[i]);
+
+ }
+
+ 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] *
+* sparse = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'un contenu d'aiguillage dispersé. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_sparse_switch(const GDexFormat *format, vmpa2t *pos, sparse_switch *sparse)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+ uint16_t i; /* Boucle de parcours */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ sparse->keys = NULL;
+ sparse->targets = NULL;
+
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &sparse->ident);
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &sparse->size);
+
+ 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));
+
+ for (i = 0; i < sparse->size && result; i++)
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &sparse->keys[i]);
+
+ for (i = 0; i < sparse->size && result; i++)
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &sparse->targets[i]);
+
+ }
+
+ 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, vmpa2t *pos, dex_switch *dswitch)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+ uint16_t ident; /* Pseudo-code d'identification*/
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &ident);
+
+ /**
+ * La tête de lecture n'est pas mise à jour volontairement !
+ */
+
+ 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);
+
+}