From 465488d5b231c2552116a305c48b5fcccea55a09 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Wed, 10 Feb 2016 11:02:16 +0100 Subject: Improved the support of the DEX format. --- ChangeLog | 39 +++++++++++++++ src/analysis/disass/links.c | 19 ++++++-- src/arch/dalvik/instruction.c | 27 +++++++++++ src/arch/dalvik/operand.c | 99 ++++++++++++++++++++++++++++++++++----- src/arch/dalvik/operand.h | 4 +- src/arch/dalvik/operands/target.c | 17 ++++--- src/arch/dalvik/operands/target.h | 2 +- src/arch/processor.c | 3 ++ src/format/dex/class.c | 47 +++++++++++++++++-- src/format/dex/class.h | 8 +++- src/format/dex/dex.c | 40 ++++++++++++++-- src/format/dex/dex.h | 4 ++ src/format/dex/method.c | 9 ++-- src/format/dex/method.h | 2 +- src/format/elf/elf.c | 12 ++--- src/format/executable-int.c | 8 +++- src/format/format-int.h | 6 +-- src/format/format.c | 29 +++++++++++- 18 files changed, 330 insertions(+), 45 deletions(-) diff --git a/ChangeLog b/ChangeLog index ddd89ea..e9f09cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,42 @@ +16-02-10 Cyrille Bagard + + * src/analysis/disass/links.c: + Translate immediate values into targets with mode care. + + * src/arch/dalvik/instruction.c: + Provide the encoding of Dalvik instructions, as required. + + * src/arch/dalvik/operand.c: + * src/arch/dalvik/operand.h: + Update the decoding of operands. Check the quantity of bytes consumed + from the binary stream. + + * src/arch/dalvik/operands/target.c: + * src/arch/dalvik/operands/target.h: + Update code. + + * src/arch/processor.c: + Check all decoded instructions have a full defined location. + + * src/format/dex/class.c: + * src/format/dex/class.h: + * src/format/dex/dex.c: + * src/format/dex/dex.h: + * src/format/dex/method.c: + * src/format/dex/method.h: + Improve the support of the DEX format. + + * src/format/elf/elf.c: + Update code. + + * src/format/executable-int.c: + Create full defined locations for architectures without virtual + addresses support. + + * src/format/format-int.h: + * src/format/format.c: + Implement common code to complete format loading. + 16-02-09 Cyrille Bagard * src/arch/raw.c: diff --git a/src/analysis/disass/links.c b/src/analysis/disass/links.c index 8d826c5..5e1e483 100644 --- a/src/analysis/disass/links.c +++ b/src/analysis/disass/links.c @@ -26,6 +26,7 @@ #include "../../arch/instruction.h" +#include "../../arch/raw.h" #include "../../arch/target.h" @@ -128,6 +129,7 @@ static void establish_natural_link(GArchInstruction *instr, GArchInstruction *pr static void convert_immediate_into_target(GArchInstruction *instr, size_t index, GBinFormat *format) { GArchOperand *op; /* Opérande numérique en place */ + GImmOperand *imm; /* Version native de l'opérande*/ virt_t addr; /* Adresse visée par le saut */ MemoryDataSize msize; /* Taille de l'opérande */ GArchOperand *new; /* Instruction de ciblage */ @@ -135,9 +137,13 @@ static void convert_immediate_into_target(GArchInstruction *instr, size_t index, op = g_arch_instruction_get_operand(instr, index); if (!G_IS_IMM_OPERAND(op)) return; - if (g_imm_operand_to_virt_t(G_IMM_OPERAND(op), &addr)) + imm = G_IMM_OPERAND(op); + + if (g_imm_operand_get_display(imm) != IOD_HEX) return; + + if (g_imm_operand_to_virt_t(imm, &addr)) { - msize = g_imm_operand_get_size(G_IMM_OPERAND(op)); + msize = g_imm_operand_get_size(imm); new = g_target_operand_new(msize, addr); @@ -167,6 +173,7 @@ static void convert_immediate_into_target(GArchInstruction *instr, size_t index, static void establish_links_for_instruction(GArchInstruction *instr, GArchInstruction *list, GBinFormat *format) { + bool skip; /* Saut des conversions */ size_t count; /* Nombre d'opérandes présents */ size_t i; /* Boucle de parcours */ GArchOperand *op; /* Opérande numérique en place */ @@ -174,11 +181,17 @@ static void establish_links_for_instruction(GArchInstruction *instr, GArchInstru vmpa2t addr; /* Localisation plus complète */ GArchInstruction *target; /* Instruction visée au final */ + if (G_IS_RAW_INSTRUCTION(instr)) + skip = g_raw_instruction_is_string(G_RAW_INSTRUCTION(instr)); + else + skip = false; + count = g_arch_instruction_count_operands(instr); for (i = 0; i < count; i++) { - convert_immediate_into_target(instr, i, format); + if (!skip) + convert_immediate_into_target(instr, i, format); op = g_arch_instruction_get_operand(instr, i); if (!G_IS_TARGET_OPERAND(op)) continue; diff --git a/src/arch/dalvik/instruction.c b/src/arch/dalvik/instruction.c index 31f02c8..4c1dee0 100644 --- a/src/arch/dalvik/instruction.c +++ b/src/arch/dalvik/instruction.c @@ -48,6 +48,9 @@ static void g_dalvik_instruction_dispose(GDalvikInstruction *); /* Procède à la libération totale de la mémoire. */ static void g_dalvik_instruction_finalize(GDalvikInstruction *); +/* Indique l'encodage d'une instruction de façon détaillée. */ +static const char *g_dalvik_instruction_get_encoding(const GDalvikInstruction *); + /* Liste les registres lus et écrits par l'instruction. */ static void g_dalvik_instruction_get_rw_registers(const GDalvikInstruction *, GArchRegister ***, size_t *, GArchRegister ***, size_t *); @@ -373,6 +376,7 @@ static void g_dalvik_instruction_class_init(GDalvikInstructionClass *klass) instr = G_ARCH_INSTRUCTION_CLASS(klass); + instr->get_encoding = (get_instruction_encoding_fc)g_dalvik_instruction_get_encoding; instr->build_key = (build_instruction_keyword_fc)dalvik_build_instruction_keyword; } @@ -469,6 +473,29 @@ GArchInstruction *g_dalvik_instruction_new(const char *keyword) /****************************************************************************** * * +* Paramètres : instr = instruction quelconque à consulter. * +* * +* Description : Indique l'encodage d'une instruction de façon détaillée. * +* * +* Retour : Description humaine de l'encodage utilisé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static const char *g_dalvik_instruction_get_encoding(const GDalvikInstruction *instr) +{ + const char *result; /* Description à retourner */ + + result = "Dalvik"; + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : instr = instruction Dalvik à consulter. * * * * Description : Indique l'opcode associé à une instruction Dalvik. * 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 #include #include @@ -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; } diff --git a/src/arch/dalvik/operand.h b/src/arch/dalvik/operand.h index 27901be..af15bde 100644 --- a/src/arch/dalvik/operand.h +++ b/src/arch/dalvik/operand.h @@ -65,6 +65,8 @@ #define DALVIK_OP_POOL(p) ((p) << DALVIK_OP_POOL_OFF) #define DALVIK_OP_GET_POOL(v) (((v) & DALVIK_OP_POOL_MASK) >> DALVIK_OP_POOL_OFF) +#define DALVIK_OP_GET_MNEMONIC(v) ((v) & 0xff) + /* Types d'opérandes supportés */ typedef enum _DalvikOperandType @@ -112,7 +114,7 @@ typedef enum _DalvikOperandType /* Procède à la lecture d'opérandes pour une instruction. */ -bool dalvik_read_operands(GArchInstruction *, GExeFormat *, const GBinContent *, vmpa2t *, SourceEndian, DalvikOperandType, ...); +bool dalvik_read_operands(GArchInstruction *, GExeFormat *, const GBinContent *, vmpa2t *, SourceEndian, DalvikOperandType); /* Procède à la lecture d'opérandes pour une instruction. */ void dalvik_mark_first_operand_as_written(GArchInstruction *); diff --git a/src/arch/dalvik/operands/target.c b/src/arch/dalvik/operands/target.c index 42d09cf..5e8b91a 100644 --- a/src/arch/dalvik/operands/target.c +++ b/src/arch/dalvik/operands/target.c @@ -169,31 +169,34 @@ static void g_dalvik_target_operand_finalize(GDalvikTargetOperand *operand) * * ******************************************************************************/ -GArchOperand *g_dalvik_target_operand_new(const GBinContent *content, vmpa2t *pos, MemoryDataSize size, SourceEndian endian, vmpa_t base) +GArchOperand *g_dalvik_target_operand_new(const GBinContent *content, vmpa2t *pos, MemoryDataSize size, SourceEndian endian, const vmpa2t *base) { GDalvikTargetOperand *result; /* Structure à retourner */ + phys_t offset; /* Emplacement de base */ int8_t val8; /* Valeur sur 8 bits */ int16_t val16; /* Valeur sur 16 bits */ int32_t val32; /* Valeur sur 32 bits */ bool test; /* Bilan de lecture */ - vmpa_t address; /* Adresse finale visée */ + phys_t address; /* Adresse finale visée */ + + offset = get_phy_addr(base); switch (size) { case MDS_8_BITS_SIGNED: test = g_binary_content_read_s8(content, pos, &val8); - address = base + val8 * sizeof(uint16_t); + address = offset + val8 * sizeof(uint16_t); break; case MDS_16_BITS_SIGNED: test = g_binary_content_read_s16(content, pos, endian, &val16); - address = base + val16 * sizeof(uint16_t); + address = offset + val16 * sizeof(uint16_t); break; case MDS_32_BITS_SIGNED: test = g_binary_content_read_s32(content, pos, endian, &val32); - address = base + val32 * sizeof(uint16_t); + address = offset + val32 * sizeof(uint16_t); break; default: - return NULL; + test = false; break; } @@ -201,7 +204,7 @@ GArchOperand *g_dalvik_target_operand_new(const GBinContent *content, vmpa2t *po return NULL; 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 */)); + result->immediate = G_IMM_OPERAND(g_imm_operand_new_from_value(MDS_32_BITS, address)); return G_ARCH_OPERAND(result); diff --git a/src/arch/dalvik/operands/target.h b/src/arch/dalvik/operands/target.h index cb0e9f1..6328546 100644 --- a/src/arch/dalvik/operands/target.h +++ b/src/arch/dalvik/operands/target.h @@ -51,7 +51,7 @@ typedef struct _GDalvikTargetOperandClass GDalvikTargetOperandClass; GType g_dalvik_target_operand_get_type(void); /* Crée un opérande visant un instruction Dalvik. */ -GArchOperand *g_dalvik_target_operand_new(const GBinContent *, vmpa2t *, MemoryDataSize, SourceEndian, vmpa_t); +GArchOperand *g_dalvik_target_operand_new(const GBinContent *, vmpa2t *, MemoryDataSize, SourceEndian, const vmpa2t *); /* Fournit l'adresse représentée par une opérande Dalvik. */ const GImmOperand *g_dalvik_target_operand_get_value(const GDalvikTargetOperand *); diff --git a/src/arch/processor.c b/src/arch/processor.c index bbe506a..21db869 100644 --- a/src/arch/processor.c +++ b/src/arch/processor.c @@ -24,6 +24,7 @@ #include "processor.h" +#include #include #include @@ -304,6 +305,8 @@ GArchInstruction *g_arch_processor_disassemble(const GArchProcessor *proc, GProc GArchInstruction *result; /* Instruction à renvoyer */ vmpa2t back; /* Position sauvegardée */ + assert(has_phys_addr(pos) && has_virt_addr(pos)); + copy_vmpa(&back, pos); result = G_ARCH_PROCESSOR_GET_CLASS(proc)->disassemble(proc, ctx, content, pos, format); diff --git a/src/format/dex/class.c b/src/format/dex/class.c index 1dc3a40..a5181d2 100644 --- a/src/format/dex/class.c +++ b/src/format/dex/class.c @@ -39,6 +39,7 @@ struct _GDexClass GObject parent; /* A laisser en premier */ class_def_item definition; /* Définition de la classe */ + class_data_item data; /* Contenu de la classe */ GDexMethod **direct_methods; /* Méthodes propres */ size_t dmethods_count; /* Quantité de ces méthodes */ @@ -204,6 +205,7 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def) result = g_object_new(G_TYPE_DEX_CLASS, NULL); result->definition = *def; + result->data = data; /** * On évite ici les méthodes (virtuelles) non définies. @@ -254,6 +256,44 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def) /****************************************************************************** * * * Paramètres : class = informations chargées à consulter. * +* * +* Description : Fournit la définition brute d'une classe. * +* * +* Retour : Données brutes issues du binaire chargé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const class_def_item *g_dex_class_get_definition(const GDexClass *class) +{ + return &class->definition; + +} + + +/****************************************************************************** +* * +* Paramètres : class = informations chargées à consulter. * +* * +* Description : Fournit la définition brute des données d'une classe. * +* * +* Retour : Données brutes issues du binaire chargé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const class_data_item *g_dex_class_get_data(const GDexClass *class) +{ + return &class->data; + +} + + +/****************************************************************************** +* * +* Paramètres : class = informations chargées à consulter. * * virtual = précise la nature des méthodes ciblées. * * * * Description : Dénombre les méthodes chargées d'un type donné. * @@ -309,6 +349,7 @@ GDexMethod *g_dex_class_get_method(const GDexClass *class, bool virtual, size_t /****************************************************************************** * * * Paramètres : class = informations chargées à consulter. * +* format = format permettant d'obtenir une adresse complète. * * layer = couche de portions à raffiner. * * * * Description : Intègre la méthode en tant que portion de code. * @@ -319,15 +360,15 @@ GDexMethod *g_dex_class_get_method(const GDexClass *class, bool virtual, size_t * * ******************************************************************************/ -void g_dex_class_include_as_portion(const GDexClass *class, GPortionLayer *layer) +void g_dex_class_include_as_portion(const GDexClass *class, const GDexFormat *format, GPortionLayer *layer) { size_t i; /* Boucle de parcours */ for (i = 0; i < class->dmethods_count; i++) - g_dex_method_include_as_portion(class->direct_methods[i], layer); + g_dex_method_include_as_portion(class->direct_methods[i], format, layer); for (i = 0; i < class->vmethods_count; i++) - g_dex_method_include_as_portion(class->virtual_methods[i], layer); + g_dex_method_include_as_portion(class->virtual_methods[i], format, layer); } diff --git a/src/format/dex/class.h b/src/format/dex/class.h index fb7cada..bee9553 100644 --- a/src/format/dex/class.h +++ b/src/format/dex/class.h @@ -57,6 +57,12 @@ GType g_dex_class_get_type(void); /* Crée une nouvelle représentation de classe issue de code. */ GDexClass *g_dex_class_new(GDexFormat *, const class_def_item *); +/* Fournit la définition brute d'une classe. */ +const class_def_item *g_dex_class_get_definition(const GDexClass *); + +/* Fournit la définition brute des données d'une classe. */ +const class_data_item *g_dex_class_get_data(const GDexClass *); + /* Dénombre les méthodes chargées d'un type donné. */ size_t g_dex_class_count_methods(const GDexClass *, bool); @@ -64,7 +70,7 @@ size_t g_dex_class_count_methods(const GDexClass *, bool); GDexMethod *g_dex_class_get_method(const GDexClass *, bool, size_t); /* Intègre la méthode en tant que portion de code. */ -void g_dex_class_include_as_portion(const GDexClass *, GPortionLayer *); +void g_dex_class_include_as_portion(const GDexClass *, const GDexFormat *, GPortionLayer *); /* Retrouve si possible la méthode associée à une adresse. */ GDexMethod *g_dex_class_find_method_by_address(const GDexClass *, vmpa_t); diff --git a/src/format/dex/dex.c b/src/format/dex/dex.c index ed2565f..764b6dc 100755 --- a/src/format/dex/dex.c +++ b/src/format/dex/dex.c @@ -256,6 +256,11 @@ GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent) if (!read_dex_header(result, &pos, &result->header)) goto gdfn_error; + + + /* TODO : vérifier que les *_id ne se chevauchent pas */ + + if (!load_all_dex_types(result)) goto gdfn_error; @@ -271,14 +276,15 @@ GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent) if (!load_all_dex_classes(result)) goto gdfn_error; + if (!g_binary_format_complete_loading(G_BIN_FORMAT(result))) + goto gdfn_error; + return G_BIN_FORMAT(result); gdfn_error: g_object_unref(G_OBJECT(result)); - exit(0); - return NULL; } @@ -328,7 +334,7 @@ static void g_dex_format_refine_portions(const GDexFormat *format, GPortionLayer max = g_dex_format_count_classes(format); for (i = 0; i < max; i++) - g_dex_class_include_as_portion(format->classes[i], layer); + g_dex_class_include_as_portion(format->classes[i], format, layer); } @@ -508,6 +514,32 @@ char *_g_data_type_to_string(const GDataType *type, bool simple) + + + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* * +* Description : Présente l'en-tête DEX du format chargé. * +* * +* Retour : Pointeur vers la description principale. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const dex_header *g_dex_format_get_header(const GDexFormat *format) +{ + return &format->header; + +} + + + + + /****************************************************************************** * * * Paramètres : format = description de l'exécutable à consulter. * @@ -542,6 +574,8 @@ size_t g_dex_format_count_classes(const GDexFormat *format) GDexClass *g_dex_format_get_class(const GDexFormat *format, size_t index) { + /* TODO : ref() */ + return format->classes[index]; } diff --git a/src/format/dex/dex.h b/src/format/dex/dex.h index 1ff3809..28d2a49 100755 --- a/src/format/dex/dex.h +++ b/src/format/dex/dex.h @@ -30,6 +30,7 @@ #include +#include "dex_def.h" #include "../../core/formats.h" @@ -57,6 +58,9 @@ GType g_dex_format_get_type(void); /* Prend en charge un nouveau format DEX. */ GBinFormat *g_dex_format_new(GBinContent *, GExeFormat *); +/* Présente l'en-tête DEX du format chargé. */ +const dex_header *g_dex_format_get_header(const GDexFormat *); + /* Redéfinition : classe issue du code source (instance) */ typedef struct _GDexClass GDexClass; diff --git a/src/format/dex/method.c b/src/format/dex/method.c index b74a713..316f094 100644 --- a/src/format/dex/method.c +++ b/src/format/dex/method.c @@ -294,6 +294,7 @@ GBinRoutine *g_dex_method_get_routine(const GDexMethod *method) /****************************************************************************** * * * Paramètres : method = représentation interne du format DEX à consulter. * +* format = format permettant d'obtenir une adresse complète. * * layer = couche de portions à raffiner. * * * * Description : Intègre la méthode en tant que portion de code. * @@ -304,16 +305,19 @@ GBinRoutine *g_dex_method_get_routine(const GDexMethod *method) * * ******************************************************************************/ -void g_dex_method_include_as_portion(const GDexMethod *method, GPortionLayer *layer) +void g_dex_method_include_as_portion(const GDexMethod *method, const GDexFormat *format, GPortionLayer *layer) { + vmpa2t addr; /* Emplacement dans le binaire */ GBinPortion *new; /* Nouvelle portion définie */ char *desc; /* Description d'une portion */ - vmpa2t addr; /* Emplacement dans le binaire */ /* Si la taille est nulle, on ne fait rien */ if (method->info.access_flags & ACC_NATIVE) return; + if (!g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), method->offset, &addr)) + return; + new = g_binary_portion_new(BPC_CODE); asprintf(&desc, _("Dalvik code")); @@ -322,7 +326,6 @@ void g_dex_method_include_as_portion(const GDexMethod *method, GPortionLayer *la free(desc); - init_vmpa(&addr, method->offset, VMPA_NO_VIRTUAL); g_binary_portion_set_values(new, &addr, method->body.insns_size * sizeof(uint16_t)); g_binary_portion_set_rights(new, PAC_READ | PAC_EXEC); diff --git a/src/format/dex/method.h b/src/format/dex/method.h index 4d29bac..4ed3960 100644 --- a/src/format/dex/method.h +++ b/src/format/dex/method.h @@ -82,7 +82,7 @@ const code_item *g_dex_method_get_dex_body(const GDexMethod *); GBinRoutine *g_dex_method_get_routine(const GDexMethod *); /* Intègre la méthode en tant que portion de code. */ -void g_dex_method_include_as_portion(const GDexMethod *, GPortionLayer *); +void g_dex_method_include_as_portion(const GDexMethod *, const GDexFormat *, GPortionLayer *); /* Indique la position de la méthode au sein du binaire. */ off_t g_dex_method_get_offset(const GDexMethod *); diff --git a/src/format/elf/elf.c b/src/format/elf/elf.c index a48e3b3..4bc8bbf 100644 --- a/src/format/elf/elf.c +++ b/src/format/elf/elf.c @@ -39,7 +39,6 @@ #include "strings.h" #include "symbols.h" #include "../../gui/panels/log.h" -#include "../../plugins/pglist.h" @@ -294,15 +293,16 @@ GBinFormat *g_elf_format_new(GBinContent *content, GExeFormat *parent) } - /* TODO : à bouger dans un épilogue commun */ + if (!g_binary_format_complete_loading(G_BIN_FORMAT(result))) + goto gefn_error; - handle_binary_format(PGA_FORMAT_LOADER_LAST, G_BIN_FORMAT(result)); + return G_BIN_FORMAT(result); - g_binary_format_delete_duplicated_symbols(G_BIN_FORMAT(result)); + gefn_error: - /* .... */ + g_object_unref(G_OBJECT(result)); - return G_BIN_FORMAT(result); + return NULL; } diff --git a/src/format/executable-int.c b/src/format/executable-int.c index c4b8e6e..0189d76 100644 --- a/src/format/executable-int.c +++ b/src/format/executable-int.c @@ -41,7 +41,13 @@ bool g_exe_format_without_virt_translate_offset_into_vmpa(const GExeFormat *format, phys_t off, vmpa2t *pos) { - init_vmpa(pos, off, VMPA_NO_VIRTUAL); + /** + * On ne peut pas initialiser la partie virtuelle à VMPA_NO_VIRTUAL + * car les manipulations au niveau des formats (par exemple, cf. la fonction + * _g_binary_format_add_symbol()) attendent des définitions complètes. + */ + + init_vmpa(pos, off, off); return true; diff --git a/src/format/format-int.h b/src/format/format-int.h index f97a4ad..84f77c4 100644 --- a/src/format/format-int.h +++ b/src/format/format-int.h @@ -78,12 +78,12 @@ struct _GBinFormatClass }; +/* Effectue les ultimes opérations de chargement d'un binaire. */ +bool g_binary_format_complete_loading(GBinFormat *); + /* Définit le contenu binaire à analyser. */ void g_binary_format_set_content(GBinFormat *, GBinContent *); -/* Supprime les éventuels doublons au sein des symboles. */ -void g_binary_format_delete_duplicated_symbols(GBinFormat *); - #endif /* _FORMAT_FORMAT_INT_H */ diff --git a/src/format/format.c b/src/format/format.c index 8395c6e..387894c 100644 --- a/src/format/format.c +++ b/src/format/format.c @@ -52,6 +52,9 @@ static void g_binary_format_init(GBinFormat *); /* Retire un symbole de la collection du format binaire. */ static void _g_binary_format_remove_symbol(GBinFormat *, size_t); +/* Supprime les éventuels doublons au sein des symboles. */ +static void g_binary_format_delete_duplicated_symbols(GBinFormat *); + /* Recherche le symbole associé à une adresse. */ static bool _g_binary_format_find_symbol(const GBinFormat *, const vmpa2t *, __compar_fn_t, GBinSymbol **); @@ -101,6 +104,30 @@ static void g_binary_format_init(GBinFormat *format) } +/****************************************************************************** +* * +* Paramètres : format = instance à traiter. * +* * +* Description : Effectue les ultimes opérations de chargement d'un binaire. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_binary_format_complete_loading(GBinFormat *format) +{ + handle_binary_format(PGA_FORMAT_LOADER_LAST, format); + + g_binary_format_delete_duplicated_symbols(format); + + return true; + +} + + + /* FIXME : g_rw_lock_clear(&format->syms_lock);*/ @@ -431,7 +458,7 @@ void g_binary_format_sort_symbols(GBinFormat *format) * * ******************************************************************************/ -void g_binary_format_delete_duplicated_symbols(GBinFormat *format) +static void g_binary_format_delete_duplicated_symbols(GBinFormat *format) { size_t i; /* Boucle de parcours */ const mrange_t *range; /* Emplacement à consulter */ -- cgit v0.11.2-87-g4458