diff --git a/arch/AArch64/mapping.c b/arch/AArch64/mapping.c index e95604428..dcf5f1d5e 100644 --- a/arch/AArch64/mapping.c +++ b/arch/AArch64/mapping.c @@ -1878,22 +1878,24 @@ void AArch64_get_insn_id(cs_insn *insn, unsigned int id) int i = insn_find(insns, ARR_SIZE(insns), id); if (i != -1) { insn->id = insns[i].mapid; + memcpy(insn->regs_read, insns[i].regs_use, sizeof(insns[i].regs_use)); + insn->regs_read_count = count_positive(insns[i].regs_use); + memcpy(insn->regs_write, insns[i].regs_mod, sizeof(insns[i].regs_mod)); + insn->regs_write_count = count_positive(insns[i].regs_mod); + memcpy(insn->groups, insns[i].groups, sizeof(insns[i].groups)); - // call cs_reg_write() with handle = 1 to pass handle check + insn->groups_count = count_positive(insns[i].groups); + + // call cs_reg_write() with handle = 1 to bypass handle check // we only need to find if this insn modifies ARM64_REG_NZCV insn->arm64.update_flags = cs_reg_write(1, insn, ARM64_REG_NZCV); if (insns[i].branch || insns[i].indirect_branch) { - // this insn also belongs to JUMP group - int j; - for (j = 0; j < ARR_SIZE(insns[i].groups); j++) { - if (insn->groups[j] == 0) { - insn->groups[j] = ARM64_GRP_JUMP; - break; - } - } + // this insn also belongs to JUMP group. add JUMP group + insn->groups[insn->groups_count] = ARM64_GRP_JUMP; + insn->groups_count++; } } } diff --git a/arch/ARM/mapping.c b/arch/ARM/mapping.c index a7b859543..79e02caea 100644 --- a/arch/ARM/mapping.c +++ b/arch/ARM/mapping.c @@ -2302,20 +2302,24 @@ void ARM_get_insn_id(cs_insn *insn, unsigned int id) int i = insn_find(insns, ARR_SIZE(insns), id); if (i != -1) { insn->id = insns[i].mapid; + memcpy(insn->regs_read, insns[i].regs_use, sizeof(insns[i].regs_use)); + insn->regs_read_count = count_positive(insns[i].regs_use); + memcpy(insn->regs_write, insns[i].regs_mod, sizeof(insns[i].regs_mod)); + insn->regs_write_count = count_positive(insns[i].regs_mod); + memcpy(insn->groups, insns[i].groups, sizeof(insns[i].groups)); + insn->groups_count = count_positive(insns[i].groups); + + // call cs_reg_write() with handle = 1 to bypass handle check + // we only need to find if this insn modifies ARM64_REG_NZCV insn->arm.update_flags = cs_reg_write(1, insn, ARM_REG_CPSR); if (insns[i].branch || insns[i].indirect_branch) { - // this insn also belongs to JUMP group - int j; - for (j = 0; j < ARR_SIZE(insns[i].groups); j++) { - if (insn->groups[j] == 0) { - insn->groups[j] = ARM_GRP_JUMP; - break; - } - } + // this insn also belongs to JUMP group. add JUMP group + insn->groups[insn->groups_count] = ARM_GRP_JUMP; + insn->groups_count++; } } } diff --git a/arch/Mips/mapping.c b/arch/Mips/mapping.c index 8127c340e..b70509d91 100644 --- a/arch/Mips/mapping.c +++ b/arch/Mips/mapping.c @@ -1386,19 +1386,20 @@ void Mips_get_insn_id(cs_insn *insn, unsigned int id) for (i = 0; i < ARR_SIZE(alias_insns); i++) { if (alias_insns[i].id == id) { insn->id = alias_insns[i].mapid; - memcpy(insn->regs_read, alias_insns[i].regs_use, sizeof(alias_insns[i].regs_use)); - memcpy(insn->regs_write, alias_insns[i].regs_mod, sizeof(alias_insns[i].regs_mod)); - memcpy(insn->groups, alias_insns[i].groups, sizeof(alias_insns[i].groups)); + + memcpy(insn->regs_read, insns[i].regs_use, sizeof(insns[i].regs_use)); + insn->regs_read_count = count_positive(insns[i].regs_use); + + memcpy(insn->regs_write, insns[i].regs_mod, sizeof(insns[i].regs_mod)); + insn->regs_write_count = count_positive(insns[i].regs_mod); + + memcpy(insn->groups, insns[i].groups, sizeof(insns[i].groups)); + insn->groups_count = count_positive(insns[i].groups); if (insns[i].branch || insns[i].indirect_branch) { - // this insn also belongs to JUMP group - int j; - for (j = 0; j < ARR_SIZE(insns[i].groups); j++) { - if (insn->groups[j] == 0) { - insn->groups[j] = MIPS_GRP_JUMP; - break; - } - } + // this insn also belongs to JUMP group. add JUMP group + insn->groups[insn->groups_count] = MIPS_GRP_JUMP; + insn->groups_count++; } return; @@ -1408,19 +1409,20 @@ void Mips_get_insn_id(cs_insn *insn, unsigned int id) i = insn_find(insns, ARR_SIZE(insns), id); if (i != -1) { insn->id = insns[i].mapid; + memcpy(insn->regs_read, insns[i].regs_use, sizeof(insns[i].regs_use)); + insn->regs_read_count = count_positive(insns[i].regs_use); + memcpy(insn->regs_write, insns[i].regs_mod, sizeof(insns[i].regs_mod)); + insn->regs_write_count = count_positive(insns[i].regs_mod); + memcpy(insn->groups, insns[i].groups, sizeof(insns[i].groups)); + insn->groups_count = count_positive(insns[i].groups); if (insns[i].branch || insns[i].indirect_branch) { - // this insn also belongs to JUMP group - int j; - for (j = 0; j < ARR_SIZE(insns[i].groups); j++) { - if (insn->groups[j] == 0) { - insn->groups[j] = MIPS_GRP_JUMP; - break; - } - } + // this insn also belongs to JUMP group. add JUMP group + insn->groups[insn->groups_count] = MIPS_GRP_JUMP; + insn->groups_count++; } } } diff --git a/arch/X86/mapping.c b/arch/X86/mapping.c index e6a3c2b1e..7c8f4a377 100644 --- a/arch/X86/mapping.c +++ b/arch/X86/mapping.c @@ -6576,19 +6576,20 @@ void X86_get_insn_id(cs_insn *insn, unsigned int id) int i = insn_find(insns, ARR_SIZE(insns), id); if (i != -1) { insn->id = insns[i].mapid; + memcpy(insn->regs_read, insns[i].regs_use, sizeof(insns[i].regs_use)); + insn->regs_read_count = count_positive(insns[i].regs_use); + memcpy(insn->regs_write, insns[i].regs_mod, sizeof(insns[i].regs_mod)); + insn->regs_write_count = count_positive(insns[i].regs_mod); + memcpy(insn->groups, insns[i].groups, sizeof(insns[i].groups)); + insn->groups_count = count_positive(insns[i].groups); if (insns[i].branch || insns[i].indirect_branch) { - // this insn also belongs to JUMP group - int j; - for (j = 0; j < ARR_SIZE(insns[i].groups); j++) { - if (insn->groups[j] == 0) { - insn->groups[j] = X86_GRP_JUMP; - break; - } - } + // this insn also belongs to JUMP group. add JUMP group + insn->groups[insn->groups_count] = X86_GRP_JUMP; + insn->groups_count++; } } } diff --git a/cs.c b/cs.c index bf8f3d6e0..1d90b0275 100644 --- a/cs.c +++ b/cs.c @@ -29,7 +29,7 @@ #include "utils.h" #define VERSION_MAJOR 1 -#define VERSION_MINOR 3 +#define VERSION_MINOR 4 cs_err cs_errno(csh handle) { @@ -366,7 +366,7 @@ bool cs_insn_group(csh handle, cs_insn *insn, unsigned int group_id) if (!handle) return false; - return arr_exist(insn->groups, ARR_SIZE(insn->groups), group_id); + return arr_exist(insn->groups, insn->groups_count, group_id); } bool cs_reg_read(csh handle, cs_insn *insn, unsigned int reg_id) @@ -374,7 +374,7 @@ bool cs_reg_read(csh handle, cs_insn *insn, unsigned int reg_id) if (!handle) return false; - return arr_exist(insn->regs_read, ARR_SIZE(insn->regs_read), reg_id); + return arr_exist(insn->regs_read, insn->regs_read_count, reg_id); } bool cs_reg_write(csh handle, cs_insn *insn, unsigned int reg_id) @@ -382,7 +382,7 @@ bool cs_reg_write(csh handle, cs_insn *insn, unsigned int reg_id) if (!handle) return false; - return arr_exist(insn->regs_write, ARR_SIZE(insn->regs_write), reg_id); + return arr_exist(insn->regs_write, insn->regs_write_count, reg_id); } int cs_op_count(csh ud, cs_insn *insn, unsigned int op_type) diff --git a/include/capstone.h b/include/capstone.h index 0a2226068..b710fdb9f 100644 --- a/include/capstone.h +++ b/include/capstone.h @@ -64,8 +64,13 @@ typedef struct cs_insn { char op_str[96]; unsigned int regs_read[32]; // list of implicit registers read by this instruction + unsigned int regs_read_count; // number of implicit registers read by this insn + unsigned int regs_write[32]; // list of implicit registers modified by this instruction + unsigned int regs_write_count; // number of implicit registers modified by this insn + unsigned int groups[8]; // list of group this instruction belong to + unsigned int groups_count; // number of groups this insn belongs to // Architecture-specific instruction info union { diff --git a/tests/test.c b/tests/test.c index 7502c831a..7a481c7da 100644 --- a/tests/test.c +++ b/tests/test.c @@ -185,8 +185,11 @@ int main() printf("@mnemonic: %u\n", offsetof(cs_insn, mnemonic)); printf("@op_str: %u\n", offsetof(cs_insn, op_str)); printf("@regs_read: %u\n", offsetof(cs_insn, regs_read)); + printf("@regs_read_count: %u\n", offsetof(cs_insn, regs_read_count)); printf("@regs_write: %u\n", offsetof(cs_insn, regs_write)); + printf("@regs_write_count: %u\n", offsetof(cs_insn, regs_write_count)); printf("@groups: %u\n", offsetof(cs_insn, groups)); + printf("@groups_count: %u\n", offsetof(cs_insn, groups_count)); printf("@arch: %u\n", offsetof(cs_insn, x86)); #endif diff --git a/tests/test_detail.c b/tests/test_detail.c index d1961900d..851d9a7a9 100644 --- a/tests/test_detail.c +++ b/tests/test_detail.c @@ -156,33 +156,27 @@ static void test() i->id, cs_insn_name(handle, i->id)); // print implicit registers used by this instruction - if (i->regs_read[0] != 0) { + if (i->regs_read_count > 0) { printf("\tImplicit registers read: "); - for (n = 0; n < 32; n++) { - if (i->regs_read[n] == 0) - break; + for (n = 0; n < i->regs_read_count; n++) { printf("%s ", cs_reg_name(handle, i->regs_read[n])); } printf("\n"); } // print implicit registers modified by this instruction - if (i->regs_write[0] != 0) { + if (i->regs_write_count > 0) { printf("\tImplicit registers modified: "); - for (n = 0; n < 32; n++) { - if (i->regs_write[n] == 0) - break; + for (n = 0; n < i->regs_write_count; n++) { printf("%s ", cs_reg_name(handle, i->regs_write[n])); } printf("\n"); } // print the groups this instruction belong to - if (i->groups[0] != 0) { + if (i->groups_count > 0) { printf("\tThis instruction belongs to groups: "); - for (n = 0; n < 8; n++) { - if (i->groups[n] == 0) - break; + for (n = 0; n < i->groups_count; n++) { printf("%u ", i->groups[n]); } printf("\n"); diff --git a/utils.c b/utils.c index 882ef2da1..539ab1466 100644 --- a/utils.c +++ b/utils.c @@ -66,3 +66,13 @@ unsigned int insn_reverse_id(insn_map *insns, unsigned int max, unsigned int id) return 0; } +// count number of positive members in a list. +// NOTE: list must be guaranteed to end in 0 +unsigned int count_positive(unsigned int *list) +{ + unsigned int c; + + for (c = 0; list[c] > 0; c++); + + return c; +} diff --git a/utils.h b/utils.h index 89f0b717c..357341dca 100644 --- a/utils.h +++ b/utils.h @@ -41,6 +41,10 @@ int name2id(name_map* map, int max, char *name); // return 0 if not found unsigned int insn_reverse_id(insn_map *insns, unsigned int max, unsigned int id); +// count number of positive members in a list. +// NOTE: list must be guaranteed to end in 0 +unsigned int count_positive(unsigned int *list); + #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0])) #endif