Example #1
0
/**
 * Check if a visibility/accessibility change would turn a method referenced
 * in a callee to virtual methods as they are inlined into the caller.
 * That is, once a callee is inlined we need to ensure that everything that was
 * referenced by a callee is visible and accessible in the caller context.
 * This step would not be needed if we changed all private instance to static.
 */
bool MultiMethodInliner::create_vmethod(DexInstruction* insn) {
  auto opcode = insn->opcode();
  if (opcode == OPCODE_INVOKE_DIRECT || opcode == OPCODE_INVOKE_DIRECT_RANGE) {
    auto method = static_cast<DexOpcodeMethod*>(insn)->get_method();
    method = resolver(method, MethodSearch::Direct);
    if (method == nullptr) {
      info.need_vmethod++;
      return true;
    }
    always_assert(method->is_def());
    if (is_init(method)) {
      if (!method->is_concrete() && !is_public(method)) {
        info.non_pub_ctor++;
        return true;
      }
      // concrete ctors we can handle because they stay invoke_direct
      return false;
    }
    info.need_vmethod++;
    return true;
  }
  return false;
}
Example #2
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 #3
0
void bparse_test( FILE *FH ) {
    char *s;
    size_t bd_sz = 0, i;
    struct bdeque **bd=xmalloc(bd_sz), /* Array of bdeque pointers */
                  *deque;

    while ( !feof(FH) ) {
        /* Get a line from the file */
        s=b_gets(FH,INPUT_BLOCKSIZE);
        /* Remove comments */
        strtrunc(s,comment_chars);
        /* Remove trailing new line */
        chomp(s);
        /* Tokenize line and load into a deque */
        deque = blex(s);

        if ( bdeque_count( deque ) > 0 ) {
            /* Grow the bdeque pointer array by one and append the new deque to the end */
            struct bdeque **temp = xrealloc(bd,sizeof(*bd)*(++bd_sz));
            bd = temp;
            bd[bd_sz-1] = deque;
        }
    }
    printf("<<DEQUE PRINT>>\n");
    /* Print the bdeques */
    for (i=0; i<bd_sz; i++)
        bdeque_print(bd[i]);
    printf("<<END DEQUE PRINT>>\n");
    for (i=0; i<bd_sz; i++) {
        struct bdeque *deque = bd[i], *dupdeque = bdeque_create();
        struct d_elem *node = deque->head;
        /* Keep track of operation count. If the line isn't 'done' and we can't do operations on it, we don't want to loop on it forever */
        unsigned int ops = 0;
        while ( node != NULL ) {
            struct d_elem *retnode = NULL; // Node returned by the current operation
            int def = is_def(*node->var->value);
            if ( def != -1 ) {
                if ( defs[def].operands == 2 ) {
                    retnode = defs[def].op( node->prev, node->next ); // Perform the binary operation of the current defined operator and place the result into retnode.
                    //bdeque_npush( dupdeque, defs[def].op( node->prev, node->next ) );
                // FIXME: I don't put my return value back into the deque.
                } else if ( defs[def].operands == 1 ) {
                    //struct d_elem *retval = defs[def].op( node->next );
                    retnode = defs[def].op( node->next ); // Perform the unary operation of the current defined operator and place the result into retnode.
                    //defs[def].op( node->next );
                    //if ( retval != NULL ) 
                    //    bdeque_npush( dupdeque, retval );
                } else if ( defs[def].operands == 0 ) {
                    defs[def].op( node->next );
                } else {
                    bdeque_npush( dupdeque, d_elem_copy(node) );
                }
            } //else {
                //bdeque_npush( dupdeque, d_elem_copy(node) );
            //}
            /*
            int def = is_def(*node->var->value);
            if ( def != -1 ) {
                if ( defs[def].operands == 1 )
                    b_PRINT( defs[def].op( node->next ) );
                else if ( defs[def].operands == 2 )
                    b_PRINT( defs[def].op( node->prev, node->next ) );
            }
            */
            if ( node->next == NULL )
                break;
            //else if ( node->next->prev == node )
            if ( retnode != NULL ) {
                
            }
            node = node->next;
        }
        bdeque_print( dupdeque );

    }
}