From 62f178cc3dcc889d56ba6d94f6fc8bba7b503c1a Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Fri, 31 Jan 2020 00:23:16 +0100 Subject: Compressed some architecture instruction properties. --- plugins/arm/v7/instruction.c | 2 +- plugins/dalvik/pseudo/fill.c | 2 +- plugins/dalvik/pseudo/switch.c | 7 ++- plugins/dalvik/v35/instruction.c | 8 +-- plugins/pychrysalide/arch/instruction.c | 4 +- src/arch/instruction-int.h | 63 ++++++++++++++++++- src/arch/instruction.c | 108 ++++++++++++++++++++++++++++---- src/arch/instruction.h | 3 + src/common/cpp.h | 7 +++ src/glibext/Makefile.am | 1 + src/glibext/objhole.h | 71 +++++++++++++++++++++ 11 files changed, 253 insertions(+), 23 deletions(-) create mode 100644 src/glibext/objhole.h diff --git a/plugins/arm/v7/instruction.c b/plugins/arm/v7/instruction.c index 97adddd..1c94887 100644 --- a/plugins/arm/v7/instruction.c +++ b/plugins/arm/v7/instruction.c @@ -210,7 +210,7 @@ GArchInstruction *g_armv7_instruction_new(itid_t uid, ARMv7Syntax sid) result = g_object_new(G_TYPE_ARMV7_INSTRUCTION, NULL); - G_ARCH_INSTRUCTION(result)->uid = uid; + g_arch_instruction_set_unique_id(G_ARCH_INSTRUCTION(result), uid); result->sid = sid; diff --git a/plugins/dalvik/pseudo/fill.c b/plugins/dalvik/pseudo/fill.c index 12382f7..cc8a412 100644 --- a/plugins/dalvik/pseudo/fill.c +++ b/plugins/dalvik/pseudo/fill.c @@ -183,7 +183,7 @@ GArchInstruction *g_dalvik_fill_instr_new(uint16_t ident, GDalvikContext *ctx, c result = g_object_new(G_TYPE_DALVIK_FILL_INSTR, NULL); - G_ARCH_INSTRUCTION(result)->uid = DPO_FILL_ARRAY_DATA; + g_arch_instruction_set_unique_id(G_ARCH_INSTRUCTION(result), DPO_FILL_ARRAY_DATA); if (!g_binary_content_read_u16(content, pos, SRE_LITTLE, &result->item_width)) goto gdfin_bad; diff --git a/plugins/dalvik/pseudo/switch.c b/plugins/dalvik/pseudo/switch.c index ea3aa90..f09fe59 100644 --- a/plugins/dalvik/pseudo/switch.c +++ b/plugins/dalvik/pseudo/switch.c @@ -193,7 +193,7 @@ GArchInstruction *g_dalvik_switch_instr_new(uint16_t ident, GDalvikContext *ctx, result = g_object_new(G_TYPE_DALVIK_SWITCH_INSTR, NULL); - G_ARCH_INSTRUCTION(result)->uid = ident; + g_arch_instruction_set_unique_id(G_ARCH_INSTRUCTION(result), ident); if (!g_binary_content_read_u16(content, pos, SRE_LITTLE, &result->switch_size)) goto gdsin_bad; @@ -237,6 +237,7 @@ GArchInstruction *g_dalvik_switch_instr_new(uint16_t ident, GDalvikContext *ctx, static bool g_dalvik_switch_decode_data(GDalvikSwitchInstr *instr, const GBinContent *content, const vmpa2t *pos) { vmpa2t iter; /* Position modifiable */ + itid_t uid; /* Identifiant unique */ int32_t first_key; /* Première clef */ uint16_t i; /* Boucle de parcours */ @@ -245,7 +246,9 @@ static bool g_dalvik_switch_decode_data(GDalvikSwitchInstr *instr, const GBinCon copy_vmpa(&iter, pos); - if (G_ARCH_INSTRUCTION(instr)->uid == DPO_PACKED_SWITCH) + uid = g_arch_instruction_get_unique_id(G_ARCH_INSTRUCTION(instr)); + + if (uid == DPO_PACKED_SWITCH) { if (!g_binary_content_read_s32(content, &iter, SRE_LITTLE, &first_key)) goto gdsdd_bad; diff --git a/plugins/dalvik/v35/instruction.c b/plugins/dalvik/v35/instruction.c index 28cb0dd..773ec7a 100644 --- a/plugins/dalvik/v35/instruction.c +++ b/plugins/dalvik/v35/instruction.c @@ -185,7 +185,7 @@ GArchInstruction *g_dalvik35_instruction_new(itid_t uid) result = g_object_new(G_TYPE_DALVIK35_INSTRUCTION, NULL); - G_ARCH_INSTRUCTION(result)->uid = uid; + g_arch_instruction_set_unique_id(G_ARCH_INSTRUCTION(result), uid); return G_ARCH_INSTRUCTION(result); @@ -232,7 +232,7 @@ static const char *g_dalvik35_instruction_get_keyword(const GDalvik35Instruction const char *result; /* Désignation à retourner */ itid_t uid; /* Accès simplifié */ - uid = G_ARCH_INSTRUCTION(instr)->uid; + uid = g_arch_instruction_get_unique_id(G_ARCH_INSTRUCTION(instr)); assert(uid < DOP35_COUNT); @@ -272,7 +272,7 @@ static void g_dalvik35_instruction_call_hook(GDalvik35Instruction *instr, InstrP base = G_ARCH_INSTRUCTION(instr); - uid = base->uid; + uid = g_arch_instruction_get_unique_id(base); assert(uid < DOP35_COUNT); @@ -301,7 +301,7 @@ static const char *g_dalvik35_instruction_get_description(const GDalvik35Instruc const char *result; /* Description à retourner */ itid_t uid; /* Accès simplifié */ - uid = G_ARCH_INSTRUCTION(instr)->uid; + uid = g_arch_instruction_get_unique_id(G_ARCH_INSTRUCTION(instr)); assert(uid < DOP35_COUNT); diff --git a/plugins/pychrysalide/arch/instruction.c b/plugins/pychrysalide/arch/instruction.c index 1be3edb..757949a 100644 --- a/plugins/pychrysalide/arch/instruction.c +++ b/plugins/pychrysalide/arch/instruction.c @@ -407,7 +407,7 @@ static int py_arch_instruction_init(PyObject *self, PyObject *args, PyObject *kw instr->cached_keyword = strdup(keyword); - G_ARCH_INSTRUCTION(instr)->uid = uid; + g_arch_instruction_set_unique_id(G_ARCH_INSTRUCTION(instr), uid); return 0; @@ -723,7 +723,7 @@ static PyObject *py_arch_instruction_get_destinations(PyObject *self, void *unus * * * Description : Fournit l'identifiant unique pour un ensemble d'instructions.* * * -* Retour : Identifiant unique par type d'instruction et architecture. * +* Retour : Identifiant unique par type d'instruction. * * * * Remarques : - * * * diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h index af897b0..fcb5453 100644 --- a/src/arch/instruction-int.h +++ b/src/arch/instruction-int.h @@ -27,6 +27,7 @@ #include "instruction.h" #include "../common/array.h" +#include "../glibext/objhole.h" @@ -58,6 +59,38 @@ typedef GBufferLine * (* print_instruction_fc) (const GArchInstruction *, GBuffe typedef void (* get_instruction_rw_regs_fc) (const GArchInstruction *, GArchRegister ***, size_t *, GArchRegister ***, size_t *); +/* Informations glissées dans la structure GObject de GArchInstruction */ +typedef union _instr_obj_extra +{ + struct + { + itid_t uid; /* Identifiant unique du type */ + + ArchInstrFlag flags; /* Informations complémentaires*/ + + }; + + gint lock; /* Gestion d'accès aux fanions */ + +} instr_obj_extra; + +/** + * Choix du bit de verrou pour le champ "lock". + */ + +#if __BYTE_ORDER == __LITTLE_ENDIAN + +# define INSTR_EXTRA_LOCK_BIT 31 + +#elif __BYTE_ORDER == __BIG_ENDIAN + +# define INSTR_EXTRA_LOCK_BIT 0 + +#else + +# error "Unknown byte order" + +#endif /* Définition générique d'une instruction d'architecture (instance) */ struct _GArchInstruction @@ -93,12 +126,38 @@ struct _GArchInstruction flat_array_t *from; /* Origines des références */ flat_array_t *to; /* Instructions visées */ - itid_t uid; /* Identifiant unique du type */ +#if __SIZEOF_INT__ == __SIZEOF_LONG__ - ArchInstrFlag flags; /* Informations complémentaires*/ + /** + * L'inclusion des informations suivantes dépend de l'architecture. + * + * Si la structure GObject possède un trou, on remplit de préférence + * ce dernier. + */ + + instr_obj_extra extra; /* Externalisation embarquée */ + +#endif }; +/** + * Accès aux informations éventuellement déportées. + */ + +#if __SIZEOF_INT__ == __SIZEOF_LONG__ + +# define INIT_ARCH_INSTR_EXTRA(ins) ins->extra.lock = 0 + +# define GET_ARCH_INSTR_EXTRA(ins) &ins->extra + +#else + +# define INIT_ARCH_INSTR_EXTRA(ins) INIT_GOBJECT_EXTRA(G_OBJECT(ins)) + +# define GET_ARCH_INSTR_EXTRA(ins) GET_GOBJECT_EXTRA(G_OBJECT(ins), instr_obj_extra) + +#endif /* Définition générique d'une instruction d'architecture (classe) */ struct _GArchInstructionClass diff --git a/src/arch/instruction.c b/src/arch/instruction.c index f571330..d3ac97e 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -139,6 +139,8 @@ static void g_arch_instruction_class_init(GArchInstructionClass *klass) static void g_arch_instruction_init(GArchInstruction *instr) { + INIT_ARCH_INSTR_EXTRA(instr); + instr->operands = NULL; instr->from = NULL; @@ -278,9 +280,20 @@ const char *g_arch_instruction_get_encoding(const GArchInstruction *instr) bool g_arch_instruction_set_flag(GArchInstruction *instr, ArchInstrFlag flag) { - instr->flags |= flag; + bool result; /* Bilan à retourner */ + instr_obj_extra *extra; /* Données insérées à modifier */ + + extra = GET_ARCH_INSTR_EXTRA(instr); + + g_bit_lock(&extra->lock, INSTR_EXTRA_LOCK_BIT); + + extra->flags |= flag; + + result = true; - return true; + g_bit_unlock(&extra->lock, INSTR_EXTRA_LOCK_BIT); + + return result; } @@ -301,8 +314,15 @@ bool g_arch_instruction_set_flag(GArchInstruction *instr, ArchInstrFlag flag) bool g_arch_instruction_has_flag(const GArchInstruction *instr, ArchInstrFlag flag) { bool result; /* Bilan à retourner */ + instr_obj_extra *extra; /* Données insérées à consulter*/ + + extra = GET_ARCH_INSTR_EXTRA(instr); + + g_bit_lock(&extra->lock, INSTR_EXTRA_LOCK_BIT); - result = (instr->flags & flag); + result = (extra->flags & flag); + + g_bit_unlock(&extra->lock, INSTR_EXTRA_LOCK_BIT); return result; @@ -323,7 +343,46 @@ bool g_arch_instruction_has_flag(const GArchInstruction *instr, ArchInstrFlag fl ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *instr) { - return instr->flags; + ArchInstrFlag result; /* Fanions à retourner */ + instr_obj_extra *extra; /* Données insérées à consulter*/ + + extra = GET_ARCH_INSTR_EXTRA(instr); + + g_bit_lock(&extra->lock, INSTR_EXTRA_LOCK_BIT); + + result = extra->flags; + + g_bit_unlock(&extra->lock, INSTR_EXTRA_LOCK_BIT); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction quelconque à consulter. * +* uid = identifiant unique par type d'instruction. * +* * +* Description : Définit l'identifiant unique pour un ensemble d'instructions.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_arch_instruction_set_unique_id(GArchInstruction *instr, itid_t uid) +{ + instr_obj_extra *extra; /* Données insérées à modifier */ + + extra = GET_ARCH_INSTR_EXTRA(instr); + + g_bit_lock(&extra->lock, INSTR_EXTRA_LOCK_BIT); + + extra->uid = uid; + + g_bit_unlock(&extra->lock, INSTR_EXTRA_LOCK_BIT); } @@ -343,8 +402,15 @@ ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *instr) itid_t g_arch_instruction_get_unique_id(const GArchInstruction *instr) { itid_t result; /* Numéro à retourner */ + instr_obj_extra *extra; /* Données insérées à consulter*/ + + extra = GET_ARCH_INSTR_EXTRA(instr); - result = instr->uid; + g_bit_lock(&extra->lock, INSTR_EXTRA_LOCK_BIT); + + result = extra->uid; + + g_bit_unlock(&extra->lock, INSTR_EXTRA_LOCK_BIT); return result; @@ -1409,6 +1475,7 @@ static bool g_arch_instruction_unserialize(GArchInstruction *instr, GAsmStorage GArchOperand *op; /* Opérande à traiter */ instr_link_t link; /* Lien vers une instruction */ packed_buffer ins_pbuf; /* Tampon des données à écrire */ + instr_obj_extra *extra; /* Données insérées à consulter*/ result = unpack_mrange(&instr->range, pbuf); @@ -1489,10 +1556,19 @@ static bool g_arch_instruction_unserialize(GArchInstruction *instr, GAsmStorage } if (result) - result = extract_packed_buffer(pbuf, &instr->uid, sizeof(itid_t), true); + { + extra = GET_ARCH_INSTR_EXTRA(instr); - if (result) - result = extract_packed_buffer(pbuf, &instr->flags, sizeof(ArchInstrFlag), true); + g_bit_lock(&extra->lock, INSTR_EXTRA_LOCK_BIT); + + result = extract_packed_buffer(pbuf, &extra->uid, sizeof(itid_t), true); + + if (result) + result = extract_packed_buffer(pbuf, &extra->flags, sizeof(ArchInstrFlag), true); + + g_bit_unlock(&extra->lock, INSTR_EXTRA_LOCK_BIT); + + } return result; @@ -1561,6 +1637,7 @@ static bool g_arch_instruction_serialize(GArchInstruction *instr, GAsmStorage *s off64_t pos; /* Position dans le flux */ size_t kept; /* Nombre de liens conservés */ const instr_link_t *link; /* Lien vers une instruction */ + instr_obj_extra *extra; /* Données insérées à consulter*/ result = pack_mrange(&instr->range, pbuf); @@ -1661,10 +1738,19 @@ static bool g_arch_instruction_serialize(GArchInstruction *instr, GAsmStorage *s } if (result) - result = extend_packed_buffer(pbuf, &instr->uid, sizeof(itid_t), true); + { + extra = GET_ARCH_INSTR_EXTRA(instr); - if (result) - result = extend_packed_buffer(pbuf, &instr->flags, sizeof(ArchInstrFlag), true); + g_bit_lock(&extra->lock, INSTR_EXTRA_LOCK_BIT); + + result = extend_packed_buffer(pbuf, &extra->uid, sizeof(itid_t), true); + + if (result) + result = extend_packed_buffer(pbuf, &extra->flags, sizeof(ArchInstrFlag), true); + + g_bit_unlock(&extra->lock, INSTR_EXTRA_LOCK_BIT); + + } return result; diff --git a/src/arch/instruction.h b/src/arch/instruction.h index af6b03a..6c04acb 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -93,6 +93,9 @@ bool g_arch_instruction_has_flag(const GArchInstruction *, ArchInstrFlag); /* Fournit les informations complémentaires d'une instruction. */ ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *); +/* Définit l'identifiant unique pour un ensemble d'instructions. */ +void g_arch_instruction_set_unique_id(GArchInstruction *, itid_t); + /* Fournit l'identifiant unique pour un ensemble d'instructions. */ itid_t g_arch_instruction_get_unique_id(const GArchInstruction *); diff --git a/src/common/cpp.h b/src/common/cpp.h index dc0c208..2305b29 100644 --- a/src/common/cpp.h +++ b/src/common/cpp.h @@ -47,5 +47,12 @@ #define SIZE_T_MAXLEN strlen(XSTR(LONG_MAX)) +/** + * Emprunt au noyau Linux (cf. include/linux/bug.h) pour les vérifications à la compilation. + */ + +#define BUILD_BUG_ON(cond) (((void)sizeof(char[1 - 2 * !!(cond)]))) + + #endif /* _COMMON_CPP_H */ diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am index 127f60c..af4f876 100644 --- a/src/glibext/Makefile.am +++ b/src/glibext/Makefile.am @@ -25,6 +25,7 @@ libglibext_la_SOURCES = \ linegen-int.h \ linegen.h linegen.c \ linesegment.h linesegment.c \ + objhole.h \ proto.h \ seq.h seq.c \ signal.h signal.c diff --git a/src/glibext/objhole.h b/src/glibext/objhole.h new file mode 100644 index 0000000..184e599 --- /dev/null +++ b/src/glibext/objhole.h @@ -0,0 +1,71 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * objhole.h - prototypes pour l'utilisation d'un espace inutilisé dans la structure GObject + * + * Copyright (C) 2019 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see . + */ + + +#ifndef _GLIBEXT_OBJHOLE_H +#define _GLIBEXT_OBJHOLE_H + + +#include + + +#include "../common/cpp.h" + + + +/** + * Une structure GObject a la définition suivante : + * + * struct _GObject + * { + * GTypeInstance g_type_instance; + * volatile guint ref_count; + * GData *qdata; + * }; + * + * L'espace entre les deux derniers champs est exploité ici. + */ + + +#define INIT_GOBJECT_EXTRA(obj) \ + do \ + { \ + guint *___space; \ + ___space = (((guint *)&obj->ref_count) + 1); \ + BUILD_BUG_ON((___space + 1) == (guint *)&obj->qdata); \ + *___space = 0; \ + } \ + while (0) + + +#define GET_GOBJECT_EXTRA(obj, tp) \ + ({ \ + BUILD_BUG_ON(sizeof(tp) > sizeof(guint)); \ + tp *___result; \ + ___result = (tp *)(((guint *)&obj->ref_count) + 1); \ + BUILD_BUG_ON((___result + 1) == (tp *)&obj->qdata); \ + ___result; \ + }) + + + +#endif /* _GLIBEXT_OBJHOLE_H */ -- cgit v0.11.2-87-g4458