summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2024-11-03 14:00:29 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2024-11-03 14:00:29 (GMT)
commit54d05927811a59db294af8a24258c0b837360492 (patch)
tree527064eea471829b12f3b0f5a5b2278cbe4524c2
parentc24b37fd74ae12a90669731f150ac99213fad5b6 (diff)
Load and store various values.
-rw-r--r--src/common/bits.c131
-rw-r--r--src/common/bits.h9
-rw-r--r--src/common/fnv1a.c33
-rw-r--r--src/common/fnv1a.h6
-rw-r--r--src/common/io.h57
-rw-r--r--src/common/leb128.c93
-rw-r--r--src/common/leb128.h6
-rw-r--r--src/common/szbin.h129
8 files changed, 435 insertions, 29 deletions
diff --git a/src/common/bits.c b/src/common/bits.c
index f730c66..26f570f 100644
--- a/src/common/bits.c
+++ b/src/common/bits.c
@@ -31,6 +31,7 @@
#include "asm.h"
+#include "leb128.h"
@@ -1291,3 +1292,133 @@ void output_bit_field(const bitfield_t *field)
}
#endif
+
+
+/******************************************************************************
+* *
+* Paramètres : fd = flux ouvert en lecture. *
+* length = éventuelle indication de la taille du champ ? *
+* def_state = éventuelle indication de l'état par défaut ? *
+* endian = ordre des bits dans la source. *
+* *
+* Description : Restaure un champ de bits depuis un flux ouvert. *
+* *
+* Retour : Adresse du champs de bits mis en place, NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bitfield_t *load_bit_field(int fd, const size_t *length, const bool *def_state, SourceEndian endian)
+{
+ bitfield_t *result; /* Structure à retourner */
+ size_t final_length; /* Nombre de bits représentés */
+ uleb128_t leb128_value; /* Valeur LEB128 chargée */
+ bool status; /* Bilan d'une lecture */
+ bool final_default_state; /* Etat d'initialisation */
+ uint8_t u8_value; /* Valeur sur 8 bits chargée */
+ size_t i; /* Boucle de parcours */
+
+ result = NULL;
+
+ if (length != NULL)
+ final_length = *length;
+ else
+ {
+ status = load_uleb128(&leb128_value, fd);
+ if (!status) goto exit;
+
+ final_length = leb128_value;
+
+ }
+
+ if (def_state != NULL)
+ final_default_state = *def_state;
+
+ else
+ {
+ status = load_u8(fd, &u8_value);
+ if (!status) goto exit;
+
+ final_default_state = !!u8_value;
+
+ }
+
+ result = _create_bit_field(final_length);
+
+ result->default_state = final_default_state;
+
+ for (i = 0; i < result->used_words; i++)
+ {
+ status = load_uleb128(&leb128_value, fd);
+
+ if (status)
+ result->bits[i] = leb128_value;
+
+ else
+ {
+ delete_bit_field(result);
+ result = NULL;
+ break;
+ }
+
+ }
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : field = champ de bits à consulter. *
+* fd = flux ouvert en écriture. *
+* skip_len = saute la sauvegarde de la taille du champ ? *
+* skip_def = saute la sauvegarde de l'état par défaut ? *
+* endian = ordre des bits dans la source. *
+* *
+* Description : Sauvegarde un champ de bits dans un flux ouvert. *
+* *
+* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool store_bit_field(const bitfield_t *field, int fd, bool skip_len, bool skip_def, SourceEndian endian)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+
+ if (skip_len)
+ result = true;
+ else
+ {
+ result = store_uleb128((const uleb128_t []) { field->length }, fd);
+ if (!result) goto exit;
+ }
+
+ if (skip_def)
+ result = true;
+ else
+ {
+ result = store_u8(fd, field->default_state);
+ if (!result) goto exit;
+ }
+
+ for (i = 0; i < field->used_words; i++)
+ {
+ result = store_uleb128((const uleb128_t []) { field->bits[i] }, fd);
+
+ if (!result)
+ break;
+
+ }
+
+ exit:
+
+ return result;
+
+}
diff --git a/src/common/bits.h b/src/common/bits.h
index 3898c73..d9c83c8 100644
--- a/src/common/bits.h
+++ b/src/common/bits.h
@@ -29,6 +29,9 @@
#include <sys/types.h>
+#include "datatypes.h"
+
+
/* Champ de bits simple */
typedef struct _bitfield_t bitfield_t;
@@ -119,6 +122,12 @@ void output_bit_field(const bitfield_t *);
#endif
+/* Restaure un champ de bits depuis un flux ouvert. */
+bitfield_t *load_bit_field(int, const size_t *, const bool *, SourceEndian);
+
+/* Sauvegarde un champ de bits dans un flux ouvert. */
+bool store_bit_field(const bitfield_t *, int, bool, bool, SourceEndian);
+
#endif /* _COMMON_BITS_H */
diff --git a/src/common/fnv1a.c b/src/common/fnv1a.c
index a8afd0a..057d6c9 100644
--- a/src/common/fnv1a.c
+++ b/src/common/fnv1a.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* fnv1a.c - implémentaton du calcul rapide d'empreintes de chaînes
*
- * Copyright (C) 2012-2018 Cyrille Bagard
+ * Copyright (C) 2012-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -87,3 +87,34 @@ fnv64_t fnv_64a_hash(const char *str)
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : data = données binaires à traiter. *
+* size = quantité de ces données. *
+* *
+* Description : Détermine l'empreinte FNV1a d'une séquence d'octets. *
+* *
+* Retour : Valeur calculée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+fnv64_t fnv_64a_hash_data(const uint8_t *data, size_t size)
+{
+ fnv64_t result; /* Valeur à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = FNV1A_64_INIT;
+
+ for (i = 0; i < size; i++)
+ {
+ result ^= (fnv64_t)data[i];
+ result *= FNV_64_PRIME;
+ }
+
+ return result;
+
+}
diff --git a/src/common/fnv1a.h b/src/common/fnv1a.h
index eec1460..4da3108 100644
--- a/src/common/fnv1a.h
+++ b/src/common/fnv1a.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* fnv1a.h - prototypes pour l'implémentaton du calcul rapide d'empreintes de chaînes
*
- * Copyright (C) 2012-2018 Cyrille Bagard
+ * Copyright (C) 2012-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -27,6 +27,7 @@
#include <stdbool.h>
#include <stdint.h>
+#include <sys/types.h>
/**
@@ -46,6 +47,9 @@ int cmp_fnv_64a(fnv64_t, fnv64_t);
/* Détermine l'empreinte FNV1a d'une chaîne de caractères. */
fnv64_t fnv_64a_hash(const char *);
+/* Détermine l'empreinte FNV1a d'une séquence d'octets. */
+fnv64_t fnv_64a_hash_data(const uint8_t *, size_t);
+
#endif /* _COMMON_FNV1A_H */
diff --git a/src/common/io.h b/src/common/io.h
index 7fe9d9d..1932b12 100644
--- a/src/common/io.h
+++ b/src/common/io.h
@@ -39,12 +39,69 @@
/* Lit des données depuis un flux local. */
bool safe_read(int, void *, size_t);
+#define load_u8(f, v) \
+ safe_read(f, v, sizeof(uint8_t));
+
+#define load_u16(f, v, e) \
+ ({ \
+ bool __ret; \
+ uint16_t __val; \
+ __ret = safe_read(f, &__val, sizeof(uint16_t)); \
+ __val = swap_u16(&__val, e); \
+ *(v) = __val; \
+ __ret; \
+ })
+
+#define load_u32(f, v, e) \
+ ({ \
+ bool __ret; \
+ uint32_t __val; \
+ __ret = safe_read(f, &__val, sizeof(uint32_t)); \
+ __val = swap_u32(&__val, e); \
+ *(v) = __val; \
+ __ret; \
+ })
+
+#define load_u64(f, v, e) \
+ ({ \
+ bool __ret; \
+ uint64_t __val; \
+ __ret = safe_read(f, &__val, sizeof(uint64_t)); \
+ __val = swap_u64(&__val, e); \
+ *(v) = __val; \
+ __ret; \
+ })
+
/* Lit des données depuis un flux local. */
ssize_t safe_read_partial(int, void *, size_t);
/* Ecrit des données dans un flux local. */
bool safe_write(int, const void *, size_t);
+#define store_u8(f, v) \
+ safe_write(f, (const uint8_t []){ v }, sizeof(uint8_t));
+
+#define store_u16(f, v, e) \
+ ({ \
+ uint16_t __val; \
+ __val = swap_u16((const uint16_t []){ v }, e); \
+ safe_write(f, &__val, sizeof(uint16_t)); \
+ })
+
+#define store_u32(f, v, e) \
+ ({ \
+ uint32_t __val; \
+ __val = swap_u32((const uint32_t []){ v }, e); \
+ safe_write(f, &__val, sizeof(uint32_t)); \
+ })
+
+#define store_u64(f, v, e) \
+ ({ \
+ uint64_t __val; \
+ __val = swap_u64((const uint64_t []){ v }, e); \
+ safe_write(f, &__val, sizeof(uint64_t)); \
+ })
+
/* Réceptionne des données depuis un flux réseau. */
bool safe_recv(int, void *, size_t, int);
diff --git a/src/common/leb128.c b/src/common/leb128.c
index c8d2ace..009aff6 100644
--- a/src/common/leb128.c
+++ b/src/common/leb128.c
@@ -24,6 +24,9 @@
#include "leb128.h"
+#include "io.h"
+
+
/******************************************************************************
* *
@@ -113,6 +116,96 @@ bool read_leb128(leb128_t *target, const bin_t *data, phys_t *pos, phys_t len)
/******************************************************************************
* *
+* Paramètres : value = valeur à constituer. [OUT] *
+* fd = flux ouvert en lecture à consulter. *
+* *
+* Description : Restaure un nombre non signé encodé au format LEB128. *
+* *
+* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_uleb128(uleb128_t *value, int fd)
+{
+ bool result; /* Bilan à retourner */
+ unsigned int shift; /* Décalage à appliquer */
+ uint8_t byte; /* Octet à transposer */
+
+ result = true;
+
+ *value = 0;
+
+ shift = 0;
+
+ while (true)
+ {
+ /* Encodage sur trop d'octets ? */
+ if (shift > (7 * sizeof(uleb128_t)))
+ {
+ result = false;
+ break;
+ }
+
+ result = safe_read(fd, &byte, sizeof(uint8_t));
+ if (!result) break;
+
+ *value |= ((byte & 0x7f) << shift);
+
+ if ((byte & 0x80) == 0x00)
+ break;
+
+ shift += 7;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : value = valeur à consigner. *
+* fd = flux ouvert en écriture. *
+* *
+* Description : Sauvegarde un nombre non signé encodé au format LEB128. *
+* *
+* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool store_uleb128(const uleb128_t *value, int fd)
+{
+ bool result; /* Bilan à retourner */
+ uleb128_t tmp; /* Valeur modifiable */
+ uint8_t byte; /* Octet à transposer */
+
+ tmp = *value;
+
+ do
+ {
+ byte = (tmp & 0x7f);
+ tmp >>= 7;
+
+ if (tmp != 0)
+ byte |= 0x80;
+
+ result = safe_write(fd, &byte, sizeof(uint8_t));
+
+ }
+ while (result && tmp != 0);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : value = valeur à consigner. *
* pbuf = tampon de données à constituer. [OUT] *
* *
diff --git a/src/common/leb128.h b/src/common/leb128.h
index f438068..0313f5c 100644
--- a/src/common/leb128.h
+++ b/src/common/leb128.h
@@ -58,6 +58,12 @@ bool read_uleb128(uleb128_t *, const bin_t *, phys_t *, phys_t);
/* Lit un nombre signé encodé au format LEB128. */
bool read_leb128(leb128_t *, const bin_t *, phys_t *, phys_t);
+/* Charge un nombre non signé encodé au format LEB128. */
+bool load_uleb128(uleb128_t *, int);
+
+/* Sauvegarde un nombre non signé encodé au format LEB128. */
+bool store_uleb128(const uleb128_t *, int);
+
/* Encode un nombre non signé encodé au format LEB128. */
bool pack_uleb128(const uleb128_t *, packed_buffer_t *);
diff --git a/src/common/szbin.h b/src/common/szbin.h
index ac938ab..5891449 100644
--- a/src/common/szbin.h
+++ b/src/common/szbin.h
@@ -29,6 +29,12 @@
#include <string.h>
+#include "datatypes.h"
+#include "io.h"
+#include "leb128.h"
+#include "sort.h"
+
+
/* Structure associant données et taille */
typedef struct _sized_binary_t
@@ -38,6 +44,9 @@ typedef struct _sized_binary_t
const char *static_data; /* Données non modifiées */
char *data; /* Chaîne de caractères */
+ const bin_t *static_bin_data; /* Données brutes non modifiées*/
+ bin_t *bin_data; /* Données brutes */
+
};
size_t size; /* Taille correspondante */
@@ -45,44 +54,110 @@ typedef struct _sized_binary_t
} sized_binary_t;
-#define init_sized_binary(sb) \
- do \
- { \
- (sb)->data = NULL; \
- (sb)->size = 0; \
- } \
+#define init_sized_binary(sb) \
+ do \
+ { \
+ (sb)->data = NULL; \
+ (sb)->size = 0; \
+ } \
while (0)
-#define setup_sized_binary(sb, s) \
- do \
- { \
- (sb)->data = malloc(s); \
- (sb)->size = s; \
- } \
+#define setup_sized_binary(sb, s) \
+ do \
+ { \
+ (sb)->data = malloc(s); \
+ (sb)->size = s; \
+ } \
while (0)
-#define dup_into_sized_binary(sb, d, s) \
- do \
- { \
- setup_sized_binary(sb, s); \
- memcpy((sb)->data, d, s); \
- } \
+#define dup_into_sized_binary(sb, d, s) \
+ do \
+ { \
+ setup_sized_binary(sb, s); \
+ memcpy((sb)->data, d, s); \
+ } \
while (0)
-#define exit_sized_binary(sb) \
- do \
- { \
- if ((sb)->data != NULL) \
- { \
- free((sb)->data); \
- init_sized_binary(sb); \
- } \
- } \
+#define dup_sized_binary(dst, src) \
+ dup_into_sized_binary((dst), (src)->static_data, (src)->size)
+
+
+#define exit_sized_binary(sb) \
+ do \
+ { \
+ if ((sb)->data != NULL) \
+ { \
+ free((sb)->data); \
+ init_sized_binary(sb); \
+ } \
+ } \
while (0)
+#define add_to_sized_binary(sb, d, s) \
+ do \
+ { \
+ size_t __old_size; \
+ __old_size = (sb)->size; \
+ (sb)->size += s; \
+ (sb)->data = realloc((sb)->data, \
+ (sb)->size); \
+ memcpy((sb)->data + __old_size, \
+ d, s); \
+ } \
+ while (0)
+
+
+#define add_static_to_sized_binary(sb, d) \
+ do \
+ { \
+ size_t __len; \
+ __len = sizeof(d) - 1; \
+ add_to_sized_binary(sb, d, __len); \
+ } \
+ while (0)
+
+
+#define memcmp_sized_binary(s1, s2) \
+ ({ \
+ int __ret; \
+ size_t __n; \
+ __n = (s1)->size < (s2)->size ? (s1)->size : (s2)->size; \
+ __ret = memcmp((s1)->data, (s2)->data, __n); \
+ if (__ret == 0) \
+ __ret = sort_unsigned_long_long((s1)->size, (s2)->size);\
+ __ret; \
+ })
+
+
+#define load_sized_binary(sb, f) \
+ ({ \
+ uleb128_t __sz; \
+ bool __ret; \
+ __ret = load_uleb128(&__sz, f); \
+ if (__ret) \
+ { \
+ setup_sized_binary(sb, __sz); \
+ __ret = safe_read(f, (sb)->data, (sb)->size); \
+ if (!__ret) \
+ exit_sized_binary(sb); \
+ } \
+ __ret; \
+ })
+
+
+#define store_sized_binary(sb, f) \
+ ({ \
+ bool __ret; \
+ __ret = store_uleb128((const uleb128_t []){ (sb)->size }, f); \
+ if (__ret) \
+ __ret = safe_write(f, (sb)->static_data, (sb)->size); \
+ __ret; \
+ })
+
+
#endif /* _COMMON_SZBIN_H */