diff options
Diffstat (limited to 'src/glibext')
-rw-r--r-- | src/glibext/gbincontent.c | 392 | ||||
-rw-r--r-- | src/glibext/gbincontent.h | 25 |
2 files changed, 414 insertions, 3 deletions
diff --git a/src/glibext/gbincontent.c b/src/glibext/gbincontent.c index c72ac15..e0c64d4 100644 --- a/src/glibext/gbincontent.c +++ b/src/glibext/gbincontent.c @@ -24,6 +24,7 @@ #include "gbincontent.h" +#include <assert.h> #include <fcntl.h> #include <malloc.h> #include <stdio.h> @@ -33,6 +34,9 @@ #include <sys/stat.h> +#include "../common/endianness.h" + + /* Aire de contenu binaire */ typedef struct _binary_part @@ -73,6 +77,9 @@ static void g_binary_content_dispose(GBinContent *); /* Procède à la libération totale de la mémoire. */ static void g_binary_content_finalize(GBinContent *); +/* Retrouve la zone adaptée pour une localisation de données. */ +static const binary_part *g_binary_content_find_part(const GBinContent *, const vmpa2t *, phys_t *); + /* Indique le type défini par la GLib pour les contenus de données. */ @@ -239,10 +246,43 @@ GBinContent *g_binary_content_new_from_file(const char *filename) } +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à venir lire. * +* addr = position de la tête de lecture globale demandée. * +* start = position de la tête de lecture dans la zone. [OUT] * +* * +* Description : Retrouve la zone adaptée pour une localisation de données. * +* * +* Retour : Partie trouvée ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ +static const binary_part *g_binary_content_find_part(const GBinContent *content, const vmpa2t *addr, phys_t *start) +{ + const binary_part *result; /* Trouvaille à retourner */ + size_t i; /* Boucle de parcours */ + binary_part *part; /* Zone mémoire manipulée */ + result = NULL; + for (i = 0; i < content->count && result == NULL; i++) + { + part = &content->parts[i]; + + if (mrange_contains_addr(&part->range, addr)) + result = part; + + } + if (result != NULL) + *start = compute_vmpa_diff(get_mrange_addr(&result->range), addr); + + return result; + +} /****************************************************************************** @@ -260,19 +300,367 @@ GBinContent *g_binary_content_new_from_file(const char *filename) * * ******************************************************************************/ -bool g_binary_content_get_raw(const GBinContent *content, const vmpa2t *addr, phys_t length, bin_t *out) +bool g_binary_content_get_raw(const GBinContent *content, vmpa2t *addr, phys_t length, bin_t *out) { + bool result; + phys_t offset; + /* FIXME */ - memcpy(out, &content->parts[0].data[get_phy_addr(addr)], length); + offset = get_phy_addr(addr); + + memcpy(out, &content->parts[0].data[offset], length); + + advance_vmpa(addr, length); + + return true; + +} + + + + + + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à venir lire. * +* addr = position de la tête de lecture. * +* low = position éventuelle des 4 bits visés. [OUT] * +* endian = ordre des bits dans la source. * +* val = lieu d'enregistrement de la lecture. [OUT] * +* * +* Description : Lit un nombre non signé sur quatre bits. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_binary_content_read_u4(const GBinContent *content, vmpa2t *addr, bool *low, SourceEndian endian, uint8_t *val) +{ + phys_t start; /* Tête de lecture relative */ + const binary_part *part; /* Zone de mémoire effective */ + bin_t *data; /* Contenu binaire représenté */ + + part = g_binary_content_find_part(content, addr, &start); + if (part == NULL) return false; + + if ((get_mrange_length(&part->range) - start) < 1) return false; + + data = part->data; + + if (*low) + { + *val = data[start] & 0x0f; + *low = false; + } + else + { + *val = (data[start] & 0xf0) >> 4; + *low = true; + advance_vmpa(addr, 4); + } + + return true; + +} + + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à venir lire. * +* addr = position de la tête de lecture. * +* endian = ordre des bits dans la source. * +* val = lieu d'enregistrement de la lecture. [OUT] * +* * +* Description : Lit un nombre non signé sur un octet. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_binary_content_read_u8(const GBinContent *content, vmpa2t *addr, SourceEndian endian, uint8_t *val) +{ + phys_t start; /* Tête de lecture relative */ + const binary_part *part; /* Zone de mémoire effective */ + bin_t *data; /* Contenu binaire représenté */ + + part = g_binary_content_find_part(content, addr, &start); + if (part == NULL) return false; + + if ((get_mrange_length(&part->range) - start) < 1) return false; + + data = part->data; + + *val = data[start]; + + advance_vmpa(addr, 1); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à venir lire. * +* addr = position de la tête de lecture. * +* 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_u16(const GBinContent *content, vmpa2t *addr, SourceEndian endian, uint16_t *val) +{ + phys_t start; /* Tête de lecture relative */ + const binary_part *part; /* Zone de mémoire effective */ + bin_t *data; /* Contenu binaire représenté */ + + part = g_binary_content_find_part(content, addr, &start); + if (part == NULL) return false; + + if ((get_mrange_length(&part->range) - start) < 2) return false; + + data = part->data; + + switch (endian) + { + case SRE_LITTLE: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *val = data[start] | (uint16_t)data[start + 1] << 8; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *val = data[start + 1] | (uint16_t)data[start] << 8; + +#else + +# error "TODO : extra byte order !" + +#endif + + break; + + case SRE_MIDDLE: + assert(false); /* TODO */ + break; + + case SRE_BIG: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *val = data[start + 1] | (uint16_t)data[start] << 8; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *val = data[start] | (uint16_t)data[start + 1] << 8; + +#else + +# error "TODO : extra byte order !" + +#endif + + break; + + + } + + advance_vmpa(addr, 2); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à venir lire. * +* addr = position de la tête de lecture. * +* endian = ordre des bits dans la source. * +* val = lieu d'enregistrement de la lecture. [OUT] * +* * +* Description : Lit un nombre non signé sur quatre octets. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_binary_content_read_u32(const GBinContent *content, vmpa2t *addr, SourceEndian endian, uint32_t *val) +{ + phys_t start; /* Tête de lecture relative */ + const binary_part *part; /* Zone de mémoire effective */ + bin_t *data; /* Contenu binaire représenté */ + + part = g_binary_content_find_part(content, addr, &start); + if (part == NULL) return false; + + if ((get_mrange_length(&part->range) - start) < 4) return false; + + data = part->data; + + switch (endian) + { + case SRE_LITTLE: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *val = data[start] | (uint32_t)data[start + 1] << 8; + *val |= data[start + 2] << 16 | (uint32_t)data[start + 3] << 24; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *val = data[start + 3] | (uint32_t)data[start + 2] << 8; + *val |= data[start + 1] << 16 | (uint32_t)data[start] << 24; + +#else + +# error "TODO : extra byte order !" + +#endif + + break; + + case SRE_MIDDLE: + assert(false); /* TODO */ + break; + + case SRE_BIG: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *val = data[start + 3] | (uint32_t)data[start + 2] << 8; + *val |= data[start + 1] << 16 | (uint32_t)data[start] << 24; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *val = data[start] | (uint32_t)data[start + 1] << 8; + *val |= data[start + 2] << 16 | (uint32_t)data[start + 3] << 24; + +#else + +# error "TODO : extra byte order !" + +#endif + + break; + + + } + + advance_vmpa(addr, 4); return true; } +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à venir lire. * +* addr = position de la tête de lecture. * +* endian = ordre des bits dans la source. * +* val = lieu d'enregistrement de la lecture. [OUT] * +* * +* Description : Lit un nombre non signé sur huit octets. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_binary_content_read_u64(const GBinContent *content, vmpa2t *addr, SourceEndian endian, uint64_t *val) +{ + phys_t start; /* Tête de lecture relative */ + const binary_part *part; /* Zone de mémoire effective */ + bin_t *data; /* Contenu binaire représenté */ + + part = g_binary_content_find_part(content, addr, &start); + if (part == NULL) return false; + + if ((get_mrange_length(&part->range) - start) < 8) return false; + data = part->data; + switch (endian) + { + case SRE_LITTLE: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *val = (uint64_t)data[start] | (uint64_t)data[start + 1] << 8; + *val |= (uint64_t)data[start + 2] << 16 | (uint64_t)data[start + 3] << 24; + *val |= (uint64_t)data[start + 4] << 32 | (uint64_t)data[start + 5] << 40; + *val |= (uint64_t)data[start + 6] << 48 | (uint64_t)data[start + 7] << 56; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *val = (uint64_t)data[start + 7] | (uint64_t)data[start + 6] << 8; + *val |= (uint64_t)data[start + 5] << 16 | (uint64_t)data[start + 4] << 24; + *val |= (uint64_t)data[start + 3] << 32 | (uint64_t)data[start + 2] << 40; + *val |= (uint64_t)data[start + 1] << 48 | (uint64_t)data[start] << 56; + +#else + +# error "TODO : extra byte order !" + +#endif + + break; + + case SRE_MIDDLE: + assert(false); /* TODO */ + break; + + case SRE_BIG: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *val = (uint64_t)data[start + 7] | (uint64_t)data[start + 6] << 8; + *val |= (uint64_t)data[start + 5] << 16 | (uint64_t)data[start + 4] << 24; + *val |= (uint64_t)data[start + 3] << 32 | (uint64_t)data[start + 2] << 40; + *val |= (uint64_t)data[start + 1] << 48 | (uint64_t)data[start] << 56; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *val = (uint64_t)data[start] | (uint64_t)data[start + 1] << 8; + *val |= (uint64_t)data[start + 2] << 16 | (uint64_t)data[start + 3] << 24; + *val |= (uint64_t)data[start + 4] << 32 | (uint64_t)data[start + 5] << 40; + *val |= (uint64_t)data[start + 6] << 48 | (uint64_t)data[start + 7] << 56; + +#else + +# error "TODO : extra byte order !" + +#endif + + break; + + + } + + advance_vmpa(addr, 8); + + return true; + +} diff --git a/src/glibext/gbincontent.h b/src/glibext/gbincontent.h index 1bfcfa5..e2f5933 100644 --- a/src/glibext/gbincontent.h +++ b/src/glibext/gbincontent.h @@ -59,10 +59,33 @@ GBinContent *g_binary_content_new_from_file(const char *); /* Fournit une portion des données représentées. */ -bool g_binary_content_get_raw(const GBinContent *, const vmpa2t *, phys_t, bin_t *); +bool g_binary_content_get_raw(const GBinContent *, vmpa2t *, phys_t, bin_t *); +/* Lit un nombre non signé sur quatre bits. */ +bool g_binary_content_read_u4(const GBinContent *, vmpa2t *, bool *, SourceEndian, uint8_t *); + +/* Lit un nombre non signé sur un octet. */ +bool g_binary_content_read_u8(const GBinContent *, vmpa2t *, SourceEndian, uint8_t *); + +/* Lit un nombre non signé sur deux octets. */ +bool g_binary_content_read_u16(const GBinContent *, vmpa2t *, SourceEndian, uint16_t *); + +/* Lit un nombre non signé sur quatre octets. */ +bool g_binary_content_read_u32(const GBinContent *, vmpa2t *, SourceEndian, uint32_t *); + +/* Lit un nombre non signé sur huit octets. */ +bool g_binary_content_read_u64(const GBinContent *, vmpa2t *, SourceEndian, uint64_t *); + + +#define g_binary_content_read_s4(c, a, l, e, v) g_binary_content_read_u4(c, a, l, e, (uint8_t *)v) +#define g_binary_content_read_s8(c, a, e, v) g_binary_content_read_u8(c, a, e, (uint8_t *)v) +#define g_binary_content_read_s16(c, a, e, v) g_binary_content_read_u16(c, a, e, (uint16_t *)v) +#define g_binary_content_read_s32(c, a, e, v) g_binary_content_read_u32(c, a, e, (uint32_t *)v) +#define g_binary_content_read_s64(c, a, e, v) g_binary_content_read_u64(c, a, e, (uint64_t *)v) + + const bin_t *g_binary_content_get(GBinContent *content, off_t *length); |