summaryrefslogtreecommitdiff
path: root/src/analysis
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/analysis
parentcb05b99a8c451ff80d88f988e2654c794b0f3750 (diff)
Support some last missing features from Kaitai: bit fields, instance search order and stream EOF.
Diffstat (limited to 'src/analysis')
-rw-r--r--src/analysis/content.c88
-rw-r--r--src/analysis/content.h3
2 files changed, 91 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 *);