summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2023-10-09 22:49:59 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2023-10-09 22:49:59 (GMT)
commit7c6fe94c90d320813d0d78a9dbef707696f31505 (patch)
tree912b5c51469c02e6ef680c0c60739787ccff4891 /src
parentcb05b99a8c451ff80d88f988e2654c794b0f3750 (diff)
Support some last missing features from Kaitai: bit fields, instance search order and stream EOF.
Diffstat (limited to 'src')
-rw-r--r--src/analysis/content.c88
-rw-r--r--src/analysis/content.h3
-rw-r--r--src/arch/vmpa.h56
3 files changed, 147 insertions, 0 deletions
diff --git a/src/analysis/content.c b/src/analysis/content.c
index 0560d73..e12237f 100644
--- a/src/analysis/content.c
+++ b/src/analysis/content.c
@@ -474,6 +474,94 @@ bool g_binary_content_read_raw(const GBinContent *content, vmpa2t *addr, phys_t
/******************************************************************************
* *
* Paramètres : content = contenu binaire à venir lire. *
+* addr = position de la tête de lecture complète. *
+* size = quantité de bits à lire. *
+* endian = ordre des bits dans la source. *
+* val = lieu d'enregistrement de la lecture. [OUT] *
+* *
+* Description : Lit un nombre non signé sur deux octets. *
+* *
+* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_binary_content_read_bits(const GBinContent *content, ext_vmpa_t *addr, uint8_t size, SourceEndian endian, uint64_t *val)
+{
+ bool result; /* Bilan de lecture à renvoyer */
+ vmpa2t pos; /* Tête de lecture courante */
+ uint8_t data; /* Données à parcourir */
+ uint8_t i; /* Boucle de parcours */
+ uint8_t remaining; /* Nombre de bits disponibles */
+ uint64_t bit; /* Nouveau bit à intégrer */
+
+ assert(addr->consumed_extra_bits < 8);
+ assert(size <= 64);
+
+ if (addr->consumed_extra_bits >= 8 || size > 64)
+ return false;
+
+ copy_vmpa(&pos, &addr->base);
+
+ result = g_binary_content_read_u8(content, &pos, &data);
+ if (!result) goto exit;
+
+ remaining = 8 - addr->consumed_extra_bits;
+
+ *val = 0;
+
+ for (i = 0; i < size; i++)
+ {
+ if (remaining == 0)
+ {
+ result = g_binary_content_read_u8(content, &pos, &data);
+ if (!result) goto exit;
+
+ remaining = 8;
+
+ }
+
+ bit = (data >> (remaining - 1)) & 0x1;
+
+ remaining--;
+
+ switch (endian)
+ {
+ case SRE_LITTLE:
+ *val |= (bit << i);
+ break;
+
+ case SRE_BIG:
+ *val |= (bit << (size - i - 1));
+ break;
+
+ default:
+ assert(false);
+ result = false;
+ break;
+
+ }
+
+ }
+
+ if (result)
+ {
+ advance_vmpa(&addr->base, get_phy_addr(&pos) - get_phy_addr(&addr->base) - 1);
+ addr->consumed_extra_bits = 8 - remaining;
+
+ }
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : content = contenu binaire à venir lire. *
* addr = position de la tête de lecture. *
* low = position éventuelle des 4 bits visés. [OUT] *
* val = lieu d'enregistrement de la lecture. [OUT] *
diff --git a/src/analysis/content.h b/src/analysis/content.h
index 5279890..ee79a9c 100644
--- a/src/analysis/content.h
+++ b/src/analysis/content.h
@@ -87,6 +87,9 @@ const bin_t *g_binary_content_get_raw_access(const GBinContent *, vmpa2t *, phys
/* Fournit une portion des données représentées. */
bool g_binary_content_read_raw(const GBinContent *, vmpa2t *, phys_t, bin_t *);
+/* Lit un nombre non signé sur deux octets. */
+bool g_binary_content_read_bits(const GBinContent *, ext_vmpa_t *, uint8_t, SourceEndian, uint64_t *);
+
/* Lit un nombre non signé sur quatre bits. */
bool g_binary_content_read_u4(const GBinContent *, vmpa2t *, bool *, uint8_t *);
diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h
index f353ebd..4f35ebe 100644
--- a/src/arch/vmpa.h
+++ b/src/arch/vmpa.h
@@ -156,6 +156,62 @@ bool store_vmpa(const vmpa2t *, const char *, bound_value **, size_t *);
+/* ------------------------ DEFINITION DE POSITION AVEC BITS ------------------------ */
+
+
+/* Adresse mémoire ou position physique */
+typedef struct _ext_vmpa_t
+{
+ vmpa2t base; /* Vision macroscopique */
+
+ uint8_t consumed_extra_bits; /* Avancée supplémentaire */
+
+} ext_vmpa_t;
+
+
+#define init_evmpa_from_vmpa(d, s) \
+ do \
+ { \
+ copy_vmpa(&(d)->base, (s)); \
+ (d)->consumed_extra_bits = 0; \
+ } \
+ while (0)
+
+#define copy_evmpa(d, s) \
+ do \
+ { \
+ copy_vmpa(&(d)->base, &(s)->base); \
+ (d)->consumed_extra_bits = (s)->consumed_extra_bits; \
+ } \
+ while (0)
+
+#define advance_evmpa_bits(a, q) \
+ do \
+ { \
+ uint8_t __sum; \
+ __sum = (a)->consumed_extra_bits + q; \
+ if (__sum > 8) \
+ { \
+ advance_vmpa(&(a)->base, __sum / 8); \
+ (a)->consumed_extra_bits = __sum % 8; \
+ } \
+ else \
+ (a)->consumed_extra_bits = __sum; \
+ } \
+ while (0)
+
+#define align_evmpa_on_byte(a) \
+ do \
+ { \
+ if ((a)->consumed_extra_bits > 0) \
+ { \
+ advance_vmpa(&(a)->base, 1); \
+ (a)->consumed_extra_bits = 0; \
+ } \
+ } \
+ while (0);
+
+
/* ------------------------ AIDES FONCTIONNELLES AUXILIAIRES ------------------------ */