/* * Copyright (C) 2012 Sony Mobile Communications AB * * This file is part of ApkAnalyser. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package andreflect.definition; import java.util.ArrayList; import org.jf.baksmali.Adaptors.MethodDefinition; import org.jf.dexlib.ClassDataItem; import org.jf.dexlib.CodeItem; import org.jf.dexlib.DebugInfoItem; import org.jf.dexlib.StringIdItem; import org.jf.dexlib.TypeIdItem; import org.jf.dexlib.Code.Instruction; import org.jf.dexlib.Debug.DebugInstructionIterator; import org.jf.dexlib.Util.SparseIntArray; public class DexMethodDefinition extends MethodDefinition { public DexMethodDefinition(ClassDataItem.EncodedMethod encodedMethod) { super(encodedMethod); } public ArrayList<String> getParameters() { final CodeItem codeItem = encodedMethod.codeItem; final ArrayList<String> params = new ArrayList<String>(); DebugInfoItem debugInfoItem = null; if (codeItem != null) { debugInfoItem = codeItem.getDebugInfo(); } int parameterCount = 0; StringIdItem[] parameterNames = null; if (debugInfoItem != null) { parameterNames = debugInfoItem.getParameterNames(); } if (parameterNames == null) { parameterNames = new StringIdItem[0]; } if (parameterCount < parameterNames.length) { parameterCount = parameterNames.length; } boolean unSolvedName = false; for (int i = 0; i < parameterCount; i++) { StringIdItem parameterName = null; if (i < parameterNames.length) { parameterName = parameterNames[i]; } if (parameterName != null) { params.add(parameterName.getStringValue()); } else { params.add(null); unSolvedName = true; } } if (unSolvedName) { DebugInstructionIterator.DecodeInstructions(debugInfoItem, codeItem.getRegisterCount(), new DebugInstructionIterator.ProcessDecodedDebugInstructionDelegate() { @Override public void ProcessStartLocal(final int codeAddress, final int length, final int registerNum, final StringIdItem name, final TypeIdItem type) { int index = getEmptyIndex(params); if (index != -1 && codeAddress == 0) { params.set(index, name.getStringValue()); } } @Override public void ProcessStartLocalExtended(final int codeAddress, final int length, final int registerNum, final StringIdItem name, final TypeIdItem type, final StringIdItem signature) { int index = getEmptyIndex(params); if (index != -1 && codeAddress == 0) { params.set(index, name.getStringValue()); } } }); } return params; } private int getEmptyIndex(ArrayList<String> params) { int ret = -1; for (int i = 0; i < params.size(); i++) { if (params.get(i) == null) { ret = i; break; } } return ret; } public void prepareLineNumbers() { final CodeItem codeItem = encodedMethod.codeItem; if (codeItem == null) { return; } Instruction[] instructions = codeItem.getInstructions(); DebugInfoItem debugInfoItem = null; if (codeItem != null) { debugInfoItem = codeItem.getDebugInfo(); } if (debugInfoItem == null) { return; } final SparseIntArray instructionMap = new SparseIntArray(instructions.length); DebugInstructionIterator.DecodeInstructions(debugInfoItem, codeItem.getRegisterCount(), new DebugInstructionIterator.ProcessDecodedDebugInstructionDelegate() { @Override public void ProcessLineEmit(int codeAddress, final int line) { instructionMap.append(codeAddress, line); } }); int currentline = instructionMap.valueAt(0); for (Instruction instruction : instructions) { int line = instructionMap.get(instruction.codeAddress, -1); if (line == -1) { instruction.line = currentline; } else { instruction.line = line; currentline = line; } } } }