Exemple #1
0
 // get immediate
 jint as_int(void) const {
   GUARANTEE(is_immediate(), "check");
   GUARANTEE(type() == T_BOOLEAN || type() == T_INT || type() == T_BYTE ||
             type() == T_CHAR || type() == T_SHORT ||
             type() == T_OBJECT || type() == T_ARRAY, "check type");
   return _low;
 }
Exemple #2
0
void NativeMovRegMem::print() {
  if (is_immediate()) {
    // offset is a signed 13-bit immediate, so casting it to int will not lose significant bits
    tty->print_cr(INTPTR_FORMAT ": mov reg, [reg + %d]", p2i(instruction_address()), (int)offset());
  } else {
    tty->print_cr(INTPTR_FORMAT ": mov reg, [reg + reg]", p2i(instruction_address()));
  }
}
Exemple #3
0
void Value::materialize() {
  GUARANTEE(is_immediate(), "value must be immediate");
  GUARANTEE(type() != T_OBJECT || must_be_null(), "object immediate is already materialized");

  Value result(type());
  result.assign_register();
  Compiler::code_generator()->move(result, *this);
  result.copy(*this);
}
Exemple #4
0
void c_func_lsl (ea_t *src, ea_t *dest, int size)
{
	char buf[256];
	unsigned int mask;
	int shift, len;
	
	c_fncall ();

	c_fnbegin ();
	if (size == BYTE) {
		mask = 0xff;
		len = 8;
	} else if (size == WORD) {
		mask = 0xffff;
		len = 16;
	} else {
		mask = 0xffffffff;
		len = 32;
	}

	c_readea (dest, buf);
	cln ("u32 val = (%s)%s;\n", c_usizes[size], buf);

	if (is_immediate (src)) {
		shift = src->imm.val;
		
		if (shift >= len) {
			cln ("X = %s;", (shift == len ? "val & 1" : "0"));
			ifC cln ("C = X;");
			cln ("val = 0;");
		} else {
			cln ("val <<= %d;", shift-1);
			cln ("X = (val & 0x%x);", 1<<(len-1));
			ifC cln ("C = X;");
			cln ("val <<= 1;");
			cln ("val &= 0x%x;", mask);
		}
	} else {
		c_readea (src, buf);
		cln ("s32 shift = %s & 63;", buf);
		cln ("if (shift >= %d) {", len);
		cln ("	X = (shift == %d ? val & 1 : 0);", len);
		ifC cln ("	C = X;");
		cln ("	val = 0;");
		cln ("} else if (shift == 0) {");
		ifC cln ("	C = 0;");
		cln ("} else {");
		cln ("	val <<= shift-1;");
		cln ("	X = (val & 0x%x);", 1<<(len-1));
		ifC cln ("	C = X;");
		cln ("	val <<= 1;");
		cln ("	val &= 0x%x;", mask);
		cln ("}");
	}

	ifZ cln ("nZ = ((%s)(val)) != 0;", c_ssizes[size]);
	ifN cln ("N = ((%s)(val)) < 0;", c_ssizes[size]);
	ifV cln ("V = 0;");
	
	c_writeea (dest, size, "val");
	c_postea (dest);
	c_postea (src);
	c_fnend ();
}
Exemple #5
0
/* src is the shift */
void c_func_asl (ea_t *src, ea_t *dest, int size)
{
	char buf[256];
	unsigned int mask;
	int shift, len;

	c_fncall ();

	c_fnbegin ();
	if (size == BYTE) {
		mask = 0xff;
		len = 8;
	} else if (size == WORD) {
		mask = 0xffff;
		len = 16;
	} else {
		mask = 0xffffffff;
		len = 32;
	}

	c_readea (dest, buf);
	cln ("u32 val = %s;\n", buf);

	if (is_immediate (src)) {
		/* mostly for the sake of -O0 compiles... */
		shift = src->imm.val;
		
		if (shift >= len) {
			ifV cln ("V = (val != 0);");
			cln ("X = %s;", (shift == len ? "val & 1" : "0"));
			ifC cln ("C = X;");
			cln ("val = 0;");
		} else {
			ifV cln ("u32 mask = (0x%x << (%d - %d)) & 0x%x;", mask, len-1, shift, mask);
			ifV cln ("V = (val & mask) != mask && (val & mask) != 0;");
			cln ("val <<= %d;", shift-1);
			cln ("X = (val & 0x%x);", 1<<(len-1));
			ifC cln ("C = (val & 0x%x);", 1<<(len-1));
			cln ("val <<= 1;");
		}
	} else {
		c_readea (src, buf);
		cln ("s32 src = %s & 63;", buf);
		cln ("if (src >= %d) {", len);
		ifV cln ("	V = (val != 0);");
		cln ("	X = (src == %d ? val & 1 : 0);", len);
		ifC cln ("C = X;");
		cln ("	val = 0;");
		cln ("} else if (src == 0) {");
		ifC cln ("	C = 0;");
		ifV cln ("	V = 0;");
		cln ("} else {");
		ifV cln ("	u32 mask = (0x%x << (%d - src)) & 0x%x;", mask, len-1, mask);
		ifV cln ("	V = (val & mask) != mask && (val & mask) != 0;");
		cln ("	val <<= src-1;");
		cln ("	X = (val & 0x%x);", 1<<(len-1));
		ifC cln ("	C = (val & 0x%x);", 1<<(len-1));
		cln ("	val <<= 1;");
		//cln ("	val &= 0x%x;", mask);
		cln ("}");
	}
	ifZ cln ("nZ = ((%s)(val)) != 0;", c_ssizes[size]);
	ifN cln ("N = ((%s)(val)) < 0;", c_ssizes[size]);
	
	c_writeea (dest, size, "val");
	c_postea (dest);
	c_postea (src);
	c_fnend ();
}
Exemple #6
0
void c_func_asr (ea_t *src, ea_t *dest, int size)
{
	char buf[256];
	unsigned int mask;
	int shift, len;

	c_fncall ();

	c_fnbegin ();
	if (size == BYTE) {
		mask = 0xff;
		len = 8;
	} else if (size == WORD) {
		mask = 0xffff;
		len = 16;
	} else {
		mask = 0xffffffff;
		len = 32;
	}

	c_readea (dest, buf);
	cln ("u32 val = (%s)%s;\n", c_usizes[size], buf);
	cln ("u32 sign = (0x%x & val) >> %d;", 1<<(len-1), len-1);

	if (is_immediate (src)) {
		shift = src->imm.val;

		if (shift >= len) {
			cln ("val = 0x%x & (u32)-sign;", mask);
			cln ("X = sign;");
			ifC cln ("C = X;");
		} else {
			cln ("val >>= %d;", shift-1);
			cln ("X = val & 1;");
			ifC cln ("C = X;");
			cln ("val >>= 1;");
			cln ("val |= (0x%x << %d) & (u32)-sign;", mask, len - shift);
		}
	} else {
		c_readea (src, buf);
		cln ("s32 src = %s & 63;", buf);
	
		cln ("if (src >= %d) {", len);
		cln ("	val = 0x%x & (u32)-sign;", mask);
		cln ("	X = sign;");
		ifC cln ("	C = X;");
		cln ("} else if (src == 0) {");
		ifC cln ("	C = 0;");
		cln ("} else {");
		cln ("	val >>= src - 1;");
		cln ("	X = val & 1;");
		ifC cln ("	C = X;");
		cln ("	val >>= 1;");
		cln ("	val |= (0x%x << (%d - src)) & (u32)-sign;", mask, len);
		//cln ("	val &= 0x%x;", mask);
		cln ("}");
	}
	ifZ cln ("nZ = ((%s)(val)) != 0;", c_ssizes[size]);
	ifN cln ("N = ((%s)(val)) < 0;", c_ssizes[size]);
	ifV cln ("V = 0;");
	
	c_writeea (dest, size, "val");
	c_postea (dest);
	c_postea (src);
	c_fnend ();
}
Exemple #7
0
 jint msw_bits() const {
   GUARANTEE(is_immediate() && type() == T_LONG,   "check");
   return (MSW_FIRST_FOR_LONG ? _low : _high);
 }
Exemple #8
0
 jlong   as_raw_long() const{
   GUARANTEE(is_immediate() && type() == T_DOUBLE,  "check");
   return *(jlong*)&_low;
 }
Exemple #9
0
 jint    as_raw_int() const {
   GUARANTEE(is_immediate() && type() == T_FLOAT,   "check");
   return _low;
 }
Exemple #10
0
 jdouble as_double() const  {
   GUARANTEE(is_immediate() && type() == T_DOUBLE, "check");
   return *(jdouble*)&_low;
 }
Exemple #11
0
 jfloat  as_float() const   {
   GUARANTEE(is_immediate() && type() == T_FLOAT,  "check");
   return *(jfloat*)(&_low);
 }
Exemple #12
0
 jlong  as_long(void) const    {
   GUARANTEE(is_immediate() && type() == T_LONG,   "check");
   return *(jlong*)&_low;
 }
/**
 * Process an instruction, and update the register values accordingly.
 */
static void
analyse_instruction(struct analysis_context *ctx,
                    struct tgsi_full_instruction *inst)
{
   struct lp_tgsi_info *info = ctx->info;
   struct lp_tgsi_channel_info (*regs)[4];
   unsigned max_regs;
   unsigned i;
   unsigned index;
   unsigned chan;

   for (i = 0; i < inst->Instruction.NumDstRegs; ++i) {
      const struct tgsi_dst_register *dst = &inst->Dst[i].Register;

      /*
       * Get the lp_tgsi_channel_info array corresponding to the destination
       * register file.
       */

      if (dst->File == TGSI_FILE_TEMPORARY) {
         regs = ctx->temp;
         max_regs = Elements(ctx->temp);
      } else if (dst->File == TGSI_FILE_OUTPUT) {
         regs = info->output;
         max_regs = Elements(info->output);
      } else if (dst->File == TGSI_FILE_ADDRESS ||
                 dst->File == TGSI_FILE_PREDICATE) {
         continue;
      } else {
         assert(0);
         continue;
      }

      /*
       * Detect direct TEX instructions
       */

      switch (inst->Instruction.Opcode) {
      case TGSI_OPCODE_TEX:
         analyse_tex(ctx, inst, LP_BLD_TEX_MODIFIER_NONE);
         break;
      case TGSI_OPCODE_TXD:
         analyse_tex(ctx, inst, LP_BLD_TEX_MODIFIER_EXPLICIT_DERIV);
         break;
      case TGSI_OPCODE_TXB:
         analyse_tex(ctx, inst, LP_BLD_TEX_MODIFIER_LOD_BIAS);
         break;
      case TGSI_OPCODE_TXL:
         analyse_tex(ctx, inst, LP_BLD_TEX_MODIFIER_EXPLICIT_LOD);
         break;
      case TGSI_OPCODE_TXP:
         analyse_tex(ctx, inst, LP_BLD_TEX_MODIFIER_PROJECTED);
         break;
      case TGSI_OPCODE_SAMPLE:
         analyse_sample(ctx, inst, LP_BLD_TEX_MODIFIER_NONE, FALSE);
         break;
      case TGSI_OPCODE_SAMPLE_C:
         analyse_sample(ctx, inst, LP_BLD_TEX_MODIFIER_NONE, TRUE);
         break;
      case TGSI_OPCODE_SAMPLE_C_LZ:
         analyse_sample(ctx, inst, LP_BLD_TEX_MODIFIER_LOD_ZERO, TRUE);
         break;
      case TGSI_OPCODE_SAMPLE_D:
         analyse_sample(ctx, inst, LP_BLD_TEX_MODIFIER_EXPLICIT_DERIV, FALSE);
         break;
      case TGSI_OPCODE_SAMPLE_B:
         analyse_sample(ctx, inst, LP_BLD_TEX_MODIFIER_LOD_BIAS, FALSE);
         break;
      case TGSI_OPCODE_SAMPLE_L:
         analyse_sample(ctx, inst, LP_BLD_TEX_MODIFIER_EXPLICIT_LOD, FALSE);
         break;
      default:
         break;
      }

      /*
       * Keep track of assignments and writes
       */

      if (dst->Indirect) {
         /*
          * It could be any register index so clear all register indices.
          */

         for (chan = 0; chan < 4; ++chan) {
            if (dst->WriteMask & (1 << chan)) {
               for (index = 0; index < max_regs; ++index) {
                  regs[index][chan].file = TGSI_FILE_NULL;
               }
            }
         }
      } else if (dst->Index < max_regs) {
         /*
          * Update this destination register value.
          */

         struct lp_tgsi_channel_info res[4];

         memset(res, 0, sizeof res);

         if (!inst->Instruction.Predicate &&
             !inst->Instruction.Saturate) {
            for (chan = 0; chan < 4; ++chan) {
               if (dst->WriteMask & (1 << chan)) {
                  if (inst->Instruction.Opcode == TGSI_OPCODE_MOV) {
                     analyse_src(ctx, &res[chan],
                                 &inst->Src[0].Register, chan);
                  } else if (inst->Instruction.Opcode == TGSI_OPCODE_MUL) {
                     /*
                      * Propagate values across 1.0 and 0.0 multiplications.
                      */

                     struct lp_tgsi_channel_info src0;
                     struct lp_tgsi_channel_info src1;

                     analyse_src(ctx, &src0, &inst->Src[0].Register, chan);
                     analyse_src(ctx, &src1, &inst->Src[1].Register, chan);

                     if (is_immediate(&src0, 0.0f)) {
                        res[chan] = src0;
                     } else if (is_immediate(&src1, 0.0f)) {
                        res[chan] = src1;
                     } else if (is_immediate(&src0, 1.0f)) {
                        res[chan] = src1;
                     } else if (is_immediate(&src1, 1.0f)) {
                        res[chan] = src0;
                     }
                  }
               }
            }
         }

         for (chan = 0; chan < 4; ++chan) {
            if (dst->WriteMask & (1 << chan)) {
               regs[dst->Index][chan] = res[chan];
            }
         }
      }
   }

   /*
    * Clear all temporaries information in presence of a control flow opcode.
    */

   switch (inst->Instruction.Opcode) {
   case TGSI_OPCODE_IF:
   case TGSI_OPCODE_UIF:
   case TGSI_OPCODE_ELSE:
   case TGSI_OPCODE_ENDIF:
   case TGSI_OPCODE_BGNLOOP:
   case TGSI_OPCODE_BRK:
   case TGSI_OPCODE_BREAKC:
   case TGSI_OPCODE_CONT:
   case TGSI_OPCODE_ENDLOOP:
   case TGSI_OPCODE_CALLNZ:
   case TGSI_OPCODE_CAL:
   case TGSI_OPCODE_BGNSUB:
   case TGSI_OPCODE_ENDSUB:
   case TGSI_OPCODE_SWITCH:
   case TGSI_OPCODE_CASE:
   case TGSI_OPCODE_DEFAULT:
   case TGSI_OPCODE_ENDSWITCH:
   case TGSI_OPCODE_RET:
   case TGSI_OPCODE_END:
      /* XXX: Are there more cases? */
      memset(&ctx->temp, 0, sizeof ctx->temp);
      memset(&info->output, 0, sizeof info->output);
   default:
      break;
   }
}
Exemple #14
0
/**
 * Prepares the stack for a 64-bit guest and places the arguments in the correct
 * register / stack locations.
 *
 * Arguments on 64-bit systems:
 * 		1st ARG: %RDI
 * 		2nd ARG: %RSI
 * 		3rd ARG: %RDX
 * 		4th ARG: %RCX
 * 		5th ARG: %R8
 * 		6th ARG: %R9
 * 		7th ARG - nth ARG: on stack from right to left
 *
 * @param inject The injection structure of the module that is injected.
 * @param virt_stack A pointer to the virtual address of the memory area
 *                   that was reserved for the stack of the module.
 */
void prepareStack64(struct kvm_vcpu *vcpu, struct injection *inject, u64 *virt_stack)
{
	u64 phys_stack = 0;
	struct x86_exception error;
	struct injection_arg *arg = NULL;
	unsigned int i = 0;
	int ret = 0;
	enum kvm_reg reg;

	// Do we actually have arguments?
	if (inject->args)
	{
		// Move all data to the stack that cannot be directly passed as an argument
		// such as strings and structures.
		for (i = 0; i < inject->args->argc; ++i)
		{
			arg = get_next_arg(inject, arg);

			if (!is_immediate(arg))
			{
				// Copy the data to the stack
				PRINT_DEBUG("Writing data of argument %d with type %d and size %d to 0x%llx\n",
							i, arg->type, arg->size, *virt_stack - arg->size);

				// Update address
				(*virt_stack) -= arg->size;
				arg->data_on_stack = (void *)(*virt_stack);

				// Write
				phys_stack = vcpu->arch.mmu.gva_to_gpa(vcpu, (*virt_stack), 0, &error);
				ret = kvm_write_guest(vcpu->kvm, phys_stack, get_arg_data(inject, arg), arg->size);

				if(ret < 0)
				{
					PRINT_ERROR("An error (code: %d) occurred while writing the argument %d to memory!\n",
								ret, i);
					return;
				}
			}
		}

		// Place arguments into the correct register / stack locations
		arg = NULL;
		for (i = inject->args->argc; i > 0 ; --i)
		{
			arg = get_prev_arg(inject, arg);

			if (i >= 7)
			{
				// Arg goes on the stack
				// ToDo: We just fix this to 8 byte here, but the size of the arg
				// may actually be shorter
				(*virt_stack) -= 8;
				phys_stack = vcpu->arch.mmu.gva_to_gpa(vcpu, (*virt_stack), 0, &error);

				if (is_immediate(arg))
				{
					PRINT_DEBUG("Writing argument %d with type %d and size %d to the stack 0x%llx\n",
								 i, arg->type, arg->size, *virt_stack);

					ret = kvm_write_guest(vcpu->kvm, phys_stack, get_arg_data(inject, arg), arg->size);
				}
				else
				{
					PRINT_DEBUG("Writing pointer 0x%lx to argument %d with type %d and size %d to the stack 0x%llx\n",
								(unsigned long)arg->data_on_stack, i, arg->type, arg->size, *virt_stack);
					ret = kvm_write_guest(vcpu->kvm, phys_stack, &arg->data_on_stack, 8);
				}

				if(ret < 0)
				{
					PRINT_ERROR("An error (code: %d) occurred while writing the argument %d "
								"to the stack!\n",
								ret, i);
					return;
				}
			}
			else
			{
				// Arg goes into a register
				switch (i)
				{
					case 1:
						reg = VCPU_REGS_RDI;
						break;
					case 2:
						reg = VCPU_REGS_RSI;
						break;
					case 3:
						reg = VCPU_REGS_RDX;
						break;
					case 4:
						reg = VCPU_REGS_RCX;
						break;
					case 5:
						reg = VCPU_REGS_R8;
						break;
					case 6:
						reg = VCPU_REGS_R9;
						break;
					default:
						PRINT_ERROR("Argument is not between one and six!\n");
				}

				if (is_immediate(arg))
				{
					PRINT_DEBUG("Writing argument %d with value 0x%lx, type %d, and size %d to register %d\n",
								 i, (unsigned long)arg->data, arg->type, arg->size, reg);
					kvm_register_write(vcpu, reg, *((unsigned long *)get_arg_data(inject, arg)));
				}
				else
				{
					PRINT_DEBUG("Writing pointer 0x%lx to argument %d with type %d and size %d to register %d\n",
								(unsigned long)arg->data_on_stack, i, arg->type, arg->size, reg);
					kvm_register_write(vcpu, reg, (unsigned long)arg->data_on_stack);
				}
			}
		}
	}

	// Add Offset to stack so the shellcode can operate
	(*virt_stack) -= STACK_AREA_SC ;

	// Place the original kernel pointer on the stack
	(*virt_stack) -= 8;

	// Write address of the original kernel stack on the new stack
	phys_stack = vcpu->arch.mmu.gva_to_gpa(vcpu, (*virt_stack), 0, &error);

	ret = kvm_write_guest(vcpu->kvm, phys_stack, &_XTIER_inject.regs.rsp, 8);
	kvm_register_write(vcpu, VCPU_REGS_RSP, (*virt_stack));
}