mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 00:04:10 -08:00
Add stack deobfuscation to dev server
This commit is contained in:
parent
68522811f2
commit
78c55437e3
|
@ -10,6 +10,7 @@
|
|||
</option>
|
||||
<option name="goals">
|
||||
<list>
|
||||
<option value="-e" />
|
||||
<option value="install" />
|
||||
<option value="-DskipTests" />
|
||||
<option value="-Dteavm.build.all=false" />
|
||||
|
|
|
@ -490,6 +490,7 @@ public class Renderer implements RenderingManager {
|
|||
writer.append(',').softNewLine();
|
||||
}
|
||||
first = false;
|
||||
debugEmitter.emitClass(cls.getName());
|
||||
writer.appendClass(cls.getName()).append(",").ws();
|
||||
|
||||
if (classesRequiringName.contains(cls.getName())) {
|
||||
|
@ -541,6 +542,7 @@ public class Renderer implements RenderingManager {
|
|||
collectMethodsToCopyFromInterfaces(classSource.get(cls.getName()), virtualMethods);
|
||||
|
||||
renderVirtualDeclarations(virtualMethods);
|
||||
debugEmitter.emitClass(null);
|
||||
}
|
||||
writer.append("]);").newLine();
|
||||
}
|
||||
|
|
|
@ -71,6 +71,10 @@ public final class TeaVMDevServerRunner {
|
|||
.withDescription("display indicator on web page")
|
||||
.withLongOpt("indicator")
|
||||
.create('i'));
|
||||
options.addOption(OptionBuilder
|
||||
.withDescription("deobfuscate stack traces")
|
||||
.withLongOpt("deobfuscate-stack")
|
||||
.create());
|
||||
options.addOption(OptionBuilder
|
||||
.withDescription("automatically reload page when compilation completes")
|
||||
.withLongOpt("auto-reload")
|
||||
|
@ -123,6 +127,7 @@ public final class TeaVMDevServerRunner {
|
|||
parseOutputOptions();
|
||||
|
||||
devServer.setIndicator(commandLine.hasOption("indicator"));
|
||||
devServer.setDeobfuscateStack(commandLine.hasOption("deobfuscate-stack"));
|
||||
devServer.setReloadedAutomatically(commandLine.hasOption("auto-reload"));
|
||||
devServer.setLog(new ConsoleTeaVMToolLog(commandLine.hasOption('v')));
|
||||
if (commandLine.hasOption("port")) {
|
||||
|
|
|
@ -122,6 +122,12 @@ public final class TeaVMRunner {
|
|||
.hasArg()
|
||||
.withDescription("WebAssembly binary version (currently, only 1 is supported)")
|
||||
.create());
|
||||
options.addOption(OptionBuilder
|
||||
.withLongOpt("entry-point")
|
||||
.withArgName("name")
|
||||
.hasArg()
|
||||
.withDescription("Entry point name in target language (main by default)")
|
||||
.create("e"));
|
||||
options.addOption(OptionBuilder
|
||||
.withLongOpt("min-heap")
|
||||
.withArgName("size")
|
||||
|
@ -166,6 +172,10 @@ public final class TeaVMRunner {
|
|||
parseWasmOptions();
|
||||
parseHeap();
|
||||
|
||||
if (commandLine.hasOption("e")) {
|
||||
tool.setEntryPointName(commandLine.getOptionValue("e"));
|
||||
}
|
||||
|
||||
interactive = commandLine.hasOption('w');
|
||||
|
||||
String[] args = commandLine.getArgs();
|
||||
|
|
|
@ -70,6 +70,7 @@ public class TeaVMTool {
|
|||
private String targetFileName = "";
|
||||
private boolean minifying = true;
|
||||
private String mainClass;
|
||||
private String entryPointName = "main";
|
||||
private Properties properties = new Properties();
|
||||
private boolean debugInformationGenerated;
|
||||
private boolean sourceMapsFileGenerated;
|
||||
|
@ -139,6 +140,10 @@ public class TeaVMTool {
|
|||
this.mainClass = mainClass;
|
||||
}
|
||||
|
||||
public void setEntryPointName(String entryPointName) {
|
||||
this.entryPointName = entryPointName;
|
||||
}
|
||||
|
||||
public boolean isDebugInformationGenerated() {
|
||||
return debugInformationGenerated;
|
||||
}
|
||||
|
@ -367,7 +372,7 @@ public class TeaVMTool {
|
|||
vm.add(transformer);
|
||||
}
|
||||
if (mainClass != null) {
|
||||
vm.entryPoint(mainClass);
|
||||
vm.entryPoint(mainClass, entryPointName);
|
||||
}
|
||||
for (String className : classesToPreserve) {
|
||||
vm.preserveType(className);
|
||||
|
|
|
@ -38,6 +38,8 @@ public interface BuildStrategy {
|
|||
|
||||
void setMainClass(String mainClass);
|
||||
|
||||
void setEntryPointName(String entryPointName);
|
||||
|
||||
void setTargetDirectory(String targetDirectory);
|
||||
|
||||
void setSourceMapsFileGenerated(boolean sourceMapsFileGenerated);
|
||||
|
|
|
@ -44,6 +44,7 @@ public class InProcessBuildStrategy implements BuildStrategy {
|
|||
private List<String> classPathEntries = new ArrayList<>();
|
||||
private TeaVMTargetType targetType;
|
||||
private String mainClass;
|
||||
private String entryPointName;
|
||||
private String targetDirectory;
|
||||
private String targetFileName = "";
|
||||
private boolean incremental;
|
||||
|
@ -98,6 +99,11 @@ public class InProcessBuildStrategy implements BuildStrategy {
|
|||
this.mainClass = mainClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEntryPointName(String entryPointName) {
|
||||
this.entryPointName = entryPointName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTargetDirectory(String targetDirectory) {
|
||||
this.targetDirectory = targetDirectory;
|
||||
|
@ -191,6 +197,7 @@ public class InProcessBuildStrategy implements BuildStrategy {
|
|||
tool.setLog(log);
|
||||
tool.setTargetType(targetType);
|
||||
tool.setMainClass(mainClass);
|
||||
tool.setEntryPointName(entryPointName);
|
||||
tool.setTargetDirectory(new File(targetDirectory));
|
||||
tool.setTargetFileName(targetFileName);
|
||||
tool.setClassLoader(buildClassLoader());
|
||||
|
|
|
@ -78,6 +78,11 @@ public class RemoteBuildStrategy implements BuildStrategy {
|
|||
request.mainClass = mainClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEntryPointName(String entryPointName) {
|
||||
request.entryPointName = entryPointName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTargetDirectory(String targetDirectory) {
|
||||
request.targetDirectory = targetDirectory;
|
||||
|
@ -219,7 +224,7 @@ public class RemoteBuildStrategy implements BuildStrategy {
|
|||
private TeaVMProgressListener listener;
|
||||
private TeaVMToolLog log;
|
||||
|
||||
public CallbackImpl(TeaVMProgressListener listener, TeaVMToolLog log) throws RemoteException {
|
||||
CallbackImpl(TeaVMProgressListener listener, TeaVMToolLog log) throws RemoteException {
|
||||
super();
|
||||
this.listener = listener;
|
||||
this.log = log;
|
||||
|
|
|
@ -141,6 +141,7 @@ public class BuildDaemon extends UnicastRemoteObject implements RemoteBuildServi
|
|||
}
|
||||
tool.setTargetType(request.targetType);
|
||||
tool.setMainClass(request.mainClass);
|
||||
tool.setEntryPointName(request.entryPointName);
|
||||
tool.setTargetDirectory(new File(request.targetDirectory));
|
||||
tool.setTargetFileName(request.tagetFileName);
|
||||
tool.setClassLoader(buildClassLoader(request.classPath, incremental && request.incremental));
|
||||
|
|
|
@ -31,6 +31,7 @@ public class RemoteBuildRequest implements Serializable {
|
|||
public String[] classesToPreserve;
|
||||
public TeaVMTargetType targetType;
|
||||
public String mainClass;
|
||||
public String entryPointName;
|
||||
public String targetDirectory;
|
||||
public String tagetFileName = "";
|
||||
public boolean sourceMapsFileGenerated;
|
||||
|
|
|
@ -61,6 +61,12 @@
|
|||
<artifactId>teavm-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.teavm</groupId>
|
||||
<artifactId>teavm-jso-apis</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.teavm</groupId>
|
||||
<artifactId>teavm-tooling</artifactId>
|
||||
|
@ -100,6 +106,41 @@
|
|||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.teavm</groupId>
|
||||
<artifactId>teavm-maven-plugin</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.teavm</groupId>
|
||||
<artifactId>teavm-jso-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.teavm</groupId>
|
||||
<artifactId>teavm-classlib</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>compile-deobfuscator</id>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
<phase>process-classes</phase>
|
||||
<configuration>
|
||||
<targetDirectory>${build.directory}/classes/teavm/devserver</targetDirectory>
|
||||
<targetFileName>deobfuscator.js</targetFileName>
|
||||
<minifying>true</minifying>
|
||||
<optimizationLevel>ADVANCED</optimizationLevel>
|
||||
<mainClass>org.teavm.devserver.deobfuscate.Deobfuscator</mainClass>
|
||||
<entryPointName>$teavm_deobfuscator</entryPointName>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
|
|
|
@ -97,9 +97,11 @@ public class CodeServlet extends HttpServlet {
|
|||
private String fileName = "classes.js";
|
||||
private String pathToFile = "/";
|
||||
private String indicatorWsPath;
|
||||
private String deobfuscatorPath;
|
||||
private List<String> sourcePath = new ArrayList<>();
|
||||
private TeaVMToolLog log = new EmptyTeaVMToolLog();
|
||||
private boolean indicator;
|
||||
private boolean deobfuscateStack;
|
||||
private boolean automaticallyReloaded;
|
||||
private int port;
|
||||
private int debugPort;
|
||||
|
@ -163,6 +165,10 @@ public class CodeServlet extends HttpServlet {
|
|||
this.indicator = indicator;
|
||||
}
|
||||
|
||||
public void setDeobfuscateStack(boolean deobfuscateStack) {
|
||||
this.deobfuscateStack = deobfuscateStack;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
@ -263,6 +269,7 @@ public class CodeServlet extends HttpServlet {
|
|||
}
|
||||
|
||||
indicatorWsPath = pathToFile + fileName + ".ws";
|
||||
deobfuscatorPath = pathToFile + fileName + ".deobfuscator.js";
|
||||
WebSocketPolicy wsPolicy = new WebSocketPolicy(WebSocketBehavior.SERVER);
|
||||
wsFactory = WebSocketServletFactory.Loader.load(config.getServletContext(), wsPolicy);
|
||||
wsFactory.setCreator((req, resp) -> {
|
||||
|
@ -304,6 +311,9 @@ public class CodeServlet extends HttpServlet {
|
|||
return;
|
||||
}
|
||||
}
|
||||
} else if (path.equals(deobfuscatorPath)) {
|
||||
serveDeobfuscator(resp);
|
||||
return;
|
||||
} else {
|
||||
byte[] fileContent;
|
||||
boolean firstTime;
|
||||
|
@ -340,6 +350,17 @@ public class CodeServlet extends HttpServlet {
|
|||
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||
}
|
||||
|
||||
private void serveDeobfuscator(HttpServletResponse resp) throws IOException {
|
||||
ClassLoader loader = CodeServlet.class.getClassLoader();
|
||||
resp.setStatus(HttpServletResponse.SC_OK);
|
||||
resp.setCharacterEncoding("UTF-8");
|
||||
resp.setContentType("text/plain");
|
||||
try (InputStream input = loader.getResourceAsStream("teavm/devserver/deobfuscator.js")) {
|
||||
IOUtils.copy(input, resp.getOutputStream());
|
||||
}
|
||||
resp.getOutputStream().flush();
|
||||
}
|
||||
|
||||
private void proxy(HttpServletRequest req, HttpServletResponse resp, String path) throws IOException {
|
||||
AsyncContext async = req.startAsync();
|
||||
|
||||
|
@ -763,9 +784,11 @@ public class CodeServlet extends HttpServlet {
|
|||
script = script.replace("WS_PATH", "localhost:" + port + pathToFile + fileName + ".ws");
|
||||
script = script.replace("BOOT_FLAG", Boolean.toString(boot));
|
||||
script = script.replace("RELOAD_FLAG", Boolean.toString(automaticallyReloaded));
|
||||
script = script.replace("FILE_NAME", "http://localhost:" + port + pathToFile + fileName);
|
||||
script = script.replace("INDICATOR_FLAG", Boolean.toString(indicator));
|
||||
script = script.replace("DEBUG_PORT", Integer.toString(debugPort));
|
||||
script = script.replace("FILE_NAME", "\"" + fileName + "\"");
|
||||
script = script.replace("PATH_TO_FILE", "\"http://localhost:" + port + pathToFile + "\"");
|
||||
script = script.replace("DEOBFUSCATE_FLAG", String.valueOf(deobfuscateStack));
|
||||
return script;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("IO error occurred writing debug information", e);
|
||||
|
|
|
@ -30,6 +30,7 @@ public class DevServer {
|
|||
private String fileName = "classes.js";
|
||||
private List<String> sourcePath = new ArrayList<>();
|
||||
private boolean indicator;
|
||||
private boolean deobfuscateStack;
|
||||
private boolean reloadedAutomatically;
|
||||
private TeaVMToolLog log;
|
||||
private CodeServlet servlet;
|
||||
|
@ -79,6 +80,10 @@ public class DevServer {
|
|||
this.indicator = indicator;
|
||||
}
|
||||
|
||||
public void setDeobfuscateStack(boolean deobfuscateStack) {
|
||||
this.deobfuscateStack = deobfuscateStack;
|
||||
}
|
||||
|
||||
public void setReloadedAutomatically(boolean reloadedAutomatically) {
|
||||
this.reloadedAutomatically = reloadedAutomatically;
|
||||
}
|
||||
|
@ -126,6 +131,7 @@ public class DevServer {
|
|||
servlet.setLog(log);
|
||||
servlet.getSourcePath().addAll(sourcePath);
|
||||
servlet.setIndicator(indicator);
|
||||
servlet.setDeobfuscateStack(deobfuscateStack);
|
||||
servlet.setAutomaticallyReloaded(reloadedAutomatically);
|
||||
servlet.setPort(port);
|
||||
servlet.setDebugPort(debugPort);
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright 2019 Alexey Andreev.
|
||||
*
|
||||
* 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 org.teavm.devserver.deobfuscate;
|
||||
|
||||
import org.teavm.jso.JSFunctor;
|
||||
import org.teavm.jso.JSObject;
|
||||
|
||||
@JSFunctor
|
||||
public interface DeobfuscateFunction extends JSObject {
|
||||
Frame[] apply(String stack);
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright 2019 Alexey Andreev.
|
||||
*
|
||||
* 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 org.teavm.devserver.deobfuscate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.teavm.debugging.information.DebugInformation;
|
||||
import org.teavm.debugging.information.SourceLocation;
|
||||
import org.teavm.jso.JSBody;
|
||||
import org.teavm.jso.ajax.XMLHttpRequest;
|
||||
import org.teavm.jso.core.JSArray;
|
||||
import org.teavm.jso.core.JSRegExp;
|
||||
import org.teavm.jso.core.JSString;
|
||||
import org.teavm.jso.typedarrays.ArrayBuffer;
|
||||
import org.teavm.jso.typedarrays.Int8Array;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
public final class Deobfuscator {
|
||||
private static final JSRegExp FRAME_PATTERN = JSRegExp.create("^ +at ([^(]+) *\\((.+):([0-9]+):([0-9]+)\\) *$");
|
||||
|
||||
private Deobfuscator() {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
loadDeobfuscator(args[0], args[1]);
|
||||
}
|
||||
|
||||
private static void loadDeobfuscator(String fileName, String classesFileName) {
|
||||
XMLHttpRequest xhr = XMLHttpRequest.create();
|
||||
xhr.setResponseType("arraybuffer");
|
||||
xhr.onComplete(() -> {
|
||||
installDeobfuscator(xhr.getResponse().cast(), classesFileName);
|
||||
});
|
||||
xhr.open("GET", fileName);
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
private static void installDeobfuscator(ArrayBuffer buffer, String classesFileName) {
|
||||
Int8Array array = Int8Array.create(buffer);
|
||||
DebugInformation debugInformation;
|
||||
try {
|
||||
debugInformation = DebugInformation.read(new Int8ArrayInputStream(array));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
setDeobfuscateFunction(stack -> {
|
||||
List<Frame> frames = new ArrayList<>();
|
||||
for (String line : splitLines(stack)) {
|
||||
JSArray<JSString> groups = FRAME_PATTERN.exec(JSString.valueOf(line));
|
||||
if (groups == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String functionName = groups.get(1).stringValue();
|
||||
String fileName = groups.get(2).stringValue();
|
||||
int lineNumber = Integer.parseInt(groups.get(3).stringValue());
|
||||
int columnNumber = Integer.parseInt(groups.get(4).stringValue());
|
||||
Frame frame = deobfuscateFrame(debugInformation, classesFileName, fileName, lineNumber, columnNumber);
|
||||
if (frame == null) {
|
||||
frame = createDefaultFrame(fileName, functionName, lineNumber);
|
||||
}
|
||||
frames.add(frame);
|
||||
}
|
||||
return frames.toArray(new Frame[0]);
|
||||
});
|
||||
DeobfuscatorCallback callback = getCallback();
|
||||
if (callback != null) {
|
||||
callback.run();
|
||||
}
|
||||
}
|
||||
|
||||
private static Frame deobfuscateFrame(DebugInformation debugInformation, String classesFileName,
|
||||
String fileName, int lineNumber, int columnNumber) {
|
||||
if (!fileName.equals(classesFileName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
MethodReference method = debugInformation.getMethodAt(lineNumber - 1, columnNumber - 1);
|
||||
if (method == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
SourceLocation location = debugInformation.getSourceLocation(lineNumber - 1, columnNumber - 1);
|
||||
|
||||
String decodedFileName = location != null ? location.getFileName() : null;
|
||||
if (decodedFileName != null) {
|
||||
decodedFileName = decodedFileName.substring(decodedFileName.lastIndexOf('/') + 1);
|
||||
}
|
||||
|
||||
Frame frame = createEmptyFrame();
|
||||
frame.setClassName(method.getClassName());
|
||||
frame.setMethodName(method.getName());
|
||||
frame.setFileName(decodedFileName);
|
||||
if (location != null) {
|
||||
frame.setLineNumber(location.getLine());
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
private static Frame createDefaultFrame(String fileName, String functionName, int lineNumber) {
|
||||
Frame frame = createEmptyFrame();
|
||||
frame.setFileName(fileName);
|
||||
frame.setMethodName(functionName != null ? functionName : "<unknown function>");
|
||||
frame.setClassName("<JS>");
|
||||
frame.setLineNumber(lineNumber);
|
||||
return frame;
|
||||
}
|
||||
|
||||
private static String[] splitLines(String text) {
|
||||
List<String> result = new ArrayList<>();
|
||||
int index = 0;
|
||||
while (index < text.length()) {
|
||||
int next = text.indexOf('\n', index);
|
||||
if (next < 0) {
|
||||
next = text.length();
|
||||
}
|
||||
result.add(text.substring(index, next));
|
||||
index = next + 1;
|
||||
}
|
||||
return result.toArray(new String[0]);
|
||||
}
|
||||
|
||||
@JSBody(script = "return {};")
|
||||
private static native Frame createEmptyFrame();
|
||||
|
||||
@JSBody(params = "f", script = "window.$rt_decodeStack = f;")
|
||||
private static native void setDeobfuscateFunction(DeobfuscateFunction f);
|
||||
|
||||
@JSBody(script = "return typeof $teavm_deobfuscator_callback === 'function'"
|
||||
+ "? $teavm_deobfuscator_callback : null;")
|
||||
private static native DeobfuscatorCallback getCallback();
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright 2019 Alexey Andreev.
|
||||
*
|
||||
* 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 org.teavm.devserver.deobfuscate;
|
||||
|
||||
import org.teavm.jso.JSFunctor;
|
||||
import org.teavm.jso.JSObject;
|
||||
|
||||
@JSFunctor
|
||||
public interface DeobfuscatorCallback extends JSObject {
|
||||
void run();
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright 2019 Alexey Andreev.
|
||||
*
|
||||
* 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 org.teavm.devserver.deobfuscate;
|
||||
|
||||
import org.teavm.jso.JSObject;
|
||||
import org.teavm.jso.JSProperty;
|
||||
|
||||
public interface Frame extends JSObject {
|
||||
@JSProperty
|
||||
void setClassName(String className);
|
||||
|
||||
@JSProperty
|
||||
void setFileName(String fileName);
|
||||
|
||||
@JSProperty
|
||||
void setMethodName(String methodName);
|
||||
|
||||
@JSProperty
|
||||
void setLineNumber(int lineNumber);
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright 2019 Alexey Andreev.
|
||||
*
|
||||
* 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 org.teavm.devserver.deobfuscate;
|
||||
|
||||
import java.io.InputStream;
|
||||
import org.teavm.jso.typedarrays.Int8Array;
|
||||
|
||||
public class Int8ArrayInputStream extends InputStream {
|
||||
private Int8Array array;
|
||||
private int pos;
|
||||
|
||||
public Int8ArrayInputStream(Int8Array array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() {
|
||||
if (pos >= array.getLength()) {
|
||||
return -1;
|
||||
}
|
||||
return array.get(pos++) & 0xFF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) {
|
||||
if (pos >= array.getLength()) {
|
||||
return -1;
|
||||
}
|
||||
int count = Math.min(len, array.getLength() - pos);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
b[off++] = array.get(pos++);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
|
@ -13,11 +13,14 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
(function () {
|
||||
(function (window) {
|
||||
var boot = BOOT_FLAG;
|
||||
var reload = RELOAD_FLAG;
|
||||
var indicatorVisible = INDICATOR_FLAG;
|
||||
var debugPort = DEBUG_PORT;
|
||||
var deobfuscate = DEOBFUSCATE_FLAG;
|
||||
var fileName = FILE_NAME;
|
||||
var pathToFile = PATH_TO_FILE;
|
||||
|
||||
function createWebSocket() {
|
||||
return new WebSocket("ws://WS_PATH");
|
||||
|
@ -128,10 +131,37 @@
|
|||
}
|
||||
}
|
||||
|
||||
function installDeobfuscator() {
|
||||
if (!deobfuscate) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof main === 'function') {
|
||||
var oldMain = main;
|
||||
main = function() {
|
||||
var args = arguments;
|
||||
window.$teavm_deobfuscator_callback = function() {
|
||||
oldMain.apply(window, args);
|
||||
};
|
||||
var elem = document.createElement("script");
|
||||
elem.src = pathToFile + fileName + ".deobfuscator.js";
|
||||
elem.onload = function() {
|
||||
$teavm_deobfuscator([pathToFile + fileName + ".teavmdbg", pathToFile + fileName]);
|
||||
};
|
||||
document.head.append(elem);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (!boot) {
|
||||
installDeobfuscator();
|
||||
}
|
||||
|
||||
function startMain() {
|
||||
ws.close();
|
||||
window.removeEventListener("load", onLoad);
|
||||
document.body.removeChild(indicator.container);
|
||||
installDeobfuscator();
|
||||
main();
|
||||
}
|
||||
|
||||
|
@ -150,7 +180,7 @@
|
|||
window.location.reload(true);
|
||||
} else if (boot) {
|
||||
var scriptElem = document.createElement("script");
|
||||
scriptElem.src = "FILE_NAME";
|
||||
scriptElem.src = pathToFile + fileName;
|
||||
scriptElem.onload = startMain;
|
||||
document.head.appendChild(scriptElem);
|
||||
}
|
||||
|
@ -181,4 +211,4 @@
|
|||
window.addEventListener("message", connectDebugAgent);
|
||||
window.postMessage({teavmDebugger: {port: debugPort}}, "*");
|
||||
}
|
||||
})();
|
||||
})(this);
|
|
@ -22,6 +22,7 @@ public class DevServerConfiguration {
|
|||
public String[] classPath;
|
||||
public String[] sourcePath;
|
||||
public boolean indicator;
|
||||
public boolean deobfuscateStack;
|
||||
public boolean autoReload;
|
||||
public int port;
|
||||
public String pathToFile;
|
||||
|
|
|
@ -122,6 +122,9 @@ public class DevServerRunner extends UnicastRemoteObject implements DevServerMan
|
|||
case "-i":
|
||||
server.setIndicator(true);
|
||||
break;
|
||||
case "-deobf":
|
||||
server.setDeobfuscateStack(true);
|
||||
break;
|
||||
case "-a":
|
||||
server.setReloadedAutomatically(true);
|
||||
break;
|
||||
|
@ -178,6 +181,9 @@ public class DevServerRunner extends UnicastRemoteObject implements DevServerMan
|
|||
if (options.indicator) {
|
||||
arguments.add("-i");
|
||||
}
|
||||
if (options.deobfuscateStack) {
|
||||
arguments.add("-deobf");
|
||||
}
|
||||
if (options.autoReload) {
|
||||
arguments.add("-a");
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ public class TeaVMDevServerConfiguration extends ModuleBasedConfiguration<RunCon
|
|||
private String pathToFile = "";
|
||||
private String fileName = "classes.js";
|
||||
private boolean indicator = true;
|
||||
private boolean deobfuscateStack = true;
|
||||
private boolean automaticallyReloaded;
|
||||
private int maxHeap = 1024;
|
||||
private String proxyUrl = "";
|
||||
|
@ -155,6 +156,16 @@ public class TeaVMDevServerConfiguration extends ModuleBasedConfiguration<RunCon
|
|||
this.indicator = indicator;
|
||||
}
|
||||
|
||||
@Property
|
||||
@Tag
|
||||
public boolean isDeobfuscateStack() {
|
||||
return deobfuscateStack;
|
||||
}
|
||||
|
||||
public void setDeobfuscateStack(boolean deobfuscateStack) {
|
||||
this.deobfuscateStack = deobfuscateStack;
|
||||
}
|
||||
|
||||
@Property
|
||||
@Tag
|
||||
public boolean isAutomaticallyReloaded() {
|
||||
|
|
|
@ -78,6 +78,7 @@ public class TeaVMDevServerRunState implements RunProfileState {
|
|||
config.fileName = configuration.getFileName();
|
||||
config.port = configuration.getPort();
|
||||
config.indicator = configuration.isIndicator();
|
||||
config.deobfuscateStack = configuration.isDeobfuscateStack();
|
||||
config.autoReload = configuration.isAutomaticallyReloaded();
|
||||
config.mainClass = configuration.getMainClass();
|
||||
config.maxHeap = configuration.getMaxHeap();
|
||||
|
|
|
@ -48,6 +48,7 @@ public class TeaVMDevServerSettingsPanel extends JPanel {
|
|||
private JTextField pathToFileField;
|
||||
private JTextField fileNameField;
|
||||
private JCheckBox indicatorField;
|
||||
private JCheckBox deobfuscateStackField;
|
||||
private JCheckBox autoReloadField;
|
||||
private JFormattedTextField maxHeapField;
|
||||
private JTextField proxyUrlField;
|
||||
|
@ -76,6 +77,7 @@ public class TeaVMDevServerSettingsPanel extends JPanel {
|
|||
fileNameField = new JTextField();
|
||||
pathToFileField = new JTextField();
|
||||
indicatorField = new JCheckBox("Display indicator on a web page:");
|
||||
deobfuscateStackField = new JCheckBox("Deobfuscate stack traces in exceptions");
|
||||
autoReloadField = new JCheckBox("Reload page automatically:");
|
||||
maxHeapField = new JFormattedTextField(new DecimalFormat("#0"));
|
||||
|
||||
|
@ -118,6 +120,7 @@ public class TeaVMDevServerSettingsPanel extends JPanel {
|
|||
add(pathToFileField, constraints);
|
||||
|
||||
add(indicatorField, constraints);
|
||||
add(deobfuscateStackField, constraints);
|
||||
add(autoReloadField, constraints);
|
||||
|
||||
add(new JLabel("Server heap limit:"), labelConstraints);
|
||||
|
@ -137,6 +140,7 @@ public class TeaVMDevServerSettingsPanel extends JPanel {
|
|||
fileNameField.setText(configuration.getFileName());
|
||||
pathToFileField.setText(configuration.getPathToFile());
|
||||
indicatorField.setSelected(configuration.isIndicator());
|
||||
deobfuscateStackField.setSelected(configuration.isDeobfuscateStack());
|
||||
autoReloadField.setSelected(configuration.isAutomaticallyReloaded());
|
||||
maxHeapField.setText(Integer.toString(configuration.getMaxHeap()));
|
||||
portField.setText(Integer.toString(configuration.getPort()));
|
||||
|
@ -151,6 +155,7 @@ public class TeaVMDevServerSettingsPanel extends JPanel {
|
|||
configuration.setFileName(fileNameField.getText().trim());
|
||||
configuration.setPathToFile(pathToFileField.getText().trim());
|
||||
configuration.setIndicator(indicatorField.isSelected());
|
||||
configuration.setDeobfuscateStack(deobfuscateStackField.isSelected());
|
||||
configuration.setAutomaticallyReloaded(autoReloadField.isSelected());
|
||||
if (!maxHeapField.getText().trim().isEmpty()) {
|
||||
configuration.setMaxHeap(Integer.parseInt(maxHeapField.getText()));
|
||||
|
|
|
@ -110,6 +110,9 @@ public class TeaVMCompileMojo extends AbstractMojo {
|
|||
@Parameter(property = "teavm.mainClass")
|
||||
private String mainClass;
|
||||
|
||||
@Parameter(property = "teavm.entryPointName", defaultValue = "main")
|
||||
private String entryPointName;
|
||||
|
||||
@Parameter
|
||||
private String[] classesToPreserve;
|
||||
|
||||
|
@ -258,6 +261,7 @@ public class TeaVMCompileMojo extends AbstractMojo {
|
|||
builder.setLog(toolLog);
|
||||
try {
|
||||
builder.setMainClass(mainClass);
|
||||
builder.setEntryPointName(entryPointName);
|
||||
if (!targetFileName.isEmpty()) {
|
||||
builder.setTargetFileName(targetFileName);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user