diff options
Diffstat (limited to 'src')
-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 |
6 files changed, 447 insertions, 147 deletions
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) { |