/// 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;
	}
}
Beispiel #2
0
// 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)) {
		uint8_t encsize;
		uint8_t opsize = X86_immediate_size(MCInst_getOpcode(MI), &encsize);

		// Print X86 immediates as signed values.
		int64_t imm = MCOperand_getImm(Op);
		if (imm < 0) {
			if (MI->csh->imm_unsigned) {
				if (opsize) {
					switch(opsize) {
						default:
							break;
						case 1:
							imm &= 0xff;
							break;
						case 2:
							imm &= 0xffff;
							break;
						case 4:
							imm &= 0xffffffff;
							break;
					}
				}

				SStream_concat(O, "$0x%"PRIx64, imm);
			} else {
				if (imm < -HEX_THRESHOLD)
					SStream_concat(O, "$-0x%"PRIx64, -imm);
				else
					SStream_concat(O, "$-%"PRIu64, -imm);
			}
		} else {
			if (imm > HEX_THRESHOLD)
				SStream_concat(O, "$0x%"PRIx64, imm);
			else
				SStream_concat(O, "$%"PRIu64, imm);
		}
	}
}
Beispiel #3
0
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 {
				uint8_t access[6];

				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];

				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];

				MI->flat_insn->detail->x86.op_count++;
			}
		}
	} else if (MCOperand_isImm(Op)) {
		// Print X86 immediates as signed values.
		uint8_t encsize;
		int64_t imm = MCOperand_getImm(Op);
		uint8_t opsize = X86_immediate_size(MCInst_getOpcode(MI), &encsize);

		if (opsize == 1)    // print 1 byte immediate in positive form
			imm = imm & 0xff;

		switch(MI->flat_insn->id) {
			default:
				if (imm >= 0) {
					if (imm > HEX_THRESHOLD)
						SStream_concat(O, "$0x%"PRIx64, imm);
					else
						SStream_concat(O, "$%"PRIu64, imm);
				} else {
					if (MI->csh->imm_unsigned) {
						if (opsize) {
							switch(opsize) {
								default:
									break;
								case 1:
									imm &= 0xff;
									break;
								case 2:
									imm &= 0xffff;
									break;
								case 4:
									imm &= 0xffffffff;
									break;
							}
						}

						SStream_concat(O, "$0x%"PRIx64, imm);
					} else {
						if (imm == 0x8000000000000000LL)  // imm == -imm
							SStream_concat0(O, "$0x8000000000000000");
						else if (imm < -HEX_THRESHOLD)
							SStream_concat(O, "$-0x%"PRIx64, -imm);
						else
							SStream_concat(O, "$-%"PRIu64, -imm);
					}
				}
				break;

			case X86_INS_MOVABS:
				// do not print number in negative form
				SStream_concat(O, "$0x%"PRIx64, imm);
				break;

			case X86_INS_IN:
			case X86_INS_OUT:
			case X86_INS_INT:
				// do not print number in negative form
				imm = imm & 0xff;
				if (imm >= 0 && imm <= HEX_THRESHOLD)
					SStream_concat(O, "$%u", imm);
				else {
					SStream_concat(O, "$0x%x", imm);
				}
				break;

			case X86_INS_LCALL:
			case X86_INS_LJMP:
				// always print address in positive form
				if (OpNo == 1) {	// selector is ptr16
					imm = imm & 0xffff;
					opsize = 2;
				}
				SStream_concat(O, "$0x%"PRIx64, imm);
				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)
					SStream_concat(O, "$%u", imm);
				else {
					imm = arch_masks[opsize? opsize : MI->imm_size] & imm;
					SStream_concat(O, "$0x%"PRIx64, imm);
				}
				break;

			case X86_INS_RET:
			case X86_INS_RETF:
				// RET imm16
				if (imm >= 0 && imm <= HEX_THRESHOLD)
					SStream_concat(O, "$%u", imm);
				else {
					imm = 0xffff & imm;
					SStream_concat(O, "$0x%x", imm);
				}
				break;
		}

		if (MI->csh->detail) {
			if (MI->csh->doing_mem) {
				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].mem.disp = imm;
			} else {
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM;
				MI->has_imm = true;
				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm;

				if (opsize > 0) {
					MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = opsize;
					MI->flat_insn->detail->x86.encoding.imm_size = encsize;
				} else if (MI->op1_size > 0)
					MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->op1_size;
				else
					MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size;

				MI->flat_insn->detail->x86.op_count++;
			}
		}
	}
}
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++;
			}
		}
	}
}