summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2024-05-17 05:50:05 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2024-05-17 05:53:14 (GMT)
commitd9d887e226902905ef56d0ccf1107df50e5e4463 (patch)
treee0da243151116e93d8585fbc80f368431187df29 /src/common
parent85e52ccd4c8aada6660d171e91c6c603f40606bb (diff)
Define datatypes.h and move the remaining endianness.[ch] content into io.[ch].
Diffstat (limited to 'src/common')
-rw-r--r--src/common/Makefile.am2
-rw-r--r--src/common/bits.h3
-rw-r--r--src/common/datatypes.h56
-rw-r--r--src/common/endianness.c871
-rw-r--r--src/common/endianness.h132
-rw-r--r--src/common/io.c851
-rw-r--r--src/common/io.h92
7 files changed, 1000 insertions, 1007 deletions
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 <stdbool.h>
+#include <sys/types.h>
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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _COMMON_DATATYPES_H
+#define _COMMON_DATATYPES_H
+
+
+#include <stdint.h>
+
+
+
+/* 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 <http://www.gnu.org/licenses/>.
- */
-
-
-#include "endianness.h"
-
-
-#include <assert.h>
-#include <stdarg.h>
-#include <string.h>
-
-
-
-/**
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _COMMON_ENDIANNESS_H
-#define _COMMON_ENDIANNESS_H
-
-
-#include <stdbool.h>
-
-
-#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 <assert.h>
#include <errno.h>
#include <malloc.h>
+#include <stdarg.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
@@ -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 <sys/types.h>
+#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 */