// fill insn with mnemonic & operands info static void fill_insn(struct cs_struct *handle, cs_insn *insn, char *buffer, MCInst *mci, PostPrinter_t postprinter, const uint8_t *code) { if (handle->detail) { // avoiding copy insn->detail memcpy(insn, &mci->flat_insn, sizeof(*insn) - sizeof(insn->detail)); // NOTE: copy details in 2 chunks, since union is always put at address divisible by 8 // copy from @regs_read until @arm memcpy(insn->detail, (void *)(&(mci->flat_insn)) + offsetof(cs_insn_flat, regs_read), offsetof(cs_detail, arm) - offsetof(cs_detail, regs_read)); // then copy from @arm until end memcpy((void *)((uintptr_t)(insn->detail) + offsetof(cs_detail, arm)), (void *)((uintptr_t)(&(mci->flat_insn)) + offsetof(cs_insn_flat, arm)), sizeof(cs_detail) - offsetof(cs_detail, arm)); } else { insn->address = mci->address; insn->size = (uint16_t)mci->insn_size; } // fill the instruction bytes memcpy(insn->bytes, code, MIN(sizeof(insn->bytes), insn->size)); // map internal instruction opcode to public insn ID if (handle->insn_id) handle->insn_id(handle, insn, MCInst_getOpcode(mci)); // alias instruction might have ID saved in OpcodePub if (MCInst_getOpcodePub(mci)) insn->id = MCInst_getOpcodePub(mci); // post printer handles some corner cases (hacky) if (postprinter) postprinter((csh)handle, insn, buffer); #ifndef CAPSTONE_DIET // fill in mnemonic & operands // find first space or tab char *sp = buffer; for (sp = buffer; *sp; sp++) if (*sp == ' '||*sp == '\t') break; if (*sp) { *sp = '\0'; // find the next non-space char sp++; for (; ((*sp == ' ') || (*sp == '\t')); sp++); strncpy(insn->op_str, sp, sizeof(insn->op_str) - 1); insn->op_str[sizeof(insn->op_str) - 1] = '\0'; } else insn->op_str[0] = '\0'; strncpy(insn->mnemonic, buffer, sizeof(insn->mnemonic) - 1); insn->mnemonic[sizeof(insn->mnemonic) - 1] = '\0'; #endif }
// fill insn with mnemonic & operands info static void fill_insn(struct cs_struct *handle, cs_insn *insn, char *buffer, MCInst *mci, PostPrinter_t postprinter, const uint8_t *code) { #ifndef CAPSTONE_DIET char *sp, *mnem; #endif unsigned int copy_size = MIN(sizeof(insn->bytes), insn->size); // fill the instruction bytes. // we might skip some redundant bytes in front in the case of X86 memcpy(insn->bytes, code + insn->size - copy_size, copy_size); insn->size = copy_size; // alias instruction might have ID saved in OpcodePub if (MCInst_getOpcodePub(mci)) insn->id = MCInst_getOpcodePub(mci); // post printer handles some corner cases (hacky) if (postprinter) postprinter((csh)handle, insn, buffer, mci); #ifndef CAPSTONE_DIET // fill in mnemonic & operands // find first space or tab sp = buffer; mnem = insn->mnemonic; for (sp = buffer; *sp; sp++) { if (*sp == ' '|| *sp == '\t') break; if (*sp == '|') // lock|rep prefix for x86 *sp = ' '; // copy to @mnemonic *mnem = *sp; mnem++; } *mnem = '\0'; // copy @op_str if (*sp) { // find the next non-space char sp++; for (; ((*sp == ' ') || (*sp == '\t')); sp++); strncpy(insn->op_str, sp, sizeof(insn->op_str) - 1); insn->op_str[sizeof(insn->op_str) - 1] = '\0'; } else insn->op_str[0] = '\0'; #endif }