wasm: add disassembler tool as a web application

This commit is contained in:
Alexey Andreev 2024-10-23 15:48:11 +02:00
parent 17b110debe
commit c56f5be2d9
6 changed files with 228 additions and 0 deletions

View File

@ -50,6 +50,7 @@ include("tools:idea")
include("tools:maven:plugin") include("tools:maven:plugin")
include("tools:maven:webapp") include("tools:maven:webapp")
include("tools:classlib-comparison-gen") include("tools:classlib-comparison-gen")
include("tools:wasm-disassembly")
include("tests") include("tests")
include("extras-slf4j") include("extras-slf4j")

View File

@ -26,11 +26,14 @@ import org.teavm.jso.core.JSObjects;
import org.teavm.jso.core.JSString; import org.teavm.jso.core.JSString;
import org.teavm.jso.core.JSSymbol; import org.teavm.jso.core.JSSymbol;
import org.teavm.jso.core.JSUndefined; import org.teavm.jso.core.JSUndefined;
import org.teavm.junit.OnlyPlatform;
import org.teavm.junit.SkipJVM; import org.teavm.junit.SkipJVM;
import org.teavm.junit.TeaVMTestRunner; import org.teavm.junit.TeaVMTestRunner;
import org.teavm.junit.TestPlatform;
@RunWith(TeaVMTestRunner.class) @RunWith(TeaVMTestRunner.class)
@SkipJVM @SkipJVM
@OnlyPlatform({ TestPlatform.JAVASCRIPT, TestPlatform.WEBASSEMBLY_GC })
public class JSSymbolTest { public class JSSymbolTest {
@Test @Test
public void getWorks() { public void getWorks() {

View File

@ -0,0 +1,70 @@
/*
* Copyright 2024 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.
*/
plugins {
`java-library`
}
configurations {
val teavmCompile = create("teavmCompile")
compileClasspath.configure {
extendsFrom(teavmCompile)
}
create("wasm")
}
dependencies {
compileOnly(project(":jso:apis"))
"teavmCompile"(project(":classlib"))
"teavmCompile"(project(":tools:core"))
}
val generateWasm by tasks.register<JavaExec>("generateWasm") {
outputs.dir(layout.buildDirectory.dir("webapp-out"))
dependsOn(tasks.classes)
classpath += configurations["teavmCompile"]
classpath += java.sourceSets.main.get().output.classesDirs
mainClass = "org.teavm.tooling.wasm.disassembly.Compiler"
args(
"org.teavm.tooling.wasm.disassembly.DisassemblerTool",
layout.buildDirectory.dir("webapp-out").get().asFile.absolutePath,
"disassembler.wasm"
)
}
val copyHtml by tasks.register<Copy>("copyHtml") {
outputs.dir(layout.buildDirectory.dir("webapp-out"))
from(sourceSets.getByName("main").resources.srcDirs)
into(layout.buildDirectory.dir("webapp-out"))
}
val copyRuntime by tasks.register<Copy>("copyRuntime") {
outputs.dir(layout.buildDirectory.dir("webapp-out"))
dependsOn(configurations["teavmCompile"])
from(providers.provider {
configurations["teavmCompile"].map { zipTree(it) }
})
into(layout.buildDirectory.dir("webapp-out"))
include("**/wasm-gc-runtime.js")
includeEmptyDirs = false
eachFile {
path = name
}
}
tasks.assemble.configure {
dependsOn(copyHtml, generateWasm, copyRuntime)
}

View File

@ -0,0 +1,47 @@
/*
* Copyright 2023 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.tooling.wasm.disassembly;
import java.io.File;
import org.teavm.tooling.ConsoleTeaVMToolLog;
import org.teavm.tooling.TeaVMProblemRenderer;
import org.teavm.tooling.TeaVMTargetType;
import org.teavm.tooling.TeaVMTool;
import org.teavm.tooling.TeaVMToolException;
import org.teavm.vm.TeaVMOptimizationLevel;
public final class Compiler {
private Compiler() {
}
public static void main(String[] args) throws TeaVMToolException {
var tool = new TeaVMTool();
var log = new ConsoleTeaVMToolLog(false);
tool.setTargetType(TeaVMTargetType.WEBASSEMBLY_GC);
tool.setMainClass(args[0]);
tool.setTargetDirectory(new File(args[1]));
tool.setTargetFileName(args[2]);
tool.setObfuscated(true);
tool.setOptimizationLevel(TeaVMOptimizationLevel.ADVANCED);
tool.setStrict(false);
tool.generate();
TeaVMProblemRenderer.describeProblems(tool.getDependencyInfo().getCallGraph(), tool.getProblemProvider(), log);
if (!tool.getProblemProvider().getSevereProblems().isEmpty()) {
System.exit(1);
}
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 2024 konsoletyper.
*
* 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.tooling.wasm.disassembly;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.teavm.backend.wasm.disasm.Disassembler;
import org.teavm.backend.wasm.disasm.DisassemblyHTMLWriter;
import org.teavm.backend.wasm.disasm.DisassemblyWriter;
import org.teavm.jso.JSExport;
public class DisassemblerTool {
private DisassemblerTool() {
}
@JSExport
public static String disassemble(byte[] data) {
var out = new StringWriter();
var writer = new PrintWriter(out);
var htmlWriter = new DisassemblyHTMLWriter(writer) {
@Override
public DisassemblyWriter prologue() {
return this;
}
@Override
public DisassemblyWriter epilogue() {
return this;
}
};
htmlWriter.setWithAddress(true);
var disassembler = new Disassembler(htmlWriter);
disassembler.disassemble(data);
return out.toString();
}
}

View File

@ -0,0 +1,58 @@
<!--
~ Copyright 2024 konsoletyper.
~
~ 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.
-->
<!DOCTYPE html>
<html>
<head>
<title>TeaVM WebAssembly disassembler</title>
<style>
.disassembly em {
color: grey;
}
</style>
<script src="wasm-gc-runtime.js"></script>
</head>
<body>
<p>Please, note that this is not full disassembler, it only supports subset of WebAssembly
used by TeaVM.</p>
<div>
<input type="file" id="file-input">
</div>
<pre class="disassembly" id="disassembly-output">
</pre>
<script>
async function load() {
let fileInput = document.getElementById("file-input");
fileInput.disabled = true;
let disassemblyOutput = document.getElementById("disassembly-output");
let module = await TeaVM.wasmGC.load("disassembler.wasm");
let disassemble = module.exports.disassemble;
fileInput.disabled = false;
fileInput.onchange = () => {
fileInput.disabled = true;
(async () => {
let file = fileInput.files[0];
let buffer = await file.arrayBuffer();
fileInput.disabled = false;
let array = new Int8Array(buffer);
disassemblyOutput.innerHTML = disassemble(array);
})();
};
}
load()
</script>
</body>
</html>