SmaliCodeFragmentFactory.java revision 6649a7553258d7651a1d6c3ee010d380c6f90e7a
1a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver/* 2a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * Copyright 2014, Google Inc. 3a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * All rights reserved. 4a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * 5a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * Redistribution and use in source and binary forms, with or without 6a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * modification, are permitted provided that the following conditions are 7a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * met: 8a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * 9a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * * Redistributions of source code must retain the above copyright 10a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * notice, this list of conditions and the following disclaimer. 11a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * * Redistributions in binary form must reproduce the above 12a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * copyright notice, this list of conditions and the following disclaimer 13a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * in the documentation and/or other materials provided with the 14a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * distribution. 15a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * * Neither the name of Google Inc. nor the names of its 16a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * contributors may be used to endorse or promote products derived from 17a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * this software without specific prior written permission. 18a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * 19a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver */ 31a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 32a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverpackage org.jf.smalidea.debugging; 33a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 34a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport com.google.common.collect.Maps; 35a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport com.intellij.debugger.DebuggerManagerEx; 36a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport com.intellij.debugger.SourcePosition; 37a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport com.intellij.debugger.engine.DebugProcessImpl; 38a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport com.intellij.debugger.engine.evaluation.*; 39a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport com.intellij.debugger.engine.events.DebuggerCommandImpl; 40a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport com.intellij.debugger.impl.DebuggerContextImpl; 41a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport com.intellij.debugger.jdi.StackFrameProxyImpl; 42a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport com.intellij.openapi.fileTypes.LanguageFileType; 43a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport com.intellij.openapi.project.Project; 44a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport com.intellij.psi.JavaCodeFragment; 45a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport com.intellij.psi.JavaRecursiveElementVisitor; 46a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport com.intellij.psi.PsiElement; 47a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport com.intellij.psi.PsiLocalVariable; 48a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport com.sun.jdi.*; 49a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport com.sun.tools.jdi.LocalVariableImpl; 50a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport com.sun.tools.jdi.LocationImpl; 51a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport org.jf.dexlib2.analysis.AnalyzedInstruction; 52a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport org.jf.dexlib2.analysis.RegisterType; 53a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport org.jf.smalidea.SmaliFileType; 54a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport org.jf.smalidea.psi.impl.SmaliInstruction; 55a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport org.jf.smalidea.psi.impl.SmaliMethod; 56a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 57a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport java.lang.reflect.Constructor; 58a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverimport java.util.Map; 59a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 60a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruverpublic class SmaliCodeFragmentFactory extends DefaultCodeFragmentFactory { 61a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver @Override 62a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver public JavaCodeFragment createCodeFragment(TextWithImports item, PsiElement context, Project project) { 63a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver return super.createCodeFragment(item, wrapContext(project, context), project); 64a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver } 65a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 66a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver @Override 67a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver public JavaCodeFragment createPresentationCodeFragment(TextWithImports item, PsiElement context, Project project) { 68a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver return super.createPresentationCodeFragment(item, wrapContext(project, context), project); 69a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver } 70a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 71a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver @Override public LanguageFileType getFileType() { 72a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver return SmaliFileType.INSTANCE; 73a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver } 74a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 75a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver private PsiElement wrapContext(final Project project, final PsiElement originalContext) { 76a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver if (project.isDefault()) return originalContext; 77a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 78a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver final DebuggerContextImpl debuggerContext = DebuggerManagerEx.getInstanceEx(project).getContext(); 79a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 80a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver SourcePosition position = debuggerContext.getSourcePosition(); 81a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver SmaliInstruction currentInstruction = (SmaliInstruction)position.getElementAt(); 82a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 83a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver final SmaliMethod containingMethod = currentInstruction.getParentMethod(); 84a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver AnalyzedInstruction analyzedInstruction = currentInstruction.getAnalyzedInstruction(); 85a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 86a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver final int firstParameterRegister = containingMethod.getRegisterCount() - 87a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver containingMethod.getParameterRegisterCount(); 88a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver 89a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver final Map<String, String> registerMap = Maps.newHashMap(); 90a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver StringBuilder variablesText = new StringBuilder(); 91a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver for (int i=0; i<containingMethod.getRegisterCount(); i++) { 92a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver int parameterRegisterNumber = i - firstParameterRegister; 93a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver 94a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(i); 95a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver switch (registerType.category) { 96a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.UNKNOWN: 97a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.UNINIT: 98a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.CONFLICTED: 99a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.LONG_HI: 100a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.DOUBLE_HI: 101a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver continue; 102a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.NULL: 103a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.ONE: 104a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.INTEGER: 105a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver variablesText.append("int v").append(i).append(";\n"); 106a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver registerMap.put("v" + i, "I"); 107a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver if (parameterRegisterNumber >= 0) { 108a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver variablesText.append("int p").append(parameterRegisterNumber).append(";\n"); 109a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver registerMap.put("p" + parameterRegisterNumber, "I"); 110a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver } 111a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver break; 112a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.BOOLEAN: 113a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver variablesText.append("boolean v").append(i).append(";\n"); 114a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver registerMap.put("v" + i, "Z"); 115a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver if (parameterRegisterNumber >= 0) { 116a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver variablesText.append("boolean p").append(parameterRegisterNumber).append(";\n"); 117a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver registerMap.put("p" + parameterRegisterNumber, "Z"); 118a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver } 119a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver break; 120a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.BYTE: 121a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.POS_BYTE: 122a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver variablesText.append("byte v").append(i).append(";\n"); 123a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver registerMap.put("v" + i, "B"); 124a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver if (parameterRegisterNumber >= 0) { 125a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver variablesText.append("byte p").append(parameterRegisterNumber).append(";\n"); 126a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver registerMap.put("p" + parameterRegisterNumber, "B"); 127a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver } 128a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver break; 129a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.SHORT: 130a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.POS_SHORT: 131a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver variablesText.append("short v").append(i).append(";\n"); 132a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver registerMap.put("v" + i, "S"); 133a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver if (parameterRegisterNumber >= 0) { 134a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver variablesText.append("short p").append(parameterRegisterNumber).append(";\n"); 135a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver registerMap.put("p" + parameterRegisterNumber, "S"); 136a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver } 137a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver break; 138a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.CHAR: 139a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver variablesText.append("char v").append(i).append(";\n"); 140a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver registerMap.put("v" + i, "C"); 141a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver if (parameterRegisterNumber >= 0) { 142a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver variablesText.append("char p").append(parameterRegisterNumber).append(";\n"); 143a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver registerMap.put("p" + parameterRegisterNumber, "C"); 144a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver } 145a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver break; 146a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.FLOAT: 147a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver variablesText.append("float v").append(i).append(";\n"); 148a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver registerMap.put("v" + i, "F"); 149a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver if (parameterRegisterNumber >= 0) { 150a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver variablesText.append("float p").append(parameterRegisterNumber).append(";\n"); 151a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver registerMap.put("p" + parameterRegisterNumber, "F"); 152a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver } 153a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver break; 154a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.LONG_LO: 155a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver variablesText.append("long v").append(i).append(";\n"); 156a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver registerMap.put("v" + i, "J"); 157a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver if (parameterRegisterNumber >= 0) { 158a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver variablesText.append("long p").append(parameterRegisterNumber).append(";\n"); 159a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver registerMap.put("p" + parameterRegisterNumber, "J"); 160a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver } 161a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver break; 162a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.DOUBLE_LO: 163a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver variablesText.append("double v").append(i).append(";\n"); 164a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver registerMap.put("v" + i, "D"); 165a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver if (parameterRegisterNumber >= 0) { 166a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver variablesText.append("double p").append(parameterRegisterNumber).append(";\n"); 167a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver registerMap.put("p" + parameterRegisterNumber, "D"); 168a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver } 169a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver break; 170a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.UNINIT_REF: 171a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.UNINIT_THIS: 172a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver case RegisterType.REFERENCE: 173a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver variablesText.append("Object v").append(i).append(";\n"); 174a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver registerMap.put("v" + i, "Ljava/lang/Object;"); 175a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver if (parameterRegisterNumber >= 0) { 176a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver variablesText.append("Object p").append(parameterRegisterNumber).append(";\n"); 177a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver registerMap.put("p" + parameterRegisterNumber, "Ljava/lang/Object;"); 178a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver } 179a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver break; 180a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver } 181a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver } 182a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver final TextWithImportsImpl textWithImports = new TextWithImportsImpl(CodeFragmentKind.CODE_BLOCK, 183a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver variablesText.toString(), "", getFileType()); 184a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 185a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver final JavaCodeFragment codeFragment = super.createCodeFragment(textWithImports, originalContext, project); 186a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 187a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver codeFragment.accept(new JavaRecursiveElementVisitor() { 188a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver public void visitLocalVariable(final PsiLocalVariable variable) { 189a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver final String name = variable.getName(); 190a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver if (registerMap.containsKey(name)) { 191a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver debuggerContext.getDebugProcess().getManagerThread().invoke(new DebuggerCommandImpl() { 192a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver @Override protected void action() throws Exception { 193a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver int registerNumber = Integer.parseInt(name.substring(1)); 194a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver if (name.charAt(0) == 'p') { 1956649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver registerNumber += ApplicationManager.getApplication().runReadAction(new Computable<Integer>() { 1966649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver @Override public Integer compute() { 1976649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver return containingMethod.getRegisterCount() - 1986649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver containingMethod.getParameterRegisterCount(); 1996649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver } 2006649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver }); 201a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver } 202a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver Value value = evaluateRegister(debuggerContext.createEvaluationContext(), 203a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver containingMethod, 204a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver registerNumber, 205a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver registerMap.get(name)); 206a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver variable.putUserData(CodeFragmentFactoryContextWrapper.LABEL_VARIABLE_VALUE_KEY, value); 207a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver } 208a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver }); 209a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 210a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 211a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver } 212a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver } 213a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver }); 214a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 215a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 216a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 217a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver int offset = variablesText.length() - 1; 218a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 219a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver final PsiElement newContext = codeFragment.findElementAt(offset); 220a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver if (newContext != null) { 221a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver return newContext; 222a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver } 223a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver return originalContext; 224a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver } 225a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 226a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver public Value evaluateRegister(EvaluationContextImpl context, final SmaliMethod smaliMethod, final int registerNum, 227a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver final String type) { 228a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver final StackFrameProxyImpl frameProxy = context.getFrameProxy(); 229a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver if (frameProxy == null) { 230a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver return null; 231a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver } 232a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 233a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver // the jdi apis don't provide any way to get the value of an arbitrary register, so we use reflection 234a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver // to create a LocalVariable instance for the register 235a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver final Value[] ret = new Value[1]; 236a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 237a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver DebugProcessImpl debugProcess = context.getDebugProcess(); 238a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver debugProcess.getManagerThread().invoke( 239a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver new DebuggerCommandImpl() { 240a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 241a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver @Override protected void action() throws Exception { 242a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver VirtualMachine vm = frameProxy.getVirtualMachine().getVirtualMachine(); 243a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver Method method = frameProxy.location().method(); 244a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 245a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver final Constructor<LocalVariableImpl> localVariableConstructor = LocalVariableImpl.class.getDeclaredConstructor( 246a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver VirtualMachine.class, Method.class, Integer.TYPE, Location.class, Location.class, String.class, 247a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver String.class, String.class); 248a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver localVariableConstructor.setAccessible(true); 249a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 250a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver Constructor<LocationImpl> locationConstructor = LocationImpl.class.getDeclaredConstructor( 251a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver VirtualMachine.class, Method.class, Long.TYPE); 252a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver locationConstructor.setAccessible(true); 253a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 254a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver // TODO: use frameProxy.location().method().locationOfCodeIndex() here 255a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver Location endLocation = locationConstructor.newInstance(vm, method, Integer.MAX_VALUE); 256a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 257a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver LocalVariable localVariable = localVariableConstructor.newInstance(vm, 258a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver method, 259a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver mapRegisterForArt(smaliMethod, registerNum), 260a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver frameProxy.location().method().locationOfCodeIndex(0), 261a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver endLocation, 262a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver String.format("v%d", registerNum), type, null); 263a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 264a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver ret[0] = frameProxy.getStackFrame().getValue(localVariable); 265a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver } 266a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver } 267a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver ); 268a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 269a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver return ret[0]; 270a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver } 271a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 2726649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver private static int mapRegisterForArt(final SmaliMethod smaliMethod, final int register) { 2736649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver return ApplicationManager.getApplication().runReadAction(new Computable<Integer>() { 2746649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver @Override public Integer compute() { 275a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 2766649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver int totalRegisters = smaliMethod.getRegisterCount(); 2776649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver int parameterRegisters = smaliMethod.getParameterRegisterCount(); 2786649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver 2796649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver if (smaliMethod.getModifierList().hasModifierProperty("static")) { 2806649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver return register; 2816649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver } 2826649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver 2836649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver // For ART, the parameter registers are rotated to the front 2846649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver if (register >= (totalRegisters - parameterRegisters)) { 2856649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver return register - (totalRegisters - parameterRegisters); 2866649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver } 2876649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver return register + parameterRegisters; 2886649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver } 2896649a7553258d7651a1d6c3ee010d380c6f90e7aBen Gruver }); 290a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver } 291a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver} 292a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver 293