Example #1
0
File: class.c Project: botvs/LoadSo
void Init_Class() {
  dummy_proc = rb_eval_string("$__loadso__dummy_proc = proc{}");
  rb_mod_define_method = get_method(rb_cObject, "define_method");
  rb_mod_public = get_method(rb_cObject, "public");
  rb_mod_private = get_method(rb_cObject, "private");
  rb_obj_singleton_class = get_global_func("singleton_class");
  rb_obj_is_kind_of_ = get_global_func("kind_of?");
  rb_mod_append_features = get_instance_method(rb_cModule, "append_features");
  rb_mod_name = get_instance_method(rb_cModule, "name");
  rb_mod_alias_method = get_instance_method(rb_cModule, "alias_method");
  rb_class_new_instance_ = get_method(rb_cObject, "new");
  obj_respond_to = get_global_func("respond_to?");
  rb_obj_class_ = get_instance_method(rb_mKernel, "class");
  rb_obj_clone_ = get_instance_method(rb_mKernel, "clone");
}
void remove_virtual_functionst::get_functions(
  const exprt &function,
  functionst &functions)
{
  const irep_idt class_id=function.get(ID_C_class);
  const irep_idt component_name=function.get(ID_component_name);
  assert(!class_id.empty());

  // iterate over all children, transitively
  std::vector<irep_idt> children=
    class_hierarchy.get_children_trans(class_id);

  for(const auto & child : children)
  {
    exprt method=get_method(child, component_name);
    if(method.is_not_nil())
    {
      functiont function;
      function.class_id=child;
      function.symbol_expr=to_symbol_expr(method);
      function.symbol_expr.set(ID_C_class, child);
      functions.push_back(function);
    }
  }

  // Start from current class, go to parents until something
  // is found.
  irep_idt c=class_id;
  while(!c.empty())
  {
    exprt method=get_method(c, component_name);
    if(method.is_not_nil())
    {
      functiont function;
      function.class_id=c;
      function.symbol_expr=to_symbol_expr(method);
      function.symbol_expr.set(ID_C_class, c);
      functions.push_back(function);
      break; // abort
    }

    const class_hierarchyt::idst &parents=
      class_hierarchy.class_map[c].parents;

    if(parents.empty()) break;
    c=parents.front();
  }
}
Example #3
0
TEST_F(PreVerify, InlineCallerTryCalleeIfThrows) {
  auto cls = find_class_named(
    classes, "Lcom/facebook/redexinline/InlineTest;");
  auto m = find_vmethod_named(*cls, "testCallerTryCalleeIfThrows");
  auto invoke = find_invoke(m, OPCODE_INVOKE_DIRECT, "throwsInIf");
  ASSERT_NE(nullptr, invoke);

  // verify that the callee has an if-else statement, and that the if block
  // (which throws an exception) comes before the return opcode
  auto callee_insns = invoke->get_method()->get_code()->get_instructions();
  auto ifop = std::find_if(callee_insns.begin(), callee_insns.end(),
    [](DexInstruction* insn) {
      return insn->opcode() == OPCODE_IF_NEZ;
    });
  ASSERT_NE(callee_insns.end(), ifop);
  auto retop = std::find_if(callee_insns.begin(), callee_insns.end(),
    [](DexInstruction* insn) {
      return insn->opcode() == OPCODE_RETURN_VOID;
    });
  ASSERT_NE(callee_insns.end(), retop);
  auto invoke_throw =
    find_invoke(ifop, retop, OPCODE_INVOKE_VIRTUAL, "wrapsThrow");
  ASSERT_NE(nullptr, invoke_throw);

  auto& code = m->get_code();
  ASSERT_EQ(code->get_tries().size(), 1);
}
Example #4
0
int
allium_ptcfg_bind_addr(const allium_ptcfg *cfg, const char *method, struct
    sockaddr *addr, socklen_t *addr_len)
{
	struct allium_ptcfg_method_s *m;

	if ((NULL == cfg) || (NULL == method) || (NULL == addr_len))
		return (ALLIUM_ERR_INVAL);

	if (!cfg->is_server)
		return (ALLIUM_ERR_PTCFG_NOT_SERVER);

	m = get_method(cfg, method);
	if (NULL == m)
		return (ALLIUM_ERR_PTCFG_INVALID_METHOD);

	if ((NULL == addr) || (*addr_len < m->bind_addr_len)) {
		*addr_len = m->bind_addr_len;
		return (ALLIUM_ERR_NOBUFS);
	}
	if (!m->has_bind_addr) {
		*addr_len = 0;
		return (ALLIUM_ERR_PTCFG_NO_ADDRESS);
	}
	memcpy(addr, &m->bind_addr, m->bind_addr_len);
	*addr_len = m->bind_addr_len;

	return (0);
}
Example #5
0
size_t delete_methods(
    std::vector<DexClass*>& scope, std::unordered_set<DexMethod*>& removable,
    std::function<DexMethod*(DexMethod*, MethodSearch search)> resolver) {

  // if a removable candidate is invoked do not delete
  walk_opcodes(scope, [](DexMethod* meth) { return true; },
      [&](DexMethod* meth, DexInstruction* insn) {
        if (is_invoke(insn->opcode())) {
          const auto mop = static_cast<DexOpcodeMethod*>(insn);
          auto callee = resolver(mop->get_method(), opcode_to_search(insn));
          if (callee != nullptr) {
            removable.erase(callee);
          }
        }
      });

  size_t deleted = 0;
  for (auto callee : removable) {
    if (!callee->is_concrete()) continue;
    if (do_not_strip(callee)) continue;
    auto cls = type_class(callee->get_class());
    always_assert_log(cls != nullptr,
        "%s is concrete but does not have a DexClass\n",
        SHOW(callee));
    if (callee->is_virtual()) {
      cls->get_vmethods().remove(callee);
    } else {
      cls->get_dmethods().remove(callee);
    }
    deleted++;
    TRACE(DELMET, 4, "removing %s\n", SHOW(callee));
  }
  return deleted;
}
Example #6
0
int
allium_ptcfg_method_requested(const allium_ptcfg *cfg, const char *method)
{
	if ((NULL == cfg) || (NULL == method))
		return (ALLIUM_ERR_INVAL);

	return (NULL != get_method(cfg, method));
}
Example #7
0
  Method* Profiler::enter_method(Env* env, robject recv, rsymbol name, rmodule mod,
                                 rmethod cm)
  {
    if(env->module_is_metaclass(mod)) {
      robject attached = env->metaclass_attached_instance(mod);

      rmodule as_module = env->cast_to_rmodule(attached);
      if(as_module) {
        return get_method(env, cm, name, env->module_name(as_module), kSingleton);
      } else {
        rstring str = env->to_s(mod);
        return get_method(env, cm, name, env->string_to_symbol(str), kSingleton);
      }
    } else {
      return get_method(env, cm, name, env->module_name(mod), kNormal);
    }
  }
Example #8
0
static void init_qtree(DATA *d) {
/*
 * Initialize the root of the search tree:
 * Since this is called from qtree_quick_select(), we know allready
 * quite a lot. This helps choosing sensible values for the 
 * top level bbox origin and size.
 */
 	const GRIDMAP *gt = NULL;
 	DATA *simlocs = NULL;
 	int i, mode;
 	BBOX bbox;

	if (is_simulation(get_method())) {
		/*
		 * sequential simulation: the simulation path (through DATA or GRIDMAP)
		 * will make up for (most of) the search locations:
		 */
		gt = (const GRIDMAP *) NULL;
		simlocs = get_dataval();
		/* in case of simulation one of them will be non-NULL */
	} 

	/* get initial estimate for top level bbox: */
	if (gt != NULL)
		bbox = bbox_from_grid(gt, NULL);
	else if (simlocs != NULL) {
		bbox = bbox_from_data(simlocs);
		if (bbox.size <= 0.0)
			bbox = bbox_from_data(d);
	} else
		bbox = bbox_from_data(d);
	if (bbox.size <= 0.0)
		bbox = bbox_from_data(get_dataval());
	if (bbox.size <= 0.0)
		ErrMsg(ER_IMPOSVAL, "bbox with zero size: remove neighbourhood settings?");
	init_qnode(&(d->qtree_root), d->n_list < gl_split, bbox); /* ML1 */
	
	mode = bbox.mode;

	for (i = 0; i < d->n_list; i++)
		qtree_push_point(d, d->list[i]); /* now they won't be rejected */ /* ML2 */

	if (DEBUG_DUMP) {
		printlog("top level search tree statistics for data(%s):\n",
			name_identifier(d->id));
		printlog("bounding box origin [");
		if (mode & X_BIT_SET)
			printlog("%g", d->qtree_root->bb.x);
		if (mode & Y_BIT_SET)
			printlog(",%g", d->qtree_root->bb.y);
		if (mode & Z_BIT_SET)
			printlog(",%g", d->qtree_root->bb.z);
		printlog("]; dimension %g\n", d->qtree_root->bb.size);
	}
	/* qtree_print(d); */
	return;
}
Example #9
0
VALUE *VALUE::send(char *method, int argc, VALUE *argv) {
  rd_method *meth = get_method(method);
  if(meth) {
    return meth->perform(argc, argv, argv);
  }

  printf("Undefined variable or method: `%s' for :%s (NameError)\n", method, name);
  exit(1);
}
Example #10
0
GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method) {

	MonoMethodSignature *sig = mono_method_signature(p_raw_method);

	int params_count = mono_signature_get_param_count(sig);
	StringName method_name = mono_method_get_name(p_raw_method);

	return get_method(p_raw_method, method_name, params_count);
}
void spec_uncompress(int in, int out, int lev) {
    level=lev;
    part_nb=0;
    clear_bufs();
    ifd=in;
    ofd=out;
    method = get_method(1);
    unzip(ifd,ofd);
}
/* function returns method of given name or NULL if not found */
const struct method *get_interface_method(const char *iname,
							const char *mname)
{
	const struct interface *iface = get_interface(iname);

	if (iface == NULL)
		return NULL;

	return get_method(iface->methods, mname);
}
Example #13
0
GDMonoMethod *GDMonoClass::get_method_with_desc(const String &p_description, bool p_include_namespace) {

	MonoMethodDesc *desc = mono_method_desc_new(p_description.utf8().get_data(), p_include_namespace);
	MonoMethod *method = mono_method_desc_search_in_class(desc, mono_class);
	mono_method_desc_free(desc);

	ERR_FAIL_COND_V(mono_method_get_class(method) != mono_class, NULL);

	return get_method(method);
}
Example #14
0
static SCM api_get_method(SCM s_)
{
  servlet *s = scm_to_pointer(s_);
  const char *method = get_method(s);
  if (method)
  {
    return scm_from_utf8_string(method);
  }
  return SCM_UNSPECIFIED;
}
Example #15
0
TEST_F(PreVerify, InlineInvokeDirect) {
  auto cls = find_class_named(
    classes, "Lcom/facebook/redexinline/InlineTest;");
  auto m = find_vmethod_named(*cls, "testInlineInvokeDirect");
  auto invoke =
      find_invoke(m, OPCODE_INVOKE_DIRECT, "hasNoninlinableInvokeDirect");
  auto noninlinable_invoke_direct =
      find_invoke(invoke->get_method(), OPCODE_INVOKE_DIRECT, "noninlinable");
  auto noninlinable = noninlinable_invoke_direct->get_method();
  ASSERT_EQ(show(noninlinable->get_proto()), "()V");

  // verify that there are two inlinable() methods in the class. The static
  // version exists to test that we don't cause a signature collision when we
  // make the instance method static.
  auto dmethods = cls->get_dmethods();
  ASSERT_EQ(2,
            std::count_if(dmethods.begin(), dmethods.end(), [](DexMethod* m) {
              return !strcmp("noninlinable", m->get_name()->c_str());
            }));
}
Example #16
0
static
jobject get_module_loader(JNIEnv *env, jobject module) {
    static jmethodID cl_method = NULL;
    jobject loader = NULL;

    if (cl_method == NULL) {
        cl_method = get_method(env, jlrM(env), "getClassLoader", "()Ljava/lang/ClassLoader;");
    }
    loader = (jobject)JNI_ENV_PTR(env)->CallObjectMethod(JNI_ENV_ARG(env, module), cl_method);
    return loader;
}
Example #17
0
steering_vector* create_steering_vector(std::string steering_string)
{
	steering_vector* sv = NULL;
	// check whether a steering vector is to be used and set up the class if it is
	std::string steering = get_method(steering_string);
	// determine which (inherited) steering class to use
	if (steering == "geostrophic")
		sv = new geo_wind_vector();
	else if (steering != "")
		throw (std::string("Unknown steering vector method: " + steering));
	// note - this function can return NULL if the steering string is empty
	return sv;
}
Example #18
0
void analyze_invoke(cfg::InstructionIterator it, Environment* env) {
  auto insn = it->insn;
  DexMethodRef* ref = insn->get_method();
  if (ref->get_name()->str() == "ordinal") {
    // All methods named `ordinal` is overly broad, but we throw out false
    // positives later
    Info info;
    info.invoke = it;
    env->set(RESULT_REGISTER, Domain(info));
  } else {
    analyze_default(it, env);
  }
}
Example #19
0
void MultiMethodInliner::inline_callees(
    InlineContext& inline_context, std::vector<DexMethod*>& callees) {
  size_t found = 0;
  auto caller = inline_context.caller;
  auto insns = caller->get_code()->get_instructions();

  // walk the caller opcodes collecting all candidates to inline
  // Build a callee to opcode map
  std::vector<std::pair<DexMethod*, DexOpcodeMethod*>> inlinables;
  for (auto insn = insns.begin(); insn != insns.end(); ++insn) {
    if (!is_invoke((*insn)->opcode())) continue;
    auto mop = static_cast<DexOpcodeMethod*>(*insn);
    auto callee = resolver(mop->get_method(), opcode_to_search(*insn));
    if (callee == nullptr) continue;
    if (std::find(callees.begin(), callees.end(), callee) == callees.end()) {
      continue;
    }
    always_assert(callee->is_concrete());
    found++;
    inlinables.push_back(std::make_pair(callee, mop));
    if (found == callees.size()) break;
  }
  if (found != callees.size()) {
    always_assert(found <= callees.size());
    info.not_found += callees.size() - found;
  }

  // attempt to inline all inlinable candidates
  for (auto inlinable : inlinables) {
    auto callee = inlinable.first;
    auto mop = inlinable.second;

    if (!is_inlinable(callee, caller)) continue;

    auto op = mop->opcode();
    if (is_invoke_range(op)) {
      info.invoke_range++;
      continue;
    }

    TRACE(MMINL, 4, "inline %s (%d) in %s (%d)\n",
        SHOW(callee), caller->get_code()->get_registers_size(),
        SHOW(caller),
        callee->get_code()->get_registers_size() -
        callee->get_code()->get_ins_size());
    change_visibility(callee);
    MethodTransform::inline_16regs(inline_context, callee, mop);
    info.calls_inlined++;
    inlined.insert(callee);
  }
}
void remove_virtual_functionst::get_functions(
  const exprt &function,
  functionst &functions)
{
  const irep_idt class_id=function.get(ID_C_class);
  const irep_idt component_name=function.get(ID_component_name);
  assert(!class_id.empty());
  functiont root_function;

  // Start from current class, go to parents until something
  // is found.
  irep_idt c=class_id;
  while(!c.empty())
  {
    exprt method=get_method(c, component_name);
    if(method.is_not_nil())
    {
      root_function.class_id=c;
      root_function.symbol_expr=to_symbol_expr(method);
      root_function.symbol_expr.set(ID_C_class, c);
      break; // abort
    }

    const class_hierarchyt::idst &parents=
      class_hierarchy.class_map[c].parents;

    if(parents.empty())
      break;
    c=parents.front();
  }

  if(root_function.class_id.empty())
  {
    // No definition here; this is an abstract function.
    root_function.class_id=class_id;
  }

  // iterate over all children, transitively
  std::set<irep_idt> visited;
  get_child_functions_rec(
    class_id,
    root_function.symbol_expr,
    component_name,
    functions,
    visited);

  if(root_function.symbol_expr!=symbol_exprt())
    functions.push_back(root_function);
}
Example #21
0
// Check that visibility / accessibility changes to the current method
// won't need to change a referenced method into a virtual or static one.
bool gather_invoked_methods_that_prevent_relocation(
    const DexMethod* method,
    std::unordered_set<DexMethodRef*>* methods_preventing_relocation) {
  auto code = method->get_code();
  always_assert(code);

  bool can_relocate = true;
  for (const auto& mie : InstructionIterable(code)) {
    auto insn = mie.insn;
    auto opcode = insn->opcode();
    if (is_invoke(opcode)) {
      auto meth = resolve_method(insn->get_method(), opcode_to_search(insn));
      if (!meth && opcode == OPCODE_INVOKE_VIRTUAL &&
          unknown_virtuals::is_method_known_to_be_public(insn->get_method())) {
        continue;
      }
      if (meth) {
        always_assert(meth->is_def());
        if (meth->is_external() && !is_public(meth)) {
          meth = nullptr;
        } else if (opcode == OPCODE_INVOKE_DIRECT && !is_init(meth)) {
          meth = nullptr;
        }
      }
      if (!meth) {
        can_relocate = false;
        if (!methods_preventing_relocation) {
          break;
        }
        methods_preventing_relocation->emplace(insn->get_method());
      }
    }
  }

  return can_relocate;
}
Example #22
0
jv_method *get_method(java_lang_Class *cls, const utf8_const *name,
                      const utf8_const *signature)
{
	for (int16_t m = 0, n = cls->method_count; m < n; ++m) {
		jv_method *method = &cls->me.methods[m];
		if (utf8_consts_equal(method->name, name)
		    && utf8_consts_equal(method->signature, signature))
			return method;
	}
	java_lang_Class *superclass = cls->superclass;
	if (superclass != NULL)
		return get_method(superclass, name, signature);
	else
		return NULL;
}
	NativeMethod* NativeInitializer::newNativeMethod(uint32_t i) const
	{
		const NativeMethodInfo* ni = get_method(i);
		if (!ni)
			return NULL;

		NativeMethod* info = new (core->GetGC()) NativeMethod(ni->thunker, ni->handler);
		info->flags |= AbstractFunction::ABSTRACT_METHOD;
#ifdef AVMPLUS_LEGACY_NATIVE_MAPS
		info->flags |= ni->flags;
		info->cookie = ni->cookie;
#else
		info->flags |= AbstractFunction::NEEDS_CODECONTEXT | AbstractFunction::NEEDS_DXNS;
#endif
		return info;
	}
Example #24
0
/**
 * Ensure the structures in DelSuperTest.java are as expected
 * following a redex transformation.
 */
TEST_F(PostVerify, DelSuper) {
  std::cout << "Loaded classes: " << classes.size() << std::endl ;

  // Should have C1 and 2 C2 still

  auto c1 = find_class_named(
    classes, "Lcom/facebook/redex/test/instr/DelSuperTest$C1;");
  ASSERT_NE(nullptr, c1);

  auto c2 = find_class_named(
    classes, "Lcom/facebook/redex/test/instr/DelSuperTest$C2;");
  ASSERT_NE(nullptr, c2);

  // C2.optimized1 and C2.optimized2 should be gone
  // XXX: optimized2() doesn't get delsuper treatment due to inlining of C1.optimize2(?)
  auto&& m2 = !m::any_vmethods(
    m::named<DexMethod>("optimized1")/* ||
    m::named<DexMethod>("optimized2")*/);
  ASSERT_TRUE(m2.matches(c2));

  // C1 and C2 should both have 4 notOptimized* methods
  auto&& m3 =
    m::any_vmethods(m::named<DexMethod>("notOptimized1")) &&
    m::any_vmethods(m::named<DexMethod>("notOptimized2")) &&
    m::any_vmethods(m::named<DexMethod>("notOptimized3")) &&
    m::any_vmethods(m::named<DexMethod>("notOptimized4"));
  ASSERT_TRUE(m3.matches(c1));
  ASSERT_TRUE(m3.matches(c2));

  // check that the invoke instructions are fixed up as well
  auto test_class = find_class_named(
    classes, "Lcom/facebook/redex/test/instr/DelSuperTest;");
  auto test_opt_1 = find_vmethod_named(*test_class, "testOptimized1");
  int optimized1_count = 0;
  for (auto& insn : test_opt_1->get_code()->get_instructions()) {
    if (is_invoke(insn->opcode())) {
      auto mop = static_cast<DexOpcodeMethod*>(insn);
      auto m = mop->get_method();
      if (strcmp(m->get_name()->c_str(), "optimized1") == 0) {
        ASSERT_STREQ(m->get_class()->get_name()->c_str(),
                     "Lcom/facebook/redex/test/instr/DelSuperTest$C1;");
        ++optimized1_count;
      }
    }
  }
  ASSERT_EQ(optimized1_count, 3);
}
Example #25
0
extrema_locator* create_extrema_locator(std::string method_string)
{
	extrema_locator* el;
	std::string method = get_method(method_string);
	// determine which class to use to do the extrema location
	if (method=="minima")
		el = new minima_locator();
	else if (method=="maxima")
		el = new maxima_locator();
	else if (method=="minima_back")		// minima with background removal
		el = new minima_background();
	else if (method=="minima_back_wind")
		el = new minima_back_wind();
	else
		throw (std::string("Unsupported extrema location method: " + method));
	return el;
}
Example #26
0
int parse_header(ci_request_t * req)
{
     int i, request_status = 0, result;
     ci_headers_list_t *h;

     h = req->request_header;
     if ((request_status = ci_read_icap_header(req, h, TIMEOUT)) < 0)
          return request_status;

     if ((result = get_method(h->buf)) >= 0) {
          req->type = result;
          if ((request_status = parse_request(req, h->buf)) != EC_100)
	      return request_status;
	 
     }
     else
          return EC_400;

     if ((request_status = ci_headers_unpack(h)) != EC_100)
          return request_status;

     for (i = 1; i < h->used; i++) {
          if (strncasecmp("Preview:", h->headers[i], 8) == 0) {
               result = strtol(h->headers[i] + 9, NULL, 10);
               if (errno != EINVAL && errno != ERANGE) {
                    req->preview = result;
                    if (result >= 0)
                         ci_buf_reset_size(&(req->preview_data), result + 64);
               }
          }
          else if (strncasecmp("Encapsulated: ", h->headers[i], 14) == 0)
               request_status = process_encapsulated(req, h->headers[i]);
          else if (strncasecmp("Connection: ", h->headers[i], 12) == 0) {
/*	       if(strncasecmp(h->headers[i]+12,"keep-alive",10)==0)*/
               if (strncasecmp(h->headers[i] + 12, "close", 5) == 0)
                    req->keepalive = 0;
               /*else the default behaviour of keepalive ..... */
          }
          else if (strncasecmp("Allow: 204", h->headers[i], 10) == 0) {
               req->allow204 = 1;
          }
     }

     return request_status;
}
Example #27
0
/* 
 * procedure map_sign() for putting history and description to maps (csf)
 * history is fixed for a session; description depends on the map contents
 */
void map_sign(GRIDMAP *m, const char *what) {
	char *pwd = NULL, *user = NULL, *timestring = NULL, *fname = NULL;
	time_t tm;

	if ((user = getenv("LOGNAME")) == NULL)
		user = ""; 
	if ((pwd = getenv("PWD")) == NULL)
		pwd = "";
	if ((fname = command_file_name) == NULL)
		fname = "";
	tm = time(&tm);
	if ((timestring = asctime(localtime(&tm))) == NULL)
		timestring = "";
	m->history = (char *) emalloc(1024 * sizeof(char));
#ifdef HAVE_SNPRINTF
	snprintf
#else 
	sprintf
#endif
		(m->history,
#ifdef HAVE_SNPRINTF
		1024,
#endif
		"%s%s\n%s %s %s\n%s%s\n%s %s\n%s %s\n%s %s (seed %lu)\n",
		*user ? 
		"creator:       " : "", user, 
		"program:      ", argv0, VERSION,
		*pwd ? 
		"path:          " : "", pwd,
		"command file: ", fname,
		"method used:  ", method_string(get_method()),
		"date:         ", timestring, get_seed());
	if (what == NULL) { /* paranoia */
		m->description = (char *) emalloc(sizeof(char));
		m->description[0] = '\0';
	} else {
		m->description = (char *) emalloc((strlen(what) + 1) * sizeof(char));
#ifdef HAVE_SNPRINTF
		snprintf(m->description, strlen(what) + 1, "%s\n", what);
#else
		sprintf(m->description, "%s\n", what);
#endif

	}
}
Example #28
0
TEST_F(PreVerify, testArrayDataInCaller) {
  auto cls = find_class_named(
    classes, "Lcom/facebook/redexinline/InlineTest;");
  auto m = find_vmethod_named(*cls, "testArrayDataInCaller");

  // check that the callee indeed has a non-terminal if, which will exercise
  // the inliner code path that searches for fopcodes in the caller
  auto callee = find_invoke(m, OPCODE_INVOKE_DIRECT, "calleeWithIf");
  auto insns = callee->get_method()->get_code()->get_instructions();
  auto ret_it =
      std::find_if(insns.begin(), insns.end(), [&](DexInstruction* insn) {
        return is_return(insn->opcode());
      });
  ASSERT_NE(ret_it, insns.end());

  auto last_insn = m->get_code()->get_instructions().back();
  ASSERT_EQ(last_insn->opcode(), FOPCODE_FILLED_ARRAY);
}
Example #29
0
/**
 * If the caller is in the primary DEX we want to make sure there are no
 * references in other DEXes that may cause a verification error.
 * Don't inline if so.
 */
bool MultiMethodInliner::refs_not_in_primary(DexMethod* callee) {

  const auto ok_from_primary = [&](DexType* type) {
    if (primary.count(type) == 0 && type_class_internal(type) != nullptr) {
      info.not_in_primary++;
      return false;
    }
    return true;
  };

  for (auto insn : callee->get_code()->get_instructions()) {
    if (insn->has_types()) {
      auto top = static_cast<DexOpcodeType*>(insn);
      if (!ok_from_primary(top->get_type())) {
        return true;
      }
    } else if (insn->has_methods()) {
      auto mop = static_cast<DexOpcodeMethod*>(insn);
      auto meth = mop->get_method();
      if (!ok_from_primary(meth->get_class())) {
        return true;
      }
      auto proto = meth->get_proto();
      if (!ok_from_primary(proto->get_rtype())) {
        return true;
      }
      auto args = proto->get_args();
      if (args == nullptr) continue;
      for (const auto& arg : args->get_type_list()) {
        if (!ok_from_primary(arg)) {
          return true;
        }
      }
    } else if (insn->has_fields()) {
      auto fop = static_cast<DexOpcodeField*>(insn);
      auto field = fop->field();
      if (!ok_from_primary(field->get_class()) ||
          !ok_from_primary(field->get_type())) {
        return true;
      }
    }
  }
  return false;
}
Example #30
0
/**
 * Change the visibility of members accessed in a callee as they are moved
 * to the caller context.
 * We make everything public but we could be more precise and only
 * relax visibility as needed.
 */
void MultiMethodInliner::change_visibility(DexMethod* callee) {
  TRACE(MMINL, 6, "checking visibility usage of members in %s\n",
      SHOW(callee));
  for (auto insn : callee->get_code()->get_instructions()) {
    if (insn->has_fields()) {
      auto fop = static_cast<DexOpcodeField*>(insn);
      auto field = fop->field();
      field = resolve_field(field, is_sfield_op(insn->opcode())
          ? FieldSearch::Static : FieldSearch::Instance);
      if (field != nullptr && field->is_concrete()) {
        TRACE(MMINL, 6, "changing visibility of %s.%s %s\n",
            SHOW(field->get_class()), SHOW(field->get_name()),
            SHOW(field->get_type()));
        set_public(field);
        set_public(type_class(field->get_class()));
        fop->rewrite_field(field);
      }
      continue;
    }
    if (insn->has_methods()) {
      auto mop = static_cast<DexOpcodeMethod*>(insn);
      auto method = mop->get_method();
      method = resolver(method, opcode_to_search(insn));
      if (method != nullptr && method->is_concrete()) {
        TRACE(MMINL, 6, "changing visibility of %s.%s: %s\n",
            SHOW(method->get_class()), SHOW(method->get_name()),
            SHOW(method->get_proto()));
        set_public(method);
        set_public(type_class(method->get_class()));
        mop->rewrite_method(method);
      }
      continue;
    }
    if (insn->has_types()) {
      auto type = static_cast<DexOpcodeType*>(insn)->get_type();
      auto cls = type_class(type);
      if (cls != nullptr && !cls->is_external()) {
        TRACE(MMINL, 6, "changing visibility of %s\n", SHOW(type));
        set_public(cls);
      }
      continue;
    }
  }
}