summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--src/arch/operand-int.h17
-rw-r--r--src/arch/operand.c536
-rw-r--r--src/arch/operand.h22
-rw-r--r--src/arch/x86/operand.c15
-rw-r--r--src/arch/x86/processor.c2
-rw-r--r--src/format/elf/symbol.c2
7 files changed, 461 insertions, 147 deletions
diff --git a/ChangeLog b/ChangeLog
index f2a4941..68d31c1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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)
{