diff options
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/bits.c | 1 | ||||
| -rw-r--r-- | src/common/leb128.c | 171 | ||||
| -rw-r--r-- | src/common/leb128.h | 11 | 
3 files changed, 137 insertions, 46 deletions
diff --git a/src/common/bits.c b/src/common/bits.c index 26f570f..27296f2 100644 --- a/src/common/bits.c +++ b/src/common/bits.c @@ -31,6 +31,7 @@  #include "asm.h" +#include "io.h"  #include "leb128.h" diff --git a/src/common/leb128.c b/src/common/leb128.c index 009aff6..7fae4d0 100644 --- a/src/common/leb128.c +++ b/src/common/leb128.c @@ -24,9 +24,20 @@  #include "leb128.h" +#include <malloc.h> + +  #include "io.h" +/** + * Quantité maximale d'octets de représentation. + * + *    sizeof([u]leb128_t) / 7 = 9.142857142857142 + * + */ +#define MAX_LEB128_BYTES 9 +  /******************************************************************************  *                                                                             * @@ -133,7 +144,7 @@ bool load_uleb128(uleb128_t *value, int fd)      unsigned int shift;                     /* Décalage à appliquer        */      uint8_t byte;                           /* Octet à transposer          */ -    result = true; +    result = false;      *value = 0; @@ -142,7 +153,7 @@ bool load_uleb128(uleb128_t *value, int fd)      while (true)      {          /* Encodage sur trop d'octets ? */ -        if (shift > (7 * sizeof(uleb128_t))) +        if (shift > (7 * MAX_LEB128_BYTES))          {              result = false;              break; @@ -153,6 +164,8 @@ bool load_uleb128(uleb128_t *value, int fd)          *value |= ((byte & 0x7f) << shift); +        result = true; +          if ((byte & 0x80) == 0x00)              break; @@ -207,7 +220,7 @@ bool store_uleb128(const uleb128_t *value, int fd)  /******************************************************************************  *                                                                             *  *  Paramètres  : value = valeur à consigner.                                  * -*                pbuf  = tampon de données à constituer. [OUT]                * +*                len   = taille du tampon de données à constitué. [OUT]       *  *                                                                             *  *  Description : Encode un nombre non signé encodé au format LEB128.          *  *                                                                             * @@ -217,26 +230,44 @@ bool store_uleb128(const uleb128_t *value, int fd)  *                                                                             *  ******************************************************************************/ -bool pack_uleb128(const uleb128_t *value, packed_buffer_t *pbuf) +void *pack_uleb128(const uleb128_t *value, size_t *len)  { -    bool result;                            /* Bilan à retourner           */ +    uint8_t *result;                        /* Données à retourner         */      uleb128_t tmp;                          /* Valeur modifiable           */ -    uint8_t byte;                           /* Octet à transposer          */ +    uint8_t *byte;                          /* Octet à transposer          */ + +    /* Calcul de la quantité d'octets nécessaires */ + +    *len = 0;      tmp = *value;      do      { -        byte = (tmp & 0x7f); +        tmp >>= 7; +        (*len)++; +    } +    while (tmp != 0); + +    /* Exportation */ + +    result = malloc(*len * sizeof(uint8_t)); +    byte = result; + +    tmp = *value; + +    do +    { +        *byte = (tmp & 0x7f);          tmp >>= 7;          if (tmp != 0) -            byte |= 0x80; +            *byte |= 0x80; -        result = extend_packed_buffer(pbuf, &byte, sizeof(uint8_t), false); +        byte++;      } -    while (result && tmp != 0); +    while (tmp != 0);      return result; @@ -246,7 +277,7 @@ bool pack_uleb128(const uleb128_t *value, packed_buffer_t *pbuf)  /******************************************************************************  *                                                                             *  *  Paramètres  : value = valeur à consigner.                                  * -*                pbuf  = tampon de données à constituer. [OUT]                * +*                len   = taille du tampon de données à constitué. [OUT]       *  *                                                                             *  *  Description : Encode un nombre signé encodé au format LEB128.              *  *                                                                             * @@ -256,19 +287,24 @@ bool pack_uleb128(const uleb128_t *value, packed_buffer_t *pbuf)  *                                                                             *  ******************************************************************************/ -bool pack_leb128(const leb128_t *value, packed_buffer_t *pbuf) +void *pack_leb128(const leb128_t *value, size_t *len)  { - -    bool result;                            /* Bilan à retourner           */ +    uint8_t *result;                        /* Données à retourner         */ +    bool negative;                          /* Nature de la valeur         */      uleb128_t tmp;                          /* Valeur modifiable           */      bool more;                              /* Poursuite des traitements   */ -    bool negative;                          /* Nature de la valeur         */      uint8_t byte;                           /* Octet à transposer          */ +    uint8_t *iter;                          /* Boucle de parcours          */ + +    negative = (*value < 0); + +    /* Calcul de la quantité d'octets nécessaires */ + +    *len = 0;      tmp = *value;      more = true; -    negative = (*value < 0);      while (more)      { @@ -291,10 +327,44 @@ bool pack_leb128(const leb128_t *value, packed_buffer_t *pbuf)          if ((tmp == 0 && (byte & 0x40) == 0x00) || (tmp == -1 && (byte & 0x40) == 0x40))              more = false; +        (*len)++; + +    } + +    /* Exportation */ + +    result = malloc(*len * sizeof(uint8_t)); +    iter = result; + +    tmp = *value; + +    more = true; + +    while (more) +    { +        *iter = (tmp & 0x7f); +        tmp >>= 7; + +        /** +         * Propagation forcée du bit de signe pour les implémentations de +         * décalage basées sur une opération logique et non arithmétique. +         */ + +        if (negative) +            tmp |= (~0llu << (LEB128_BITS_COUNT - 7)); + +        /** +         * Le bit de signe n'est pas le bit de poids fort ici : +         * On travaille sur 7 bits, donc le masque est 0x40 ! +         */ + +        if ((tmp == 0 && (*iter & 0x40) == 0x00) || (tmp == -1 && (*iter & 0x40) == 0x40)) +            more = false; +          else -            byte |= 0x80; +            *iter |= 0x80; -        result = extend_packed_buffer(pbuf, &byte, sizeof(uint8_t), false); +        iter++;      } @@ -306,7 +376,8 @@ bool pack_leb128(const leb128_t *value, packed_buffer_t *pbuf)  /******************************************************************************  *                                                                             *  *  Paramètres  : value = valeur à constituer. [OUT]                           * -*                pbuf  = tampon de données à consulter.                       * +*                pos   = tête de lecture à faire évoluer. [OUT]               * +*                max   = position maximale liée à la fin des données.         *  *                                                                             *  *  Description : Décode un nombre non signé encodé au format LEB128.          *  *                                                                             * @@ -316,38 +387,45 @@ bool pack_leb128(const leb128_t *value, packed_buffer_t *pbuf)  *                                                                             *  ******************************************************************************/ -bool unpack_uleb128(uleb128_t *value, packed_buffer_t *pbuf) +bool unpack_uleb128(uleb128_t *value, const void **pos, const void *max)  {      bool result;                            /* Bilan à retourner           */      unsigned int shift;                     /* Décalage à appliquer        */ -    uint8_t byte;                           /* Octet à transposer          */ +    uint8_t *byte;                          /* Octet à transposer          */ -    result = true; +    result = false;      *value = 0;      shift = 0; +    byte = *(uint8_t **)pos; -    while (true) +    do      {          /* Encodage sur trop d'octets ? */ -        if (shift > (7 * sizeof(uleb128_t))) +        if (shift > (7 * MAX_LEB128_BYTES))          {              result = false;              break;          } -        result = extract_packed_buffer(pbuf, &byte, sizeof(uint8_t), false); -        if (!result) break; +        /* Atteinte de la fin des données ? */ +        if ((void *)byte >= max) +        { +            result = false; +            break; +        } -        *value |= ((byte & 0x7f) << shift); +        *value |= ((*byte & 0x7f) << shift); -        if ((byte & 0x80) == 0x00) -            break; +        result = true;          shift += 7;      } +    while ((*byte++ & 0x80) == 0x80); + +    *pos = byte;      return result; @@ -357,7 +435,8 @@ bool unpack_uleb128(uleb128_t *value, packed_buffer_t *pbuf)  /******************************************************************************  *                                                                             *  *  Paramètres  : value = valeur à constituer. [OUT]                           * -*                pbuf  = tampon de données à consulter.                       * +*                pos   = tête de lecture à faire évoluer. [OUT]               * +*                max   = position maximale liée à la fin des données.         *  *                                                                             *  *  Description : Décode un nombre signé encodé au format LEB128.              *  *                                                                             * @@ -367,44 +446,56 @@ bool unpack_uleb128(uleb128_t *value, packed_buffer_t *pbuf)  *                                                                             *  ******************************************************************************/ -bool unpack_leb128(leb128_t *value, packed_buffer_t *pbuf) +bool unpack_leb128(leb128_t *value, const void **pos, const void *max)  {      bool result;                            /* Bilan à retourner           */      unsigned int shift;                     /* Décalage à appliquer        */ -    uint8_t byte;                           /* Octet à transposer          */ +    uint8_t *byte;                          /* Octet à transposer          */ -    result = true; +    result = false;      *value = 0;      shift = 0; +    byte = *(uint8_t **)pos;      do      {          /* Encodage sur trop d'octets ? */ -        if (shift > (7 * sizeof(leb128_t))) +        if (shift > (7 * MAX_LEB128_BYTES))          {              result = false;              break;          } -        result = extract_packed_buffer(pbuf, &byte, sizeof(uint8_t), false); -        if (!result) break; +        /* Atteinte de la fin des données ? */ +        if ((void *)byte >= max) +        { +            result = false; +            break; +        } -        *value |= ((byte & 0x7f) << shift); +        *value |= ((*byte & 0x7f) << shift); + +        result = true;          shift += 7;      } -    while ((byte & 0x80) == 0x80); +    while ((*byte++ & 0x80) == 0x80);      /**       * Le bit de signe n'est pas le bit de poids fort ici :       * On travaille sur 7 bits, donc le masque est 0x40 !       */ -    if (shift < LEB128_BITS_COUNT && (byte & 0x40) == 0x40) -        *value |= (~0llu << shift); +    if (result) +    { +        if (shift < LEB128_BITS_COUNT && (byte[-1] & 0x40) == 0x40) +            *value |= (~0llu << shift); +    } + +    *pos = byte;      return result; diff --git a/src/common/leb128.h b/src/common/leb128.h index 0313f5c..cb712a3 100644 --- a/src/common/leb128.h +++ b/src/common/leb128.h @@ -30,7 +30,6 @@  #include "datatypes.h" -#include "packed.h" @@ -65,16 +64,16 @@ bool load_uleb128(uleb128_t *, int);  bool store_uleb128(const uleb128_t *, int);  /* Encode un nombre non signé encodé au format LEB128. */ -bool pack_uleb128(const uleb128_t *, packed_buffer_t *); +void *pack_uleb128(const uleb128_t *, size_t *);  /* Encode un nombre signé encodé au format LEB128. */ -bool pack_leb128(const leb128_t *, packed_buffer_t *); +void *pack_leb128(const leb128_t *, size_t *); -/* Décode un nombre non signé encodé au format LEB128. */ -bool unpack_uleb128(uleb128_t *, packed_buffer_t *); +/* Encode un nombre non signé encodé au format LEB128. */ +bool unpack_uleb128(uleb128_t *, const void **, const void *);  /* Décode un nombre signé encodé au format LEB128. */ -bool unpack_leb128(leb128_t *, packed_buffer_t *); +bool unpack_leb128(leb128_t *, const void **, const void *);  | 
