summaryrefslogtreecommitdiff
path: root/src/arch/dalvik/operand.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2016-02-10 10:02:16 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2016-02-10 10:02:16 (GMT)
commit465488d5b231c2552116a305c48b5fcccea55a09 (patch)
treef4d072ad9cf56466f4e55d0608f7a3fe9204efaf /src/arch/dalvik/operand.c
parent946f5f093c7265dc5a5e00694325605b249eea43 (diff)
Improved the support of the DEX format.
Diffstat (limited to 'src/arch/dalvik/operand.c')
-rw-r--r--src/arch/dalvik/operand.c99
1 files changed, 88 insertions, 11 deletions
diff --git a/src/arch/dalvik/operand.c b/src/arch/dalvik/operand.c
index f8f7b39..83d95e5 100644
--- a/src/arch/dalvik/operand.c
+++ b/src/arch/dalvik/operand.c
@@ -24,6 +24,7 @@
#include "operand.h"
+#include <assert.h>
#include <malloc.h>
#include <stdarg.h>
@@ -56,7 +57,7 @@ typedef enum _DalvikOperandID
/* Procède à la lecture d'opérandes pour une instruction. */
-static bool dalvik_read_basic_operands(GArchInstruction *, GDexFormat *, const GBinContent *, vmpa2t *, bool *, SourceEndian, DalvikOperandType, va_list);
+static bool dalvik_read_basic_operands(GArchInstruction *, GDexFormat *, const GBinContent *, vmpa2t *, bool *, SourceEndian, DalvikOperandType, ...);
/* Procède à la lecture d'opérandes pour une instruction. */
static bool dalvik_read_fixed_operands(GArchInstruction *, GDexFormat *, const GBinContent *, vmpa2t *, bool *, SourceEndian, DalvikOperandType);
@@ -75,7 +76,7 @@ static bool dalvik_read_variatic_operands(GArchInstruction *, GDexFormat *, cons
* 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. *
+* ... = éventuels arguments complémentaires. *
* *
* Description : Procède à la lecture d'opérandes pour une instruction. *
* *
@@ -85,7 +86,7 @@ static bool dalvik_read_variatic_operands(GArchInstruction *, GDexFormat *, cons
* *
******************************************************************************/
-static bool dalvik_read_basic_operands(GArchInstruction *instr, GDexFormat *format, const GBinContent *content, vmpa2t *pos, bool *low, SourceEndian endian, DalvikOperandType model, va_list ap)
+static bool dalvik_read_basic_operands(GArchInstruction *instr, GDexFormat *format, const GBinContent *content, vmpa2t *pos, bool *low, SourceEndian endian, DalvikOperandType model, ...)
{
bool result; /* Bilan à retourner */
DalvikOperandID *types; /* Liste des chargements */
@@ -93,6 +94,8 @@ static bool dalvik_read_basic_operands(GArchInstruction *instr, GDexFormat *form
GArchOperand *op; /* Opérande unique décodé */
uint16_t value16; /* Valeur sur 16 bits */
DalvikPoolType pool_type; /* Type de table à manipuler */
+ va_list ap; /* Arguments complémentaires */
+ const vmpa2t *base; /* Base pour les sauts de code */
result = true;
@@ -334,15 +337,24 @@ static bool dalvik_read_basic_operands(GArchInstruction *instr, GDexFormat *form
break;
case DOI_TARGET_8:
- op = g_dalvik_target_operand_new(content, pos, MDS_8_BITS_SIGNED, endian, va_arg(ap, vmpa_t));
+ va_start(ap, model);
+ base = va_arg(ap, const vmpa2t *);
+ op = g_dalvik_target_operand_new(content, pos, MDS_8_BITS_SIGNED, endian, base);
+ va_end(ap);
break;
case DOI_TARGET_16:
- op = g_dalvik_target_operand_new(content, pos, MDS_16_BITS_SIGNED, endian, va_arg(ap, vmpa_t));
+ va_start(ap, model);
+ base = va_arg(ap, const vmpa2t *);
+ op = g_dalvik_target_operand_new(content, pos, MDS_16_BITS_SIGNED, endian, base);
+ va_end(ap);
break;
case DOI_TARGET_32:
- op = g_dalvik_target_operand_new(content, pos, MDS_32_BITS_SIGNED, endian, va_arg(ap, vmpa_t));
+ va_start(ap, model);
+ base = va_arg(ap, const vmpa2t *);
+ op = g_dalvik_target_operand_new(content, pos, MDS_32_BITS_SIGNED, endian, base);
+ va_end(ap);
break;
default:
@@ -413,6 +425,12 @@ static bool dalvik_read_fixed_operands(GArchInstruction *instr, GDexFormat *form
}
+ /* Consommation pleine et entière */
+
+ for (; i < 4; i++)
+ if (!g_binary_content_read_u4(content, pos, low, (uint8_t []) { 0 }))
+ goto err_padding;
+
/* Rajout des éléments finaux déjà chargés */
if (a == 5)
@@ -428,6 +446,8 @@ static bool dalvik_read_fixed_operands(GArchInstruction *instr, GDexFormat *form
return true;
+ err_padding:
+
err_registers:
g_object_unref(G_OBJECT(target));
@@ -522,7 +542,6 @@ static bool dalvik_read_variatic_operands(GArchInstruction *instr, GDexFormat *f
* pos = position courante dans ce flux. [OUT] *
* 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. *
* *
@@ -532,12 +551,21 @@ static bool dalvik_read_variatic_operands(GArchInstruction *instr, GDexFormat *f
* *
******************************************************************************/
-bool dalvik_read_operands(GArchInstruction *instr, GExeFormat *format, const GBinContent *content, vmpa2t *pos, SourceEndian endian, DalvikOperandType model, ...)
+bool dalvik_read_operands(GArchInstruction *instr, GExeFormat *format, const GBinContent *content, vmpa2t *pos, SourceEndian endian, DalvikOperandType model)
{
bool result; /* Bilan à retourner */
GDexFormat *dformat; /* Autre version du format */
bool low; /* Partie d'octets à lire */
+#ifndef NDEBUG
+ vmpa2t old; /* Position avant traitements */
+#endif
+ vmpa2t base; /* Base pour les sauts de code */
+ vmpa2t *extra; /* Information complémentaire */
va_list ap; /* Arguments complémentaires */
+#ifndef NDEBUG
+ phys_t expected; /* Consommation attendue */
+ phys_t consumed; /* Consommation réelle */
+#endif
result = true;
@@ -545,6 +573,42 @@ bool dalvik_read_operands(GArchInstruction *instr, GExeFormat *format, const GBi
low = true;
+#ifndef NDEBUG
+
+ copy_vmpa(&old, pos);
+
+#endif
+
+ /* Récupération de la base ? */
+
+ if (DALVIK_OP_GET_MNEMONIC(model) == 'T')
+ {
+ extra = &base;
+
+ copy_vmpa(extra, pos);
+ deminish_vmpa(extra, 1);
+
+ }
+ else extra = NULL;
+
+ /* Bourrage : ØØ|op ? */
+
+ switch (model & ~DALVIK_OP_EXTRA_MASK)
+ {
+ case DALVIK_OPT_10X:
+ case DALVIK_OPT_20T:
+ case DALVIK_OPT_30T:
+ case DALVIK_OPT_32X:
+ advance_vmpa(pos, 1);
+ break;
+
+ default:
+ break;
+
+ }
+
+ /* Décodage... */
+
switch (model & ~DALVIK_OP_EXTRA_MASK)
{
case DALVIK_OPT_10T:
@@ -568,9 +632,7 @@ bool dalvik_read_operands(GArchInstruction *instr, GExeFormat *format, const GBi
case DALVIK_OPT_31T:
case DALVIK_OPT_32X:
case DALVIK_OPT_51L:
- va_start(ap, model);
- result = dalvik_read_basic_operands(instr, dformat, content, pos, &low, endian, model, ap);
- va_end(ap);
+ result = dalvik_read_basic_operands(instr, dformat, content, pos, &low, endian, model, extra);
break;
case DALVIK_OPT_35C:
@@ -588,6 +650,21 @@ bool dalvik_read_operands(GArchInstruction *instr, GExeFormat *format, const GBi
}
+#ifndef NDEBUG
+
+ /* Vérification d'implémentation */
+
+ if (result)
+ {
+ expected = DALVIK_OP_GET_LEN(model) * 2;
+ consumed = 1 + compute_vmpa_diff(&old, pos);
+
+ assert(consumed == expected);
+
+ }
+
+#endif
+
return result;
}