Home | History | Annotate | Download | only in analysis
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*
     18  * Dalvik verification subroutines.
     19  */
     20 #include "Dalvik.h"
     21 #include "analysis/CodeVerify.h"
     22 #include "libdex/InstrUtils.h"
     23 
     24 
     25 /*
     26  * This is used when debugging to apply a magnifying glass to the
     27  * verification of a particular method.
     28  */
     29 bool dvmWantVerboseVerification(const Method* meth)
     30 {
     31     return false;       /* COMMENT OUT to enable verbose debugging */
     32 
     33     const char* cd = "Lcom/android/server/am/ActivityManagerService;";
     34     const char* mn = "trimApplications";
     35     const char* sg = "()V";
     36     return (strcmp(meth->clazz->descriptor, cd) == 0 &&
     37             dvmCompareNameDescriptorAndMethod(mn, sg, meth) == 0);
     38 }
     39 
     40 /*
     41  * Output a code verifier warning message.  For the pre-verifier it's not
     42  * a big deal if something fails (and it may even be expected), but if
     43  * we're doing just-in-time verification it's significant.
     44  */
     45 void dvmLogVerifyFailure(const Method* meth, const char* format, ...)
     46 {
     47     va_list ap;
     48     int logLevel;
     49 
     50     if (gDvm.optimizing) {
     51         return;
     52         //logLevel = ANDROID_LOG_DEBUG;
     53     } else {
     54         logLevel = ANDROID_LOG_WARN;
     55     }
     56 
     57     va_start(ap, format);
     58     LOG_PRI_VA(logLevel, LOG_TAG, format, ap);
     59     if (meth != NULL) {
     60         char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
     61         LOG_PRI(logLevel, LOG_TAG, "VFY:  rejected %s.%s %s",
     62             meth->clazz->descriptor, meth->name, desc);
     63         free(desc);
     64     }
     65 }
     66 
     67 /*
     68  * Show a relatively human-readable message describing the failure to
     69  * resolve a class.
     70  *
     71  * TODO: this is somewhat misleading when resolution fails because of
     72  * illegal access rather than nonexistent class.
     73  */
     74 void dvmLogUnableToResolveClass(const char* missingClassDescr,
     75     const Method* meth)
     76 {
     77     if (gDvm.optimizing) {
     78         return;
     79     }
     80 
     81     std::string dotMissingClass = dvmHumanReadableDescriptor(missingClassDescr);
     82     std::string dotFromClass = dvmHumanReadableDescriptor(meth->clazz->descriptor);
     83     LOGE("Could not find class '%s', referenced from method %s.%s",
     84             dotMissingClass.c_str(), dotFromClass.c_str(), meth->name);
     85 }
     86 
     87 /*
     88  * Extract the relative offset from a branch instruction.
     89  *
     90  * Returns "false" on failure (e.g. this isn't a branch instruction).
     91  */
     92 bool dvmGetBranchOffset(const Method* meth, const InsnFlags* insnFlags,
     93     int curOffset, s4* pOffset, bool* pConditional)
     94 {
     95     const u2* insns = meth->insns + curOffset;
     96 
     97     switch (*insns & 0xff) {
     98     case OP_GOTO:
     99         *pOffset = ((s2) *insns) >> 8;
    100         *pConditional = false;
    101         break;
    102     case OP_GOTO_32:
    103         *pOffset = insns[1] | (((u4) insns[2]) << 16);
    104         *pConditional = false;
    105         break;
    106     case OP_GOTO_16:
    107         *pOffset = (s2) insns[1];
    108         *pConditional = false;
    109         break;
    110     case OP_IF_EQ:
    111     case OP_IF_NE:
    112     case OP_IF_LT:
    113     case OP_IF_GE:
    114     case OP_IF_GT:
    115     case OP_IF_LE:
    116     case OP_IF_EQZ:
    117     case OP_IF_NEZ:
    118     case OP_IF_LTZ:
    119     case OP_IF_GEZ:
    120     case OP_IF_GTZ:
    121     case OP_IF_LEZ:
    122         *pOffset = (s2) insns[1];
    123         *pConditional = true;
    124         break;
    125     default:
    126         return false;
    127         break;
    128     }
    129 
    130     return true;
    131 }
    132