SmaliCodeFragmentFactory.java revision a5efca6fe61d8fa6a5b7d1430b836635ba455f1e
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') {
195a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver                                registerNumber += containingMethod.getRegisterCount() -
196a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver                                        containingMethod.getParameterRegisterCount();
197a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver                            }
198a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                            Value value = evaluateRegister(debuggerContext.createEvaluationContext(),
199a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                                    containingMethod,
200a5efca6fe61d8fa6a5b7d1430b836635ba455f1eBen Gruver                                    registerNumber,
201a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                                    registerMap.get(name));
202a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                            variable.putUserData(CodeFragmentFactoryContextWrapper.LABEL_VARIABLE_VALUE_KEY, value);
203a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                        }
204a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                    });
205a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver
206a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver
207a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                }
208a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver            }
209a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        });
210a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver
211a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver
212a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver
213a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        int offset = variablesText.length() - 1;
214a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver
215a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        final PsiElement newContext = codeFragment.findElementAt(offset);
216a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        if (newContext != null) {
217a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver            return newContext;
218a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        }
219a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        return originalContext;
220a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver    }
221a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver
222a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver    public Value evaluateRegister(EvaluationContextImpl context, final SmaliMethod smaliMethod, final int registerNum,
223a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                                  final String type) {
224a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        final StackFrameProxyImpl frameProxy = context.getFrameProxy();
225a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        if (frameProxy == null) {
226a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver            return null;
227a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        }
228a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver
229a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        // the jdi apis don't provide any way to get the value of an arbitrary register, so we use reflection
230a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        // to create a LocalVariable instance for the register
231a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        final Value[] ret = new Value[1];
232a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver
233a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        DebugProcessImpl debugProcess = context.getDebugProcess();
234a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        debugProcess.getManagerThread().invoke(
235a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                new DebuggerCommandImpl() {
236a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver
237a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                    @Override protected void action() throws Exception {
238a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                        VirtualMachine vm = frameProxy.getVirtualMachine().getVirtualMachine();
239a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                        Method method = frameProxy.location().method();
240a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver
241a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                        final Constructor<LocalVariableImpl> localVariableConstructor = LocalVariableImpl.class.getDeclaredConstructor(
242a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                                VirtualMachine.class, Method.class, Integer.TYPE, Location.class, Location.class, String.class,
243a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                                String.class, String.class);
244a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                        localVariableConstructor.setAccessible(true);
245a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver
246a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                        Constructor<LocationImpl> locationConstructor = LocationImpl.class.getDeclaredConstructor(
247a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                                VirtualMachine.class, Method.class, Long.TYPE);
248a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                        locationConstructor.setAccessible(true);
249a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver
250a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                        // TODO: use frameProxy.location().method().locationOfCodeIndex() here
251a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                        Location endLocation = locationConstructor.newInstance(vm, method, Integer.MAX_VALUE);
252a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver
253a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                        LocalVariable localVariable = localVariableConstructor.newInstance(vm,
254a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                                method,
255a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                                mapRegisterForArt(smaliMethod, registerNum),
256a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                                frameProxy.location().method().locationOfCodeIndex(0),
257a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                                endLocation,
258a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                                String.format("v%d", registerNum), type, null);
259a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver
260a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                        ret[0] = frameProxy.getStackFrame().getValue(localVariable);
261a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                    }
262a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver                }
263a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        );
264a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver
265a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        return ret[0];
266a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver    }
267a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver
268a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver    private static int mapRegisterForArt(SmaliMethod smaliMethod, int register) {
269a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        int totalRegisters = smaliMethod.getRegisterCount();
270a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        int parameterRegisters = smaliMethod.getParameterRegisterCount();
271a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver
272a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        // For ART, the parameter registers are rotated to the front
273a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        if (register >= (totalRegisters - parameterRegisters)) {
274a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver            return register - (totalRegisters - parameterRegisters);
275a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        }
276a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver        return register + parameterRegisters;
277a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver    }
278a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver}
279a28e8f236378cb6c2299a5bc9816702f8fc75bd8Ben Gruver
280