/* OpenIDA - Outil d'analyse de fichiers binaires
* operand.c - gestion des operandes de l'architecture Dalvik
*
* 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 "operand.h"
#include
#include
#include "register.h"
#include "../operand-int.h"
/* ----------------------- COQUILLE VIDE POUR OPERANDE DALVIK ----------------------- */
/* Définition d'un opérande de Dalvik (instance) */
struct _GDalvikOperand
{
GArchOperand parent; /* Instance parente */
};
/* Définition d'un opérande de Dalvik (classe) */
struct _GDalvikOperandClass
{
GArchOperandClass parent; /* Classe parente */
};
/* Initialise la classe des opérandes Dalvik de base. */
static void g_dalvik_operand_class_init(GDalvikOperandClass *);
/* Initialise une instance d'opérande de base pour Dalvik. */
static void g_dalvik_operand_init(GDalvikOperand *);
/* --------------------- OPERANDES VISANT UN REGISTRE DE DALVIK --------------------- */
/* Définition d'un opérande visant un registre Dalvik (instance) */
struct _GDalvikRegisterOperand
{
GDalvikOperand parent; /* Instance parente */
GDalvikRegister *reg; /* Registre représenté */
};
/* Définition d'un opérande visant un registre Dalvik (classe) */
struct _GDalvikRegisterOperandClass
{
GDalvikOperandClass parent; /* Classe parente */
};
/* Initialise la classe des opérandes de registre Dalvik. */
static void g_dalvik_register_operand_class_init(GDalvikRegisterOperandClass *);
/* Initialise une instance d'opérande de registre Dalvik. */
static void g_dalvik_register_operand_init(GDalvikRegisterOperand *);
/* Compare un opérande avec un autre. */
static bool g_dalvik_register_operand_compare(const GDalvikRegisterOperand *, const GDalvikRegisterOperand *);
/* Ajoute du texte simple à un fichier ouvert en écriture. */
static void g_dalvik_register_operand_add_text(const GDalvikRegisterOperand *, GRenderingOptions *, MainRendering, FILE *);
/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */
static void g_dalvik_register_operand_to_buffer(const GDalvikRegisterOperand *, GBufferLine *, GRenderingOptions *);
/* -------------------- LISTE D'OPERANDES RASSEMBLES EN ARGUMENT -------------------- */
/* Définition d'un opérande visant une liste d'opérandes Dalvik (instance) */
struct _GDalvikArgsOperand
{
GDalvikOperand parent; /* Instance parente */
GArchOperand **args; /* Liste d'arguments */
size_t count; /* Taille de cette liste */
};
/* Définition d'un opérande visant une liste d'opérandes Dalvik (classe) */
struct _GDalvikArgsOperandClass
{
GDalvikOperandClass parent; /* Classe parente */
};
/* Initialise la classe des listes d'opérandes Dalvik. */
static void g_dalvik_args_operand_class_init(GDalvikArgsOperandClass *);
/* Initialise une instance de liste d'opérandes Dalvik. */
static void g_dalvik_args_operand_init(GDalvikArgsOperand *);
/* Ajoute du texte simple à un fichier ouvert en écriture. */
static void g_dalvik_args_operand_add_text(const GDalvikArgsOperand *, GRenderingOptions *, MainRendering, FILE *);
/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */
static void g_dalvik_args_operand_to_buffer(const GDalvikArgsOperand *, GBufferLine *, GRenderingOptions *);
/* ----------------- OPERANDES POINTANT VERS LA TABLE DE CONSTANTES ----------------- */
/* Définition d'un opérande visant un élément de table de constantes Dalvik (instance) */
struct _GDalvikPoolOperand
{
GDalvikOperand parent; /* Instance parente */
DalvikPoolType type; /* Type de table visée */
uint32_t index; /* Indice de l'élément visé */
};
/* Définition d'un opérande visant un élément de table de constantes Dalvik (classe) */
struct _GDalvikPoolOperandClass
{
GDalvikOperandClass parent; /* Classe parente */
};
/* Initialise la classe des opérandes de constante Dalvik. */
static void g_dalvik_pool_operand_class_init(GDalvikPoolOperandClass *);
/* Initialise une instance d'opérande de constante Dalvik. */
static void g_dalvik_pool_operand_init(GDalvikPoolOperand *);
/* Ajoute du texte simple à un fichier ouvert en écriture. */
static void g_dalvik_pool_operand_add_text(const GDalvikPoolOperand *, GRenderingOptions *, MainRendering, FILE *);
/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */
static void g_dalvik_pool_operand_to_buffer(const GDalvikPoolOperand *, GBufferLine *, GRenderingOptions *);
/* ---------------------- OPERANDES VISANT UNE ADRESSE DE CODE ---------------------- */
/* Définition d'un opérande visant une adresse de code Dalvik (instance) */
struct _GDalvikTargetOperand
{
GDalvikOperand parent; /* Instance parente */
GImmOperand *immediate; /* Adresse visée reconstituée */
};
/* Définition d'un opérande visant une adresse de code Dalvik (classe) */
struct _GDalvikTargetOperandClass
{
GDalvikOperandClass parent; /* Classe parente */
};
/* Initialise la classe des opérandes de ciblage de code Dalvik. */
static void g_dalvik_target_operand_class_init(GDalvikTargetOperandClass *);
/* Initialise une instance d'opérande de ciblage de code Dalvik. */
static void g_dalvik_target_operand_init(GDalvikTargetOperand *);
/* Ajoute du texte simple à un fichier ouvert en écriture. */
static void g_dalvik_target_operand_add_text(const GDalvikTargetOperand *, GRenderingOptions *, MainRendering, FILE *);
/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */
static void g_dalvik_target_operand_to_buffer(const GDalvikTargetOperand *, GBufferLine *, GRenderingOptions *);
/* ------------------------- AIDE A LA CREATION D'OPERANDES ------------------------- */
/* Liste de tous les types d'opérandes */
typedef enum _DalvikOperandID
{
DOI_INVALID,
DOI_REGISTER_4,
DOI_REGISTER_8,
DOI_IMMEDIATE_4,
DOI_IMMEDIATE_8,
DOI_IMMEDIATE_16,
DOI_IMMEDIATE_32,
DOI_IMMEDIATE_64,
DOI_IMMEDIATE_H16,
DOI_POOL_CONST,
DOI_TARGET_8,
DOI_TARGET_16,
DOI_TARGET_32
} DalvikOperandID;
/* Procède à la lecture d'opérandes pour une instruction. */
static bool dalvik_read_basic_operands(GArchInstruction *, const bin_t *, off_t *, off_t, bool *, SourceEndian, DalvikOperandType, va_list);
/* Procède à la lecture d'opérandes pour une instruction. */
static bool dalvik_read_fixed_operands(GArchInstruction *, const bin_t *, off_t *, off_t, bool *, SourceEndian, DalvikOperandType);
/* ---------------------------------------------------------------------------------- */
/* COQUILLE VIDE POUR OPERANDE DALVIK */
/* ---------------------------------------------------------------------------------- */
/* Indique le type défini par la GLib pour un opérande de Dalvik. */
G_DEFINE_TYPE(GDalvikOperand, g_dalvik_operand, G_TYPE_ARCH_OPERAND);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des opérandes Dalvik de base. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_dalvik_operand_class_init(GDalvikOperandClass *klass)
{
}
/******************************************************************************
* *
* Paramètres : operand = instance à initialiser. *
* *
* Description : Initialise une instance d'opérande de base pour Dalvik. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_dalvik_operand_init(GDalvikOperand *operand)
{
}
/* ---------------------------------------------------------------------------------- */
/* OPERANDES VISANT UN REGISTRE DE DALVIK */
/* ---------------------------------------------------------------------------------- */
/* Indique le type défini par la GLib pour un opérande de registre Dalvik. */
G_DEFINE_TYPE(GDalvikRegisterOperand, g_dalvik_register_operand, G_TYPE_DALVIK_OPERAND);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des opérandes de registre Dalvik. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_dalvik_register_operand_class_init(GDalvikRegisterOperandClass *klass)
{
}
/******************************************************************************
* *
* Paramètres : operand = instance à initialiser. *
* *
* Description : Initialise une instance d'opérande de registre Dalvik. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_dalvik_register_operand_init(GDalvikRegisterOperand *operand)
{
GContentExporter *parent; /* Instance parente #1 */
GArchOperand *arch; /* Instance parente #2 */
parent = G_CONTENT_EXPORTER(operand);
parent->add_text = (add_text_fc)g_dalvik_register_operand_add_text;
parent->export_buffer = (export_buffer_fc)g_dalvik_register_operand_to_buffer;
arch = G_ARCH_OPERAND(operand);
arch->compare = (operand_compare_fc)g_dalvik_register_operand_compare;
}
/******************************************************************************
* *
* Paramètres : data = flux de données à analyser. *
* pos = position courante dans ce flux. [OUT] *
* len = taille totale des données à analyser. *
* low = position éventuelle des 4 bits visés. [OUT] *
* size = taille de l'opérande, et donc du registre. *
* endian = ordre des bits dans la source. *
* *
* Description : Crée un opérande visant un registre Dalvik. *
* *
* Retour : Opérande mis en place. *
* *
* Remarques : - *
* *
******************************************************************************/
GArchOperand *g_dalvik_register_operand_new(const bin_t *data, off_t *pos, off_t len, bool *low, MemoryDataSize size, SourceEndian endian)
{
GDalvikRegisterOperand *result; /* Structure à retourner */
uint8_t index8; /* Indice sur 8 bits */
uint16_t index16; /* Indice sur 16 bits */
bool test; /* Bilan de lecture */
switch (size)
{
case MDS_4_BITS:
test = read_u4(&index8, data, pos, len, low, endian);
break;
case MDS_8_BITS:
test = read_u8(&index8, data, pos, len, endian);
break;
case MDS_16_BITS:
test = read_u16(&index16, data, pos, len, endian);
break;
default:
test = false;
break;
}
if (!test)
return NULL;
result = g_object_new(G_TYPE_DALVIK_REGISTER_OPERAND, NULL);
switch (size)
{
case MDS_4_BITS:
case MDS_8_BITS:
result->reg = g_dalvik_register_new(index8);
break;
case MDS_16_BITS:
result->reg = g_dalvik_register_new(index16);
break;
default:
break;
}
return G_ARCH_OPERAND(result);
}
/******************************************************************************
* *
* Paramètres : a = premier opérande à consulter. *
* b = second opérande à consulter. *
* *
* Description : Compare un opérande avec un autre. *
* *
* Retour : Bilan de la comparaison. *
* *
* Remarques : - *
* *
******************************************************************************/
static bool g_dalvik_register_operand_compare(const GDalvikRegisterOperand *a, const GDalvikRegisterOperand *b)
{
return g_dalvik_register_compare(a->reg, b->reg);
}
/******************************************************************************
* *
* Paramètres : operand = opérande à transcrire. *
* options = options de rendu. *
* rendering = support effectif final des lignes de code. *
* stream = flux ouvert en écriture. *
* *
* Description : Ajoute du texte simple à un fichier ouvert en écriture. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_dalvik_register_operand_add_text(const GDalvikRegisterOperand *operand, GRenderingOptions *options, MainRendering rendering, FILE *stream)
{
g_content_exporter_add_text(G_CONTENT_EXPORTER(operand->reg), options, rendering, stream);
}
/******************************************************************************
* *
* Paramètres : operand = opérande à transcrire. *
* buffer = espace où placer ledit contenu. *
* options = options de rendu. *
* *
* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_dalvik_register_operand_to_buffer(const GDalvikRegisterOperand *operand, GBufferLine *buffer, GRenderingOptions *options)
{
g_content_exporter_to_buffer(G_CONTENT_EXPORTER(operand->reg), buffer, options);
}
/* ---------------------------------------------------------------------------------- */
/* LISTE D'OPERANDES RASSEMBLES EN ARGUMENT */
/* ---------------------------------------------------------------------------------- */
/* Indique le type défini par la GLib pour une liste d'arguments Dalvik. */
G_DEFINE_TYPE(GDalvikArgsOperand, g_dalvik_args_operand, G_TYPE_DALVIK_OPERAND);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des listes d'opérandes Dalvik. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_dalvik_args_operand_class_init(GDalvikArgsOperandClass *klass)
{
}
/******************************************************************************
* *
* Paramètres : operand = instance à initialiser. *
* *
* Description : Initialise une instance de liste d'opérandes Dalvik. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_dalvik_args_operand_init(GDalvikArgsOperand *operand)
{
GContentExporter *parent; /* Instance parente */
parent = G_CONTENT_EXPORTER(operand);
parent->add_text = (add_text_fc)g_dalvik_args_operand_add_text;
parent->export_buffer = (export_buffer_fc)g_dalvik_args_operand_to_buffer;
}
/******************************************************************************
* *
* Paramètres : - *
* *
* Description : Crée un réceptacle pour opérandes Dalvik servant d'arguments.*
* *
* Retour : Opérande mis en place. *
* *
* Remarques : - *
* *
******************************************************************************/
GArchOperand *g_dalvik_args_operand_new(void)
{
GDalvikArgsOperand *result; /* Structure à retourner */
result = g_object_new(G_TYPE_DALVIK_ARGS_OPERAND, NULL);
return G_ARCH_OPERAND(result);
}
/******************************************************************************
* *
* Paramètres : operand = opérande à compléter. *
* arg = nouvel argument pour un appel. *
* *
* Description : Ajoute un élément à la liste d'arguments Dalvik. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_dalvik_args_operand_add(GDalvikArgsOperand *operand, GArchOperand *arg)
{
operand->args = (GArchOperand **)realloc(operand->args, ++operand->count * sizeof(GArchOperand *));
operand->args[operand->count - 1] = arg;
}
/******************************************************************************
* *
* Paramètres : operand = opérande à transcrire. *
* options = options de rendu. *
* rendering = support effectif final des lignes de code. *
* stream = flux ouvert en écriture. *
* *
* Description : Ajoute du texte simple à un fichier ouvert en écriture. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_dalvik_args_operand_add_text(const GDalvikArgsOperand *operand, GRenderingOptions *options, MainRendering rendering, FILE *stream)
{
GContentExporter *exporter; /* Autre vision de l'objet */
size_t i; /* Boucle de parcours */
exporter = G_CONTENT_EXPORTER(operand);
g_content_exporter_insert_text(exporter, stream, "{", 1, RTT_HOOK);
if (operand->count > 0)
{
g_content_exporter_add_text(G_CONTENT_EXPORTER(operand->args[0]),
options, rendering, stream);
for (i = 1; i < operand->count; i++)
{
g_content_exporter_insert_text(exporter, stream, ",", 1, RTT_NONE/* FIXME */);
g_content_exporter_insert_text(exporter, stream, " ", 1, RTT_NONE);
g_content_exporter_add_text(G_CONTENT_EXPORTER(operand->args[i]),
options, rendering, stream);
}
}
g_content_exporter_insert_text(exporter, stream, "}", 1, RTT_HOOK);
}
/******************************************************************************
* *
* Paramètres : operand = opérande à transcrire. *
* buffer = espace où placer ledit contenu. *
* options = options de rendu. *
* *
* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_dalvik_args_operand_to_buffer(const GDalvikArgsOperand *operand, GBufferLine *buffer, GRenderingOptions *options)
{
GContentExporter *exporter; /* Autre vision de l'objet */
size_t i; /* Boucle de parcours */
exporter = G_CONTENT_EXPORTER(operand);
g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY,
"{", 1, RTT_HOOK);
if (operand->count > 0)
{
g_content_exporter_to_buffer(G_CONTENT_EXPORTER(operand->args[0]), buffer, options);
for (i = 1; i < operand->count; i++)
{
g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY,
",", 1, RTT_NONE/* FIXME */);
g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY,
" ", 1, RTT_NONE);
g_content_exporter_to_buffer(G_CONTENT_EXPORTER(operand->args[i]), buffer, options);
}
}
g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY,
"}", 1, RTT_HOOK);
}
/* ---------------------------------------------------------------------------------- */
/* OPERANDES POINTANT VERS LA TABLE DE CONSTANTES */
/* ---------------------------------------------------------------------------------- */
/* Indique le type défini par la GLib pour un un élément de table de constantes Dalvik. */
G_DEFINE_TYPE(GDalvikPoolOperand, g_dalvik_pool_operand, G_TYPE_DALVIK_OPERAND);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des opérandes de constante Dalvik. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_dalvik_pool_operand_class_init(GDalvikPoolOperandClass *klass)
{
}
/******************************************************************************
* *
* Paramètres : operand = instance à initialiser. *
* *
* Description : Initialise une instance d'opérande de constante Dalvik. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_dalvik_pool_operand_init(GDalvikPoolOperand *operand)
{
GContentExporter *parent; /* Instance parente */
parent = G_CONTENT_EXPORTER(operand);
parent->add_text = (add_text_fc)g_dalvik_pool_operand_add_text;
parent->export_buffer = (export_buffer_fc)g_dalvik_pool_operand_to_buffer;
}
/******************************************************************************
* *
* Paramètres : type = type de table visée avec la référence. *
* data = flux de données à analyser. *
* pos = position courante dans ce flux. [OUT] *
* len = taille totale des données à analyser. *
* size = taille de l'opérande, et donc du registre. *
* endian = ordre des bits dans la source. *
* *
* Description : Crée un opérande visant un élément constant Dalvik. *
* *
* Retour : Opérande mis en place. *
* *
* Remarques : - *
* *
******************************************************************************/
GArchOperand *g_dalvik_pool_operand_new(DalvikPoolType type, const bin_t *data, off_t *pos, off_t len, MemoryDataSize size, SourceEndian endian)
{
GDalvikPoolOperand *result; /* Structure à retourner */
uint8_t index8; /* Indice sur 8 bits */
uint16_t index16; /* Indice sur 16 bits */
bool test; /* Bilan de lecture */
switch (size)
{
case MDS_8_BITS:
test = read_u8(&index8, data, pos, len, endian);
break;
case MDS_16_BITS:
test = read_u16(&index16, data, pos, len, endian);
break;
default:
test = false;
break;
}
if (!test)
return NULL;
result = g_object_new(G_TYPE_DALVIK_POOL_OPERAND, NULL);
result->type = type;
result->index = (size == MDS_8_BITS ? index8 : index16);
return G_ARCH_OPERAND(result);
}
/******************************************************************************
* *
* Paramètres : operand = opérande à transcrire. *
* options = options de rendu. *
* rendering = support effectif final des lignes de code. *
* stream = flux ouvert en écriture. *
* *
* Description : Ajoute du texte simple à un fichier ouvert en écriture. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_dalvik_pool_operand_add_text(const GDalvikPoolOperand *operand, GRenderingOptions *options, MainRendering rendering, FILE *stream)
{
//g_content_exporter_add_text(G_CONTENT_EXPORTER(operand->reg), options, rendering, stream);
}
/******************************************************************************
* *
* Paramètres : operand = opérande à transcrire. *
* buffer = espace où placer ledit contenu. *
* options = options de rendu. *
* *
* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_dalvik_pool_operand_to_buffer(const GDalvikPoolOperand *operand, GBufferLine *buffer, GRenderingOptions *options)
{
GContentExporter *exporter; /* Autre vision de l'opérande */
char value[20]; /* Chaîne à imprimer */
size_t len; /* Taille de l'élément inséré */
exporter = G_CONTENT_EXPORTER(operand);
switch (operand->type)
{
case DPT_NONE:
g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY,
"????", 4, RTT_SECTION);
break;
case DPT_STRING:
g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY,
"string", 6, RTT_SECTION);
break;
case DPT_TYPE:
g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY,
"type", 4, RTT_SECTION);
break;
case DPT_PROTO:
g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY,
"proto", 5, RTT_SECTION);
break;
case DPT_FIELD:
g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY,
"field", 5, RTT_SECTION);
break;
case DPT_METHOD:
g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY,
"method", 6, RTT_SECTION);
break;
}
g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY,
"@", 1, RTT_SIGNS);
//g_content_exporter_to_buffer(G_CONTENT_EXPORTER(operand->reg), buffer, options);
len = snprintf(value, 20, "%d", operand->index);
/*
strcpy(value, "12345");
len = 5;
*/
g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY,
value, len, RTT_IMMEDIATE);
}
/******************************************************************************
* *
* Paramètres : operand = opérande à consulter. *
* *
* Description : Indique la nature de la table de constantes visée ici. *
* *
* Retour : Type de table constantes visée. *
* *
* Remarques : - *
* *
******************************************************************************/
DalvikPoolType g_dalvik_pool_operand_get_pool_type(const GDalvikPoolOperand *operand)
{
return operand->type;
}
/******************************************************************************
* *
* Paramètres : operand = opérande à consulter. *
* *
* Description : Indique l'indice de l'élément dans la table de constantes. *
* *
* Retour : Indice de l'élément visé dans la table de constantes. *
* *
* Remarques : - *
* *
******************************************************************************/
uint32_t g_dalvik_pool_operand_get_index(const GDalvikPoolOperand *operand)
{
return operand->index;
}
/* ---------------------------------------------------------------------------------- */
/* OPERANDES VISANT UNE ADRESSE DE CODE */
/* ---------------------------------------------------------------------------------- */
/* Indique le type défini par la GLib pour un opérande de ciblage de code Dalvik. */
G_DEFINE_TYPE(GDalvikTargetOperand, g_dalvik_target_operand, G_TYPE_DALVIK_OPERAND);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des opérandes de ciblage de code Dalvik.*
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_dalvik_target_operand_class_init(GDalvikTargetOperandClass *klass)
{
}
/******************************************************************************
* *
* Paramètres : operand = instance à initialiser. *
* *
* Description : Initialise une instance d'opérande de ciblage de code Dalvik.*
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_dalvik_target_operand_init(GDalvikTargetOperand *operand)
{
GContentExporter *parent; /* Instance parente */
parent = G_CONTENT_EXPORTER(operand);
parent->add_text = (add_text_fc)g_dalvik_target_operand_add_text;
parent->export_buffer = (export_buffer_fc)g_dalvik_target_operand_to_buffer;
}
/******************************************************************************
* *
* Paramètres : data = flux de données à analyser. *
* pos = position courante dans ce flux. [OUT] *
* len = taille totale des données à analyser. *
* size = taille de l'opérande. *
* endian = ordre des bits dans la source. *
* base = adresse de référence pour le calcul. *
* *
* Description : Crée un opérande visant un instruction Dalvik. *
* *
* Retour : Opérande mis en place. *
* *
* Remarques : - *
* *
******************************************************************************/
GArchOperand *g_dalvik_target_operand_new(const bin_t *data, off_t *pos, off_t len, MemoryDataSize size, SourceEndian endian, vmpa_t base)
{
GDalvikTargetOperand *result; /* Structure à retourner */
int8_t val8; /* Valeur sur 8 bits */
int16_t val16; /* Valeur sur 16 bits */
int32_t val32; /* Valeur sur 32 bits */
vmpa_t address; /* Adresse finale visée */
switch (size)
{
case MDS_8_BITS_SIGNED:
read_s8(&val8, data, pos, len, endian);
address = base + val8 * sizeof(uint16_t);
break;
case MDS_16_BITS_SIGNED:
read_s16(&val16, data, pos, len, endian);
address = base + val16 * sizeof(uint16_t);
break;
case MDS_32_BITS_SIGNED:
read_s32(&val32, data, pos, len, endian);
address = base + val32 * sizeof(uint16_t);
break;
default:
return NULL;
break;
}
result = g_object_new(G_TYPE_DALVIK_TARGET_OPERAND, NULL);
result->immediate = G_IMM_OPERAND(g_imm_operand_new_from_value(MDS_32_BITS/*FIXME*/, (uint32_t)address/* FIXME */));
return G_ARCH_OPERAND(result);
}
/******************************************************************************
* *
* Paramètres : operand = opérande à transcrire. *
* options = options de rendu. *
* rendering = support effectif final des lignes de code. *
* stream = flux ouvert en écriture. *
* *
* Description : Ajoute du texte simple à un fichier ouvert en écriture. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_dalvik_target_operand_add_text(const GDalvikTargetOperand *operand, GRenderingOptions *options, MainRendering rendering, FILE *stream)
{
g_content_exporter_add_text(G_CONTENT_EXPORTER(operand->immediate), options, rendering, stream);
}
/******************************************************************************
* *
* Paramètres : operand = opérande à transcrire. *
* buffer = espace où placer ledit contenu. *
* options = options de rendu. *
* *
* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_dalvik_target_operand_to_buffer(const GDalvikTargetOperand *operand, GBufferLine *buffer, GRenderingOptions *options)
{
g_content_exporter_to_buffer(G_CONTENT_EXPORTER(operand->immediate), buffer, options);
}
/******************************************************************************
* *
* Paramètres : operand = opérande à traiter. *
* *
* Description : Fournit l'adresse représentée par une opérande Dalvik. *
* *
* Retour : Valeur portée par l'opérande. *
* *
* Remarques : - *
* *
******************************************************************************/
const GImmOperand *g_dalvik_target_operand_get_value(const GDalvikTargetOperand *operand)
{
return operand->immediate;
}
/* ---------------------------------------------------------------------------------- */
/* AIDE A LA CREATION D'OPERANDES */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
* Paramètres : instr = instruction dont la définition est incomplète. [OUT]*
* data = flux de données à analyser. *
* pos = position courante dans ce flux. [OUT] *
* len = taille totale des données à analyser. *
* low = position éventuelle des 4 bits visés. [OUT] *
* endian = boutisme lié au binaire accompagnant. *
* model = type d'opérandes attendues. *
* ap = éventuels arguments complémentaires. *
* *
* Description : Procède à la lecture d'opérandes pour une instruction. *
* *
* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
* *
* Remarques : - *
* *
******************************************************************************/
static bool dalvik_read_basic_operands(GArchInstruction *instr, const bin_t *data, off_t *pos, off_t len, bool *low, SourceEndian endian, DalvikOperandType model, va_list ap)
{
bool result; /* Bilan à retourner */
DalvikOperandID *types; /* Liste des chargements */
DalvikOperandID *iter; /* Boucle de parcours */
GArchOperand *op; /* Opérande unique décodé */
uint16_t value16; /* Valeur sur 16 bits */
result = true;
/* Choix des opérandes à charger */
switch (model & ~DALVIK_OP_EXTRA_MASK)
{
case DALVIK_OPT_10T:
types = (DalvikOperandID []) {
DOI_TARGET_8,
DOI_INVALID
};
break;
case DALVIK_OPT_11N:
types = (DalvikOperandID []) {
DOI_REGISTER_4,
DOI_IMMEDIATE_4,
DOI_INVALID
};
break;
case DALVIK_OPT_11X:
types = (DalvikOperandID []) {
DOI_REGISTER_8,
DOI_INVALID
};
break;
case DALVIK_OPT_12X:
types = (DalvikOperandID []) {
DOI_REGISTER_4,
DOI_REGISTER_4,
DOI_INVALID
};
break;
case DALVIK_OPT_20T:
types = (DalvikOperandID []) {
DOI_TARGET_16,
DOI_INVALID
};
break;
case DALVIK_OPT_21C:
types = (DalvikOperandID []) {
DOI_REGISTER_8,
DOI_POOL_CONST,
DOI_INVALID
};
break;
case DALVIK_OPT_21H:
types = (DalvikOperandID []) {
DOI_REGISTER_8,
DOI_IMMEDIATE_H16,
DOI_INVALID
};
break;
case DALVIK_OPT_21S:
types = (DalvikOperandID []) {
DOI_REGISTER_8,
DOI_IMMEDIATE_16,
DOI_INVALID
};
break;
case DALVIK_OPT_21T:
types = (DalvikOperandID []) {
DOI_REGISTER_8,
DOI_TARGET_16,
DOI_INVALID
};
break;
case DALVIK_OPT_22B:
types = (DalvikOperandID []) {
DOI_REGISTER_8,
DOI_REGISTER_8,
DOI_IMMEDIATE_8,
DOI_INVALID
};
break;
case DALVIK_OPT_22C:
types = (DalvikOperandID []) {
DOI_REGISTER_4,
DOI_REGISTER_4,
DOI_POOL_CONST,
DOI_INVALID
};
break;
case DALVIK_OPT_22S:
types = (DalvikOperandID []) {
DOI_REGISTER_4,
DOI_REGISTER_4,
DOI_IMMEDIATE_16,
DOI_INVALID
};
break;
case DALVIK_OPT_22T:
types = (DalvikOperandID []) {
DOI_REGISTER_4,
DOI_REGISTER_4,
DOI_TARGET_16,
DOI_INVALID
};
break;
case DALVIK_OPT_23X:
types = (DalvikOperandID []) {
DOI_REGISTER_8,
DOI_REGISTER_8,
DOI_REGISTER_8,
DOI_INVALID
};
break;
case DALVIK_OPT_30T:
types = (DalvikOperandID []) {
DOI_TARGET_32,
DOI_INVALID
};
break;
case DALVIK_OPT_31I:
types = (DalvikOperandID []) {
DOI_REGISTER_8,
DOI_IMMEDIATE_32,
DOI_INVALID
};
break;
case DALVIK_OPT_51L:
types = (DalvikOperandID []) {
DOI_REGISTER_8,
DOI_IMMEDIATE_64,
DOI_INVALID
};
break;
default:
types = (DalvikOperandID []) {
DOI_INVALID
};
break;
}
/* Chargement des opérandes */
for (iter = types; *iter != G_TYPE_INVALID && result; iter++)
{
switch (*iter)
{
case DOI_REGISTER_4:
op = g_dalvik_register_operand_new(data, pos, len, low, MDS_4_BITS, endian);
break;
case DOI_REGISTER_8:
op = g_dalvik_register_operand_new(data, pos, len, NULL, MDS_8_BITS, endian);
break;
case DOI_IMMEDIATE_4:
op = _g_imm_operand_new_from_data(MDS_4_BITS, data, pos, len, low, endian);
break;
case DOI_IMMEDIATE_8:
op = g_imm_operand_new_from_data(MDS_8_BITS, data, pos, len, endian);
break;
case DOI_IMMEDIATE_16:
op = g_imm_operand_new_from_data(MDS_16_BITS, data, pos, len, endian);
break;
case DOI_IMMEDIATE_32:
op = g_imm_operand_new_from_data(MDS_32_BITS, data, pos, len, endian);
break;
case DOI_IMMEDIATE_64:
op = g_imm_operand_new_from_data(MDS_64_BITS, data, pos, len, endian);
break;
case DOI_IMMEDIATE_H16:
result = read_u16(&value16, data, pos, len, endian);
if (result)
op = g_imm_operand_new_from_value(MDS_32_BITS_SIGNED, ((uint32_t)value16) << 16);
break;
case DOI_POOL_CONST:
op = g_dalvik_pool_operand_new(DALVIK_OP_GET_POOL(model), data, pos, len, MDS_16_BITS, endian);
break;
case DOI_TARGET_8:
op = g_dalvik_target_operand_new(data, pos, len, MDS_8_BITS_SIGNED, endian, va_arg(ap, vmpa_t));
break;
case DOI_TARGET_16:
op = g_dalvik_target_operand_new(data, pos, len, MDS_16_BITS_SIGNED, endian, va_arg(ap, vmpa_t));
break;
case DOI_TARGET_32:
op = g_dalvik_target_operand_new(data, pos, len, MDS_32_BITS_SIGNED, endian, va_arg(ap, vmpa_t));
break;
default:
op = NULL;
break;
}
if (op == NULL) result = false;
else g_arch_instruction_attach_extra_operand(instr, op);
}
return result;
}
/******************************************************************************
* *
* Paramètres : instr = instruction dont la définition est incomplète. [OUT]*
* data = flux de données à analyser. *
* pos = position courante dans ce flux. [OUT] *
* len = taille totale des données à analyser. *
* low = position éventuelle des 4 bits visés. [OUT] *
* endian = boutisme lié au binaire accompagnant. *
* model = type d'opérandes attendues. *
* *
* Description : Procède à la lecture d'opérandes pour une instruction. *
* *
* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
* *
* Remarques : - *
* *
******************************************************************************/
static bool dalvik_read_fixed_operands(GArchInstruction *instr, const bin_t *data, off_t *pos, off_t len, bool *low, SourceEndian endian, DalvikOperandType model)
{
GArchOperand *opa; /* Opérande vA décodé */
uint8_t b; /* Nbre. de registres utilisés */
GArchOperand *target1; /* Opérande visant la table #1 */
GArchOperand *target2; /* Opérande visant la table #2 */
GArchOperand *args; /* Liste des opérandes */
uint8_t i; /* Boucle de parcours */
GArchOperand *op; /* Opérande unique décodé */
opa = g_dalvik_register_operand_new(data, pos, len, low, MDS_4_BITS, endian);
if (!read_u4(&b, data, pos, len, low, endian))
goto err_va;
target1 = g_dalvik_pool_operand_new(DALVIK_OP_GET_POOL(model), data, pos, len, MDS_16_BITS, endian);
if (target1 == NULL) goto err_target1;
target2 = NULL;
if (0)
{
/* FIXME */
if (target2 == NULL) goto err_target2;
}
args = g_dalvik_args_operand_new();
g_arch_instruction_attach_extra_operand(instr, args);
/* Mise en place des arguments */
for (i = 0; i < MIN(b, 4); i++)
{
op = g_dalvik_register_operand_new(data, pos, len, low, MDS_4_BITS, endian);
if (op == NULL) goto err_registers;
g_dalvik_args_operand_add(G_DALVIK_ARGS_OPERAND(args), op);
}
/* Rajout des éléments finaux déjà chargés */
if (b < 5) g_object_unref(G_OBJECT(opa));
else g_dalvik_args_operand_add(G_DALVIK_ARGS_OPERAND(args), opa);
g_arch_instruction_attach_extra_operand(instr, target1);
if (target2 != NULL)
g_arch_instruction_attach_extra_operand(instr, target2);
return true;
err_registers:
if (target2 != NULL)
g_object_unref(G_OBJECT(target2));
err_target2:
g_object_unref(G_OBJECT(target1));
err_target1:
g_object_unref(G_OBJECT(opa));
err_va:
return false;
}
/******************************************************************************
* *
* Paramètres : instr = instruction dont la définition est incomplète. [OUT]*
* data = flux de données à analyser. *
* pos = position courante dans ce flux. [OUT] *
* len = taille totale des données à analyser. *
* endian = boutisme lié au binaire accompagnant. *
* model = type d'opérandes attendues. *
* ... = éventuelles données complémentaires. *
* *
* Description : Procède à la lecture d'opérandes pour une instruction. *
* *
* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
* *
* Remarques : - *
* *
******************************************************************************/
bool dalvik_read_operands(GArchInstruction *instr, const bin_t *data, off_t *pos, off_t len, SourceEndian endian, DalvikOperandType model, ...)
{
bool result; /* Bilan à retourner */
bool low;
off_t old_pos;
va_list ap; /* Arguments complémentaires */
off_t length;
result = true;
old_pos = *pos;
low = true;
switch (model & ~DALVIK_OP_EXTRA_MASK)
{
case DALVIK_OPT_10T:
case DALVIK_OPT_11N:
case DALVIK_OPT_11X:
case DALVIK_OPT_12X:
case DALVIK_OPT_20T:
case DALVIK_OPT_21C:
case DALVIK_OPT_21H:
case DALVIK_OPT_21S:
case DALVIK_OPT_21T:
case DALVIK_OPT_22B:
case DALVIK_OPT_22C:
case DALVIK_OPT_22S:
case DALVIK_OPT_22T:
case DALVIK_OPT_23X:
case DALVIK_OPT_30T:
case DALVIK_OPT_31I:
case DALVIK_OPT_51L:
va_start(ap, model);
result = dalvik_read_basic_operands(instr, data, pos, len, &low, endian, model, ap);
va_end(ap);
break;
case DALVIK_OPT_35C:
result = dalvik_read_fixed_operands(instr, data, pos, len, &low, endian, model);
break;
default:
break;
}
*pos = old_pos;
if (*pos < len)
{
(*pos)++;
length = DALVIK_OP_GET_LEN(model);
if (length > 1)
*pos += (length - 1) * sizeof(uint16_t);
}
return result;
}