add CS_OPT_UNSIGNED option to print immediate in unsigned form. only ARM is supported for now (issue #585)
diff --git a/arch/ARM/ARMInstPrinter.c b/arch/ARM/ARMInstPrinter.c
index 39773bc..4f10cef 100644
--- a/arch/ARM/ARMInstPrinter.c
+++ b/arch/ARM/ARMInstPrinter.c
@@ -34,6 +34,7 @@
#define GET_SUBTARGETINFO_ENUM
#include "ARMGenSubtargetInfo.inc"
+
static void printRegName(cs_struct *h, SStream *OS, unsigned RegNo);
// Autogenerated by tblgen.
@@ -847,28 +848,14 @@
imm += (int32_t)MI->address + 8;
}
- if (imm >= 0) {
- if (imm > HEX_THRESHOLD)
- SStream_concat(O, "#0x%x", imm);
- else
- SStream_concat(O, "#%u", imm);
- } else {
- SStream_concat(O, "#0x%x", imm);
- }
+ printUInt32Bang(O, imm);
} else {
switch(MI->flat_insn->id) {
default:
- if (imm >= 0) {
- if (imm > HEX_THRESHOLD)
- SStream_concat(O, "#0x%x", imm);
- else
- SStream_concat(O, "#%u", imm);
- } else {
- if (imm < -HEX_THRESHOLD)
- SStream_concat(O, "#-0x%x", -imm);
- else
- SStream_concat(O, "#-%u", -imm);
- }
+ if (MI->csh->imm_unsigned)
+ printUInt32Bang(O, imm);
+ else
+ printInt32Bang(O, imm);
break;
case ARM_INS_AND:
case ARM_INS_ORR:
@@ -876,10 +863,7 @@
case ARM_INS_BIC:
case ARM_INS_MVN:
// do not print number in negative form
- if (imm >= 0 && imm <= HEX_THRESHOLD)
- SStream_concat(O, "#%u", imm);
- else
- SStream_concat(O, "#0x%x", imm);
+ printUInt32Bang(O, imm);
break;
}
}
@@ -912,10 +896,7 @@
if (isSub) {
SStream_concat(O, "#-0x%x", -OffImm);
} else {
- if (OffImm > HEX_THRESHOLD)
- SStream_concat(O, "#0x%x", OffImm);
- else
- SStream_concat(O, "#%u", OffImm);
+ printUInt32Bang(O, OffImm);
}
SStream_concat0(O, "]");
@@ -1386,10 +1367,7 @@
int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
//assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
- if (lsb > HEX_THRESHOLD)
- SStream_concat(O, "#0x%x", lsb);
- else
- SStream_concat(O, "#%u", lsb);
+ printUInt32Bang(O, lsb);
if (width > HEX_THRESHOLD)
SStream_concat(O, ", #0x%x", width);
@@ -1895,10 +1873,9 @@
static void printThumbS4ImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
{
unsigned tmp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum)) * 4;
- if (tmp > HEX_THRESHOLD)
- SStream_concat(O, "#0x%x", tmp);
- else
- SStream_concat(O, "#%u", tmp);
+
+ printUInt32Bang(O, tmp);
+
if (MI->csh->detail) {
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
@@ -1910,10 +1887,8 @@
{
unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
unsigned tmp = Imm == 0 ? 32 : Imm;
- if (tmp > HEX_THRESHOLD)
- SStream_concat(O, "#0x%x", tmp);
- else
- SStream_concat(O, "#%u", tmp);
+
+ printUInt32Bang(O, tmp);
if (MI->csh->detail) {
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
@@ -1988,10 +1963,7 @@
if (ImmOffs) {
tmp = ImmOffs * Scale;
SStream_concat0(O, ", ");
- if (tmp > HEX_THRESHOLD)
- SStream_concat(O, "#0x%x", tmp);
- else
- SStream_concat(O, "#%u", tmp);
+ printUInt32Bang(O, tmp);
if (MI->csh->detail)
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = tmp;
}
@@ -2184,10 +2156,7 @@
if (MCOperand_getImm(MO2)) {
SStream_concat0(O, ", ");
tmp = (unsigned int)MCOperand_getImm(MO2) * 4;
- if (tmp > HEX_THRESHOLD)
- SStream_concat(O, "#0x%x", tmp);
- else
- SStream_concat(O, "#%u", tmp);
+ printUInt32Bang(O, tmp);
if (MI->csh->detail)
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = tmp;
}
@@ -2209,17 +2178,7 @@
MI->flat_insn->detail->arm.op_count++;
}
} else {
- if (OffImm < 0) {
- if (OffImm < -HEX_THRESHOLD)
- SStream_concat(O, "#-0x%x", -OffImm);
- else
- SStream_concat(O, "#-%u", -OffImm);
- } else {
- if (OffImm > HEX_THRESHOLD)
- SStream_concat(O, "#0x%x", OffImm);
- else
- SStream_concat(O, "#%u", OffImm);
- }
+ printInt32Bang(O, OffImm);
if (MI->csh->detail) {
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = OffImm;
@@ -2245,17 +2204,7 @@
MI->flat_insn->detail->arm.op_count++;
}
} else {
- if (OffImm < 0) {
- if (OffImm < -HEX_THRESHOLD)
- SStream_concat(O, "#-0x%x", -OffImm);
- else
- SStream_concat(O, "#-%u", -OffImm);
- } else {
- if (OffImm > HEX_THRESHOLD)
- SStream_concat(O, "#0x%x", OffImm);
- else
- SStream_concat(O, "#%u", OffImm);
- }
+ printInt32Bang(O, OffImm);
if (MI->csh->detail) {
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = OffImm;
@@ -2417,10 +2366,8 @@
unsigned tmp;
tmp = 16 - (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
- if (tmp > HEX_THRESHOLD)
- SStream_concat(O, "#0x%x", tmp);
- else
- SStream_concat(O, "#%u", tmp);
+ printUInt32Bang(O, tmp);
+
if (MI->csh->detail) {
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
@@ -2433,10 +2380,8 @@
unsigned tmp;
tmp = 32 - (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
- if (tmp > HEX_THRESHOLD)
- SStream_concat(O, "#0x%x", tmp);
- else
- SStream_concat(O, "#%u", tmp);
+ printUInt32Bang(O, tmp);
+
if (MI->csh->detail) {
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
diff --git a/bindings/python/capstone/__init__.py b/bindings/python/capstone/__init__.py
index 5943c88..cba23d7 100644
--- a/bindings/python/capstone/__init__.py
+++ b/bindings/python/capstone/__init__.py
@@ -161,6 +161,7 @@
CS_OPT_SKIPDATA = 5 # Skip data when disassembling
CS_OPT_SKIPDATA_SETUP = 6 # Setup user-defined function for SKIPDATA option
CS_OPT_MNEMONIC = 7 # Customize instruction mnemonic
+CS_OPT_UNSIGNED = 8 # Print immediate in unsigned form
# Capstone option value
CS_OPT_OFF = 0 # Turn OFF an option - default option of CS_OPT_DETAIL
@@ -771,6 +772,7 @@
self._syntax = None
self._detail = False # by default, do not produce instruction details
+ self._imm_unsigned = False # by default, print immediate operands as signed numbers
self._diet = cs_support(CS_SUPPORT_DIET)
self._x86reduce = cs_support(CS_SUPPORT_X86_REDUCE)
@@ -900,6 +902,25 @@
self._detail = opt
+ # is detail mode enable?
+ @property
+ def imm_unsigned(self):
+ return self._imm_unsigned
+
+
+ # modify detail mode.
+ @imm_unsigned.setter
+ def imm_unsigned(self, opt): # opt is boolean type, so must be either 'True' or 'False'
+ if opt == False:
+ status = _cs.cs_option(self.csh, CS_OPT_UNSIGNED, CS_OPT_OFF)
+ else:
+ status = _cs.cs_option(self.csh, CS_OPT_UNSIGNED, CS_OPT_ON)
+ if status != CS_ERR_OK:
+ raise CsError(status)
+ # save detail
+ self._imm_unsigned = opt
+
+
# return disassembly mode of this engine.
@property
def mode(self):
diff --git a/cs.c b/cs.c
index 8f22d7b..ebd8109 100644
--- a/cs.c
+++ b/cs.c
@@ -423,6 +423,10 @@
default:
break;
+ case CS_OPT_UNSIGNED:
+ handle->imm_unsigned = (cs_opt_value)value;
+ return CS_ERR_OK;
+
case CS_OPT_DETAIL:
handle->detail = (cs_opt_value)value;
return CS_ERR_OK;
diff --git a/cs_priv.h b/cs_priv.h
index 7818cd2..bb7cb0d 100644
--- a/cs_priv.h
+++ b/cs_priv.h
@@ -63,7 +63,7 @@
PostPrinter_t post_printer;
cs_err errnum;
ARM_ITStatus ITBlock; // for Arm only
- cs_opt_value detail;
+ cs_opt_value detail, imm_unsigned;
int syntax; // asm syntax for simple printer such as ARM, Mips & PPC
bool doing_mem; // handling memory operand in InstPrinter code
unsigned short *insn_cache; // index caching for mapping.c
diff --git a/include/capstone/capstone.h b/include/capstone/capstone.h
index 3e61a90..164db6b 100644
--- a/include/capstone/capstone.h
+++ b/include/capstone/capstone.h
@@ -151,11 +151,12 @@
CS_OPT_SKIPDATA, // Skip data when disassembling. Then engine is in SKIPDATA mode.
CS_OPT_SKIPDATA_SETUP, // Setup user-defined function for SKIPDATA option
CS_OPT_MNEMONIC, // Customize instruction mnemonic
+ CS_OPT_UNSIGNED, // print immediate operands in unsigned form
} cs_opt_type;
// Runtime option value (associated with option type above)
typedef enum cs_opt_value {
- CS_OPT_OFF = 0, // Turn OFF an option - default option of CS_OPT_DETAIL, CS_OPT_SKIPDATA.
+ CS_OPT_OFF = 0, // Turn OFF an option - default for CS_OPT_DETAIL, CS_OPT_SKIPDATA, CS_OPT_UNSIGNED.
CS_OPT_ON = 3, // Turn ON an option (CS_OPT_DETAIL, CS_OPT_SKIPDATA).
CS_OPT_SYNTAX_DEFAULT = 0, // Default asm syntax (CS_OPT_SYNTAX).
CS_OPT_SYNTAX_INTEL, // X86 Intel asm syntax - default on X86 (CS_OPT_SYNTAX).