diff options
author | 2023-10-10 14:33:42 +0000 | |
---|---|---|
committer | 2023-10-10 14:33:42 +0000 | |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /capstone/arch/AArch64/AArch64Mapping.c | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'capstone/arch/AArch64/AArch64Mapping.c')
-rw-r--r-- | capstone/arch/AArch64/AArch64Mapping.c | 600 |
1 files changed, 600 insertions, 0 deletions
diff --git a/capstone/arch/AArch64/AArch64Mapping.c b/capstone/arch/AArch64/AArch64Mapping.c new file mode 100644 index 000000000..442461dfe --- /dev/null +++ b/capstone/arch/AArch64/AArch64Mapping.c @@ -0,0 +1,600 @@ +/* Capstone Disassembly Engine */ +/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */ + +#ifdef CAPSTONE_HAS_ARM64 + +#include <stdio.h> // debug +#include <string.h> + +#include "../../utils.h" + +#include "AArch64Mapping.h" + +#define GET_INSTRINFO_ENUM +#include "AArch64GenInstrInfo.inc" + +#ifndef CAPSTONE_DIET +// NOTE: this reg_name_maps[] reflects the order of registers in arm64_reg +static const char * const reg_name_maps[] = { + NULL, /* ARM64_REG_INVALID */ + + "ffr", + "fp", + "lr", + "nzcv", + "sp", + "wsp", + "wzr", + "xzr", + + "b0", + "b1", + "b2", + "b3", + "b4", + "b5", + "b6", + "b7", + "b8", + "b9", + "b10", + "b11", + "b12", + "b13", + "b14", + "b15", + "b16", + "b17", + "b18", + "b19", + "b20", + "b21", + "b22", + "b23", + "b24", + "b25", + "b26", + "b27", + "b28", + "b29", + "b30", + "b31", + + "d0", + "d1", + "d2", + "d3", + "d4", + "d5", + "d6", + "d7", + "d8", + "d9", + "d10", + "d11", + "d12", + "d13", + "d14", + "d15", + "d16", + "d17", + "d18", + "d19", + "d20", + "d21", + "d22", + "d23", + "d24", + "d25", + "d26", + "d27", + "d28", + "d29", + "d30", + "d31", + + "h0", + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "h7", + "h8", + "h9", + "h10", + "h11", + "h12", + "h13", + "h14", + "h15", + "h16", + "h17", + "h18", + "h19", + "h20", + "h21", + "h22", + "h23", + "h24", + "h25", + "h26", + "h27", + "h28", + "h29", + "h30", + "h31", + + "p0", + "p1", + "p2", + "p3", + "p4", + "p5", + "p6", + "p7", + "p8", + "p9", + "p10", + "p11", + "p12", + "p13", + "p14", + "p15", + + "q0", + "q1", + "q2", + "q3", + "q4", + "q5", + "q6", + "q7", + "q8", + "q9", + "q10", + "q11", + "q12", + "q13", + "q14", + "q15", + "q16", + "q17", + "q18", + "q19", + "q20", + "q21", + "q22", + "q23", + "q24", + "q25", + "q26", + "q27", + "q28", + "q29", + "q30", + "q31", + "s0", + "s1", + "s2", + "s3", + "s4", + "s5", + "s6", + "s7", + "s8", + "s9", + "s10", + "s11", + "s12", + "s13", + "s14", + "s15", + "s16", + "s17", + "s18", + "s19", + "s20", + "s21", + "s22", + "s23", + "s24", + "s25", + "s26", + "s27", + "s28", + "s29", + "s30", + "s31", + + "w0", + "w1", + "w2", + "w3", + "w4", + "w5", + "w6", + "w7", + "w8", + "w9", + "w10", + "w11", + "w12", + "w13", + "w14", + "w15", + "w16", + "w17", + "w18", + "w19", + "w20", + "w21", + "w22", + "w23", + "w24", + "w25", + "w26", + "w27", + "w28", + "w29", + "w30", + + "x0", + "x1", + "x2", + "x3", + "x4", + "x5", + "x6", + "x7", + "x8", + "x9", + "x10", + "x11", + "x12", + "x13", + "x14", + "x15", + "x16", + "x17", + "x18", + "x19", + "x20", + "x21", + "x22", + "x23", + "x24", + "x25", + "x26", + "x27", + "x28", + + "z0", + "z1", + "z2", + "z3", + "z4", + "z5", + "z6", + "z7", + "z8", + "z9", + "z10", + "z11", + "z12", + "z13", + "z14", + "z15", + "z16", + "z17", + "z18", + "z19", + "z20", + "z21", + "z22", + "z23", + "z24", + "z25", + "z26", + "z27", + "z28", + "z29", + "z30", + "z31", + + "v0", + "v1", + "v2", + "v3", + "v4", + "v5", + "v6", + "v7", + "v8", + "v9", + "v10", + "v11", + "v12", + "v13", + "v14", + "v15", + "v16", + "v17", + "v18", + "v19", + "v20", + "v21", + "v22", + "v23", + "v24", + "v25", + "v26", + "v27", + "v28", + "v29", + "v30", + "v31", +}; +#endif + +const char *AArch64_reg_name(csh handle, unsigned int reg) +{ +#ifndef CAPSTONE_DIET + if (reg >= ARR_SIZE(reg_name_maps)) + return NULL; + + return reg_name_maps[reg]; +#else + return NULL; +#endif +} + +static const insn_map insns[] = { + // dummy item + { + 0, 0, +#ifndef CAPSTONE_DIET + { 0 }, { 0 }, { 0 }, 0, 0 +#endif + }, + +#include "AArch64MappingInsn.inc" +}; + +// given internal insn id, return public instruction info +void AArch64_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id) +{ + int i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache); + if (i != 0) { + insn->id = insns[i].mapid; + + if (h->detail) { +#ifndef CAPSTONE_DIET + cs_struct handle; + handle.detail = h->detail; + + memcpy(insn->detail->regs_read, insns[i].regs_use, sizeof(insns[i].regs_use)); + insn->detail->regs_read_count = (uint8_t)count_positive(insns[i].regs_use); + + memcpy(insn->detail->regs_write, insns[i].regs_mod, sizeof(insns[i].regs_mod)); + insn->detail->regs_write_count = (uint8_t)count_positive(insns[i].regs_mod); + + memcpy(insn->detail->groups, insns[i].groups, sizeof(insns[i].groups)); + insn->detail->groups_count = (uint8_t)count_positive8(insns[i].groups); + + insn->detail->arm64.update_flags = cs_reg_write((csh)&handle, insn, ARM64_REG_NZCV); +#endif + } + } +} + +static const char * const insn_name_maps[] = { + NULL, // ARM64_INS_INVALID +#include "AArch64MappingInsnName.inc" + "sbfiz", + "ubfiz", + "sbfx", + "ubfx", + "bfi", + "bfxil", + "ic", + "dc", + "at", + "tlbi", +}; + +const char *AArch64_insn_name(csh handle, unsigned int id) +{ +#ifndef CAPSTONE_DIET + if (id >= ARM64_INS_ENDING) + return NULL; + + if (id < ARR_SIZE(insn_name_maps)) + return insn_name_maps[id]; + + // not found + return NULL; +#else + return NULL; +#endif +} + +#ifndef CAPSTONE_DIET +static const name_map group_name_maps[] = { + // generic groups + { ARM64_GRP_INVALID, NULL }, + { ARM64_GRP_JUMP, "jump" }, + { ARM64_GRP_CALL, "call" }, + { ARM64_GRP_RET, "return" }, + { ARM64_GRP_PRIVILEGE, "privilege" }, + { ARM64_GRP_INT, "int" }, + { ARM64_GRP_BRANCH_RELATIVE, "branch_relative" }, + { ARM64_GRP_PAC, "pointer authentication" }, + + // architecture-specific groups + { ARM64_GRP_CRYPTO, "crypto" }, + { ARM64_GRP_FPARMV8, "fparmv8" }, + { ARM64_GRP_NEON, "neon" }, + { ARM64_GRP_CRC, "crc" }, + + { ARM64_GRP_AES, "aes" }, + { ARM64_GRP_DOTPROD, "dotprod" }, + { ARM64_GRP_FULLFP16, "fullfp16" }, + { ARM64_GRP_LSE, "lse" }, + { ARM64_GRP_RCPC, "rcpc" }, + { ARM64_GRP_RDM, "rdm" }, + { ARM64_GRP_SHA2, "sha2" }, + { ARM64_GRP_SHA3, "sha3" }, + { ARM64_GRP_SM4, "sm4" }, + { ARM64_GRP_SVE, "sve" }, + { ARM64_GRP_V8_1A, "v8_1a" }, + { ARM64_GRP_V8_3A, "v8_3a" }, + { ARM64_GRP_V8_4A, "v8_4a" }, +}; +#endif + +const char *AArch64_group_name(csh handle, unsigned int id) +{ +#ifndef CAPSTONE_DIET + return id2name(group_name_maps, ARR_SIZE(group_name_maps), id); +#else + return NULL; +#endif +} + +// map instruction name to public instruction ID +arm64_insn AArch64_map_insn(const char *name) +{ + unsigned int i; + + for(i = 1; i < ARR_SIZE(insn_name_maps); i++) { + if (!strcmp(name, insn_name_maps[i])) + return i; + } + + // not found + return ARM64_INS_INVALID; +} + +// map internal raw vregister to 'public' register +arm64_reg AArch64_map_vregister(unsigned int r) +{ + static const unsigned short RegAsmOffsetvreg[] = { +#include "AArch64GenRegisterV.inc" + }; + + if (r < ARR_SIZE(RegAsmOffsetvreg)) + return RegAsmOffsetvreg[r - 1]; + + // cannot find this register + return 0; +} + +void arm64_op_addVectorArrSpecifier(MCInst * MI, int sp) +{ + if (MI->csh->detail) { + MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].vas = sp; + } +} + +void arm64_op_addFP(MCInst *MI, float fp) +{ + if (MI->csh->detail) { + MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_FP; + MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].fp = fp; + MI->flat_insn->detail->arm64.op_count++; + } +} + +void arm64_op_addImm(MCInst *MI, int64_t imm) +{ + if (MI->csh->detail) { + MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM; + MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = (int)imm; + MI->flat_insn->detail->arm64.op_count++; + } +} + +#ifndef CAPSTONE_DIET + +// map instruction to its characteristics +typedef struct insn_op { + unsigned int eflags_update; // how this instruction update status flags + uint8_t access[5]; +} insn_op; + +static const insn_op insn_ops[] = { + { + /* NULL item */ + 0, { 0 } + }, + +#include "AArch64MappingInsnOp.inc" +}; + +// given internal insn id, return operand access info +const uint8_t *AArch64_get_op_access(cs_struct *h, unsigned int id) +{ + int i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache); + if (i != 0) { + return insn_ops[i].access; + } + + return NULL; +} + +void AArch64_reg_access(const cs_insn *insn, + cs_regs regs_read, uint8_t *regs_read_count, + cs_regs regs_write, uint8_t *regs_write_count) +{ + uint8_t i; + uint8_t read_count, write_count; + cs_arm64 *arm64 = &(insn->detail->arm64); + + read_count = insn->detail->regs_read_count; + write_count = insn->detail->regs_write_count; + + // implicit registers + memcpy(regs_read, insn->detail->regs_read, read_count * sizeof(insn->detail->regs_read[0])); + memcpy(regs_write, insn->detail->regs_write, write_count * sizeof(insn->detail->regs_write[0])); + + // explicit registers + for (i = 0; i < arm64->op_count; i++) { + cs_arm64_op *op = &(arm64->operands[i]); + switch((int)op->type) { + case ARM64_OP_REG: + if ((op->access & CS_AC_READ) && !arr_exist(regs_read, read_count, op->reg)) { + regs_read[read_count] = (uint16_t)op->reg; + read_count++; + } + if ((op->access & CS_AC_WRITE) && !arr_exist(regs_write, write_count, op->reg)) { + regs_write[write_count] = (uint16_t)op->reg; + write_count++; + } + break; + case ARM_OP_MEM: + // registers appeared in memory references always being read + if ((op->mem.base != ARM64_REG_INVALID) && !arr_exist(regs_read, read_count, op->mem.base)) { + regs_read[read_count] = (uint16_t)op->mem.base; + read_count++; + } + if ((op->mem.index != ARM64_REG_INVALID) && !arr_exist(regs_read, read_count, op->mem.index)) { + regs_read[read_count] = (uint16_t)op->mem.index; + read_count++; + } + if ((arm64->writeback) && (op->mem.base != ARM64_REG_INVALID) && !arr_exist(regs_write, write_count, op->mem.base)) { + regs_write[write_count] = (uint16_t)op->mem.base; + write_count++; + } + default: + break; + } + } + + *regs_read_count = read_count; + *regs_write_count = write_count; +} +#endif + +#endif |