From d9d887e226902905ef56d0ccf1107df50e5e4463 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Fri, 17 May 2024 07:50:05 +0200 Subject: Define datatypes.h and move the remaining endianness.[ch] content into io.[ch]. --- src/arch/vmpa.h | 5 +- src/common/Makefile.am | 2 +- src/common/bits.h | 3 +- src/common/datatypes.h | 56 ++++ src/common/endianness.c | 871 ------------------------------------------------ src/common/endianness.h | 132 -------- src/common/io.c | 851 +++++++++++++++++++++++++++++++++++++++++++++- src/common/io.h | 92 ++++- src/glibext/Makefile.am | 6 +- src/gtkext/Makefile.am | 2 +- 10 files changed, 1007 insertions(+), 1013 deletions(-) create mode 100644 src/common/datatypes.h delete mode 100644 src/common/endianness.c delete mode 100644 src/common/endianness.h diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h index 4f35ebe..fe98ed4 100644 --- a/src/arch/vmpa.h +++ b/src/arch/vmpa.h @@ -32,6 +32,7 @@ #include "archbase.h" #include "../common/cpp.h" +#include "../common/datatypes.h" #include "../common/packed.h" #include "../common/sqlite.h" @@ -48,8 +49,8 @@ /* Types pour respectivement une position physique et une adresse virtuelle */ -#define phys_t uint64_t -#define virt_t uint64_t +//#define phys_t uint64_t +//#define virt_t uint64_t /* Equivalents pour GLib */ #define G_TYPE_PHYS uint64_t diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 7da1a13..1c2d11a 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -11,7 +11,6 @@ libcommon_la_SOURCES = \ cpp.h \ cpu.h cpu.c \ dllist.h dllist.c \ - endianness.h endianness.c \ environment.h environment.c \ extstr.h extstr.c \ hex.h hex.c \ @@ -56,6 +55,7 @@ libcommon4_la_SOURCES = \ asm.h asm.c \ bits.h bits.c \ compiler.h \ + datatypes.h \ environment.h environment.c \ extstr.h extstr.c \ io.h io.c \ diff --git a/src/common/bits.h b/src/common/bits.h index 608db39..a66c6f0 100644 --- a/src/common/bits.h +++ b/src/common/bits.h @@ -25,7 +25,8 @@ #define _COMMON_BITS_H -#include "../arch/vmpa.h" +#include +#include diff --git a/src/common/datatypes.h b/src/common/datatypes.h new file mode 100644 index 0000000..3983267 --- /dev/null +++ b/src/common/datatypes.h @@ -0,0 +1,56 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * datatypes.h - prototypes des définitions de base pour les données + * + * Copyright (C) 2024 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 _COMMON_DATATYPES_H +#define _COMMON_DATATYPES_H + + +#include + + + +/* Octet de données binaires */ +typedef uint8_t bin_t; + +/* Types pour respectivement une position physique et une adresse virtuelle */ +typedef uint64_t phys_t; +typedef uint64_t virt_t; + + +#define NO_PHYSICAL ((phys_t)-1) +#define NO_VIRTUAL ((virt_t)-2) + + +/* Type de boutismes existants */ +typedef enum _SourceEndian +{ + SRE_LITTLE, /* Petits boutistes */ + SRE_LITTLE_WORD, /* Moyens, façon Honeywell */ + SRE_BIG_WORD, /* Moyens, façon PDP-11 */ + SRE_BIG /* Gros boutistes */ + +} SourceEndian; + + + +#endif /* _COMMON_DATATYPES_H */ diff --git a/src/common/endianness.c b/src/common/endianness.c deleted file mode 100644 index 53dc19d..0000000 --- a/src/common/endianness.c +++ /dev/null @@ -1,871 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * endianness.c - manipulation abstraite des nombres - * - * Copyright (C) 2009-2018 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 . - */ - - -#include "endianness.h" - - -#include -#include -#include - - - -/** - * Mutualisation des aiguillages... - */ - -#if __BYTE_ORDER != __LITTLE_ENDIAN && __BYTE_ORDER != __BIG_ENDIAN - - /* __PDP_ENDIAN et Cie... */ -# error "Congratulations! Your byte order is not supported!" - -#endif - - - -/* ---------------------------------------------------------------------------------- */ -/* CONVERSION ENTRE BOUTISMES */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : value = valeur d'origine à manipuler. * -* endian = ordre des bits dans la source. * -* * -* Description : Adapte un nombre sur 16 bits à un boutisme donné. * -* * -* Retour : Valeur transformée au besoin. * -* * -* Remarques : - * -* * -******************************************************************************/ - -uint16_t swap_u16(const uint16_t *value, SourceEndian endian) -{ - uint16_t result; /* Valeur à retourner */ - - switch (endian) - { - case SRE_LITTLE: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - result = *value; - -#elif __BYTE_ORDER == __BIG_ENDIAN - - result = ((*value >> 0) & 0xff) << 8 | ((*value >> 8) & 0xff) << 0; - -#endif - - break; - - case SRE_BIG: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - result = ((*value >> 0) & 0xff) << 8 | ((*value >> 8) & 0xff) << 0; - -#elif __BYTE_ORDER == __BIG_ENDIAN - - result = *value; - -#endif - - break; - - default: - assert(false); - result = -1; - break; - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : value = valeur d'origine à manipuler. * -* endian = ordre des bits dans la source. * -* * -* Description : Adapte un nombre sur 16 bits à un boutisme donné. * -* * -* Retour : Valeur transformée au besoin. * -* * -* Remarques : - * -* * -******************************************************************************/ - -uint32_t swap_u32(const uint32_t *value, SourceEndian endian) -{ - uint32_t result; /* Valeur à retourner */ - - switch (endian) - { - case SRE_LITTLE: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - result = *value; - -#elif __BYTE_ORDER == __BIG_ENDIAN - - result = ((*value >> 0) & 0xff) << 24 | ((*value >> 8) & 0xff) << 16 - | ((*value >> 16) & 0xff) << 8 | ((*value >> 24) & 0xff) << 0; - -#endif - - break; - - case SRE_BIG: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - result = ((*value >> 0) & 0xff) << 24 | ((*value >> 8) & 0xff) << 16 - | ((*value >> 16) & 0xff) << 8 | ((*value >> 24) & 0xff) << 0; - -#elif __BYTE_ORDER == __BIG_ENDIAN - - result = *value; - -#endif - - break; - - default: - assert(false); - result = -1; - break; - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : value = valeur d'origine à manipuler. * -* endian = ordre des bits dans la source. * -* * -* Description : Adapte un nombre sur 16 bits à un boutisme donné. * -* * -* Retour : Valeur transformée au besoin. * -* * -* Remarques : - * -* * -******************************************************************************/ - -uint64_t swap_u64(const uint64_t *value, SourceEndian endian) -{ - uint64_t result; /* Valeur à retourner */ - - switch (endian) - { - case SRE_LITTLE: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - result = *value; - -#elif __BYTE_ORDER == __BIG_ENDIAN - - result = ((*value >> 0) & 0xff) << 56 | ((*value >> 8) & 0xff) << 48 - | ((*value >> 16) & 0xff) << 40 | ((*value >> 24) & 0xff) << 32 - | ((*value >> 32) & 0xff) << 24 | ((*value >> 40) & 0xff) << 16 - | ((*value >> 48) & 0xff) << 8 | ((*value >> 56) & 0xff) << 0; - -#endif - - break; - - case SRE_BIG: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - result = ((*value >> 0) & 0xff) << 56 | ((*value >> 8) & 0xff) << 48 - | ((*value >> 16) & 0xff) << 40 | ((*value >> 24) & 0xff) << 32 - | ((*value >> 32) & 0xff) << 24 | ((*value >> 40) & 0xff) << 16 - | ((*value >> 48) & 0xff) << 8 | ((*value >> 56) & 0xff) << 0; - -#elif __BYTE_ORDER == __BIG_ENDIAN - - result = *value; - -#endif - - break; - - default: - assert(false); - result = -1; - break; - - } - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* BOUTISME DES ENTREES / SORTIES */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : target = lieu d'enregistrement de la lecture. [OUT] * -* data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* end = limite des données à analyser. * -* low = position éventuelle des 4 bits visés. [OUT] * -* * -* Description : Lit un nombre non signé sur 4 bits. * -* * -* Retour : Bilan de l'opération : true en cas de succès, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool read_u4(uint8_t *target, const bin_t *data, phys_t *pos, phys_t end, bool *low) -{ - if (end < 1) return false; - if (*pos > (end - 1)) return false; - - if (*low) - { - *target = data[*pos] & 0x0f; - *low = false; - } - else - { - *target = (data[*pos] & 0xf0) >> 4; - *low = true; - *pos += 1; - } - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : target = lieu d'enregistrement de la lecture. [OUT] * -* data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* end = limite des données à analyser. * -* * -* 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 read_u8(uint8_t *target, const bin_t *data, phys_t *pos, phys_t end) -{ - if (end < 1) return false; - if (*pos > (end - 1)) return false; - - *target = data[*pos]; - - *pos += 1; - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : target = lieu d'enregistrement de la lecture. [OUT] * -* data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* end = limite des données à analyser. * -* endian = ordre des bits dans la source. * -* * -* 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 read_u16(uint16_t *target, const bin_t *data, phys_t *pos, phys_t end, SourceEndian endian) -{ - if (end < 2) return false; - if (*pos > (end - 2)) return false; - - switch (endian) - { - case SRE_LITTLE: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - *target = data[*pos] | (uint16_t)data[*pos + 1] << 8; - -#elif __BYTE_ORDER == __BIG_ENDIAN - - *target = data[*pos + 1] | (uint16_t)data[*pos] << 8; - -#endif - - break; - - case SRE_LITTLE_WORD: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - *target = data[*pos] << 8 | (uint16_t)data[*pos + 1]; - -#elif __BYTE_ORDER == __BIG_ENDIAN - - *target = data[*pos + 1] << 8 | (uint16_t)data[*pos]; - -#endif - - break; - - case SRE_BIG_WORD: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - *target = data[*pos + 1] << 8 | (uint16_t)data[*pos]; - -#elif __BYTE_ORDER == __BIG_ENDIAN - - *target = data[*pos] << 8 | (uint16_t)data[*pos + 1]; - -#endif - - break; - - case SRE_BIG: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - *target = data[*pos + 1] | (uint16_t)data[*pos] << 8; - -#elif __BYTE_ORDER == __BIG_ENDIAN - - *target = data[*pos] | (uint16_t)data[*pos + 1] << 8; - -#endif - - break; - - default: - return false; - break; - - } - - *pos += 2; - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : target = lieu d'enregistrement de la lecture. [OUT] * -* data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* end = limite des données à analyser. * -* endian = ordre des bits dans la source. * -* * -* 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 read_u32(uint32_t *target, const bin_t *data, phys_t *pos, phys_t end, SourceEndian endian) -{ - if (end < 4) return false; - if (*pos > (end - 4)) return false; - - switch (endian) - { - case SRE_LITTLE: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - *target = data[*pos] | (uint32_t)data[*pos + 1] << 8; - *target |= data[*pos + 2] << 16 | (uint32_t)data[*pos + 3] << 24; - -#elif __BYTE_ORDER == __BIG_ENDIAN - - *target = data[*pos + 3] | (uint32_t)data[*pos + 2] << 8; - *target |= data[*pos + 1] << 16 | (uint32_t)data[*pos] << 24; - -#endif - - break; - - case SRE_LITTLE_WORD: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - *target = data[*pos] << 8 | (uint32_t)data[*pos + 1]; - *target |= data[*pos + 2] << 24 | (uint32_t)data[*pos + 3] << 16; - -#elif __BYTE_ORDER == __BIG_ENDIAN - - *target = data[*pos + 3] << 8 | (uint32_t)data[*pos + 2]; - *target |= data[*pos + 1] << 24 | (uint32_t)data[*pos] << 16; - -#endif - - break; - - case SRE_BIG_WORD: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - *target = data[*pos + 3] << 8 | (uint32_t)data[*pos + 2]; - *target |= data[*pos + 1] << 24 | (uint32_t)data[*pos] << 16; - -#elif __BYTE_ORDER == __BIG_ENDIAN - - *target = data[*pos] << 8 | (uint32_t)data[*pos + 1]; - *target |= data[*pos + 2] << 24 | (uint32_t)data[*pos + 3] << 16; - -#endif - - break; - - case SRE_BIG: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - *target = data[*pos + 3] | (uint32_t)data[*pos + 2] << 8; - *target |= data[*pos + 1] << 16 | (uint32_t)data[*pos] << 24; - -#elif __BYTE_ORDER == __BIG_ENDIAN - - *target = data[*pos] | (uint32_t)data[*pos + 1] << 8; - *target |= data[*pos + 2] << 16 | (uint32_t)data[*pos + 3] << 24; - -#endif - - break; - - default: - return false; - break; - - } - - *pos += 4; - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : target = lieu d'enregistrement de la lecture. [OUT] * -* data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* end = limite des données à analyser. * -* endian = ordre des bits dans la source. * -* * -* 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 read_u64(uint64_t *target, const bin_t *data, phys_t *pos, phys_t end, SourceEndian endian) -{ - if (end < 8) return false; - if (*pos > (end - 8)) return false; - - switch (endian) - { - case SRE_LITTLE: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - *target = (uint64_t)data[*pos] | (uint64_t)data[*pos + 1] << 8; - *target |= (uint64_t)data[*pos + 2] << 16 | (uint64_t)data[*pos + 3] << 24; - *target |= (uint64_t)data[*pos + 4] << 32 | (uint64_t)data[*pos + 5] << 40; - *target |= (uint64_t)data[*pos + 6] << 48 | (uint64_t)data[*pos + 7] << 56; - -#elif __BYTE_ORDER == __BIG_ENDIAN - - *target = (uint64_t)data[*pos + 7] | (uint64_t)data[*pos + 6] << 8; - *target |= (uint64_t)data[*pos + 5] << 16 | (uint64_t)data[*pos + 4] << 24; - *target |= (uint64_t)data[*pos + 3] << 32 | (uint64_t)data[*pos + 2] << 40; - *target |= (uint64_t)data[*pos + 1] << 48 | (uint64_t)data[*pos] << 56; - -#endif - - break; - - case SRE_LITTLE_WORD: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - *target = (uint64_t)data[*pos] << 8 | (uint64_t)data[*pos + 1]; - *target |= (uint64_t)data[*pos + 2] << 24 | (uint64_t)data[*pos + 3] << 16; - *target |= (uint64_t)data[*pos + 4] << 40 | (uint64_t)data[*pos + 5] << 32; - *target |= (uint64_t)data[*pos + 6] << 56 | (uint64_t)data[*pos + 7] << 48; - -#elif __BYTE_ORDER == __BIG_ENDIAN - - *target = (uint64_t)data[*pos + 7] << 8 | (uint64_t)data[*pos + 6]; - *target |= (uint64_t)data[*pos + 5] << 24 | (uint64_t)data[*pos + 4] << 16; - *target |= (uint64_t)data[*pos + 3] << 40 | (uint64_t)data[*pos + 2] << 32; - *target |= (uint64_t)data[*pos + 1] << 56 | (uint64_t)data[*pos] << 48; - -#endif - - break; - - case SRE_BIG_WORD: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - *target = (uint64_t)data[*pos + 7] << 8 | (uint64_t)data[*pos + 6]; - *target |= (uint64_t)data[*pos + 5] << 24 | (uint64_t)data[*pos + 4] << 16; - *target |= (uint64_t)data[*pos + 3] << 40 | (uint64_t)data[*pos + 2] << 32; - *target |= (uint64_t)data[*pos + 1] << 56 | (uint64_t)data[*pos] << 48; - -#elif __BYTE_ORDER == __BIG_ENDIAN - - *target = (uint64_t)data[*pos] << 8| (uint64_t)data[*pos + 1]; - *target |= (uint64_t)data[*pos + 2] << 24 | (uint64_t)data[*pos + 3] << 16; - *target |= (uint64_t)data[*pos + 4] << 40 | (uint64_t)data[*pos + 5] << 32; - *target |= (uint64_t)data[*pos + 6] << 56 | (uint64_t)data[*pos + 7] << 48; - -#endif - - break; - - case SRE_BIG: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - *target = (uint64_t)data[*pos + 7] | (uint64_t)data[*pos + 6] << 8; - *target |= (uint64_t)data[*pos + 5] << 16 | (uint64_t)data[*pos + 4] << 24; - *target |= (uint64_t)data[*pos + 3] << 32 | (uint64_t)data[*pos + 2] << 40; - *target |= (uint64_t)data[*pos + 1] << 48 | (uint64_t)data[*pos] << 56; - -#elif __BYTE_ORDER == __BIG_ENDIAN - - *target = (uint64_t)data[*pos] | (uint64_t)data[*pos + 1] << 8; - *target |= (uint64_t)data[*pos + 2] << 16 | (uint64_t)data[*pos + 3] << 24; - *target |= (uint64_t)data[*pos + 4] << 32 | (uint64_t)data[*pos + 5] << 40; - *target |= (uint64_t)data[*pos + 6] << 48 | (uint64_t)data[*pos + 7] << 56; - -#endif - - break; - - default: - return false; - break; - - } - - *pos += 8; - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : value = source de la valeur à transcrire. * -* size = taille de cette source de données. * -* data = flux de données à modifier. [OUT] * -* pos = position courante dans ce flux. [OUT] * -* end = limite des données à analyser. * -* endian = ordre des bits dans la source. * -* * -* Description : Ecrit un nombre non signé sur n octets. * -* * -* Retour : Bilan de l'opération : true en cas de succès, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool _write_un(const bin_t *value, size_t size, bin_t *data, off_t *pos, off_t end, SourceEndian endian) -{ - size_t i; /* Boucle de parcours */ - - if (end < size) return false; - if (*pos > (end - size)) return false; - - switch (endian) - { - case SRE_LITTLE: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - memcpy(&data[*pos], value, size); - (*pos) += size; - -#elif __BYTE_ORDER == __BIG_ENDIAN - - for (i = 0; i < size; i++, (*pos)++) - *(data + *pos) = *(value + size - i - 1); - -#endif - - break; - - case SRE_BIG: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - for (i = 0; i < size; i++, (*pos)++) - *(data + *pos) = *(value + size - i - 1); - -#elif __BYTE_ORDER == __BIG_ENDIAN - - memcpy(&data[*pos], value, size); - (*pos) += size; - -#endif - - break; - - default: - return false; - break; - - } - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : target = lieu d'enregistrement de la lecture. [OUT] * -* data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* end = limite des données à analyser. * -* endian = ordre des bits dans la source. * -* * -* Description : Lit un nombre hexadécimal non signé sur deux octets. * -* * -* Retour : Bilan de l'opération : true en cas de succès, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool strtou8(uint8_t *target, const char *data, size_t *pos, size_t end, SourceEndian endian) -{ - size_t i; /* Boucle de parcours */ - - if (end < 2) return false; - if (*pos > (end - 2)) return false; - - *target = 0; - - for (i = 0; i < 2; i++) - switch (data[*pos + i]) - { - case '0' ... '9': - *target |= ((data[*pos + i] - '0') << (4 * (1 - i))); - break; - - case 'A' ... 'F': - *target |= ((data[*pos + i] + 10 - 'A') << (4 * (1 - i))); - break; - - case 'a' ... 'f': - *target |= ((data[*pos + i] + 10 - 'a') << (4 * (1 - i))); - break; - - } - - *pos += 2; - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : n = nombre d'octets constituant le nombre à lire. * -* data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* end = limite des données à analyser. * -* endian = ordre des bits dans la source. * -* ... = lieu d'enregistrement de la lecture. [OUT] * -* * -* Description : Lit un nombre hexadécimal non signé sur n octets. * -* * -* Retour : Bilan de l'opération : true en cas de succès, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool _strtoun(uint8_t n, const char *data, size_t *pos, size_t end, SourceEndian endian, ...) -{ - bool result; /* Bilan à renvoyer */ - va_list ap; /* Arguments variables */ - uint8_t *target8; /* Enregistrement sur 8 bits */ - uint16_t *target16; /* Enregistrement sur 16 bits */ - uint32_t *target32; /* Enregistrement sur 32 bits */ - uint64_t *target64; /* Enregistrement sur 64 bits */ - uint8_t i; /* Boucle de parcours #1 */ - size_t j; /* Boucle de parcours #2 */ - uint8_t tmp; /* Valeur temporaire de 8 bits */ - - if (end < (n * 2)) return false; - if (*pos > (end - (n * 2))) return false; - - /* Récupération de la destination */ - - va_start(ap, endian); - - switch (n) - { - case 1: - target8 = va_arg(ap, uint8_t *); - *target8 = 0; - target64 = (uint64_t *)target8; - break; - case 2: - target16 = va_arg(ap, uint16_t *); - *target16 = 0; - target64 = (uint64_t *)target16; - break; - case 4: - target32 = va_arg(ap, uint32_t *); - *target32 = 0; - target64 = (uint64_t *)target32; - break; - case 8: - target64 = va_arg(ap, uint64_t *); - *target64 = 0ull; - break; - default: - va_end(ap); - return false; - break; - } - - va_end(ap); - - /* Lecture des données */ - - result = true; - - for (i = 0; i < n && result; i++) - { - tmp = 0; - - for (j = 0; j < 2 && result; j++) - switch (data[*pos + j]) - { - case '0' ... '9': - tmp |= ((data[*pos + j] - '0') << (4 * (1 - j))); - break; - - case 'A' ... 'F': - tmp |= ((data[*pos + j] + 10 - 'A') << (4 * (1 - j))); - break; - - case 'a' ... 'f': - tmp |= ((data[*pos + j] + 10 - 'a') << (4 * (1 - j))); - break; - - default: - result = false; - break; - - } - - *pos += 2; - - switch (endian) - { - case SRE_LITTLE: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - *target64 |= ((uint64_t)tmp) << (8 * i); - -#elif __BYTE_ORDER == __BIG_ENDIAN - - *target64 |= ((uint64_t)tmp) << (8 * (n - 1 - i)); - -#endif - - break; - - case SRE_BIG: - -#if __BYTE_ORDER == __LITTLE_ENDIAN - - *target64 |= ((uint64_t)tmp) << (8 * (n - 1 - i)); - -#elif __BYTE_ORDER == __BIG_ENDIAN - - *target64 |= ((uint64_t)tmp) << (8 * i); - -#endif - - break; - - default: - return false; - break; - - } - - } - - return result; - -} diff --git a/src/common/endianness.h b/src/common/endianness.h deleted file mode 100644 index aabdb57..0000000 --- a/src/common/endianness.h +++ /dev/null @@ -1,132 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * endianness.h - prototypes pour la manipulation abstraite des nombres - * - * Copyright (C) 2009-2018 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 _COMMON_ENDIANNESS_H -#define _COMMON_ENDIANNESS_H - - -#include - - -#include "../arch/archbase.h" -#include "../arch/vmpa.h" - - - -/* Type de boutismes existants */ -typedef enum _SourceEndian -{ - SRE_LITTLE, /* Petits boutistes */ - SRE_LITTLE_WORD, /* Moyens, façon Honeywell */ - SRE_BIG_WORD, /* Moyens, façon PDP-11 */ - SRE_BIG /* Gros boutistes */ - -} SourceEndian; - - - -/* --------------------------- CONVERSION ENTRE BOUTISMES --------------------------- */ - - -/* Adapte un nombre sur 16 bits à un boutisme donné. */ -uint16_t swap_u16(const uint16_t *, SourceEndian); - -/* Adapte un nombre sur 16 bits à un boutisme donné. */ -uint32_t swap_u32(const uint32_t *, SourceEndian); - -/* Adapte un nombre sur 16 bits à un boutisme donné. */ -uint64_t swap_u64(const uint64_t *, SourceEndian); - - -#define from_u16(v, e) swap_u16(v, e) -#define from_u32(v, e) swap_u32(v, e) -#define from_u64(v, e) swap_u64(v, e) - - -#define to_u16(v, e) swap_u16(v, e) -#define to_u32(v, e) swap_u32(v, e) -#define to_u64(v, e) swap_u64(v, e) - - - -/* ------------------------- BOUTISME DES ENTREES / SORTIES ------------------------- */ - - -/* Lit un nombre non signé sur 4 bits. */ -bool read_u4(uint8_t *, const bin_t *, phys_t *, phys_t, bool *); - -/* Lit un nombre non signé sur un octet. */ -bool read_u8(uint8_t *, const bin_t *, phys_t *, phys_t); - -/* Lit un nombre non signé sur deux octets. */ -bool read_u16(uint16_t *, const bin_t *, phys_t *, phys_t, SourceEndian); - -/* Lit un nombre non signé sur quatre octets. */ -bool read_u32(uint32_t *, const bin_t *, phys_t *, phys_t, SourceEndian); - -/* Lit un nombre non signé sur huit octets. */ -bool read_u64(uint64_t *, const bin_t *, phys_t *, phys_t, SourceEndian); - - -#define read_s4(target, data, pos, len, low) read_u4((uint8_t *)target, data, pos, len, low) -#define read_s8(target, data, pos, len) read_u8((uint8_t *)target, data, pos, len) -#define read_s16(target, data, pos, len, endian) read_u16((uint16_t *)target, data, pos, len, endian) -#define read_s32(target, data, pos, len, endian) read_u32((uint32_t *)target, data, pos, len, endian) -#define read_s64(target, data, pos, len, endian) read_u64((uint64_t *)target, data, pos, len, endian) - - -/* Ecrit un nombre non signé sur n octets. */ -bool _write_un(const bin_t *, size_t, bin_t *, off_t *, off_t, SourceEndian); - - -#define write_un(value, data, pos, len, endian, type) \ - ({ \ - type __tmp; \ - (void)(value == &__tmp); \ - _write_un((bin_t *)value, sizeof(type), data, pos, len, endian); \ - }) - - -#define write_u8(value, data, pos, len, endian) write_un(value, data, pos, len, endian, uint8_t) -#define write_u16(value, data, pos, len, endian) write_un(value, data, pos, len, endian, uint16_t) -#define write_u32(value, data, pos, len, endian) write_un(value, data, pos, len, endian, uint32_t) -#define write_u64(value, data, pos, len, endian) write_un(value, data, pos, len, endian, uint64_t) - -#define write_s8(value, data, pos, len, endian) write_un(value, data, pos, len, endian, sint8_t) -#define write_s16(value, data, pos, len, endian) write_un(value, data, pos, len, endian, sint16_t) -#define write_s32(value, data, pos, len, endian) write_un(value, data, pos, len, endian, sint32_t) -#define write_s64(value, data, pos, len, endian) write_un(value, data, pos, len, endian, sint64_t) - - -/* Lit un nombre hexadécimal non signé sur deux octets. */ -bool strtou8(uint8_t *, const char *, size_t *, size_t, SourceEndian); - -/* Lit un nombre hexadécimal non signé sur n octets. */ -bool _strtoun(uint8_t, const char *, size_t *, size_t, SourceEndian, ...); - - -#define strtou32(target, data, pos, len, endian) _strtoun(4, data, pos, len, endian, target) - - - -#endif /* _COMMON_ENDIANNESS_H */ diff --git a/src/common/io.c b/src/common/io.c index 3208a2a..f325e7d 100644 --- a/src/common/io.c +++ b/src/common/io.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * io.c - entrées sorties fiables + * io.c - entrées sorties fiables et manipulation des nombres * * Copyright (C) 2014-2019 Cyrille Bagard * @@ -24,8 +24,10 @@ #include "io.h" +#include #include #include +#include #include #include #include @@ -37,6 +39,24 @@ +/** + * Mutualisation des aiguillages... + */ + +#if __BYTE_ORDER != __LITTLE_ENDIAN && __BYTE_ORDER != __BIG_ENDIAN + + /* __PDP_ENDIAN et Cie... */ +# error "Congratulations! Your byte order is not supported!" + +#endif + + + +/* ---------------------------------------------------------------------------------- */ +/* ENTREES/SORTIES BRUTES ENCADREES */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * * Paramètres : fd = flux ouvert en lecture. * @@ -284,3 +304,832 @@ bool safe_send(int sockfd, const void *buf, size_t len, int flags) return (remaining == 0); } + + + +/* ---------------------------------------------------------------------------------- */ +/* CONVERSION ENTRE BOUTISMES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : value = valeur d'origine à manipuler. * +* endian = ordre des bits dans la source. * +* * +* Description : Adapte un nombre sur 16 bits à un boutisme donné. * +* * +* Retour : Valeur transformée au besoin. * +* * +* Remarques : - * +* * +******************************************************************************/ + +uint16_t swap_u16(const uint16_t *value, SourceEndian endian) +{ + uint16_t result; /* Valeur à retourner */ + + switch (endian) + { + case SRE_LITTLE: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + result = *value; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + result = ((*value >> 0) & 0xff) << 8 | ((*value >> 8) & 0xff) << 0; + +#endif + + break; + + case SRE_BIG: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + result = ((*value >> 0) & 0xff) << 8 | ((*value >> 8) & 0xff) << 0; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + result = *value; + +#endif + + break; + + default: + assert(false); + result = -1; + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : value = valeur d'origine à manipuler. * +* endian = ordre des bits dans la source. * +* * +* Description : Adapte un nombre sur 16 bits à un boutisme donné. * +* * +* Retour : Valeur transformée au besoin. * +* * +* Remarques : - * +* * +******************************************************************************/ + +uint32_t swap_u32(const uint32_t *value, SourceEndian endian) +{ + uint32_t result; /* Valeur à retourner */ + + switch (endian) + { + case SRE_LITTLE: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + result = *value; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + result = ((*value >> 0) & 0xff) << 24 | ((*value >> 8) & 0xff) << 16 + | ((*value >> 16) & 0xff) << 8 | ((*value >> 24) & 0xff) << 0; + +#endif + + break; + + case SRE_BIG: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + result = ((*value >> 0) & 0xff) << 24 | ((*value >> 8) & 0xff) << 16 + | ((*value >> 16) & 0xff) << 8 | ((*value >> 24) & 0xff) << 0; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + result = *value; + +#endif + + break; + + default: + assert(false); + result = -1; + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : value = valeur d'origine à manipuler. * +* endian = ordre des bits dans la source. * +* * +* Description : Adapte un nombre sur 16 bits à un boutisme donné. * +* * +* Retour : Valeur transformée au besoin. * +* * +* Remarques : - * +* * +******************************************************************************/ + +uint64_t swap_u64(const uint64_t *value, SourceEndian endian) +{ + uint64_t result; /* Valeur à retourner */ + + switch (endian) + { + case SRE_LITTLE: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + result = *value; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + result = ((*value >> 0) & 0xff) << 56 | ((*value >> 8) & 0xff) << 48 + | ((*value >> 16) & 0xff) << 40 | ((*value >> 24) & 0xff) << 32 + | ((*value >> 32) & 0xff) << 24 | ((*value >> 40) & 0xff) << 16 + | ((*value >> 48) & 0xff) << 8 | ((*value >> 56) & 0xff) << 0; + +#endif + + break; + + case SRE_BIG: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + result = ((*value >> 0) & 0xff) << 56 | ((*value >> 8) & 0xff) << 48 + | ((*value >> 16) & 0xff) << 40 | ((*value >> 24) & 0xff) << 32 + | ((*value >> 32) & 0xff) << 24 | ((*value >> 40) & 0xff) << 16 + | ((*value >> 48) & 0xff) << 8 | ((*value >> 56) & 0xff) << 0; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + result = *value; + +#endif + + break; + + default: + assert(false); + result = -1; + break; + + } + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* BOUTISME DES ENTREES / SORTIES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : target = lieu d'enregistrement de la lecture. [OUT] * +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* end = limite des données à analyser. * +* low = position éventuelle des 4 bits visés. [OUT] * +* * +* Description : Lit un nombre non signé sur 4 bits. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_u4(uint8_t *target, const bin_t *data, phys_t *pos, phys_t end, bool *low) +{ + if (end < 1) return false; + if (*pos > (end - 1)) return false; + + if (*low) + { + *target = data[*pos] & 0x0f; + *low = false; + } + else + { + *target = (data[*pos] & 0xf0) >> 4; + *low = true; + *pos += 1; + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : target = lieu d'enregistrement de la lecture. [OUT] * +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* end = limite des données à analyser. * +* * +* 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 read_u8(uint8_t *target, const bin_t *data, phys_t *pos, phys_t end) +{ + if (end < 1) return false; + if (*pos > (end - 1)) return false; + + *target = data[*pos]; + + *pos += 1; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : target = lieu d'enregistrement de la lecture. [OUT] * +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* end = limite des données à analyser. * +* endian = ordre des bits dans la source. * +* * +* 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 read_u16(uint16_t *target, const bin_t *data, phys_t *pos, phys_t end, SourceEndian endian) +{ + if (end < 2) return false; + if (*pos > (end - 2)) return false; + + switch (endian) + { + case SRE_LITTLE: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *target = data[*pos] | (uint16_t)data[*pos + 1] << 8; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *target = data[*pos + 1] | (uint16_t)data[*pos] << 8; + +#endif + + break; + + case SRE_LITTLE_WORD: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *target = data[*pos] << 8 | (uint16_t)data[*pos + 1]; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *target = data[*pos + 1] << 8 | (uint16_t)data[*pos]; + +#endif + + break; + + case SRE_BIG_WORD: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *target = data[*pos + 1] << 8 | (uint16_t)data[*pos]; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *target = data[*pos] << 8 | (uint16_t)data[*pos + 1]; + +#endif + + break; + + case SRE_BIG: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *target = data[*pos + 1] | (uint16_t)data[*pos] << 8; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *target = data[*pos] | (uint16_t)data[*pos + 1] << 8; + +#endif + + break; + + default: + return false; + break; + + } + + *pos += 2; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : target = lieu d'enregistrement de la lecture. [OUT] * +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* end = limite des données à analyser. * +* endian = ordre des bits dans la source. * +* * +* 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 read_u32(uint32_t *target, const bin_t *data, phys_t *pos, phys_t end, SourceEndian endian) +{ + if (end < 4) return false; + if (*pos > (end - 4)) return false; + + switch (endian) + { + case SRE_LITTLE: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *target = data[*pos] | (uint32_t)data[*pos + 1] << 8; + *target |= data[*pos + 2] << 16 | (uint32_t)data[*pos + 3] << 24; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *target = data[*pos + 3] | (uint32_t)data[*pos + 2] << 8; + *target |= data[*pos + 1] << 16 | (uint32_t)data[*pos] << 24; + +#endif + + break; + + case SRE_LITTLE_WORD: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *target = data[*pos] << 8 | (uint32_t)data[*pos + 1]; + *target |= data[*pos + 2] << 24 | (uint32_t)data[*pos + 3] << 16; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *target = data[*pos + 3] << 8 | (uint32_t)data[*pos + 2]; + *target |= data[*pos + 1] << 24 | (uint32_t)data[*pos] << 16; + +#endif + + break; + + case SRE_BIG_WORD: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *target = data[*pos + 3] << 8 | (uint32_t)data[*pos + 2]; + *target |= data[*pos + 1] << 24 | (uint32_t)data[*pos] << 16; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *target = data[*pos] << 8 | (uint32_t)data[*pos + 1]; + *target |= data[*pos + 2] << 24 | (uint32_t)data[*pos + 3] << 16; + +#endif + + break; + + case SRE_BIG: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *target = data[*pos + 3] | (uint32_t)data[*pos + 2] << 8; + *target |= data[*pos + 1] << 16 | (uint32_t)data[*pos] << 24; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *target = data[*pos] | (uint32_t)data[*pos + 1] << 8; + *target |= data[*pos + 2] << 16 | (uint32_t)data[*pos + 3] << 24; + +#endif + + break; + + default: + return false; + break; + + } + + *pos += 4; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : target = lieu d'enregistrement de la lecture. [OUT] * +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* end = limite des données à analyser. * +* endian = ordre des bits dans la source. * +* * +* 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 read_u64(uint64_t *target, const bin_t *data, phys_t *pos, phys_t end, SourceEndian endian) +{ + if (end < 8) return false; + if (*pos > (end - 8)) return false; + + switch (endian) + { + case SRE_LITTLE: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *target = (uint64_t)data[*pos] | (uint64_t)data[*pos + 1] << 8; + *target |= (uint64_t)data[*pos + 2] << 16 | (uint64_t)data[*pos + 3] << 24; + *target |= (uint64_t)data[*pos + 4] << 32 | (uint64_t)data[*pos + 5] << 40; + *target |= (uint64_t)data[*pos + 6] << 48 | (uint64_t)data[*pos + 7] << 56; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *target = (uint64_t)data[*pos + 7] | (uint64_t)data[*pos + 6] << 8; + *target |= (uint64_t)data[*pos + 5] << 16 | (uint64_t)data[*pos + 4] << 24; + *target |= (uint64_t)data[*pos + 3] << 32 | (uint64_t)data[*pos + 2] << 40; + *target |= (uint64_t)data[*pos + 1] << 48 | (uint64_t)data[*pos] << 56; + +#endif + + break; + + case SRE_LITTLE_WORD: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *target = (uint64_t)data[*pos] << 8 | (uint64_t)data[*pos + 1]; + *target |= (uint64_t)data[*pos + 2] << 24 | (uint64_t)data[*pos + 3] << 16; + *target |= (uint64_t)data[*pos + 4] << 40 | (uint64_t)data[*pos + 5] << 32; + *target |= (uint64_t)data[*pos + 6] << 56 | (uint64_t)data[*pos + 7] << 48; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *target = (uint64_t)data[*pos + 7] << 8 | (uint64_t)data[*pos + 6]; + *target |= (uint64_t)data[*pos + 5] << 24 | (uint64_t)data[*pos + 4] << 16; + *target |= (uint64_t)data[*pos + 3] << 40 | (uint64_t)data[*pos + 2] << 32; + *target |= (uint64_t)data[*pos + 1] << 56 | (uint64_t)data[*pos] << 48; + +#endif + + break; + + case SRE_BIG_WORD: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *target = (uint64_t)data[*pos + 7] << 8 | (uint64_t)data[*pos + 6]; + *target |= (uint64_t)data[*pos + 5] << 24 | (uint64_t)data[*pos + 4] << 16; + *target |= (uint64_t)data[*pos + 3] << 40 | (uint64_t)data[*pos + 2] << 32; + *target |= (uint64_t)data[*pos + 1] << 56 | (uint64_t)data[*pos] << 48; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *target = (uint64_t)data[*pos] << 8| (uint64_t)data[*pos + 1]; + *target |= (uint64_t)data[*pos + 2] << 24 | (uint64_t)data[*pos + 3] << 16; + *target |= (uint64_t)data[*pos + 4] << 40 | (uint64_t)data[*pos + 5] << 32; + *target |= (uint64_t)data[*pos + 6] << 56 | (uint64_t)data[*pos + 7] << 48; + +#endif + + break; + + case SRE_BIG: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *target = (uint64_t)data[*pos + 7] | (uint64_t)data[*pos + 6] << 8; + *target |= (uint64_t)data[*pos + 5] << 16 | (uint64_t)data[*pos + 4] << 24; + *target |= (uint64_t)data[*pos + 3] << 32 | (uint64_t)data[*pos + 2] << 40; + *target |= (uint64_t)data[*pos + 1] << 48 | (uint64_t)data[*pos] << 56; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *target = (uint64_t)data[*pos] | (uint64_t)data[*pos + 1] << 8; + *target |= (uint64_t)data[*pos + 2] << 16 | (uint64_t)data[*pos + 3] << 24; + *target |= (uint64_t)data[*pos + 4] << 32 | (uint64_t)data[*pos + 5] << 40; + *target |= (uint64_t)data[*pos + 6] << 48 | (uint64_t)data[*pos + 7] << 56; + +#endif + + break; + + default: + return false; + break; + + } + + *pos += 8; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : value = source de la valeur à transcrire. * +* size = taille de cette source de données. * +* data = flux de données à modifier. [OUT] * +* pos = position courante dans ce flux. [OUT] * +* end = limite des données à analyser. * +* endian = ordre des bits dans la source. * +* * +* Description : Ecrit un nombre non signé sur n octets. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool _write_un(const bin_t *value, size_t size, bin_t *data, off_t *pos, off_t end, SourceEndian endian) +{ + size_t i; /* Boucle de parcours */ + + if (end < size) return false; + if (*pos > (end - size)) return false; + + switch (endian) + { + case SRE_LITTLE: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + memcpy(&data[*pos], value, size); + (*pos) += size; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + for (i = 0; i < size; i++, (*pos)++) + *(data + *pos) = *(value + size - i - 1); + +#endif + + break; + + case SRE_BIG: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + for (i = 0; i < size; i++, (*pos)++) + *(data + *pos) = *(value + size - i - 1); + +#elif __BYTE_ORDER == __BIG_ENDIAN + + memcpy(&data[*pos], value, size); + (*pos) += size; + +#endif + + break; + + default: + return false; + break; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : target = lieu d'enregistrement de la lecture. [OUT] * +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* end = limite des données à analyser. * +* endian = ordre des bits dans la source. * +* * +* Description : Lit un nombre hexadécimal non signé sur deux octets. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool strtou8(uint8_t *target, const char *data, size_t *pos, size_t end, SourceEndian endian) +{ + size_t i; /* Boucle de parcours */ + + if (end < 2) return false; + if (*pos > (end - 2)) return false; + + *target = 0; + + for (i = 0; i < 2; i++) + switch (data[*pos + i]) + { + case '0' ... '9': + *target |= ((data[*pos + i] - '0') << (4 * (1 - i))); + break; + + case 'A' ... 'F': + *target |= ((data[*pos + i] + 10 - 'A') << (4 * (1 - i))); + break; + + case 'a' ... 'f': + *target |= ((data[*pos + i] + 10 - 'a') << (4 * (1 - i))); + break; + + } + + *pos += 2; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : n = nombre d'octets constituant le nombre à lire. * +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* end = limite des données à analyser. * +* endian = ordre des bits dans la source. * +* ... = lieu d'enregistrement de la lecture. [OUT] * +* * +* Description : Lit un nombre hexadécimal non signé sur n octets. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool _strtoun(uint8_t n, const char *data, size_t *pos, size_t end, SourceEndian endian, ...) +{ + bool result; /* Bilan à renvoyer */ + va_list ap; /* Arguments variables */ + uint8_t *target8; /* Enregistrement sur 8 bits */ + uint16_t *target16; /* Enregistrement sur 16 bits */ + uint32_t *target32; /* Enregistrement sur 32 bits */ + uint64_t *target64; /* Enregistrement sur 64 bits */ + uint8_t i; /* Boucle de parcours #1 */ + size_t j; /* Boucle de parcours #2 */ + uint8_t tmp; /* Valeur temporaire de 8 bits */ + + if (end < (n * 2)) return false; + if (*pos > (end - (n * 2))) return false; + + /* Récupération de la destination */ + + va_start(ap, endian); + + switch (n) + { + case 1: + target8 = va_arg(ap, uint8_t *); + *target8 = 0; + target64 = (uint64_t *)target8; + break; + case 2: + target16 = va_arg(ap, uint16_t *); + *target16 = 0; + target64 = (uint64_t *)target16; + break; + case 4: + target32 = va_arg(ap, uint32_t *); + *target32 = 0; + target64 = (uint64_t *)target32; + break; + case 8: + target64 = va_arg(ap, uint64_t *); + *target64 = 0ull; + break; + default: + va_end(ap); + return false; + break; + } + + va_end(ap); + + /* Lecture des données */ + + result = true; + + for (i = 0; i < n && result; i++) + { + tmp = 0; + + for (j = 0; j < 2 && result; j++) + switch (data[*pos + j]) + { + case '0' ... '9': + tmp |= ((data[*pos + j] - '0') << (4 * (1 - j))); + break; + + case 'A' ... 'F': + tmp |= ((data[*pos + j] + 10 - 'A') << (4 * (1 - j))); + break; + + case 'a' ... 'f': + tmp |= ((data[*pos + j] + 10 - 'a') << (4 * (1 - j))); + break; + + default: + result = false; + break; + + } + + *pos += 2; + + switch (endian) + { + case SRE_LITTLE: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *target64 |= ((uint64_t)tmp) << (8 * i); + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *target64 |= ((uint64_t)tmp) << (8 * (n - 1 - i)); + +#endif + + break; + + case SRE_BIG: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *target64 |= ((uint64_t)tmp) << (8 * (n - 1 - i)); + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *target64 |= ((uint64_t)tmp) << (8 * i); + +#endif + + break; + + default: + return false; + break; + + } + + } + + return result; + +} diff --git a/src/common/io.h b/src/common/io.h index 82fb41e..7fe9d9d 100644 --- a/src/common/io.h +++ b/src/common/io.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * io.h - prototypes pour des entrées sorties fiables + * io.h - prototypes pour des entrées sorties fiables et la manipulation des nombres * * Copyright (C) 2014-2019 Cyrille Bagard * @@ -29,6 +29,12 @@ #include +#include "datatypes.h" + + + +/* ------------------------ ENTREES/SORTIES BRUTES ENCADREES ------------------------ */ + /* Lit des données depuis un flux local. */ bool safe_read(int, void *, size_t); @@ -47,4 +53,88 @@ bool safe_send(int, const void *, size_t, int); +/* --------------------------- CONVERSION ENTRE BOUTISMES --------------------------- */ + + +/* Adapte un nombre sur 16 bits à un boutisme donné. */ +uint16_t swap_u16(const uint16_t *, SourceEndian); + +/* Adapte un nombre sur 16 bits à un boutisme donné. */ +uint32_t swap_u32(const uint32_t *, SourceEndian); + +/* Adapte un nombre sur 16 bits à un boutisme donné. */ +uint64_t swap_u64(const uint64_t *, SourceEndian); + + +#define from_u16(v, e) swap_u16(v, e) +#define from_u32(v, e) swap_u32(v, e) +#define from_u64(v, e) swap_u64(v, e) + + +#define to_u16(v, e) swap_u16(v, e) +#define to_u32(v, e) swap_u32(v, e) +#define to_u64(v, e) swap_u64(v, e) + + + +/* ------------------------- BOUTISME DES ENTREES / SORTIES ------------------------- */ + + +/* Lit un nombre non signé sur 4 bits. */ +bool read_u4(uint8_t *, const bin_t *, phys_t *, phys_t, bool *); + +/* Lit un nombre non signé sur un octet. */ +bool read_u8(uint8_t *, const bin_t *, phys_t *, phys_t); + +/* Lit un nombre non signé sur deux octets. */ +bool read_u16(uint16_t *, const bin_t *, phys_t *, phys_t, SourceEndian); + +/* Lit un nombre non signé sur quatre octets. */ +bool read_u32(uint32_t *, const bin_t *, phys_t *, phys_t, SourceEndian); + +/* Lit un nombre non signé sur huit octets. */ +bool read_u64(uint64_t *, const bin_t *, phys_t *, phys_t, SourceEndian); + + +#define read_s4(target, data, pos, len, low) read_u4((uint8_t *)target, data, pos, len, low) +#define read_s8(target, data, pos, len) read_u8((uint8_t *)target, data, pos, len) +#define read_s16(target, data, pos, len, endian) read_u16((uint16_t *)target, data, pos, len, endian) +#define read_s32(target, data, pos, len, endian) read_u32((uint32_t *)target, data, pos, len, endian) +#define read_s64(target, data, pos, len, endian) read_u64((uint64_t *)target, data, pos, len, endian) + + +/* Ecrit un nombre non signé sur n octets. */ +bool _write_un(const bin_t *, size_t, bin_t *, off_t *, off_t, SourceEndian); + + +#define write_un(value, data, pos, len, endian, type) \ + ({ \ + type __tmp; \ + (void)(value == &__tmp); \ + _write_un((bin_t *)value, sizeof(type), data, pos, len, endian); \ + }) + + +#define write_u8(value, data, pos, len, endian) write_un(value, data, pos, len, endian, uint8_t) +#define write_u16(value, data, pos, len, endian) write_un(value, data, pos, len, endian, uint16_t) +#define write_u32(value, data, pos, len, endian) write_un(value, data, pos, len, endian, uint32_t) +#define write_u64(value, data, pos, len, endian) write_un(value, data, pos, len, endian, uint64_t) + +#define write_s8(value, data, pos, len, endian) write_un(value, data, pos, len, endian, sint8_t) +#define write_s16(value, data, pos, len, endian) write_un(value, data, pos, len, endian, sint16_t) +#define write_s32(value, data, pos, len, endian) write_un(value, data, pos, len, endian, sint32_t) +#define write_s64(value, data, pos, len, endian) write_un(value, data, pos, len, endian, sint64_t) + + +/* Lit un nombre hexadécimal non signé sur deux octets. */ +bool strtou8(uint8_t *, const char *, size_t *, size_t, SourceEndian); + +/* Lit un nombre hexadécimal non signé sur n octets. */ +bool _strtoun(uint8_t, const char *, size_t *, size_t, SourceEndian, ...); + + +#define strtou32(target, data, pos, len, endian) _strtoun(4, data, pos, len, endian, target) + + + #endif /* _COMMON_IO_H */ diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am index 58ddb93..860f3b9 100644 --- a/src/glibext/Makefile.am +++ b/src/glibext/Makefile.am @@ -48,8 +48,8 @@ endif libglibext_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -libglibext_la_LIBADD = \ - generators/libglibextgenerators.la +#libglibext_la_LIBADD = \ +# generators/libglibextgenerators.la libglibext4_la_SOURCES = \ @@ -63,7 +63,7 @@ devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) dev_HEADERS = $(libglibext_la_SOURCES:%c=) -SUBDIRS = generators +#SUBDIRS = generators chrysamarshal.h: chrysamarshal.list diff --git a/src/gtkext/Makefile.am b/src/gtkext/Makefile.am index 45c9a1c..9d3d16c 100644 --- a/src/gtkext/Makefile.am +++ b/src/gtkext/Makefile.am @@ -53,7 +53,7 @@ devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) dev_HEADERS = $(libgtkext_la_SOURCES:%c=) -SUBDIRS = graph +#SUBDIRS = graph resources.c: gresource.xml $(UI_FILES_4_) -- cgit v0.11.2-87-g4458