public static boolean looksLikeSyntheticAccessor(MethodIdItem methodIdItem) { return methodIdItem.getMethodName().getStringValue().startsWith("access$"); }
/** * Looks up a <code>MethodIdItem</code> from the given <code>DexFile</code> for the given * values * @param dexFile The <code>DexFile</code> that this item belongs to * @param classType the class that the method is a member of * @param methodPrototype the type of the method * @param methodName the name of the method * @return a <code>MethodIdItem</code> from the given <code>DexFile</code> for the given * values, or null if it doesn't exist */ public static MethodIdItem lookupMethodIdItem(DexFile dexFile, TypeIdItem classType, ProtoIdItem methodPrototype, StringIdItem methodName) { MethodIdItem methodIdItem = new MethodIdItem(dexFile, classType, methodPrototype, methodName); return dexFile.MethodIdsSection.getInternedItem(methodIdItem); }
@Override public int hashCode() { //there's a small possibility that the actual hash code will be 0. If so, we'll //just end up recalculating it each time if (hashCode == 0) calcHashCode(); return hashCode; }
/** {@inheritDoc} */ public void writeValue(AnnotatedOutput out) { byte[] bytes = EncodedValueUtils.encodeUnsignedIntegralValue(value.getIndex()); if (out.annotates()) { out.annotate(1, "value_type=" + ValueType.VALUE_METHOD.name() + ",value_arg=" + (bytes.length - 1)); out.annotate(bytes.length, "value: " + value.getMethodString()); } out.writeByte(ValueType.VALUE_METHOD.value | ((bytes.length - 1) << 5)); out.write(bytes); }
TypeIdItem methodClass = methodIdItem.getContainingClass(); boolean isInit = false; if (methodIdItem.getMethodName().getStringValue().charAt(0) == '<') { if ((invokeType & INVOKE_DIRECT) != 0) { isInit = true; } else { throw new ValidationException(String.format("Cannot call constructor %s with %s", methodIdItem.getMethodString(), analyzedInstruction.instruction.opcode.name)); if (!methodClassDef.isInterface()) { throw new ValidationException(String.format("Cannot call method %s with %s. %s is not an interface " + "class.", methodIdItem.getMethodString(), analyzedInstruction.instruction.opcode.name, methodClassDef.getClassType())); if (methodClassDef.isInterface()) { throw new ValidationException(String.format("Cannot call method %s with %s. %s is an interface class." + " Use invoke-interface or invoke-interface/range instead.", methodIdItem.getMethodString(), analyzedInstruction.instruction.opcode.name, methodClassDef.getClassType())); ClassPath.ClassDef currentMethodClassDef = ClassPath.getClassDef(encodedMethod.method.getContainingClass()); if (currentMethodClassDef.getSuperclass() == null) { throw new ValidationException(String.format("Cannot call method %s with %s. %s has no superclass", methodIdItem.getMethodString(), analyzedInstruction.instruction.opcode.name, methodClassDef.getSuperclass().getClassType())); "of the current class %s", methodIdItem.getMethodString(), analyzedInstruction.instruction.opcode.name, methodClass.getTypeDescriptor(), encodedMethod.method.getContainingClass().getTypeDescriptor()));
int parameterRegisters = methodIdItem.getPrototype().getParameterRegisterCount(); setPostRegisterTypeAndPropagateChanges(startOfMethod, thisRegister, RegisterType.getRegisterType(RegisterType.Category.UninitThis, ClassPath.getClassDef(methodIdItem.getContainingClass()))); } else { setPostRegisterTypeAndPropagateChanges(startOfMethod, thisRegister, RegisterType.getRegisterType(RegisterType.Category.Reference, ClassPath.getClassDef(methodIdItem.getContainingClass()))); TypeListItem parameters = methodIdItem.getPrototype().getParameters(); if (parameters != null) { RegisterType[] parameterTypes = getParameterTypes(parameters, parameterRegisters); ex.addContext(String.format("opcode: %s", instructionToAnalyze.instruction.opcode.name)); ex.addContext(String.format("CodeAddress: %d", codeAddress)); ex.addContext(String.format("Method: %s", encodedMethod.method.getMethodString())); break;
/** {@inheritDoc} */ public String getConciseIdentity() { return "method_id_item: " + getMethodString(); }
private static void checkItem(Opcode opcode, Item item, int regCount) { if (opcode == FILLED_NEW_ARRAY) { //check data for filled-new-array opcode String type = ((TypeIdItem) item).getTypeDescriptor(); if (type.charAt(0) != '[') { throw new RuntimeException("The type must be an array type"); } if (type.charAt(1) == 'J' || type.charAt(1) == 'D') { throw new RuntimeException("The type cannot be an array of longs or doubles"); } } else if (opcode.value >= INVOKE_VIRTUAL.value && opcode.value <= INVOKE_INTERFACE.value || opcode == INVOKE_DIRECT_EMPTY) { //check data for invoke-* opcodes MethodIdItem methodIdItem = (MethodIdItem) item; int parameterRegisterCount = methodIdItem.getPrototype().getParameterRegisterCount(); if (opcode != INVOKE_STATIC) { parameterRegisterCount++; } if (parameterRegisterCount != regCount) { throw new RuntimeException("regCount does not match the number of arguments of the method"); } } }
/** * Compares this <code>EncodedMethod</code> to another, based on the comparison of the associated * <code>MethodIdItem</code> * @param other The <code>EncodedMethod</code> to compare against * @return a standard integer comparison value indicating the relationship */ public int compareTo(EncodedMethod other) { return method.compareTo(other.method); }
@Override public int hashCode() { return value.hashCode(); } }
ClassDefItem classDefItem = classMap.getClassDefByType(methodIdItem.getContainingClass()); if (classDefItem == null) { return null;
if (!currentMethodClassDef.getSuperclass().hasVirtualMethod(methodIdItem.getShortMethodString())) { throw new ValidationException(String.format("Cannot call method %s with %s. The superclass %s has" + "no such method", methodIdItem.getMethodString(), "reference type %s", methodIdItem.getMethodString(), objectRegisterType.type.getClassType())); if (isInit) { throw new ValidationException(String.format("Cannot invoke %s on initialized reference type %s", methodIdItem.getMethodString(), objectRegisterType.type.getClassType())); methodIdItem.getMethodString())); methodIdItem.getMethodString(), objectRegisterType.toString())); if (!encodedMethod.method.getMethodName().getStringValue().equals("<init>")) { throw new ValidationException(String.format("Cannot call %s on type %s. The object type must " + "match the method type exactly", methodIdItem.getMethodString(), objectRegisterType.type.getClassType())); "does not extend %s.", methodIdItem.getMethodString(), objectRegisterType.type.getClassType(), methodClassDef.getClassType()));
this.deodexUtil = new DeodexUtil(encodedMethod.method.getDexFile(), inlineResolver); } else { this.deodexUtil = new DeodexUtil(encodedMethod.method.getDexFile());
/** * Writes the <code>EncodedMethod</code> to the given <code>AnnotatedOutput</code> object * @param out the <code>AnnotatedOutput</code> object to write to * @param previousEncodedMethod The previous <code>EncodedMethod</code> in the list containing this * <code>EncodedMethod</code>. */ private void writeTo(AnnotatedOutput out, EncodedMethod previousEncodedMethod) { int previousIndex = previousEncodedMethod==null?0:previousEncodedMethod.method.getIndex(); if (out.annotates()) { out.annotate("method: " + method.getMethodString()); out.writeUnsignedLeb128(method.getIndex() - previousIndex); out.annotate("access_flags: " + AccessFlags.formatAccessFlagsForMethod(accessFlags)); out.writeUnsignedLeb128(accessFlags); if (codeItem != null) { out.annotate("code_off: 0x" + Integer.toHexString(codeItem.getOffset())); out.writeUnsignedLeb128(codeItem.getOffset()); } else { out.annotate("code_off: 0x0"); out.writeUnsignedLeb128(0); } }else { out.writeUnsignedLeb128(method.getIndex() - previousIndex); out.writeUnsignedLeb128(accessFlags); out.writeUnsignedLeb128(codeItem==null?0:codeItem.getOffset()); } }
int parameterRegisters = methodIdItem.getPrototype().getParameterRegisterCount(); setPostRegisterTypeAndPropagateChanges(startOfMethod, thisRegister, RegisterType.getRegisterType(RegisterType.Category.UninitThis, ClassPath.getClassDef(methodIdItem.getContainingClass()))); } else { setPostRegisterTypeAndPropagateChanges(startOfMethod, thisRegister, RegisterType.getRegisterType(RegisterType.Category.Reference, ClassPath.getClassDef(methodIdItem.getContainingClass()))); TypeListItem parameters = methodIdItem.getPrototype().getParameters(); if (parameters != null) { RegisterType[] parameterTypes = getParameterTypes(parameters, parameterRegisters); ex.addContext(String.format("opcode: %s", instructionToAnalyze.instruction.opcode.name)); ex.addContext(String.format("CodeAddress: %d", codeAddress)); ex.addContext(String.format("Method: %s", encodedMethod.method.getMethodString())); break;
/** {@inheritDoc} */ public String getConciseIdentity() { if (this.parent == null) { return "code_item @0x" + Integer.toHexString(getOffset()); } return "code_item @0x" + Integer.toHexString(getOffset()) + " (" + parent.method.getMethodString() + ")"; }
private static void checkItem(Opcode opcode, Item item, int regCount) { if (opcode == FILLED_NEW_ARRAY_RANGE) { //check data for filled-new-array/range opcode String type = ((TypeIdItem) item).getTypeDescriptor(); if (type.charAt(0) != '[') { throw new RuntimeException("The type must be an array type"); } if (type.charAt(1) == 'J' || type.charAt(1) == 'D') { throw new RuntimeException("The type cannot be an array of longs or doubles"); } } else if (opcode.value >= INVOKE_VIRTUAL_RANGE.value && opcode.value <= INVOKE_INTERFACE_RANGE.value || opcode == INVOKE_OBJECT_INIT_RANGE) { //check data for invoke-*/range opcodes MethodIdItem methodIdItem = (MethodIdItem) item; int parameterRegisterCount = methodIdItem.getPrototype().getParameterRegisterCount(); if (opcode != INVOKE_STATIC_RANGE) { parameterRegisterCount++; } if (parameterRegisterCount != regCount) { throw new RuntimeException("regCount does not match the number of arguments of the method"); } } }
private static EncodedMethod findMethodByMethodIdInternal(int methodIdItemIndex, EncodedMethod[] encodedMethods) { int min = 0; int max = encodedMethods.length; while (min<max) { int index = (min+max)>>1; EncodedMethod encodedMethod = encodedMethods[index]; int encodedMethodIndex = encodedMethod.method.getIndex(); if (encodedMethodIndex == methodIdItemIndex) { return encodedMethod; } else if (encodedMethodIndex < methodIdItemIndex) { if (min == index) { break; } min = index; } else { if (max == index) { break; } max = index; } } return null; }
public int compareTo(ParameterAnnotation other) { return method.compareTo(other.method); } }