/* OpenIDA - Outil d'analyse de fichiers binaires
* dex-int.c - structures internes du format DEX
*
* 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 .
*/
#include "dex-int.h"
#include
#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 */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
* 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, off_t *pos, string_id_item *str_id)
{
bool result; /* Bilan à retourner */
const bin_t *content; /* Contenu binaire à lire */
off_t length; /* Taille totale du contenu */
result = true;
content = G_BIN_FORMAT(format)->content;
length = G_BIN_FORMAT(format)->length;
result &= read_u32(&str_id->string_data_off, content, pos, length, SRE_LITTLE);
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, off_t *pos, string_data_item *str_data)
{
bool result; /* Bilan à retourner */
const bin_t *content; /* Contenu binaire à lire */
off_t length; /* Taille totale du contenu */
result = true;
content = G_BIN_FORMAT(format)->content;
length = G_BIN_FORMAT(format)->length;
result &= read_uleb128(&str_data->utf16_size, content, pos, length);
str_data->data = &content[*pos];
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, off_t *pos, type_id_item *item)
{
bool result; /* Bilan à retourner */
const bin_t *content; /* Contenu binaire à lire */
off_t length; /* Taille totale du contenu */
result = true;
content = G_BIN_FORMAT(format)->content;
length = G_BIN_FORMAT(format)->length;
result &= read_u32(&item->descriptor_idx, content, pos, length, SRE_LITTLE);
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, off_t *pos, proto_id_item *proto_id)
{
bool result; /* Bilan à retourner */
const bin_t *content; /* Contenu binaire à lire */
off_t length; /* Taille totale du contenu */
result = true;
content = G_BIN_FORMAT(format)->content;
length = G_BIN_FORMAT(format)->length;
result &= read_u32(&proto_id->shorty_idx, content, pos, length, SRE_LITTLE);
result &= read_u32(&proto_id->return_type_idx, content, pos, length, SRE_LITTLE);
result &= read_u32(&proto_id->parameters_off, content, pos, length, SRE_LITTLE);
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, off_t *pos, field_id_item *field_id)
{
bool result; /* Bilan à retourner */
const bin_t *content; /* Contenu binaire à lire */
off_t length; /* Taille totale du contenu */
result = true;
content = G_BIN_FORMAT(format)->content;
length = G_BIN_FORMAT(format)->length;
result &= read_u16(&field_id->class_idx, content, pos, length, SRE_LITTLE);
result &= read_u16(&field_id->type_idx, content, pos, length, SRE_LITTLE);
result &= read_u32(&field_id->name_idx, content, pos, length, SRE_LITTLE);
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, off_t *pos, method_id_item *meth_id)
{
bool result; /* Bilan à retourner */
const bin_t *content; /* Contenu binaire à lire */
off_t length; /* Taille totale du contenu */
result = true;
content = G_BIN_FORMAT(format)->content;
length = G_BIN_FORMAT(format)->length;
result &= read_u16(&meth_id->class_idx, content, pos, length, SRE_LITTLE);
result &= read_u16(&meth_id->proto_idx, content, pos, length, SRE_LITTLE);
result &= read_u32(&meth_id->name_idx, content, pos, length, SRE_LITTLE);
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, off_t *pos, class_def_item *class_def)
{
bool result; /* Bilan à retourner */
const bin_t *content; /* Contenu binaire à lire */
off_t length; /* Taille totale du contenu */
result = true;
content = G_BIN_FORMAT(format)->content;
length = G_BIN_FORMAT(format)->length;
result &= read_u32(&class_def->class_idx, content, pos, length, SRE_LITTLE);
result &= read_u32(&class_def->access_flags, content, pos, length, SRE_LITTLE);
result &= read_u32(&class_def->superclass_idx, content, pos, length, SRE_LITTLE);
result &= read_u32(&class_def->interfaces_off, content, pos, length, SRE_LITTLE);
result &= read_u32(&class_def->source_file_idx, content, pos, length, SRE_LITTLE);
result &= read_u32(&class_def->annotations_off, content, pos, length, SRE_LITTLE);
result &= read_u32(&class_def->class_data_off, content, pos, length, SRE_LITTLE);
result &= read_u32(&class_def->static_values_off, content, pos, length, SRE_LITTLE);
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, off_t *pos, encoded_field *field)
{
bool result; /* Bilan à retourner */
const bin_t *content; /* Contenu binaire à lire */
off_t length; /* Taille totale du contenu */
result = true;
content = G_BIN_FORMAT(format)->content;
length = G_BIN_FORMAT(format)->length;
result &= read_uleb128(&field->field_idx_diff, content, pos, length);
result &= read_uleb128(&field->access_flags, content, pos, length);
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, off_t *pos, encoded_method *method)
{
bool result; /* Bilan à retourner */
const bin_t *content; /* Contenu binaire à lire */
off_t length; /* Taille totale du contenu */
result = true;
content = G_BIN_FORMAT(format)->content;
length = G_BIN_FORMAT(format)->length;
result &= read_uleb128(&method->method_idx_diff, content, pos, length);
result &= read_uleb128(&method->access_flags, content, pos, length);
result &= read_uleb128(&method->code_off, content, pos, length);
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, off_t *pos, type_item *item)
{
bool result; /* Bilan à retourner */
const bin_t *content; /* Contenu binaire à lire */
off_t length; /* Taille totale du contenu */
result = true;
content = G_BIN_FORMAT(format)->content;
length = G_BIN_FORMAT(format)->length;
result &= read_u16(&item->type_idx, content, pos, length, SRE_LITTLE);
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, off_t *pos, type_list *list)
{
bool result; /* Bilan à retourner */
const bin_t *content; /* Contenu binaire à lire */
off_t length; /* Taille totale du contenu */
result = true;
content = G_BIN_FORMAT(format)->content;
length = G_BIN_FORMAT(format)->length;
result &= read_u32(&list->size, content, pos, length, SRE_LITTLE);
list->list = (type_item *)&content[*pos];
result &= ((*pos + list->size * sizeof(type_item)) <= length);
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, off_t *pos, class_data_item *item)
{
bool result; /* Bilan à retourner */
const bin_t *content; /* Contenu binaire à lire */
off_t length; /* Taille totale du contenu */
uleb128_t i; /* Boucle de parcours */
result = true;
content = G_BIN_FORMAT(format)->content;
length = G_BIN_FORMAT(format)->length;
item->static_fields = NULL;
item->instance_fields = NULL;
item->direct_methods = NULL;
item->virtual_methods = NULL;
result &= read_uleb128(&item->static_fields_size, content, pos, length);
result &= read_uleb128(&item->instance_fields_size, content, pos, length);
result &= read_uleb128(&item->direct_methods_size, content, pos, length);
result &= read_uleb128(&item->virtual_methods_size, content, pos, length);
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, off_t *pos, encoded_type_addr_pair *pair)
{
bool result; /* Bilan à retourner */
const bin_t *content; /* Contenu binaire à lire */
off_t length; /* Taille totale du contenu */
result = true;
content = G_BIN_FORMAT(format)->content;
length = G_BIN_FORMAT(format)->length;
result &= read_uleb128(&pair->type_idx, content, pos, length);
result &= read_uleb128(&pair->addr, content, pos, length);
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, off_t *pos, encoded_catch_handler *handler)
{
bool result; /* Bilan à retourner */
const bin_t *content; /* Contenu binaire à lire */
off_t length; /* Taille totale du contenu */
leb128_t count; /* Nombre de gestionnaires */
leb128_t i; /* Boucle de parcours */
result = true;
content = G_BIN_FORMAT(format)->content;
length = G_BIN_FORMAT(format)->length;
handler->offset = *pos;
result &= read_leb128(&handler->size, content, pos, length);
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 &= read_uleb128(&handler->catch_all_addr, content, pos, length);
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, off_t *pos, encoded_catch_handler_list *list)
{
bool result; /* Bilan à retourner */
const bin_t *content; /* Contenu binaire à lire */
off_t length; /* Taille totale du contenu */
off_t saved_off; /* Sauvegarde de position */
uleb128_t i; /* Boucle de parcours */
result = true;
content = G_BIN_FORMAT(format)->content;
length = G_BIN_FORMAT(format)->length;
saved_off = *pos;
result &= read_uleb128(&list->size, content, pos, length);
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, off_t *pos, try_item *item)
{
bool result; /* Bilan à retourner */
const bin_t *content; /* Contenu binaire à lire */
off_t length; /* Taille totale du contenu */
result = true;
content = G_BIN_FORMAT(format)->content;
length = G_BIN_FORMAT(format)->length;
result &= read_u32(&item->start_addr, content, pos, length, SRE_LITTLE);
result &= read_u16(&item->insn_count, content, pos, length, SRE_LITTLE);
result &= read_u16(&item->handler_off, content, pos, length, SRE_LITTLE);
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, off_t *pos, code_item *item)
{
bool result; /* Bilan à retourner */
const bin_t *content; /* Contenu binaire à lire */
off_t length; /* Taille totale du contenu */
uint16_t padding; /* Eventuel alignement */
uint16_t i; /* Boucle de parcours */
result = true;
content = G_BIN_FORMAT(format)->content;
length = G_BIN_FORMAT(format)->length;
result &= read_u16(&item->registers_size, content, pos, length, SRE_LITTLE);
result &= read_u16(&item->ins_size, content, pos, length, SRE_LITTLE);
result &= read_u16(&item->outs_size, content, pos, length, SRE_LITTLE);
result &= read_u16(&item->tries_size, content, pos, length, SRE_LITTLE);
result &= read_u32(&item->debug_info_off, content, pos, length, SRE_LITTLE);
result &= read_u32(&item->insns_size, content, pos, length, SRE_LITTLE);
item->insns = (uint16_t *)pos;
*pos += item->insns_size * sizeof(uint16_t);
/* Padding ? */
if (item->tries_size > 0 && item->insns_size % 2 == 1)
result &= read_u16(&padding, content, pos, length, SRE_LITTLE);
if (item->tries_size > 0 && result)
{
item->tries = (try_item *)calloc(item->tries_size, sizeof(try_item));
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);
}
}
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_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, 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] *
* 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, off_t *pos, sparse_switch *sparse)
{
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;
sparse->keys = NULL;
sparse->targets = NULL;
result &= read_u16(&sparse->ident, content, pos, length, SRE_LITTLE);
result &= read_u16(&sparse->size, 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));
for (i = 0; i < sparse->size && result; i++)
result &= read_u32(&sparse->keys[i], content, pos, length, SRE_LITTLE);
for (i = 0; i < sparse->size && result; i++)
result &= read_u32(&sparse->targets[i], 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);
}