// This method is called while executing the raw bytecodes, so none of
  // the adjustments that BytecodeStream performs applies.
  void trace(methodHandle method, address bcp, uintptr_t tos, uintptr_t tos2) {
    MutexLocker ml(BytecodeTrace_lock);
    ResourceMark rm;
    if (_current_method != method()) {
      // Note 1: This code will not work as expected with true MT/MP.
      //         Need an explicit lock or a different solution.
      tty->cr();
      tty->print("[%d] ", (int) Thread::current()->osthread()->thread_id());
      method->print_name(tty);
      tty->cr();
      _current_method = method();
    }
    Bytecodes::Code code;
    if (is_wide()) {
      // bcp wasn't advanced if previous bytecode was _wide.
      code = Bytecodes::cast(*(bcp+1));
    } else {
      code = Bytecodes::cast(*bcp);
    }
    int bci = bcp - method->code_base();
    tty->print("[%d] ", (int) Thread::current()->osthread()->thread_id());
    if (Verbose) {
      tty->print("%8d  %4d  " INTPTR_FORMAT " " INTPTR_FORMAT " %s", 
	   BytecodeCounter::counter_value(), bci, tos, tos2, Bytecodes::name(code));
    } else {
      tty->print("%8d  %4d  %s", 
	   BytecodeCounter::counter_value(), bci, Bytecodes::name(code));
    }
    _next_pc = is_wide() ? bcp+2 : bcp+1;
    print_attributes(code, bci);
    // Set is_wide for the next one, since the caller of this doesn't skip
    // the next bytecode.
    _is_wide = (code == Bytecodes::_wide);
  }
Example #2
0
void BaseBytecodeStream::assert_raw_index_size(int size) const {
  if (raw_code() == Bytecodes::_invokedynamic && is_raw()) {
    // in raw mode, pretend indy is "bJJ__"
    assert(size == 2, "raw invokedynamic instruction has 2-byte index only");
  } else {
    bytecode()->assert_index_size(size, raw_code(), is_wide());
  }
}
 // Used for methodOop::print_codes().  The input bcp comes from
 // BytecodeStream, which will skip wide bytecodes.
 void trace(methodHandle method, address bcp, outputStream* st) {
   _current_method = method();
   ResourceMark rm;
   Bytecodes::Code code = Bytecodes::code_at(bcp);
   // Set is_wide
   _is_wide = (code == Bytecodes::_wide);
   if (is_wide()) {
     code = Bytecodes::code_at(bcp+1);
   }
   int bci = bcp - method->code_base();
   // Print bytecode index and name
   if (is_wide()) {
     st->print("%d %s_w", bci, Bytecodes::name(code));
   } else {
     st->print("%d %s", bci, Bytecodes::name(code));
   }
   _next_pc = is_wide() ? bcp+2 : bcp+1;
   print_attributes(code, bci, st);
   bytecode_epilog(bci, st);
 }
 // This method is called while executing the raw bytecodes, so none of
 // the adjustments that BytecodeStream performs applies.
 void trace(methodHandle method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) {
   ResourceMark rm;
   if (_current_method != method()) {
     // Note 1: This code will not work as expected with true MT/MP.
     //         Need an explicit lock or a different solution.
     // It is possible for this block to be skipped, if a garbage
     // _current_method pointer happens to have the same bits as
     // the incoming method.  We could lose a line of trace output.
     // This is acceptable in a debug-only feature.
     st->cr();
     st->print("[%ld] ", (long) Thread::current()->osthread()->thread_id());
     method->print_name(st);
     st->cr();
     _current_method = method();
   }
   Bytecodes::Code code;
   if (is_wide()) {
     // bcp wasn't advanced if previous bytecode was _wide.
     code = Bytecodes::code_at(method(), bcp+1);
   } else {
     code = Bytecodes::code_at(method(), bcp);
   }
   _code = code;
    int bci = bcp - method->code_base();
   st->print("[%ld] ", (long) Thread::current()->osthread()->thread_id());
   if (Verbose) {
     st->print("%8d  %4d  " INTPTR_FORMAT " " INTPTR_FORMAT " %s",
          BytecodeCounter::counter_value(), bci, tos, tos2, Bytecodes::name(code));
   } else {
     st->print("%8d  %4d  %s",
          BytecodeCounter::counter_value(), bci, Bytecodes::name(code));
   }
   _next_pc = is_wide() ? bcp+2 : bcp+1;
   print_attributes(bci);
   // Set is_wide for the next one, since the caller of this doesn't skip
   // the next bytecode.
   _is_wide = (code == Bytecodes::_wide);
   _code = Bytecodes::_illegal;
 }
Example #5
0
  void assert_index_size(int required_size) const {
#ifdef ASSERT
    int isize = instruction_size() - (is_wide() ? 1 : 0) - 1;
    if (isize == 2 &&  cur_bc() == Bytecodes::_iinc)
      isize = 1;
    else if (isize <= 2)
      ;                         // no change
    else if (has_giant_index())
      isize = 4;
    else
      isize = 2;
    assert(isize = required_size, "wrong index size");
#endif
  }
Example #6
0
// ------------------------------------------------------------------
// ciBytecodeStream::next_wide_or_table
//
// Special handling for switch ops
Bytecodes::Code ciBytecodeStream::next_wide_or_table(Bytecodes::Code bc) {
  switch (bc) {                // Check for special bytecode handling
  case Bytecodes::_wide:
    // Special handling for the wide bytcode
    // Get following bytecode; do not return wide
    assert(Bytecodes::Code(_pc[0]) == Bytecodes::_wide, "");
    bc = Bytecodes::java_code(_raw_bc = (Bytecodes::Code)_pc[1]);
    assert(Bytecodes::wide_length_for(bc) > 2, "must make progress");
    _pc += Bytecodes::wide_length_for(bc);
    _was_wide = _pc;              // Flag last wide bytecode found
    assert(is_wide(), "accessor works right");
    break;

  case Bytecodes::_lookupswitch:
    _pc++;                      // Skip wide bytecode
    _pc += (_start-_pc)&3;      // Word align
    _table_base = (jint*)_pc;   // Capture for later usage
                                // table_base[0] is default far_dest
    // Table has 2 lead elements (default, length), then pairs of u4 values.
    // So load table length, and compute address at end of table
    _pc = (address)&_table_base[2+ 2*Bytes::get_Java_u4((address)&_table_base[1])];
    break;

  case Bytecodes::_tableswitch: {
    _pc++;                      // Skip wide bytecode
    _pc += (_start-_pc)&3;      // Word align
    _table_base = (jint*)_pc;   // Capture for later usage
                                // table_base[0] is default far_dest
    int lo = Bytes::get_Java_u4((address)&_table_base[1]);// Low bound
    int hi = Bytes::get_Java_u4((address)&_table_base[2]);// High bound
    int len = hi - lo + 1;      // Dense table size
    _pc = (address)&_table_base[3+len]; // Skip past table
    break;
  }

  default:
    fatal("unhandled bytecode");
  }
  return bc;
}
 int       get_index_special()      { return (is_wide()) ? get_index_u2() : get_index_u1(); }
void BytecodePrinter::print_attributes(int bci, outputStream* st) {
  // Show attributes of pre-rewritten codes
  Bytecodes::Code code = Bytecodes::java_code(raw_code());
  // If the code doesn't have any fields there's nothing to print.
  // note this is ==1 because the tableswitch and lookupswitch are
  // zero size (for some reason) and we want to print stuff out for them.
  if (Bytecodes::length_for(code) == 1) {
    st->cr();
    return;
  }

  switch(code) {
    // Java specific bytecodes only matter.
    case Bytecodes::_bipush:
      st->print_cr(" " INT32_FORMAT, get_byte());
      break;
    case Bytecodes::_sipush:
      st->print_cr(" " INT32_FORMAT, get_short());
      break;
    case Bytecodes::_ldc:
      if (Bytecodes::uses_cp_cache(raw_code())) {
        print_constant(get_index_u1_cpcache(), st);
      } else {
        print_constant(get_index_u1(), st);
      }
      break;

    case Bytecodes::_ldc_w:
    case Bytecodes::_ldc2_w:
      if (Bytecodes::uses_cp_cache(raw_code())) {
        print_constant(get_index_u2_cpcache(), st);
      } else {
        print_constant(get_index_u2(), st);
      }
      break;

    case Bytecodes::_iload:
    case Bytecodes::_lload:
    case Bytecodes::_fload:
    case Bytecodes::_dload:
    case Bytecodes::_aload:
    case Bytecodes::_istore:
    case Bytecodes::_lstore:
    case Bytecodes::_fstore:
    case Bytecodes::_dstore:
    case Bytecodes::_astore:
      st->print_cr(" #%d", get_index_special());
      break;

    case Bytecodes::_iinc:
      { int index = get_index_special();
        jint offset = is_wide() ? get_short(): get_byte();
        st->print_cr(" #%d " INT32_FORMAT, index, offset);
      }
      break;

    case Bytecodes::_newarray: {
        BasicType atype = (BasicType)get_index_u1();
        const char* str = type2name(atype);
        if (str == NULL || atype == T_OBJECT || atype == T_ARRAY) {
          assert(false, "Unidentified basic type");
        }
        st->print_cr(" %s", str);
      }
      break;
    case Bytecodes::_anewarray: {
        int klass_index = get_index_u2();
        ConstantPool* constants = method()->constants();
        Symbol* name = constants->klass_name_at(klass_index);
        st->print_cr(" %s ", name->as_C_string());
      }
      break;
    case Bytecodes::_multianewarray: {
        int klass_index = get_index_u2();
        int nof_dims = get_index_u1();
        ConstantPool* constants = method()->constants();
        Symbol* name = constants->klass_name_at(klass_index);
        st->print_cr(" %s %d", name->as_C_string(), nof_dims);
      }
      break;

    case Bytecodes::_ifeq:
    case Bytecodes::_ifnull:
    case Bytecodes::_iflt:
    case Bytecodes::_ifle:
    case Bytecodes::_ifne:
    case Bytecodes::_ifnonnull:
    case Bytecodes::_ifgt:
    case Bytecodes::_ifge:
    case Bytecodes::_if_icmpeq:
    case Bytecodes::_if_icmpne:
    case Bytecodes::_if_icmplt:
    case Bytecodes::_if_icmpgt:
    case Bytecodes::_if_icmple:
    case Bytecodes::_if_icmpge:
    case Bytecodes::_if_acmpeq:
    case Bytecodes::_if_acmpne:
    case Bytecodes::_goto:
    case Bytecodes::_jsr:
      st->print_cr(" %d", bci + get_short());
      break;

    case Bytecodes::_goto_w:
    case Bytecodes::_jsr_w:
      st->print_cr(" %d", bci + get_int());
      break;

    case Bytecodes::_ret: st->print_cr(" %d", get_index_special()); break;

    case Bytecodes::_tableswitch:
      { align();
        int  default_dest = bci + get_int();
        int  lo           = get_int();
        int  hi           = get_int();
        int  len          = hi - lo + 1;
        jint* dest        = NEW_RESOURCE_ARRAY(jint, len);
        for (int i = 0; i < len; i++) {
          dest[i] = bci + get_int();
        }
        st->print(" %d " INT32_FORMAT " " INT32_FORMAT " ",
                      default_dest, lo, hi);
        int first = true;
        for (int ll = lo; ll <= hi; ll++, first = false)  {
          int idx = ll - lo;
          const char *format = first ? " %d:" INT32_FORMAT " (delta: %d)" :
                                       ", %d:" INT32_FORMAT " (delta: %d)";
          st->print(format, ll, dest[idx], dest[idx]-bci);
        }
        st->cr();
      }
      break;
    case Bytecodes::_lookupswitch:
      { align();
        int  default_dest = bci + get_int();
        int  len          = get_int();
        jint* key         = NEW_RESOURCE_ARRAY(jint, len);
        jint* dest        = NEW_RESOURCE_ARRAY(jint, len);
        for (int i = 0; i < len; i++) {
          key [i] = get_int();
          dest[i] = bci + get_int();
        };
        st->print(" %d %d ", default_dest, len);
        bool first = true;
        for (int ll = 0; ll < len; ll++, first = false)  {
          const char *format = first ? " " INT32_FORMAT ":" INT32_FORMAT :
                                       ", " INT32_FORMAT ":" INT32_FORMAT ;
          st->print(format, key[ll], dest[ll]);
        }
        st->cr();
      }
      break;

    case Bytecodes::_putstatic:
    case Bytecodes::_getstatic:
    case Bytecodes::_putfield:
    case Bytecodes::_getfield:
      print_field_or_method(get_index_u2_cpcache(), st);
      break;

    case Bytecodes::_invokevirtual:
    case Bytecodes::_invokespecial:
    case Bytecodes::_invokestatic:
      print_field_or_method(get_index_u2_cpcache(), st);
      break;

    case Bytecodes::_invokeinterface:
      { int i = get_index_u2_cpcache();
        int n = get_index_u1();
        get_byte();            // ignore zero byte
        print_field_or_method(i, st);
      }
      break;

    case Bytecodes::_invokedynamic:
      print_field_or_method(get_index_u4(), st);
      break;

    case Bytecodes::_new:
    case Bytecodes::_checkcast:
    case Bytecodes::_instanceof:
      { int i = get_index_u2();
        ConstantPool* constants = method()->constants();
        Symbol* name = constants->klass_name_at(i);
        st->print_cr(" %d <%s>", i, name->as_C_string());
      }
      break;

    case Bytecodes::_wide:
      // length is zero not one, but printed with no more info.
      break;

    default:
      ShouldNotReachHere();
      break;
  }
}
Example #9
0
 // Get a byte index following this bytecode.
 // If prefixed with a wide bytecode, get a wide index.
 int get_index() const {
   assert_index_size(is_wide() ? 2 : 1);
   return (_pc == _was_wide)   // was widened?
     ? Bytes::get_Java_u2(_bc_start+2) // yes, return wide index
     : _bc_start[1];           // no, return narrow index
 }
Example #10
0
//Dump LIR stmts stored in fu->lirList array.
void dump_lir2(LIR * lir, DexFile * df, INT pos)
{
	if (g_tfile == NULL || lir == NULL) return;
	if (pos < 0) {
		fprintf(g_tfile, "%s", LIR_name(lir));
	} else {
		fprintf(g_tfile, "(%dth)%s", pos, LIR_name(lir));
	}
	switch (LIR_opcode(lir)) {
	case LOP_NOP:
		break;
	case LOP_CONST:
		switch (LIR_dt(lir)) {
		case LIR_JDT_unknown:
			fprintf(g_tfile, ", INT");
			if (is_s4(LIR_int_imm(lir)) && LIR_res(lir) < 16) {
				//AB
				fprintf(g_tfile, ", v%d <- %d",
						LIR_res(lir), (INT)LIR_int_imm(lir));
			} else if (is_s16(LIR_int_imm(lir))) {
				//AABBBB
				fprintf(g_tfile, ", v%d <- %d",
						LIR_res(lir), (INT)LIR_int_imm(lir));
			} else {
				//AABBBBBBBB
				fprintf(g_tfile, ", v%d <- %d",
						LIR_res(lir), (INT)LIR_int_imm(lir));
			}
			break;
		case LIR_JDT_wide:
			fprintf(g_tfile, ", %s", get_dt_name(lir));
			if (is_swide16(LIR_int_imm(lir))) {
				//AABBBB
				fprintf(g_tfile, ", (v%d,v%d) <- %d",
						LIR_res(lir), LIR_res(lir) + 1, (INT)LIR_int_imm(lir));
			} else if (is_swide32(LIR_int_imm(lir))) {
				//AABBBBBBBB
				fprintf(g_tfile, ", (v%d,v%d) <- %d",
						LIR_res(lir), LIR_res(lir) + 1, (INT)LIR_int_imm(lir));
			} else {
				//AABBBBBBBBBBBBBBBB
				fprintf(g_tfile, ", (v%d,v%d) <- %lld",
						LIR_res(lir), LIR_res(lir) + 1, LIR_int_imm(lir));
			}
			break;
		default:
			/* It seems dex does not distinguish
			float and integer const. And regard float as
			32bit integer, double will be 64bit integer. */
			IS_TRUE0(0);
		}
		break;
	case LOP_RETURN:
		{
			switch (LIR_dt(lir)) {
			case LIR_JDT_unknown: //return preg.
				fprintf(g_tfile, ", INT");
				fprintf(g_tfile, ", v%d", LIR_res(lir));
				break;
			case LIR_JDT_void: //No return value.
				break;
			case LIR_JDT_object: //return object.
				fprintf(g_tfile, ", obj_ptr:v%d", LIR_res(lir));
				break;
			case LIR_JDT_wide:
				fprintf(g_tfile, ", %s", get_dt_name(lir));
				fprintf(g_tfile, ", (v%d,v%d)", LIR_res(lir), LIR_res(lir) + 1);
				break;
			default: IS_TRUE0(0);
			}
		}
		break;
	case LOP_THROW: //AA
		//Throws an exception object.
		//The reference of the exception object is in vx.
		fprintf(g_tfile, ", v%d", LIR_res(lir));
		break;
	case LOP_MONITOR_ENTER  :
		fprintf(g_tfile, ", v%d", LIR_res(lir));
		break;
	case LOP_MONITOR_EXIT   :
		break;
	case LOP_MOVE_RESULT    :
		{
			//Move function return value to regisiter.
			//AA
			LIRAOp * p = (LIRAOp*)lir;
			switch (LIR_dt(lir)) {
			case LIR_JDT_unknown: //lexOpcode = lc_mov_result32; break;
				fprintf(g_tfile, ", INT");
				fprintf(g_tfile, ", retval -> v%d", LIR_res(lir));
				break;
			case LIR_JDT_wide: //lexOpcode = lc_mov_result64; break;
				fprintf(g_tfile, ", %s", get_dt_name(lir));
				fprintf(g_tfile, ", retval -> (v%d,v%d)",
						LIR_res(lir), LIR_res(lir) + 1);
				break;
			case LIR_JDT_object: //lexOpcode = lc_mov_result_object; break;
				fprintf(g_tfile, ", obj-ptr");
				fprintf(g_tfile, ", retval -> v%d", LIR_res(lir));
				break;
			}
		}
		break;
	case LOP_MOVE_EXCEPTION : //AA
		fprintf(g_tfile, ", v%d", LIR_res(lir));
		break;
	case LOP_GOTO		    : //AABBBBBBBB
		{
			LIRGOTOOp * p = (LIRGOTOOp*)lir;
			fprintf(g_tfile, ", (lirIdx)%dth", p->target);
		}
		break;
	case LOP_MOVE		:
		switch (LIR_dt(lir)) {
		case LIR_JDT_unknown:
			fprintf(g_tfile, ", INT");
			if ((LIR_op0(lir) | LIR_res(lir)) < 16) {
				//AB
				fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
			} else if (LIR_res(lir) < 256) {
				//AABBBB
				fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
			} else {
				//AAAABBBB
				fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
			}
			break;
		case LIR_JDT_wide:
			fprintf(g_tfile, ", %s", get_dt_name(lir));
			if ((LIR_op0(lir) | LIR_res(lir)) < 16) {
				//AB
				fprintf(g_tfile, ", (v%d,v%d) <- (v%d,v%d)",
						LIR_res(lir), LIR_res(lir) + 1,
						LIR_op0(lir), LIR_op0(lir) + 1);
			} else if (LIR_res(lir) < 256) {
				//AABBBB
				fprintf(g_tfile, ", (v%d,v%d) <- (v%d,v%d)",
						LIR_res(lir), LIR_res(lir) + 1,
						LIR_op0(lir), LIR_op0(lir) + 1);
			} else {
				//AAAABBBB
				fprintf(g_tfile, ", (v%d,v%d) <- (v%d,v%d)",
						LIR_res(lir), LIR_res(lir) + 1,
						LIR_op0(lir), LIR_op0(lir) + 1);
			}
			break;
		case LIR_JDT_object:
			fprintf(g_tfile, ", obj-ptr");
			if ((LIR_op0(lir) | LIR_res(lir)) < 16) {
				//AB
				fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
			} else if (LIR_res(lir) < 256) {
				//AABBBB
				fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
			} else {
				//AAAABBBB
				fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
			}
			break;
		}
		break;
	case LOP_NEG        : //AB
	case LOP_NOT		: //AB
		fprintf(g_tfile, ", %s", get_dt_name(lir));
		if (is_wide(lir)) {
			fprintf(g_tfile, ", (v%d,v%d) <- (v%d,v%d)",
					LIR_res(lir), LIR_res(lir)+1, LIR_op0(lir), LIR_op0(lir)+1);
		} else {
			fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
		}
		break;
	case LOP_CONVERT	: //AB
		switch (LIR_dt(lir)) {
		case LIR_convert_i2l:
			fprintf(g_tfile, ", INT->LONG");
			fprintf(g_tfile, ", (v%d,v%d) <- v%d",
					LIR_res(lir), LIR_res(lir)+1, LIR_op0(lir));
			break;
		case LIR_convert_i2f: fprintf(g_tfile, ", INT->FLOAT");  break;
		case LIR_convert_i2d:
			fprintf(g_tfile, ", INT->DOUBLE");
			fprintf(g_tfile, ", (v%d,v%d) <- v%d",
					LIR_res(lir), LIR_res(lir)+1, LIR_op0(lir));
			break;
		case LIR_convert_l2i:
			fprintf(g_tfile, ", LONG->INT");
			fprintf(g_tfile, ", v%d <- (v%d,v%d)",
					LIR_res(lir), LIR_op0(lir), LIR_op0(lir)+1);
			break;
		case LIR_convert_l2f:
			fprintf(g_tfile, ", LONG->FLOAT");
			fprintf(g_tfile, ", v%d <- (v%d,v%d)",
					LIR_res(lir), LIR_op0(lir), LIR_op0(lir)+1);
			break;
		case LIR_convert_l2d:
			fprintf(g_tfile, ", LONG->DOUBLE");
			fprintf(g_tfile, ", (v%d,v%d) <- (v%d,v%d)",
					LIR_res(lir), LIR_res(lir)+1, LIR_op0(lir), LIR_op0(lir)+1);
			break;
		case LIR_convert_f2i: fprintf(g_tfile, ", FLOAT->INT");  break;
		case LIR_convert_f2l:
			fprintf(g_tfile, ", FLOAT->LONG");
			fprintf(g_tfile, ", (v%d,v%d) <- v%d",
					LIR_res(lir), LIR_res(lir)+1, LIR_op0(lir));
			break;
		case LIR_convert_f2d:
			fprintf(g_tfile, ", FLOAT->DOUBLE");
			fprintf(g_tfile, ", (v%d,v%d) <- v%d",
					LIR_res(lir), LIR_res(lir)+1, LIR_op0(lir));
			break;
		case LIR_convert_d2i:
			fprintf(g_tfile, ", DOUBLE->INT");
			fprintf(g_tfile, ", v%d <- (v%d,v%d)",
					LIR_res(lir), LIR_op0(lir), LIR_op0(lir)+1);
			break;
		case LIR_convert_d2l:
			fprintf(g_tfile, ", DOUBLE->LONG");
			fprintf(g_tfile, ", (v%d,v%d) <- (v%d,v%d)",
					LIR_res(lir), LIR_res(lir)+1, LIR_op0(lir), LIR_op0(lir)+1);
			break;
		case LIR_convert_d2f:
			fprintf(g_tfile, ", DOUBLE->FLOAT");
			fprintf(g_tfile, ", v%d <- (v%d,v%d)",
					LIR_res(lir), LIR_op0(lir), LIR_op0(lir)+1);
			break;
		case LIR_convert_i2b:
			fprintf(g_tfile, ", INT->BOOL");
			fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
			break;
		case LIR_convert_i2c:
			fprintf(g_tfile, ", INT->CHAR");
			fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
			break;
		case LIR_convert_i2s:
			fprintf(g_tfile, ", INT->SHORT");
			fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
			break;
		default:
			IS_TRUE0(0);
		}
		break;
	case LOP_ADD_ASSIGN :
	case LOP_SUB_ASSIGN :
	case LOP_MUL_ASSIGN :
	case LOP_DIV_ASSIGN :
	case LOP_REM_ASSIGN :
	case LOP_AND_ASSIGN :
	case LOP_OR_ASSIGN  :
	case LOP_XOR_ASSIGN :
	case LOP_SHL_ASSIGN :
	case LOP_SHR_ASSIGN :
	case LOP_USHR_ASSIGN:
		fprintf(g_tfile, ", %s", get_dt_name(lir));
		if (is_wide(lir)) {
			fprintf(g_tfile, ", (v%d,v%d) <- (v%d,v%d), (v%d,v%d)",
					LIR_res(lir), LIR_res(lir)+1,
					LIR_res(lir), LIR_res(lir)+1,
					LIR_op0(lir), LIR_op0(lir)+1);
		} else {
			fprintf(g_tfile, ", v%d <- v%d, v%d",
					LIR_res(lir), LIR_res(lir), LIR_op0(lir));
		}
		break;
	case LOP_ARRAY_LENGTH: //AABBBB
		//Calculates the number of elements of the array referenced by vy
		//and puts the length value into vx.
		fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
		break;
	case LOP_IFZ         :
		//AABBBB
		switch (LIR_dt(lir)) {
		case LIR_cond_EQ: fprintf(g_tfile, ", =="); break;
		case LIR_cond_NE: fprintf(g_tfile, ", !="); break;
		case LIR_cond_LT: fprintf(g_tfile, ", <"); break;
		case LIR_cond_GE: fprintf(g_tfile, ", >="); break;
		case LIR_cond_GT: fprintf(g_tfile, ", >"); break;
		case LIR_cond_LE: fprintf(g_tfile, ", <="); break;
		}
		if (is_wide(lir)) {
			fprintf(g_tfile, ", (v%d,v%d), 0, (lirIdx)%dth",
					LIR_res(lir), LIR_res(lir)+1, LIR_op0(lir));
		} else {
			fprintf(g_tfile, ", v%d, 0, (lirIdx)%dth",
					LIR_res(lir), LIR_op0(lir));
		}
		break;
	case LOP_NEW_INSTANCE:
		//AABBBB
		//LIR_op0(lir) is class-type-id, not class-declaration-id.
		IS_TRUE0(df);
		fprintf(g_tfile, ", (obj_ptr)v%d <- (clsname<%d>)%s",
				LIR_res(lir),
				LIR_op0(lir),
				get_class_name(df, LIR_op0(lir)));
		break;
	case LOP_CONST_STRING:
		//AABBBB or AABBBBBBBB
		IS_TRUE0(df);
		fprintf(g_tfile, ", v%d <- (strofst<%d>)\"%s\"",
				LIR_res(lir),
				LIR_op0(lir),
				dexStringById(df, LIR_op0(lir)));
		break;
	case LOP_CONST_CLASS :
		//AABBBB
		//const-class vx,type_id
		//Moves the class object of a class identified by
		//type_id (e.g. Object.class) into vx.
		fprintf(g_tfile, ", v%d <- (clsname<%d>)%s",
				LIR_res(lir),
				LIR_op0(lir),
				dexStringByTypeIdx(df, LIR_op0(lir)));
		break;
	case LOP_SGET        :
		//AABBBB
		fprintf(g_tfile, ", %s", get_dt_name(lir));
		IS_TRUE0(df);
		fprintf(g_tfile, ", v%d <- (ofst<%d>)%s::%s",
				LIR_res(lir),
				LIR_op0(lir),
				get_field_class_name(df, LIR_op0(lir)),
				get_field_name(df, LIR_op0(lir)));
		break;
	case LOP_CHECK_CAST  :
		//AABBBB
		IS_TRUE0(df);
		fprintf(g_tfile, ", v%d '%s'",
				LIR_res(lir),
				dexStringByTypeIdx(df, LIR_op0(lir)));
		break;
	case LOP_SPUT        :
		{
			//AABBBB
			LIRABOp * p = (LIRABOp*)lir;
			fprintf(g_tfile, ", %s", get_dt_name(lir));
			IS_TRUE0(df);
			if (is_wide(lir)) {
				fprintf(g_tfile, ", (v%d,v%d) -> %s::%s",
						LIR_res(lir), LIR_res(lir)+1,
						get_field_class_name(df, LIR_op0(lir)),
						get_field_name(df, LIR_op0(lir)));
			} else {
				fprintf(g_tfile, ", v%d -> %s::%s",
						LIR_res(lir),
						get_field_class_name(df, LIR_op0(lir)),
						get_field_name(df, LIR_op0(lir)));
			}
		}
		break;
	case LOP_APUT        :
		//AABBCC
		fprintf(g_tfile, ", %s", get_dt_name(lir));
		IS_TRUE0(df);
		if (is_wide(lir)) {
			fprintf(g_tfile, ", (v%d,v%d) -> (array_base_ptr)v%d, (array_elem)v%d",
					LIR_res(lir), LIR_res(lir)+1,
					LIR_op0(lir), (UINT)LIR_op1(lir));
		} else {
			fprintf(g_tfile, ", v%d -> (array_base_ptr)v%d, (array_elem)v%d",
					LIR_res(lir), LIR_op0(lir), (UINT)LIR_op1(lir));
		}
		break;
	case LOP_AGET      :
		//AABBCC
		fprintf(g_tfile, ", %s", get_dt_name(lir));
		IS_TRUE0(df);
		if (is_wide(lir)) {
			fprintf(g_tfile, ", (v%d,v%d) <- (array_base_ptr)v%d, (array_elem)v%d",
					LIR_res(lir), LIR_res(lir)+1,
					LIR_op0(lir), (UINT)LIR_op1(lir));
		} else {
			fprintf(g_tfile, ", v%d <- (array_base_ptr)v%d, (array_elem)v%d",
					LIR_res(lir), LIR_op0(lir), (UINT)LIR_op1(lir));
		}
		break;
	case LOP_CMPL      :
	case LOP_CMP_LONG  :
		//AABBCC
		IS_TRUE0(df);
		switch (LIR_dt(lir)) {
		case LIR_CMP_float:
			fprintf(g_tfile, ", FLOAT");
			fprintf(g_tfile, ", v%d, v%d, %d",
					LIR_res(lir), LIR_op0(lir), (UINT)LIR_op1(lir));
			break;
		case LIR_CMP_double:
			fprintf(g_tfile, ", DOUBLE");
			fprintf(g_tfile, ", (v%d,v%d), (v%d,v%d), %d",
					LIR_res(lir), LIR_res(lir)+1,
					LIR_op0(lir), LIR_op0(lir)+1,
					(UINT)LIR_op1(lir));
			break;
		default: IS_TRUE0(0);
		}
		break;
	case LOP_ADD       :
	case LOP_SUB       :
	case LOP_MUL       :
	case LOP_DIV       :
	case LOP_REM       :
	case LOP_AND       :
	case LOP_OR        :
	case LOP_XOR       :
	case LOP_SHL       :
	case LOP_SHR       :
	case LOP_USHR      :
		{
			fprintf(g_tfile, ", %s", get_dt_name(lir));
			LIRABCOp * p = (LIRABCOp*)lir;
			if (is_wide(lir)) {
				fprintf(g_tfile, ", (v%d,v%d) <- (v%d,v%d), (v%d,v%d)",
						LIR_res(lir), LIR_res(lir)+1,
						LIR_op0(lir), LIR_op0(lir)+1,
						(UINT)LIR_op1(lir), (UINT)LIR_op1(lir)+1);
			} else {
				fprintf(g_tfile, ", v%d <- v%d, v%d",
						LIR_res(lir), LIR_op0(lir), (UINT)LIR_op1(lir));
			}
		}
		break;
	case LOP_IF        :
		//ABCCCC
		switch (LIR_dt(lir)) {
		case LIR_cond_EQ: fprintf(g_tfile, ", =="); break;
		case LIR_cond_NE: fprintf(g_tfile, ", !="); break;
		case LIR_cond_LT: fprintf(g_tfile, ", <"); break;
		case LIR_cond_GE: fprintf(g_tfile, ", >="); break;
		case LIR_cond_GT: fprintf(g_tfile, ", >"); break;
		case LIR_cond_LE: fprintf(g_tfile, ", <="); break;
		}
		fprintf(g_tfile, ", v%d, v%d, (lirIdx)%dth",
				LIR_res(lir), LIR_op0(lir), (UINT)LIR_op1(lir));
		break;
	case LOP_ADD_LIT   : //AABBCC, AABBCCCC
	case LOP_SUB_LIT   : //AABBCC, AABBCCCC
	case LOP_MUL_LIT   : //AABBCC, AABBCCCC
	case LOP_DIV_LIT   : //AABBCC, AABBCCCC
	case LOP_REM_LIT   : //AABBCC, AABBCCCC
	case LOP_AND_LIT   : //AABBCC, AABBCCCC
	case LOP_OR_LIT    : //AABBCC, AABBCCCC
	case LOP_XOR_LIT   : //AABBCC, AABBCCCC
	case LOP_SHL_LIT   : //AABBCC
	case LOP_SHR_LIT   : //AABBCC
	case LOP_USHR_LIT   : //AABBCC
		{
			fprintf(g_tfile, ", %s", get_dt_name(lir));
			LIRABCOp * p = (LIRABCOp*)lir;
			if (is_wide(lir)) {
				fprintf(g_tfile, ", (v%d,v%d) <- (v%d,v%d),",
						LIR_res(lir), LIR_res(lir)+1,
						LIR_op0(lir), LIR_op0(lir)+1);
			} else {
				fprintf(g_tfile, ", v%d <- v%d,",
						LIR_res(lir), LIR_op0(lir));
			}

			if (is_s8((INT)LIR_op1(lir))) {
				//8bit imm
				fprintf(g_tfile, "(lit8)%d", (INT)LIR_op1(lir));
			} else if (is_s16((INT)LIR_op1(lir))) {
				//16bit imm
				fprintf(g_tfile, "(lit16)%d", (INT)LIR_op1(lir));
			} else {
				IS_TRUE0(0);
			}
		}
		break;
	case LOP_IPUT       :
		fprintf(g_tfile, ", %s", get_dt_name(lir));
		//ABCCCC
		IS_TRUE0(df);
		if (is_wide(lir)) {
			fprintf(g_tfile, ", (v%d,v%d) -> (obj_ptr)v%d, (ofst<%d>)%s::%s",
					LIR_res(lir), LIR_res(lir)+1,
					LIR_op0(lir), (UINT)LIR_op1(lir),
					get_field_class_name(df, (UINT)LIR_op1(lir)),
					get_field_name(df, (UINT)LIR_op1(lir)));
		} else {
			fprintf(g_tfile, ", v%d -> (obj_ptr)v%d, (ofst<%d>)%s::%s",
					LIR_res(lir),
					LIR_op0(lir),
					(UINT)LIR_op1(lir),
					get_field_class_name(df, (UINT)LIR_op1(lir)),
					get_field_name(df, (UINT)LIR_op1(lir)));
		}
		break;
	case LOP_IGET       :
		fprintf(g_tfile, ", %s", get_dt_name(lir));
		//ABCCCC
		IS_TRUE0(df);
		if (is_wide(lir)) {
			fprintf(g_tfile, ", (v%d,v%d) <- (obj_ptr)v%d, (ofst<%d>)%s::%s",
					LIR_res(lir), LIR_res(lir)+1,
					LIR_op0(lir),
					(UINT)LIR_op1(lir),
					get_field_class_name(df, (UINT)LIR_op1(lir)),
					get_field_name(df, (UINT)LIR_op1(lir)));
		} else {
			fprintf(g_tfile, ", v%d <- (obj_ptr)v%d, (ofst<%d>)%s::%s",
					LIR_res(lir),
					LIR_op0(lir),
					(UINT)LIR_op1(lir),
					get_field_class_name(df, (UINT)LIR_op1(lir)),
					get_field_name(df, (UINT)LIR_op1(lir)));
		}
		break;
	case LOP_INSTANCE_OF:
		fprintf(g_tfile, ", (pred)v%d <- v%d, (clsname<%d>)'%s'",
				LIR_res(lir),
				LIR_op0(lir),
				(UINT)LIR_op1(lir),
				dexStringByTypeIdx(df, (UINT)LIR_op1(lir)));
		break;
	case LOP_NEW_ARRAY  :
		//ABCCCC
		//new-array v%d(res) <- v%d(op0), LCAnimal(op1)
		fprintf(g_tfile, ", %s", get_dt_name(lir));
		//ABCCCC
		IS_TRUE0(df);
		fprintf(g_tfile, ", v%d <- (num_of_elem)v%d, (elem_type<%d>)'%s'",
				LIR_res(lir),
				LIR_op0(lir),
				(UINT)LIR_op1(lir),
				dexStringByTypeIdx(df, (UINT)LIR_op1(lir)));
		break;
	case LOP_TABLE_SWITCH:
		{
			LIRSwitchOp * p = (LIRSwitchOp*)lir;
			IS_TRUE0(LIR_dt(p) == 0x1);
			fprintf(g_tfile, ", v%d", p->value);
			USHORT * pdata = p->data;

			//data[0]: flag to indicate switch-table type:
			//	0x1 TABLE_SWITCH, 0x2 LOOKUP_SWITCH
			USHORT f = pdata[0];
			IS_TRUE0(f == 0x100);
			//data[1]: the number of CASE entry.
			USHORT num_of_case = pdata[1];

			//data[2..3]: the base value of case-table
			UINT base_val = *((UINT*)(&pdata[2]));
			fprintf(g_tfile, ", basev:%d", base_val);

			//((BYTE*)data)[4..num_of_case*4]:
			//	the position of the index table is at current instruction.
			if (num_of_case > 0) {
				UINT * pcase_entry = (UINT*)&pdata[4];
				fprintf(g_tfile, " tgtidx:");
				for (USHORT i = 0; i < num_of_case; i++) {
					UINT idx_of_insn = pcase_entry[i];
					fprintf(g_tfile, "%d", idx_of_insn);
					if (i != num_of_case - 1) {
						fprintf(g_tfile, ",");
					}
				}
			}
		}
		break;
	case LOP_LOOKUP_SWITCH:
		{
			LIRSwitchOp * p = (LIRSwitchOp*)lir;
			IS_TRUE0(LIR_dt(p) == 0x2);
			fprintf(g_tfile, ", v%d", p->value);
			USHORT * pdata = p->data;

			//pdata[0]: flag to indicate switch-table type:
			//	0x1 TABLE_SWITCH, 0x2 LOOKUP_SWITCH
			UINT f = pdata[0];
			IS_TRUE0(f == 0x200);

			//pdata[1]: the number of CASE entry.
			UINT num_of_case = pdata[1];
			if (num_of_case > 0) {
				BYTE * tp = (BYTE*)pdata;
				//((BYTE*)pdata)[4..4+num_of_case*4-1]: the case-value buffer.
				UINT * pcase_value = (UINT*)&tp[4];

				//((BYTE*)pdata)[4+num_of_case*4, 4+num_of_case*8-1]:
				//	the position of the index table is at current instruction.
				UINT * pcase_entry = (UINT*)&tp[4 + num_of_case * 4];
				fprintf(g_tfile, " val2idx(");
				for (UINT i = 0; i < num_of_case; i++) {
					UINT idx_of_insn = pcase_entry[i];
					fprintf(g_tfile, "%d:%d", pcase_value[i], idx_of_insn);
					if (i != num_of_case - 1) {
						fprintf(g_tfile, ",");
					}
				}
				fprintf(g_tfile, ")");
			}
		}
		break;
	case LOP_FILL_ARRAY_DATA:
		{
			fprintf(g_tfile, ", %s", get_dt_name(lir));
			//AABBBBBBBB
			//pdata[0]: the magic number of code
			//0x100 PACKED_SWITCH, 0x200 SPARSE_SWITCH, 0x300 FILL_ARRAY_DATA
			LIRSwitchOp * r = (LIRSwitchOp*)lir;
			UInt16 const* pdata = (UInt16 const*)r->data;
			IS_TRUE0(pdata[0] == 0x300);
			//pdata[1]: size of each element.
			//pdata[2]: the number of element.
			UINT size_of_elem = pdata[1];
			UINT num_of_elem = pdata[2];
			UINT data_size = num_of_elem * size_of_elem;
			//fprintf(g_tfile, ", (elem_sz<%d>), (elem_num<%d>), (data_ptr)0x%x",
			fprintf(g_tfile, ", (elem_sz<%d>), (elem_num<%d>)",
					size_of_elem, num_of_elem);
		}
		break;
	case LOP_INVOKE:
		{
			/*
			ABCCCCDDDD the layout clarifies:
				A(p4), B(argc), CCCC(method_id), DDDD(p0, p1, p2, p3)
				where p0,p1,p2,p3,p4 are five parameters.

			AABBBBCCCC the layout clarifies:
				AA(argc), BBBB(method_id), CCCC(p0,p1,...p(argc-1))
			*/
			LIRInvokeOp * r = (LIRInvokeOp*)lir;
			UINT flags = LIR_dt(lir);
			UINT flag1 = flags & 0x0F;
			UINT flag2 = flags & 0xF0;
			IS_TRUE(flag1 != 0, ("means LIR is LOP_FILLED_NEW_ARRAY"));
			DexMethodId const* method_id = dexGetMethodId(df, r->ref);
			IS_TRUE0(method_id);
			CHAR const* method_name = dexStringById(df, method_id->nameIdx);
			CHAR const* class_name =
				dexStringByTypeIdx(df, method_id->classIdx);
			IS_TRUE0(method_name);
			DexProtoId const* proto_id =
				dexGetProtoId(df, method_id->protoIdx);
			CHAR const* shorty_name = dexStringById(df, proto_id->shortyIdx);
			fprintf(g_tfile, ", %s::%s", class_name, method_name);

			UINT k = LIR_dt(lir);
			bool is_range = HAVE_FLAG((k & 0xf0), LIR_Range);
			if (is_range) {
				switch (k & 0x0f) {
				case LIR_invoke_unknown: IS_TRUE0(0); break;
				case LIR_invoke_virtual:
					fprintf(g_tfile, ", virtual-range"); break;
				case LIR_invoke_direct:
					fprintf(g_tfile, ", direct-range"); break;
				case LIR_invoke_super:
					fprintf(g_tfile, ", super-range"); break;
				case LIR_invoke_interface:
					fprintf(g_tfile, ", interface-range"); break;
				case LIR_invoke_static:
					fprintf(g_tfile, ", static-range"); break;
				default: IS_TRUE0(0);
				}
			} else {
				switch (k & 0x0f) {
				case LIR_invoke_unknown: IS_TRUE0(0); break;
				case LIR_invoke_virtual:
					fprintf(g_tfile, ", virtual"); break;
				case LIR_invoke_direct:
					fprintf(g_tfile, ", direct"); break;
				case LIR_invoke_super:
					fprintf(g_tfile, ", super"); break;
				case LIR_invoke_interface:
					fprintf(g_tfile, ", interface"); break;
				case LIR_invoke_static:
					fprintf(g_tfile, ", static"); break;
				default: IS_TRUE0(0);
				}
			}

			if (r->argc != 0) {
				fprintf(g_tfile, ", arg(");
				for (USHORT i = 0; i < r->argc; i++) {
					fprintf(g_tfile, "v%d", r->args[i]);
					if (i != r->argc-1) {
						fprintf(g_tfile, ",");
					}
				}
				fprintf(g_tfile, ")");
			}
		}
		break;
	case LOP_FILLED_NEW_ARRAY:
		{
			/*
			AABBBBCCCC or ABCCCCDEFG
			e.g:
				A(argc), B,D,E,F,G(parampters), CCCC(class_tyid)
			*/
			LIRInvokeOp * r = (LIRInvokeOp*)lir;
			UINT flags = LIR_dt(lir);
			CHAR const* class_name = dexStringByTypeIdx(df, r->ref);
			IS_TRUE0(class_name);
			fprintf(g_tfile, ", %s", class_name);
			if (r->argc != 0) {
				fprintf(g_tfile, ", arg(");
				for (USHORT i = 0; i < r->argc; i++) {
					fprintf(g_tfile, "v%d", r->args[i]);
					if (i != r->argc-1) {
						fprintf(g_tfile, ",");
					}
				}
				fprintf(g_tfile, ")");
			}
		}
		break;
	case LOP_CMPG:
		//AABBCC
		IS_TRUE0(df);
		switch (LIR_dt(lir)) {
		case LIR_CMP_float:
			fprintf(g_tfile, ", FLOAT");
			fprintf(g_tfile, ", v%d, v%d, %d",
					LIR_res(lir),
					LIR_op0(lir),
					(INT)LIR_op1(lir));
			break;
		case LIR_CMP_double:
			fprintf(g_tfile, ", DOUBLE");
			fprintf(g_tfile, ", (v%d,v%d), v%d, %d",
					LIR_res(lir), LIR_res(lir)+1,
					LIR_op0(lir),
					(INT)LIR_op1(lir));
			break;
		default: IS_TRUE0(0);
		}
		break;
	case LOP_PHI:
		IS_TRUE0(0);
		break;
	default: IS_TRUE0(0);
	} //end switch
	fflush(g_tfile);
}
 int       get_index_special()      { return (is_wide()) ? get_big_index() : get_index(); }
Example #12
0
 void assert_wide(bool require_wide) const {
   if (require_wide)
        { assert(is_wide(),  "must be a wide instruction"); }
   else { assert(!is_wide(), "must not be a wide instruction"); }
 }