static void printMemOffset(MCInst *MI, unsigned Op, SStream *O) { MCOperand *DispSpec = MCInst_getOperand(MI, Op); MCOperand *SegReg = MCInst_getOperand(MI, Op + 1); int reg; if (MI->csh->detail) { #ifndef CAPSTONE_DIET uint8_t access[6]; #endif MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM; MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize; MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID; MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID; MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID; MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1; MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0; #ifndef CAPSTONE_DIET get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags); MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count]; #endif } // If this has a segment register, print it. reg = MCOperand_getReg(SegReg); if (reg) { _printOperand(MI, Op + 1, O); SStream_concat0(O, ":"); if (MI->csh->detail) { MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = reg; } } SStream_concat0(O, "["); if (MCOperand_isImm(DispSpec)) { int64_t imm = MCOperand_getImm(DispSpec); if (MI->csh->detail) MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm; if (imm < 0) printImm(MI->csh->syntax, O, arch_masks[MI->csh->mode] & imm, true); else printImm(MI->csh->syntax, O, imm, true); } SStream_concat0(O, "]"); if (MI->csh->detail) MI->flat_insn->detail->x86.op_count++; if (MI->op1_size == 0) MI->op1_size = MI->x86opsize; }
// local printOperand, without updating public operands static void _printOperand(MCInst *MI, unsigned OpNo, SStream *O) { MCOperand *Op = MCInst_getOperand(MI, OpNo); if (MCOperand_isReg(Op)) { printRegName(O, MCOperand_getReg(Op)); } else if (MCOperand_isImm(Op)) { int64_t imm = MCOperand_getImm(Op); printImm(MI->csh->syntax, O, imm, false); } }
/// printPCRelImm - This is used to print an immediate value that ends up /// being encoded as a pc-relative value. static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O) { MCOperand *Op = MCInst_getOperand(MI, OpNo); if (MCOperand_isImm(Op)) { int64_t imm = MCOperand_getImm(Op) + MI->flat_insn->size + MI->address; int opsize = X86_immediate_size(MI->Opcode); // truncat imm for non-64bit if (MI->csh->mode != CS_MODE_64) { imm = imm & 0xffffffff; } if (MI->csh->mode == CS_MODE_16 && (MI->Opcode != X86_JMP_4 && MI->Opcode != X86_CALLpcrel32)) imm = imm & 0xffff; // Hack: X86 16bit with opcode X86_JMP_4 if (MI->csh->mode == CS_MODE_16 && (MI->Opcode == X86_JMP_4 && MI->x86_prefix[2] != 0x66)) imm = imm & 0xffff; // CALL/JMP rel16 is special if (MI->Opcode == X86_CALLpcrel16 || MI->Opcode == X86_JMP_2) imm = imm & 0xffff; printImm(MI->csh->syntax, O, imm, true); if (MI->csh->detail) { #ifndef CAPSTONE_DIET uint8_t access[6]; #endif MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM; // if op_count > 0, then this operand's size is taken from the destination op if (MI->flat_insn->detail->x86.op_count > 0) MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->flat_insn->detail->x86.operands[0].size; else if (opsize > 0) MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = opsize; else MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size; MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm; #ifndef CAPSTONE_DIET get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags); MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count]; #endif MI->flat_insn->detail->x86.op_count++; } if (MI->op1_size == 0) MI->op1_size = MI->imm_size; } }
static void printU8Imm(MCInst *MI, unsigned Op, SStream *O) { uint8_t val = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0xff; printImm(MI->csh->syntax, O, val, true); if (MI->csh->detail) { #ifndef CAPSTONE_DIET uint8_t access[6]; #endif MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM; MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = val; #ifndef CAPSTONE_DIET get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags); MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count]; #endif MI->flat_insn->detail->x86.op_count++; } }
static void printMemReference(MCInst *MI, unsigned Op, SStream *O) { bool NeedPlus = false; MCOperand *BaseReg = MCInst_getOperand(MI, Op + X86_AddrBaseReg); uint64_t ScaleVal = MCOperand_getImm(MCInst_getOperand(MI, Op + X86_AddrScaleAmt)); MCOperand *IndexReg = MCInst_getOperand(MI, Op + X86_AddrIndexReg); MCOperand *DispSpec = MCInst_getOperand(MI, Op + X86_AddrDisp); MCOperand *SegReg = MCInst_getOperand(MI, Op + X86_AddrSegmentReg); int reg; if (MI->csh->detail) { #ifndef CAPSTONE_DIET uint8_t access[6]; #endif MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM; MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize; MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID; MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = MCOperand_getReg(BaseReg); MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = MCOperand_getReg(IndexReg); MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = (int)ScaleVal; MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0; #ifndef CAPSTONE_DIET get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags); MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count]; #endif } // If this has a segment register, print it. reg = MCOperand_getReg(SegReg); if (reg) { _printOperand(MI, Op + X86_AddrSegmentReg, O); if (MI->csh->detail) { MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = reg; } SStream_concat0(O, ":"); } SStream_concat0(O, "["); if (MCOperand_getReg(BaseReg)) { _printOperand(MI, Op + X86_AddrBaseReg, O); NeedPlus = true; } if (MCOperand_getReg(IndexReg)) { if (NeedPlus) SStream_concat0(O, " + "); _printOperand(MI, Op + X86_AddrIndexReg, O); if (ScaleVal != 1) SStream_concat(O, "*%u", ScaleVal); NeedPlus = true; } if (MCOperand_isImm(DispSpec)) { int64_t DispVal = MCOperand_getImm(DispSpec); if (MI->csh->detail) MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = DispVal; if (DispVal) { if (NeedPlus) { if (DispVal < 0) { SStream_concat0(O, " - "); printImm(MI->csh->syntax, O, -DispVal, true); } else { SStream_concat0(O, " + "); printImm(MI->csh->syntax, O, DispVal, true); } } else { // memory reference to an immediate address if (DispVal < 0) { printImm(MI->csh->syntax, O, arch_masks[MI->csh->mode] & DispVal, true); } else { printImm(MI->csh->syntax, O, DispVal, true); } } } else { // DispVal = 0 if (!NeedPlus) // [0] SStream_concat0(O, "0"); } } SStream_concat0(O, "]"); if (MI->csh->detail) MI->flat_insn->detail->x86.op_count++; if (MI->op1_size == 0) MI->op1_size = MI->x86opsize; }
static void printOperand(MCInst *MI, unsigned OpNo, SStream *O) { MCOperand *Op = MCInst_getOperand(MI, OpNo); if (MCOperand_isReg(Op)) { unsigned int reg = MCOperand_getReg(Op); printRegName(O, reg); if (MI->csh->detail) { if (MI->csh->doing_mem) { MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = reg; } else { #ifndef CAPSTONE_DIET uint8_t access[6]; #endif MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_REG; MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].reg = reg; MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->csh->regsize_map[reg]; #ifndef CAPSTONE_DIET get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags); MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count]; #endif MI->flat_insn->detail->x86.op_count++; } } if (MI->op1_size == 0) MI->op1_size = MI->csh->regsize_map[reg]; } else if (MCOperand_isImm(Op)) { int64_t imm = MCOperand_getImm(Op); int opsize = X86_immediate_size(MCInst_getOpcode(MI)); if (opsize == 1) // print 1 byte immediate in positive form imm = imm & 0xff; switch(MI->flat_insn->id) { default: printImm(MI->csh->syntax, O, imm, false); break; case X86_INS_INT: // do not print number in negative form imm = imm & 0xff; printImm(MI->csh->syntax, O, imm, true); break; case X86_INS_LCALL: case X86_INS_LJMP: // always print address in positive form if (OpNo == 1) { // ptr16 part imm = imm & 0xffff; opsize = 2; } printImm(MI->csh->syntax, O, imm, true); break; case X86_INS_AND: case X86_INS_OR: case X86_INS_XOR: // do not print number in negative form if (imm >= 0 && imm <= HEX_THRESHOLD) printImm(MI->csh->syntax, O, imm, true); else { imm = arch_masks[opsize? opsize : MI->imm_size] & imm; printImm(MI->csh->syntax, O, imm, true); } break; case X86_INS_RET: // RET imm16 if (imm >= 0 && imm <= HEX_THRESHOLD) printImm(MI->csh->syntax, O, imm, true); else { imm = 0xffff & imm; printImm(MI->csh->syntax, O, imm, true); } break; } if (MI->csh->detail) { if (MI->csh->doing_mem) { MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm; } else { #ifndef CAPSTONE_DIET uint8_t access[6]; #endif MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM; if (opsize > 0) MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = opsize; else if (MI->flat_insn->detail->x86.op_count > 0) { if (MI->flat_insn->id != X86_INS_LCALL && MI->flat_insn->id != X86_INS_LJMP) { MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->flat_insn->detail->x86.operands[0].size; } else MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size; } else MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size; MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm; #ifndef CAPSTONE_DIET get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags); MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count]; #endif MI->flat_insn->detail->x86.op_count++; } } } }
void printImm(T value, Args... args) { cout << value << " "; printImm(args...); }