public BuilderMutableMethodImplementation(DexBuilder dexBuilder, @Nonnull MethodImplementation methodImplementation) { this.dexBuilder = dexBuilder; this.registerCount = methodImplementation.getRegisterCount(); for (Instruction instruction : methodImplementation.getInstructions()) { codeAddress += instruction.getCodeUnits(); index++; for (final Instruction instruction : methodImplementation.getInstructions()) { final MethodLocation location = instructionList.get(index); final Opcode opcode = instruction.getOpcode(); for (DebugItem debugItem : methodImplementation.getDebugItems()) { int debugCodeAddress = debugItem.getCodeAddress(); int locationIndex = mapCodeAddressToIndex(codeAddressToIndex, debugCodeAddress); for (TryBlock<? extends ExceptionHandler> tryBlock : methodImplementation.getTryBlocks()) { Label startLabel = newLabel(codeAddressToIndex, tryBlock.getStartCodeAddress()); Label endLabel = newLabel(codeAddressToIndex, tryBlock.getStartCodeAddress() + tryBlock.getCodeUnitCount());
tries = code.getTryBlocks(); numRegisters = code.getRegisterCount(); numParameterRegisters = MethodUtil.getParameterRegisterCount(method); if (!isStatic) { for (DebugItem di : code.getDebugItems()) { if (di instanceof ImmutableLineNumber) { ImmutableLineNumber ln = (ImmutableLineNumber) di;
for (Instruction instruction: methodImpl.getInstructions()) { hasInstruction = true; if (instruction instanceof ReferenceInstruction) { List<? extends TryBlock> tryBlocks = methodImpl.getTryBlocks(); if (!hasInstruction && tryBlocks.size() > 0) { throw new ExceptionWithContext("Method %s has no instructions, but has try blocks.", for (TryBlock<? extends ExceptionHandler> tryBlock: methodImpl.getTryBlocks()) { for (ExceptionHandler handler: tryBlock.getExceptionHandlers()) { dexPool.typeSection.internNullable(handler.getExceptionType());
if (Iterables.isEmpty(methodImplementation.getInstructions())) { if (!isAbstract && !isNative) { throw new SemanticException(input, I_METHOD72, "A non-abstract/non-native method must have at least 1 instruction"); if (methodImplementation.getTryBlocks().size() > 0) { throw new SemanticException(input, I_METHOD72, "try/catch blocks cannot be present in %s method", methodType); if (!Iterables.isEmpty(methodImplementation.getDebugItems())) { throw new SemanticException(input, I_METHOD72, "debug directives cannot be present in %s method", methodType);
@Nullable @Override public Iterable<? extends Instruction> getInstructions(@Nonnull PoolMethod method) { MethodImplementation impl = method.getImplementation(); if (impl != null) { return impl.getInstructions(); } return null; }
@Nonnull @Override public List<? extends TryBlock<? extends ExceptionHandler>> getTryBlocks( @Nonnull PoolMethod method) { MethodImplementation impl = method.getImplementation(); if (impl != null) { return impl.getTryBlocks(); } return ImmutableList.of(); }
@Override public int getRegisterCount(@Nonnull PoolMethod method) { MethodImplementation impl = method.getImplementation(); if (impl != null) { return impl.getRegisterCount(); } return 0; }
private void buildInstructionList() { int registerCount = methodImpl.getRegisterCount(); ImmutableList<Instruction> instructions = ImmutableList.copyOf(methodImpl.getInstructions()); List<? extends TryBlock<? extends ExceptionHandler>> tries = methodImpl.getTryBlocks(); tries = TryListBuilder.massageTryBlocks(tries); int triesIndex = 0;
private void addDebugInfo(final List<MethodItem> methodItems) { for (DebugItem debugItem: methodImpl.getDebugItems()) { methodItems.add(DebugMethodItem.build(registerFormatter, debugItem)); } }
if (Iterables.isEmpty(methodImplementation.getInstructions())) { if (!isAbstract && !isNative) { throw new SemanticException(input, I_METHOD70, "A non-abstract/non-native method must have at least 1 instruction"); if (methodImplementation.getTryBlocks().size() > 0) { throw new SemanticException(input, I_METHOD70, "try/catch blocks cannot be present in %s method", methodType); if (!Iterables.isEmpty(methodImplementation.getDebugItems())) { throw new SemanticException(input, I_METHOD70, "debug directives cannot be present in %s method", methodType);
private boolean needsAnalyzed() { for (Instruction instruction: methodImpl.getInstructions()) { if (instruction.getOpcode().odexOnly()) { return true; } } return false; }
private String[] buildExceptions(Method method) { if (method.getImplementation() == null) { return null; } Set<String> exceptionTypes = new HashSet<>(); for (TryBlock<? extends ExceptionHandler> tryBlock : method.getImplementation() .getTryBlocks()) { for (ExceptionHandler handler : tryBlock.getExceptionHandlers()) { String type = handler.getExceptionType(); if (type == null) { // Type is null if it's a catchall continue; } exceptionTypes.add(stripName(type)); } } return exceptionTypes.toArray(new String[0]); }
public MethodAnalyzer(@Nonnull ClassPath classPath, @Nonnull Method method, @Nullable InlineMethodResolver inlineResolver, boolean normalizeVirtualMethods) { this.classPath = classPath; this.inlineResolver = inlineResolver; this.normalizeVirtualMethods = normalizeVirtualMethods; this.method = method; MethodImplementation methodImpl = method.getImplementation(); if (methodImpl == null) { throw new IllegalArgumentException("The method has no implementation"); } this.methodImpl = methodImpl; // Override AnalyzedInstruction and provide custom implementations of some of the methods, so that we don't // have to handle the case this special case of instruction being null, in the main class startOfMethod = new AnalyzedInstruction(this, new ImmutableInstruction10x(Opcode.NOP), -1, methodImpl.getRegisterCount()) { @Override protected boolean addPredecessor(AnalyzedInstruction predecessor) { throw new UnsupportedOperationException(); } @Override @Nonnull public RegisterType getPredecessorRegisterType(@Nonnull AnalyzedInstruction predecessor, int registerNumber) { throw new UnsupportedOperationException(); } }; buildInstructionList(); analyzedState = new BitSet(analyzedInstructions.size()); paramRegisterCount = MethodUtil.getParameterRegisterCount(method); analyze(); }
for (Instruction instruction: methodImpl.getInstructions()) { hasInstruction = true; if (instruction instanceof ReferenceInstruction) { List<? extends TryBlock> tryBlocks = methodImpl.getTryBlocks(); if (!hasInstruction && tryBlocks.size() > 0) { throw new ExceptionWithContext("Method %s has no instructions, but has try blocks.", for (TryBlock<? extends ExceptionHandler> tryBlock: methodImpl.getTryBlocks()) { for (ExceptionHandler handler: tryBlock.getExceptionHandlers()) { typePool.internNullable(handler.getExceptionType());
@Nullable @Override public Iterable<? extends DebugItem> getDebugItems(@Nonnull PoolMethod method) { MethodImplementation impl = method.getImplementation(); if (impl != null) { return impl.getDebugItems(); } return null; }
@Nullable public static ImmutableMethodImplementation of(@Nullable MethodImplementation methodImplementation) { if (methodImplementation == null) { return null; } if (methodImplementation instanceof ImmutableMethodImplementation) { return (ImmutableMethodImplementation)methodImplementation; } return new ImmutableMethodImplementation( methodImplementation.getRegisterCount(), methodImplementation.getInstructions(), methodImplementation.getTryBlocks(), methodImplementation.getDebugItems()); }
if (Iterables.isEmpty(methodImplementation.getInstructions())) { if (!isAbstract && !isNative) { throw new SemanticException(input, I_METHOD72, "A non-abstract/non-native method must have at least 1 instruction"); if (methodImplementation.getTryBlocks().size() > 0) { throw new SemanticException(input, I_METHOD72, "try/catch blocks cannot be present in %s method", methodType); if (!Iterables.isEmpty(methodImplementation.getDebugItems())) { throw new SemanticException(input, I_METHOD72, "debug directives cannot be present in %s method", methodType);
/** * Extracts the list of dalvik instructions from dexlib and converts them into our own instruction data model * * @param code * The dexlib method implementation */ protected void extractDexInstructions(MethodImplementation code) { int address = 0; for (Instruction instruction : code.getInstructions()) { DexlibAbstractInstruction dexInstruction = fromInstruction(instruction, address); instructions.add(dexInstruction); instructionAtAddress.put(address, dexInstruction); address += instruction.getCodeUnits(); } }
private void addTries(List<MethodItem> methodItems) { List<? extends TryBlock<? extends ExceptionHandler>> tryBlocks = methodImpl.getTryBlocks(); if (tryBlocks.size() == 0) { return;
int oldRegisterCount = builderMethod.getImplementation().getRegisterCount(); int registerCount = oldRegisterCount + invokeRegisterCount; setRegisterCount(builderMethod, registerCount); int oldRegisterCount = builderMethod.getImplementation().getRegisterCount(); int registerCount = oldRegisterCount + invokeRegisterCount; setRegisterCount(builderMethod, registerCount);