diff options
| author | Cyrille Bagard <nocbos@gmail.com> | 2008-11-16 23:16:47 (GMT) | 
|---|---|---|
| committer | Cyrille Bagard <nocbos@gmail.com> | 2008-11-16 23:16:47 (GMT) | 
| commit | 3d6e959ad3e56681ba39bd8f0a003b8a1aff132c (patch) | |
| tree | 9a8c7608f60d05c8b968f443567fc77825fff8ff | |
| parent | 12b4201890b4b2eefffaa6615b4b3076253dff6f (diff) | |
Took care of signed immediate values as well as unsigned ones.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@42 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
| -rw-r--r-- | ChangeLog | 14 | ||||
| -rw-r--r-- | src/arch/operand-int.h | 17 | ||||
| -rw-r--r-- | src/arch/operand.c | 536 | ||||
| -rw-r--r-- | src/arch/operand.h | 22 | ||||
| -rw-r--r-- | src/arch/x86/operand.c | 15 | ||||
| -rw-r--r-- | src/arch/x86/processor.c | 2 | ||||
| -rw-r--r-- | src/format/elf/symbol.c | 2 | 
7 files changed, 461 insertions, 147 deletions
| @@ -1,3 +1,17 @@ +2008-11-17  Cyrille Bagard <nocbos@gmail.com> + +	* src/arch/operand.c: +	* src/arch/operand.h: +	* src/arch/operand-int.h: +	* src/arch/x86/operand.c: +	Take care of signed immediate values as well as unsigned ones. + +	* src/arch/x86/processor.c: +	Replace 'value' by 'unsigned_imm'. + +	* src/format/elf/symbol.c: +	Replace AOS_64_BITS by AOS_64_BITS_UNSIGNED. +  2008-11-10  Cyrille Bagard <nocbos@gmail.com>  	* src/arch/instruction.c: diff --git a/src/arch/operand-int.h b/src/arch/operand-int.h index db63a9c..000700c 100644 --- a/src/arch/operand-int.h +++ b/src/arch/operand-int.h @@ -49,6 +49,21 @@ struct _asm_operand      AsmOperandType type;                    /* Type d'opérande             */      AsmOperandSize size;                    /* Taille de l'opérande        */ +    /** +     * Note : dans le cas d'une valeur signée, +     * signed_imm contient la valeur lue/donnée, et +     * unsigned_imm la valeur humainement lisible (ie. positive). +     */ + +    union +    { +        uint8_t val8;                       /* Valeur sur 8 bits           */ +        uint16_t val16;                     /* Valeur sur 16 bits          */ +        uint32_t val32;                     /* Valeur sur 32 bits          */ +        uint64_t val64;                     /* Valeur sur 64 bits          */ + +    } unsigned_imm; +      union      {          uint8_t val8;                       /* Valeur sur 8 bits           */ @@ -56,7 +71,7 @@ struct _asm_operand          uint32_t val32;                     /* Valeur sur 32 bits          */          uint64_t val64;                     /* Valeur sur 64 bits          */ -    } value; +    } signed_imm;  }; diff --git a/src/arch/operand.c b/src/arch/operand.c index fa43416..6f7cdc4 100644 --- a/src/arch/operand.c +++ b/src/arch/operand.c @@ -48,9 +48,9 @@  bool fill_db_operand(asm_operand *operand, uint8_t value)  {      operand->type = AOT_NONE; -    operand->size = AOS_8_BITS; +    operand->size = AOS_8_BITS_UNSIGNED; -    operand->value.val8 = value; +    operand->unsigned_imm.val8 = value;      return true; @@ -77,11 +77,11 @@ void print_db_operand(const asm_operand *operand, char *buffer, size_t len, AsmS      switch (syntax)      {          case ASX_INTEL: -            snprintf(buffer, len, "0x%02hhx", operand->value.val8); +            snprintf(buffer, len, "0x%02hhx", operand->unsigned_imm.val8);              break;          case ASX_ATT: -            snprintf(buffer, len, "$0x%02hhx", operand->value.val8); +            snprintf(buffer, len, "$0x%02hhx", operand->unsigned_imm.val8);              break;      } @@ -116,16 +116,20 @@ bool read_imm_value(AsmOperandSize size, const uint8_t *data, off_t *pos, off_t      /* Vérifications sanitaires */      switch (size)      { -        case AOS_8_BITS: +        case AOS_8_BITS_UNSIGNED: +        case AOS_8_BITS_SIGNED:              if ((len - *pos) < 1) return false;              break; -        case AOS_16_BITS: +        case AOS_16_BITS_UNSIGNED: +        case AOS_16_BITS_SIGNED:              if ((len - *pos) < 2) return false;              break; -        case AOS_32_BITS: +        case AOS_32_BITS_UNSIGNED: +        case AOS_32_BITS_SIGNED:              if ((len - *pos) < 4) return false;              break; -        case AOS_64_BITS: +        case AOS_64_BITS_UNSIGNED: +        case AOS_64_BITS_SIGNED:              if ((len - *pos) < 8) return false;              break;      } @@ -134,23 +138,27 @@ bool read_imm_value(AsmOperandSize size, const uint8_t *data, off_t *pos, off_t      switch (size)      { -        case AOS_8_BITS: +        case AOS_8_BITS_UNSIGNED: +        case AOS_8_BITS_SIGNED:              val8 = va_arg(ap, uint8_t *);              *val8 = data[*pos];              *pos += 1;              break; -        case AOS_16_BITS: +        case AOS_16_BITS_UNSIGNED: +        case AOS_16_BITS_SIGNED:              val16 = va_arg(ap, uint16_t *);              *val16 = data[*pos] | (uint16_t)data[*pos + 1] << 8;              *pos += 2;              break; -        case AOS_32_BITS: +        case AOS_32_BITS_UNSIGNED: +        case AOS_32_BITS_SIGNED:              val32 = va_arg(ap, uint32_t *);              *val32 = data[*pos] | (uint32_t)data[*pos + 1] << 8                  | (uint32_t)data[*pos + 2] << 16 | (uint32_t)data[*pos + 3] << 24;              *pos += 4;              break; -        case AOS_64_BITS: +        case AOS_64_BITS_UNSIGNED: +        case AOS_64_BITS_SIGNED:              val64 = va_arg(ap, uint64_t *);              *val64 = data[*pos] | (uint64_t)data[*pos + 1] << 8 | (uint64_t)data[*pos + 2] << 16                  | (uint64_t)data[*pos + 3] << 24 | (uint64_t)data[*pos + 4] << 32 | (uint64_t)data[*pos + 5] << 40 @@ -169,65 +177,167 @@ bool read_imm_value(AsmOperandSize size, const uint8_t *data, off_t *pos, off_t  /******************************************************************************  *                                                                             *  *  Paramètres  : operand = structure dont le contenu est à définir.           * +*                                                                             * +*  Description : Indique le signe d'une valeur immédiate.                     * +*                                                                             * +*  Retour      : true si la valeur est strictement négative, false sinon.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool is_imm_operand_negative(const asm_operand *operand) +{ +    bool result;                            /* Bilan à renvoyer            */ + +    result = false; + +    switch (operand->size) +    { +        case AOS_8_BITS_SIGNED: +            result = (operand->signed_imm.val8 & 0x80); +            break; +        case AOS_16_BITS_SIGNED: +            result = (operand->signed_imm.val16 & 0x8000); +            break; +        case AOS_32_BITS_SIGNED: +            result = (operand->signed_imm.val32 & 0x80000000); +            break; +        case AOS_64_BITS_SIGNED: +            result = (operand->signed_imm.val64 & 0x8000000000000000ll); +            break; +        default: +            /* Traitement non nécessaire */ +            break; +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : operand = structure dont le contenu est à définir.           *  *                size    = taille de l'opérande souhaitée.                    * -*                data    = flux de données à analyser.                        * -*                pos     = position courante dans ce flux. [OUT]              * -*                len     = taille totale des données à analyser.              *  *                                                                             * -*  Description : Crée une opérande contenant une valeur sur x bits.           * +*  Description : Précalcule une valeur humaine lisible d'une valeur signée.   *  *                                                                             * -*  Retour      : true si l'opération s'est effectuée avec succès, false sinon.* +*  Retour      : -                                                            *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -bool fill_imm_operand(asm_operand *operand, AsmOperandSize size, const uint8_t *data, off_t *pos, off_t len) +void cache_signed_imm_value(asm_operand *operand, AsmOperandSize size)  { -    /* Vérifications sanitaires */ +    int8_t val8;                            /* Valeur sur 8 bits           */ +    int16_t val16;                          /* Valeur sur 16 bits          */ +    int32_t val32;                          /* Valeur sur 32 bits          */ +    int64_t val64;                          /* Valeur sur 64 bits          */ +      switch (size)      { -        case AOS_8_BITS: -            if ((len - *pos) < 1) return false; +        case AOS_8_BITS_SIGNED: +            if (operand->signed_imm.val8 & 0x80) +            { +                val8 = operand->signed_imm.val8 - 1; +                val8 = ~val8; +                operand->unsigned_imm.val8 = val8; +            } +            else operand->unsigned_imm.val8 = operand->signed_imm.val8;              break; -        case AOS_16_BITS: -            if ((len - *pos) < 2) return false; +        case AOS_16_BITS_SIGNED: +            if (operand->signed_imm.val16 & 0x8000) +            { +                val16 = operand->signed_imm.val16 - 1; +                val16 = ~val16; +                operand->unsigned_imm.val16 = val16; +            } +            else operand->unsigned_imm.val16 = operand->signed_imm.val16;              break; -        case AOS_32_BITS: -            if ((len - *pos) < 4) return false; +        case AOS_32_BITS_SIGNED: +            if (operand->signed_imm.val32 & 0x80000000) +            { +                val32 = operand->signed_imm.val32 - 1; +                val32 = ~val32; +                operand->unsigned_imm.val32 = val32; +            } +            else operand->unsigned_imm.val32 = operand->signed_imm.val32;              break; -        case AOS_64_BITS: -            if ((len - *pos) < 8) return false; +        case AOS_64_BITS_SIGNED: +            if (operand->signed_imm.val64 & 0x8000000000000000ll) +            { +                val64 = operand->signed_imm.val64 - 1; +                val64 = ~val64; +                operand->unsigned_imm.val64 = val64; +            } +            else operand->unsigned_imm.val64 = operand->signed_imm.val64; +            break; +        default: +            /* Traitement non nécessaire */              break;      } +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : operand = structure dont le contenu est à définir.           * +*                size    = taille de l'opérande souhaitée.                    * +*                data    = flux de données à analyser.                        * +*                pos     = position courante dans ce flux. [OUT]              * +*                len     = taille totale des données à analyser.              * +*                                                                             * +*  Description : Crée une opérande contenant une valeur sur x bits.           * +*                                                                             * +*  Retour      : true si l'opération s'est effectuée avec succès, false sinon.* +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool fill_imm_operand(asm_operand *operand, AsmOperandSize size, const uint8_t *data, off_t *pos, off_t len) +{ +    bool result;                            /* Bilan à retourner           */ +      operand->type = AOT_IMM;      operand->size = size;      switch (size)      { -        case AOS_8_BITS: -            operand->value.val8 = data[*pos]; -            *pos += 1; +        case AOS_8_BITS_UNSIGNED: +            result = read_imm_value(size, data, pos, len, &operand->unsigned_imm.val8);              break; -        case AOS_16_BITS: -            operand->value.val16 = data[*pos] | (uint16_t)data[*pos + 1] << 8; -            *pos += 2; +        case AOS_16_BITS_UNSIGNED: +            result = read_imm_value(size, data, pos, len, &operand->unsigned_imm.val16);              break; -        case AOS_32_BITS: -            operand->value.val32 = data[*pos] | (uint32_t)data[*pos + 1] << 8 -                | (uint32_t)data[*pos + 2] << 16 | (uint32_t)data[*pos + 3] << 24; -            *pos += 4; +        case AOS_32_BITS_UNSIGNED: +            result = read_imm_value(size, data, pos, len, &operand->unsigned_imm.val32);              break; -        case AOS_64_BITS: -            operand->value.val64 = data[*pos] | (uint64_t)data[*pos + 1] << 8 | (uint64_t)data[*pos + 2] << 16 -                | (uint64_t)data[*pos + 3] << 24 | (uint64_t)data[*pos + 4] << 32 | (uint64_t)data[*pos + 5] << 40 -                | (uint64_t)data[*pos + 6] << 48 | (uint64_t)data[*pos + 7] << 56; -            *pos += 8; +        case AOS_64_BITS_UNSIGNED: +            result = read_imm_value(size, data, pos, len, &operand->unsigned_imm.val64); +            break; +        case AOS_8_BITS_SIGNED: +            result = read_imm_value(size, data, pos, len, &operand->signed_imm.val8); +            cache_signed_imm_value(operand, size); +            break; +        case AOS_16_BITS_SIGNED: +            result = read_imm_value(size, data, pos, len, &operand->signed_imm.val16); +            cache_signed_imm_value(operand, size); +            break; +        case AOS_32_BITS_SIGNED: +            result = read_imm_value(size, data, pos, len, &operand->signed_imm.val32); +            cache_signed_imm_value(operand, size); +            break; +        case AOS_64_BITS_SIGNED: +            result = read_imm_value(size, data, pos, len, &operand->signed_imm.val64); +            cache_signed_imm_value(operand, size);              break;      } -    return true; +    return result;  } @@ -249,10 +359,14 @@ bool fill_imm_operand(asm_operand *operand, AsmOperandSize size, const uint8_t *  bool fill_imm_operand_with_value(asm_operand *operand, AsmOperandSize size, ...)  {      va_list ap;                             /* Récupération d'argument     */ -    const uint8_t *val8;                    /* Valeur sur 8 bits           */ -    const uint16_t *val16;                  /* Valeur sur 16 bits          */ -    const uint32_t *val32;                  /* Valeur sur 32 bits          */ -    const uint64_t *val64;                  /* Valeur sur 64 bits          */ +    const uint8_t *us_val8;                 /* Valeur sur 8 bits n.-s.     */ +    const uint16_t *us_val16;               /* Valeur sur 16 bits n.-s.    */ +    const uint32_t *us_val32;               /* Valeur sur 32 bits n.-s.    */ +    const uint64_t *us_val64;               /* Valeur sur 64 bits n.-s.    */ +    const int8_t *s_val8;                   /* Valeur sur 8 bits signés    */ +    const int16_t *s_val16;                 /* Valeur sur 16 bits signés   */ +    const int32_t *s_val32;                 /* Valeur sur 32 bits signés   */ +    const int64_t *s_val64;                 /* Valeur sur 64 bits signés   */      operand->type = AOT_IMM;      operand->size = size; @@ -261,21 +375,41 @@ bool fill_imm_operand_with_value(asm_operand *operand, AsmOperandSize size, ...)      switch (size)      { -        case AOS_8_BITS: -            val8 = va_arg(ap, const uint8_t *); -            operand->value.val8 = *val8; +        case AOS_8_BITS_UNSIGNED: +            us_val8 = va_arg(ap, const uint8_t *); +            operand->unsigned_imm.val8 = *us_val8; +            break; +        case AOS_16_BITS_UNSIGNED: +            us_val16 = va_arg(ap, const uint16_t *); +            operand->unsigned_imm.val16 = *us_val16; +            break; +        case AOS_32_BITS_UNSIGNED: +            us_val32 = va_arg(ap, const uint32_t *); +            operand->unsigned_imm.val32 = *us_val32; +            break; +        case AOS_64_BITS_UNSIGNED: +            us_val64 = va_arg(ap, const uint64_t *); +            operand->unsigned_imm.val64 = *us_val64; +            break; +        case AOS_8_BITS_SIGNED: +            s_val8 = va_arg(ap, const uint8_t *); +            operand->signed_imm.val8 = *s_val8; +            cache_signed_imm_value(operand, size);              break; -        case AOS_16_BITS: -            val16 = va_arg(ap, const uint16_t *); -            operand->value.val16 = *val16; +        case AOS_16_BITS_SIGNED: +            s_val16 = va_arg(ap, const uint16_t *); +            operand->signed_imm.val16 = *s_val16; +            cache_signed_imm_value(operand, size);              break; -        case AOS_32_BITS: -            val32 = va_arg(ap, const uint32_t *); -            operand->value.val32 = *val32; +        case AOS_32_BITS_SIGNED: +            s_val32 = va_arg(ap, const uint32_t *); +            operand->signed_imm.val32 = *s_val32; +            cache_signed_imm_value(operand, size);              break; -        case AOS_64_BITS: -            val64 = va_arg(ap, const uint64_t *); -            operand->value.val64 = *val64; +        case AOS_64_BITS_SIGNED: +            s_val64 = va_arg(ap, const uint64_t *); +            operand->signed_imm.val64 = *s_val64; +            cache_signed_imm_value(operand, size);              break;      } @@ -319,44 +453,44 @@ bool fill_relimm_operand(asm_operand *operand, AsmOperandSize size, const uint8_          switch (size)          {              case AOS_8_BITS: -                if (operand->value.val8 & 0x80) +                if (operand->unsigned_imm.val8 & 0x80)                  { -                    val8 = operand->value.val8 - 1; +                    val8 = operand->unsigned_imm.val8 - 1;                      val8 = ~val8; -                    operand->value.val8 = ref + (*pos - old_pos); -                    operand->value.val8 -= val8; +                    operand->unsigned_imm.val8 = ref + (*pos - old_pos); +                    operand->unsigned_imm.val8 -= val8;                  } -                else operand->value.val8 += ref + (*pos - old_pos); +                else operand->unsigned_imm.val8 += ref + (*pos - old_pos);                  break;              case AOS_16_BITS: -                if (operand->value.val16 & 0x8000) +                if (operand->unsigned_imm.val16 & 0x8000)                  { -                    val16 = operand->value.val16 - 1; +                    val16 = operand->unsigned_imm.val16 - 1;                      val16 = ~val16; -                    operand->value.val16 = ref + (*pos - old_pos); -                    operand->value.val16 -= val16; +                    operand->unsigned_imm.val16 = ref + (*pos - old_pos); +                    operand->unsigned_imm.val16 -= val16;                  } -                else operand->value.val16 += ref + (*pos - old_pos); +                else operand->unsigned_imm.val16 += ref + (*pos - old_pos);                  break;              case AOS_32_BITS: -                if (operand->value.val32 & 0x80000000) +                if (operand->unsigned_imm.val32 & 0x80000000)                  { -                    val32 = operand->value.val32 - 1; +                    val32 = operand->unsigned_imm.val32 - 1;                      val32 = ~val32; -                    operand->value.val32 = ref + (*pos - old_pos); -                    operand->value.val32 -= val32; +                    operand->unsigned_imm.val32 = ref + (*pos - old_pos); +                    operand->unsigned_imm.val32 -= val32;                  } -                else operand->value.val32 += ref + (*pos - old_pos); +                else operand->unsigned_imm.val32 += ref + (*pos - old_pos);                  break;              case AOS_64_BITS: -                if (operand->value.val64 & 0x8000000000000000ull) +                if (operand->unsigned_imm.val64 & 0x8000000000000000ull)                  { -                    val64 = operand->value.val64 - 1; +                    val64 = operand->unsigned_imm.val64 - 1;                      val64 = ~val64; -                    operand->value.val64 = ref + (*pos - old_pos); -                    operand->value.val64 -= val64; +                    operand->unsigned_imm.val64 = ref + (*pos - old_pos); +                    operand->unsigned_imm.val64 -= val64;                  } -                else operand->value.val64 += ref + (*pos - old_pos); +                else operand->unsigned_imm.val64 += ref + (*pos - old_pos);                  break;          } @@ -383,10 +517,14 @@ bool get_imm_operand_value(asm_operand *operand, AsmOperandSize size, ...)  {      bool result;                            /* Bilan à retourner           */      va_list ap;                             /* Récupération d'argument     */ -    uint8_t *val8;                          /* Valeur sur 8 bits           */ -    uint16_t *val16;                        /* Valeur sur 16 bits          */ -    uint32_t *val32;                        /* Valeur sur 32 bits          */ -    uint64_t *val64;                        /* Valeur sur 64 bits          */ +    uint8_t *us_val8;                       /* Valeur sur 8 bits n.-s.     */ +    uint16_t *us_val16;                     /* Valeur sur 16 bits n.-s.    */ +    uint32_t *us_val32;                     /* Valeur sur 32 bits n.-s.    */ +    uint64_t *us_val64;                     /* Valeur sur 64 bits n.-s.    */ +    int8_t *s_val8;                         /* Valeur sur 8 bits signés    */ +    int16_t *s_val16;                       /* Valeur sur 16 bits signés   */ +    int32_t *s_val32;                       /* Valeur sur 32 bits signés   */ +    int64_t *s_val64;                       /* Valeur sur 64 bits signés   */      result = true; @@ -394,78 +532,202 @@ bool get_imm_operand_value(asm_operand *operand, AsmOperandSize size, ...)      switch (size)      { -        case AOS_8_BITS: -            val8 = va_arg(ap, uint8_t *); +        case AOS_8_BITS_UNSIGNED: +            us_val8 = va_arg(ap, uint8_t *);              switch (operand->size)              { -                case AOS_8_BITS: -                    *val8 = operand->value.val8; +                case AOS_8_BITS_UNSIGNED: +                    *us_val8 = operand->unsigned_imm.val8;                      break; -                case AOS_16_BITS: +                case AOS_8_BITS_SIGNED: +                    *us_val8 = operand->signed_imm.val8; +                    break; +                default:                      result = false;                      break; -                case AOS_32_BITS: +            } +            break; + +        case AOS_16_BITS_UNSIGNED: +            us_val16 = va_arg(ap, uint16_t *); +            switch (operand->size) +            { +                case AOS_8_BITS_UNSIGNED: +                    *us_val16 = operand->unsigned_imm.val8; +                    break; +                case AOS_16_BITS_UNSIGNED: +                    *us_val16 = operand->unsigned_imm.val16; +                    break; +                case AOS_8_BITS_SIGNED: +                    *us_val16 = operand->signed_imm.val8; +                    break; +                case AOS_16_BITS_SIGNED: +                    *us_val16 = operand->signed_imm.val16; +                    break; +                default:                      result = false;                      break; -                case AOS_64_BITS: +            } +            break; + +        case AOS_32_BITS_UNSIGNED: +            us_val32 = va_arg(ap, uint32_t *); +            switch (operand->size) +            { +                case AOS_8_BITS_UNSIGNED: +                    *us_val32 = operand->unsigned_imm.val8; +                    break; +                case AOS_16_BITS_UNSIGNED: +                    *us_val32 = operand->unsigned_imm.val16; +                    break; +                case AOS_32_BITS_UNSIGNED: +                    *us_val32 = operand->unsigned_imm.val32; +                    break; +                case AOS_8_BITS_SIGNED: +                    *us_val32 = operand->signed_imm.val8; +                    break; +                case AOS_16_BITS_SIGNED: +                    *us_val32 = operand->signed_imm.val16; +                    break; +                case AOS_32_BITS_SIGNED: +                    *us_val32 = operand->signed_imm.val32; +                    break; +                default:                      result = false;                      break;              }              break; -        case AOS_16_BITS: -            val16 = va_arg(ap, uint16_t *); +        case AOS_64_BITS_UNSIGNED: +            us_val64 = va_arg(ap, uint64_t *);              switch (operand->size)              { -                case AOS_8_BITS: -                    *val16 = operand->value.val8; +                case AOS_8_BITS_UNSIGNED: +                    *us_val64 = operand->unsigned_imm.val8; +                    break; +                case AOS_16_BITS_UNSIGNED: +                    *us_val64 = operand->unsigned_imm.val16; +                    break; +                case AOS_32_BITS_UNSIGNED: +                    *us_val64 = operand->unsigned_imm.val32;                      break; -                case AOS_16_BITS: -                    *val16 = operand->value.val16; +                case AOS_64_BITS_UNSIGNED: +                    *us_val64 = operand->unsigned_imm.val64;                      break; -                case AOS_32_BITS: +                case AOS_8_BITS_SIGNED: +                    *us_val64 = operand->signed_imm.val8; +                    break; +                case AOS_16_BITS_SIGNED: +                    *us_val64 = operand->signed_imm.val16; +                    break; +                case AOS_32_BITS_SIGNED: +                    *us_val64 = operand->signed_imm.val32; +                    break; +                case AOS_64_BITS_SIGNED: +                    *us_val64 = operand->signed_imm.val64; +                    break; +                default:                      result = false;                      break; -                case AOS_64_BITS: +            } +            break; + +        case AOS_8_BITS_SIGNED: +            s_val8 = va_arg(ap, int8_t *); +            switch (operand->size) +            { +                case AOS_8_BITS_UNSIGNED: +                    *s_val8 = operand->unsigned_imm.val8; +                    break; +                case AOS_8_BITS_SIGNED: +                    *s_val8 = operand->signed_imm.val8; +                    break; +                default:                      result = false;                      break;              }              break; -        case AOS_32_BITS: -            val32 = va_arg(ap, uint32_t *); +        case AOS_16_BITS_SIGNED: +            s_val16 = va_arg(ap, int16_t *);              switch (operand->size)              { -                case AOS_8_BITS: -                    *val32 = operand->value.val8; +                case AOS_8_BITS_UNSIGNED: +                    *s_val16 = operand->unsigned_imm.val8;                      break; -                case AOS_16_BITS: -                    *val32 = operand->value.val16; +                case AOS_16_BITS_UNSIGNED: +                    *s_val16 = operand->unsigned_imm.val16;                      break; -                case AOS_32_BITS: -                    *val32 = operand->value.val32; +                case AOS_8_BITS_SIGNED: +                    *s_val16 = operand->signed_imm.val8;                      break; -                case AOS_64_BITS: +                case AOS_16_BITS_SIGNED: +                    *s_val16 = operand->signed_imm.val16; +                    break; +                default:                      result = false;                      break;              }              break; -        case AOS_64_BITS: -            val64 = va_arg(ap, uint64_t *); +        case AOS_32_BITS_SIGNED: +            s_val32 = va_arg(ap, int32_t *);              switch (operand->size)              { -                case AOS_8_BITS: -                    *val64 = operand->value.val8; +                case AOS_8_BITS_UNSIGNED: +                    *s_val32 = operand->unsigned_imm.val8;                      break; -                case AOS_16_BITS: -                    *val64 = operand->value.val16; +                case AOS_16_BITS_UNSIGNED: +                    *s_val32 = operand->unsigned_imm.val16;                      break; -                case AOS_32_BITS: -                    *val64 = operand->value.val32; +                case AOS_32_BITS_UNSIGNED: +                    *s_val32 = operand->unsigned_imm.val32;                      break; -                case AOS_64_BITS: -                    *val64 = operand->value.val64; +                case AOS_8_BITS_SIGNED: +                    *s_val32 = operand->signed_imm.val8; +                    break; +                case AOS_16_BITS_SIGNED: +                    *s_val32 = operand->signed_imm.val16; +                    break; +                case AOS_32_BITS_SIGNED: +                    *s_val32 = operand->signed_imm.val32; +                    break; +                default: +                    result = false; +                    break; +            } +            break; + +        case AOS_64_BITS_SIGNED: +            s_val64 = va_arg(ap, int64_t *); +            switch (operand->size) +            { +                case AOS_8_BITS_UNSIGNED: +                    *s_val64 = operand->unsigned_imm.val8; +                    break; +                case AOS_16_BITS_UNSIGNED: +                    *s_val64 = operand->unsigned_imm.val16; +                    break; +                case AOS_32_BITS_UNSIGNED: +                    *s_val64 = operand->unsigned_imm.val32; +                    break; +                case AOS_64_BITS_UNSIGNED: +                    *s_val64 = operand->unsigned_imm.val64; +                    break; +                case AOS_8_BITS_SIGNED: +                    *s_val64 = operand->signed_imm.val8; +                    break; +                case AOS_16_BITS_SIGNED: +                    *s_val64 = operand->signed_imm.val16; +                    break; +                case AOS_32_BITS_SIGNED: +                    *s_val64 = operand->signed_imm.val32; +                    break; +                case AOS_64_BITS_SIGNED: +                    *s_val64 = operand->signed_imm.val64; +                    break; +                default: +                    result = false;                      break;              }              break; @@ -505,17 +767,21 @@ void print_imm_operand(const asm_operand *operand, char *buffer, size_t len, Asm          case ASX_INTEL:              switch (operand->size)              { -                case AOS_8_BITS: -                    snprintf(buffer, len, "0x%hhx", operand->value.val8); +                case AOS_8_BITS_UNSIGNED: +                case AOS_8_BITS_SIGNED: +                    snprintf(buffer, len, "0x%hhx", operand->unsigned_imm.val8);                      break; -                case AOS_16_BITS: -                    snprintf(buffer, len, "0x%hx", operand->value.val16); +                case AOS_16_BITS_UNSIGNED: +                case AOS_16_BITS_SIGNED: +                    snprintf(buffer, len, "0x%hx", operand->unsigned_imm.val16);                      break; -                case AOS_32_BITS: -                    snprintf(buffer, len, "0x%x", operand->value.val32); +                case AOS_32_BITS_UNSIGNED: +                case AOS_32_BITS_SIGNED: +                    snprintf(buffer, len, "0x%x", operand->unsigned_imm.val32);                      break; -                case AOS_64_BITS: -                    snprintf(buffer, len, "0x%llx", operand->value.val64); +                case AOS_64_BITS_UNSIGNED: +                case AOS_64_BITS_SIGNED: +                    snprintf(buffer, len, "0x%llx", operand->unsigned_imm.val64);                      break;              }              break; @@ -523,17 +789,21 @@ void print_imm_operand(const asm_operand *operand, char *buffer, size_t len, Asm          case ASX_ATT:              switch (operand->size)              { -                case AOS_8_BITS: -                    snprintf(buffer, len, "$0x%hhx", operand->value.val8); +                case AOS_8_BITS_UNSIGNED: +                case AOS_8_BITS_SIGNED: +                    snprintf(buffer, len, "$0x%hhx", operand->unsigned_imm.val8);                      break; -                case AOS_16_BITS: -                    snprintf(buffer, len, "$0x%hx", operand->value.val16); +                case AOS_16_BITS_UNSIGNED: +                case AOS_16_BITS_SIGNED: +                    snprintf(buffer, len, "$0x%hx", operand->unsigned_imm.val16);                      break; -                case AOS_32_BITS: -                    snprintf(buffer, len, "$0x%x", operand->value.val32); +                case AOS_32_BITS_UNSIGNED: +                case AOS_32_BITS_SIGNED: +                    snprintf(buffer, len, "$0x%x", operand->unsigned_imm.val32);                      break; -                case AOS_64_BITS: -                    snprintf(buffer, len, "$0x%llx", operand->value.val64); +                case AOS_64_BITS_UNSIGNED: +                case AOS_64_BITS_SIGNED: +                    snprintf(buffer, len, "$0x%llx", operand->unsigned_imm.val64);                      break;              }              break; diff --git a/src/arch/operand.h b/src/arch/operand.h index 0a00d9f..fab1344 100644 --- a/src/arch/operand.h +++ b/src/arch/operand.h @@ -36,14 +36,25 @@ typedef enum _AsmOperandSize  {      AOS_UNDEFINED,                          /* Taille non définie          */ -    AOS_8_BITS,                             /* Opérande sur 8 bits         */ -    AOS_16_BITS,                            /* Opérande sur 16 bits        */ -    AOS_32_BITS,                            /* Opérande sur 32 bits        */ -    AOS_64_BITS                             /* Opérande sur 64 bits        */ +    AOS_8_BITS_UNSIGNED,                    /* Opérande sur 8 bits n.-s.   */ +    AOS_16_BITS_UNSIGNED,                   /* Opérande sur 16 bits n.-s.  */ +    AOS_32_BITS_UNSIGNED,                   /* Opérande sur 32 bits n.-s.  */ +    AOS_64_BITS_UNSIGNED,                   /* Opérande sur 64 bits n.-s.  */ + +    AOS_8_BITS_SIGNED,                      /* Opérande sur 8 bits  signés */ +    AOS_16_BITS_SIGNED,                     /* Opérande sur 16 bits signés */ +    AOS_32_BITS_SIGNED,                     /* Opérande sur 32 bits signés */ +    AOS_64_BITS_SIGNED                      /* Opérande sur 64 bits signés */  } AsmOperandSize; +#define AOS_8_BITS  AOS_8_BITS_UNSIGNED +#define AOS_16_BITS AOS_16_BITS_UNSIGNED +#define AOS_32_BITS AOS_32_BITS_UNSIGNED +#define AOS_64_BITS AOS_64_BITS_UNSIGNED + +  /* Définition générique d'une opérande */  typedef struct _asm_operand asm_operand; @@ -67,6 +78,9 @@ void print_db_operand(const asm_operand *, char *, size_t, AsmSyntax);  /* Lit une valeur (signée ou non) sur x bits. */  bool read_imm_value(AsmOperandSize, const uint8_t *, off_t *, off_t, ...); +/* Indique le signe d'une valeur immédiate. */ +bool is_imm_operand_negative(const asm_operand *); +  /* Crée une opérande contenant une valeur sur x bits. */  bool fill_imm_operand(asm_operand *, AsmOperandSize, const uint8_t *, off_t *, off_t); diff --git a/src/arch/x86/operand.c b/src/arch/x86/operand.c index a028dc2..38e1468 100644 --- a/src/arch/x86/operand.c +++ b/src/arch/x86/operand.c @@ -179,7 +179,7 @@ asm_x86_operand *create_new_x86_operand(void)  *                                                                             *  *  Retour      : true si la définition est opérée, false sinon.               *  *                                                                             * -*  Remarques   : -                                                            * +*  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ @@ -409,7 +409,7 @@ asm_x86_operand *x86_create_content1632_operand(const uint8_t *data, off_t *pos,          case 0x40:              result->displacement = create_new_x86_operand(); -            if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_8_BITS, data, pos, len)) +            if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_8_BITS_SIGNED, data, pos, len))              {                  (*pos) -= 2;                  free(result->displacement); @@ -420,7 +420,7 @@ asm_x86_operand *x86_create_content1632_operand(const uint8_t *data, off_t *pos,          case 0x80:              result->displacement = create_new_x86_operand(); -            if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_32_BITS, data, pos, len)) +            if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_32_BITS_SIGNED, data, pos, len))              {                  (*pos) -= 2;                  free(result->displacement); @@ -572,7 +572,7 @@ asm_x86_operand *x86_create_rm8_operand(const uint8_t *data, off_t *pos, off_t l          case 0x40:              result->displacement = create_new_x86_operand(); -            if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_8_BITS, data, pos, len)) +            if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_8_BITS_SIGNED, data, pos, len))              {                  free(result->displacement);                  free(result); @@ -766,7 +766,7 @@ asm_x86_operand *x86_create_rm1632_operand(const uint8_t *data, off_t *pos, off_          case 0x40:              result->displacement = create_new_x86_operand(); -            if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_8_BITS, data, pos, len)) +            if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_8_BITS_SIGNED, data, pos, len))              {                  free(result->displacement);                  free(result); @@ -776,7 +776,7 @@ asm_x86_operand *x86_create_rm1632_operand(const uint8_t *data, off_t *pos, off_          case 0x80:              result->displacement = create_new_x86_operand(); -            if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_32_BITS, data, pos, len)) +            if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_32_BITS_SIGNED, data, pos, len))              {                  free(result->displacement);                  free(result); @@ -1092,7 +1092,8 @@ void x86_print_reg_operand(const asm_x86_operand *operand, char *buffer, size_t              if (operand->displacement != NULL)              { -                strcat(buffer, "+");    /* TODO: n */ +                if (is_imm_operand_negative(operand->displacement)) strcat(buffer, "-"); +                else strcat(buffer, "+");                  pos = strlen(buffer);                  print_imm_operand(operand->displacement, &buffer[pos], len - pos, syntax); diff --git a/src/arch/x86/processor.c b/src/arch/x86/processor.c index 8be503c..820c6a1 100644 --- a/src/arch/x86/processor.c +++ b/src/arch/x86/processor.c @@ -494,7 +494,7 @@ void x86_print_instruction(const asm_x86_processor *proc, const exe_format *form              case AOT_IMM:                  print_imm_operand(ASM_OPERAND(ASM_INSTRUCTION(instr)->operands[i]), opbuffer[i], 256, syntax); -                offset = ASM_OPERAND(ASM_INSTRUCTION(instr)->operands[i])->value.val32; /* FIXME !!! */ +                offset = ASM_OPERAND(ASM_INSTRUCTION(instr)->operands[i])->unsigned_imm.val32; /* FIXME !!! */                  if (ASM_OPERAND(ASM_INSTRUCTION(instr)->operands[i])->size == proc->operand_size                      && resolve_exe_symbol(format, &label, &symtype, &offset)) diff --git a/src/format/elf/symbol.c b/src/format/elf/symbol.c index c8a0dac..c80ceb4 100644 --- a/src/format/elf/symbol.c +++ b/src/format/elf/symbol.c @@ -553,7 +553,7 @@ void translate_elf_relocations(elf_format *format, asm_instr **instructions, siz              && instructions[i + 1]->type == AIT_PUSH              && instructions[i + 2]->type == AIT_JUMP)          { -            if (get_imm_operand_value(instructions[i]->operands[0], AOS_64_BITS, &address)) +            if (get_imm_operand_value(instructions[i]->operands[0], AOS_64_BITS_UNSIGNED, &address))                  for (j = 0; j < format->sym_count; j++)                      if (format->symbols[j].address == address)                      { | 
