From 8b1acdf9d762272f787ac78ba41f9eacd721deb1 Mon Sep 17 00:00:00 2001 From: dorving Date: Wed, 29 Mar 2023 10:06:18 +0200 Subject: [PATCH] Added G-Wasm project sources --- G-Earth/build.gradle.kts | 25 +- G-Wasm/.gitignore | 11 + G-Wasm/README.md | 4 + G-Wasm/build.gradle.kts | 13 + G-Wasm/pom.xml | 60 +++++ G-Wasm/src/main/java/wasm/GWasm.java | 27 ++ .../disassembly/InvalidOpCodeException.java | 8 + .../java/wasm/disassembly/WASMOpCode.java | 9 + .../disassembly/conventions/Assembler.java | 10 + .../wasm/disassembly/conventions/Creator.java | 13 + .../disassembly/conventions/CustomVector.java | 47 ++++ .../wasm/disassembly/conventions/Vector.java | 44 +++ .../disassembly/instructions/Expression.java | 44 +++ .../wasm/disassembly/instructions/Instr.java | 33 +++ .../instructions/InstrFactory.java | 86 ++++++ .../instructions/InstrSupplier.java | 13 + .../disassembly/instructions/InstrType.java | 233 ++++++++++++++++ .../instructions/control/BlockInstr.java | 62 +++++ .../instructions/control/BlockType.java | 72 +++++ .../instructions/control/BranchInstr.java | 39 +++ .../control/BranchTableInstr.java | 53 ++++ .../control/CallIndirectInstr.java | 44 +++ .../instructions/control/CallInstr.java | 39 +++ .../instructions/control/IfElseInstr.java | 88 ++++++ .../instructions/memory/Mem0Instr.java | 24 ++ .../instructions/memory/MemArg.java | 48 ++++ .../instructions/memory/MemInstr.java | 38 +++ .../instructions/misc/SingleByteInstr.java | 20 ++ .../numeric/NumericF32ConstInstr.java | 39 +++ .../numeric/NumericF64ConstInstr.java | 39 +++ .../numeric/NumericI32ConstInstr.java | 39 +++ .../numeric/NumericI64ConstInstr.java | 39 +++ .../instructions/numeric/NumericInstr.java | 21 ++ .../instructions/numeric/TruncSatInstr.java | 42 +++ .../variable/GlobalVariableInstr.java | 39 +++ .../variable/LocalVariableInstr.java | 39 +++ .../java/wasm/disassembly/modules/Magic.java | 31 +++ .../java/wasm/disassembly/modules/Module.java | 253 ++++++++++++++++++ .../wasm/disassembly/modules/Version.java | 40 +++ .../disassembly/modules/indices/FuncIdx.java | 48 ++++ .../modules/indices/GlobalIdx.java | 36 +++ .../disassembly/modules/indices/LabelIdx.java | 36 +++ .../disassembly/modules/indices/LocalIdx.java | 36 +++ .../disassembly/modules/indices/MemIdx.java | 36 +++ .../disassembly/modules/indices/TableIdx.java | 36 +++ .../disassembly/modules/indices/TypeIdx.java | 41 +++ .../disassembly/modules/sections/Section.java | 57 ++++ .../modules/sections/SectionSupplier.java | 12 + .../modules/sections/code/Code.java | 43 +++ .../modules/sections/code/CodeSection.java | 123 +++++++++ .../modules/sections/code/Func.java | 75 ++++++ .../modules/sections/code/Locals.java | 57 ++++ .../sections/custom/CustomSection.java | 38 +++ .../sections/custom/CustomSectionFactory.java | 24 ++ .../custom/UnImplementedCustomSection.java | 40 +++ .../custom/namesection/NameSection.java | 74 +++++ .../subsections/FunctionNamesSubSection.java | 40 +++ .../subsections/LocalNamesSubSection.java | 42 +++ .../subsections/ModuleNameSubSection.java | 39 +++ .../namesection/subsections/SubSection.java | 44 +++ .../namemaps/IndirectNameAssoc.java | 48 ++++ .../subsections/namemaps/IndirectNameMap.java | 38 +++ .../subsections/namemaps/NameAssoc.java | 49 ++++ .../subsections/namemaps/NameMap.java | 38 +++ .../modules/sections/data/Data.java | 67 +++++ .../modules/sections/data/DataSection.java | 57 ++++ .../modules/sections/element/Elem.java | 63 +++++ .../sections/element/ElementSection.java | 57 ++++ .../modules/sections/export/Export.java | 48 ++++ .../modules/sections/export/ExportDesc.java | 76 ++++++ .../sections/export/ExportSection.java | 58 ++++ .../sections/function/FunctionSection.java | 90 +++++++ .../modules/sections/global/Global.java | 49 ++++ .../sections/global/GlobalSection.java | 42 +++ .../modules/sections/imprt/Import.java | 60 +++++ .../modules/sections/imprt/ImportDesc.java | 75 ++++++ .../modules/sections/imprt/ImportSection.java | 119 ++++++++ .../modules/sections/memory/Mem.java | 37 +++ .../sections/memory/MemorySection.java | 43 +++ .../modules/sections/start/Start.java | 37 +++ .../modules/sections/start/StartSection.java | 40 +++ .../modules/sections/table/Table.java | 36 +++ .../modules/sections/table/TableSection.java | 42 +++ .../modules/sections/type/TypeSection.java | 65 +++++ .../java/wasm/disassembly/types/ElemType.java | 26 ++ .../java/wasm/disassembly/types/FuncType.java | 68 +++++ .../wasm/disassembly/types/GlobalType.java | 47 ++++ .../java/wasm/disassembly/types/Limits.java | 62 +++++ .../java/wasm/disassembly/types/MemType.java | 34 +++ .../wasm/disassembly/types/Mutability.java | 26 ++ .../wasm/disassembly/types/ResultType.java | 70 +++++ .../wasm/disassembly/types/TableType.java | 50 ++++ .../java/wasm/disassembly/types/ValType.java | 29 ++ .../java/wasm/disassembly/values/WDouble.java | 22 ++ .../java/wasm/disassembly/values/WFloat.java | 22 ++ .../java/wasm/disassembly/values/WName.java | 25 ++ .../wasm/disassembly/values/WSignedInt.java | 59 ++++ .../wasm/disassembly/values/WSignedLong.java | 54 ++++ .../wasm/disassembly/values/WUnsignedInt.java | 47 ++++ .../disassembly/values/WUnsignedLong.java | 58 ++++ G-Wasm/src/main/java/wasm/misc/Function.java | 78 ++++++ .../java/wasm/misc/StreamReplacement.java | 19 ++ settings.gradle.kts | 1 + 103 files changed, 4930 insertions(+), 6 deletions(-) create mode 100644 G-Wasm/.gitignore create mode 100644 G-Wasm/README.md create mode 100644 G-Wasm/build.gradle.kts create mode 100644 G-Wasm/pom.xml create mode 100644 G-Wasm/src/main/java/wasm/GWasm.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/InvalidOpCodeException.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/WASMOpCode.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/conventions/Assembler.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/conventions/Creator.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/conventions/CustomVector.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/conventions/Vector.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/Expression.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/Instr.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/InstrFactory.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/InstrSupplier.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/InstrType.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/control/BlockInstr.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/control/BlockType.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/control/BranchInstr.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/control/BranchTableInstr.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/control/CallIndirectInstr.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/control/CallInstr.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/control/IfElseInstr.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/memory/Mem0Instr.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/memory/MemArg.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/memory/MemInstr.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/misc/SingleByteInstr.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericF32ConstInstr.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericF64ConstInstr.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericI32ConstInstr.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericI64ConstInstr.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericInstr.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/TruncSatInstr.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/variable/GlobalVariableInstr.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/instructions/variable/LocalVariableInstr.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/Magic.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/Module.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/Version.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/indices/FuncIdx.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/indices/GlobalIdx.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/indices/LabelIdx.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/indices/LocalIdx.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/indices/MemIdx.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/indices/TableIdx.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/indices/TypeIdx.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/Section.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/SectionSupplier.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/code/Code.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/code/CodeSection.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/code/Func.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/code/Locals.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/CustomSection.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/CustomSectionFactory.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/UnImplementedCustomSection.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/NameSection.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/FunctionNamesSubSection.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/LocalNamesSubSection.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/ModuleNameSubSection.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/SubSection.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/namemaps/IndirectNameAssoc.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/namemaps/IndirectNameMap.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/namemaps/NameAssoc.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/namemaps/NameMap.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/data/Data.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/data/DataSection.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/element/Elem.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/element/ElementSection.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/export/Export.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/export/ExportDesc.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/export/ExportSection.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/function/FunctionSection.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/global/Global.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/global/GlobalSection.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/imprt/Import.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/imprt/ImportDesc.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/imprt/ImportSection.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/memory/Mem.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/memory/MemorySection.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/start/Start.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/start/StartSection.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/table/Table.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/table/TableSection.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/modules/sections/type/TypeSection.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/types/ElemType.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/types/FuncType.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/types/GlobalType.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/types/Limits.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/types/MemType.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/types/Mutability.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/types/ResultType.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/types/TableType.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/types/ValType.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/values/WDouble.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/values/WFloat.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/values/WName.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/values/WSignedInt.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/values/WSignedLong.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/values/WUnsignedInt.java create mode 100644 G-Wasm/src/main/java/wasm/disassembly/values/WUnsignedLong.java create mode 100644 G-Wasm/src/main/java/wasm/misc/Function.java create mode 100644 G-Wasm/src/main/java/wasm/misc/StreamReplacement.java diff --git a/G-Earth/build.gradle.kts b/G-Earth/build.gradle.kts index 3aa67a6..c26eae7 100644 --- a/G-Earth/build.gradle.kts +++ b/G-Earth/build.gradle.kts @@ -12,18 +12,25 @@ plugins { description = "G-Earth" repositories { + mavenLocal() mavenCentral() - maven("https://jitpack.io") +// maven("https://jitpack.io") } /** * TODO: move dependency version declarations to different gradle file */ dependencies { - implementation("com.github.dorving:G-Wasm:minimal-SNAPSHOT") + implementation(project(":G-Wasm")) +// implementation("com.github.dorving:G-Wasm:minimal-SNAPSHOT") implementation("at.favre.lib:bytes:1.5.0") - implementation("com.github.tulskiy:jkeymaster:1.3") - implementation("com.github.ganskef:littleproxy-mitm:1.1.0") + implementation("com.github.tulskiy:jkeymaster:1.3") { + exclude("org.slf4j", "slf4j-api") + } + implementation("com.github.ganskef:littleproxy-mitm:1.1.0") { + exclude("org.slf4j", "slf4j-api") + exclude("org.slf4j", "slf4j-log4j12") + } implementation("commons-io:commons-io:2.10.0") implementation("javax.websocket:javax.websocket-api:1.1") implementation("org.apache.maven:maven-artifact:3.6.3") @@ -31,12 +38,15 @@ dependencies { implementation("org.eclipse.jetty.websocket:javax-websocket-server-impl:9.4.43.v20210629") { exclude("javax.websocket", "javax.websocket-client-api") } + implementation("com.dustinredmond.fxtrayicon:FXTrayIcon:4.0.1") implementation("org.eclipse.jetty:jetty-http:9.4.43.v20210629") implementation("org.fxmisc.richtext:richtextfx:0.10.5") implementation("org.json:json:20190722") implementation("org.jsoup:jsoup:1.14.2") - implementation("org.slf4j:slf4j-jdk14:2.0.0-alpha0") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.3") +// implementation("org.slf4j:slf4j-jdk14:2.0.0-alpha0") + implementation("ch.qos.logback:logback-core:1.3.5") + implementation("ch.qos.logback:logback-classic:1.3.5") } java { @@ -74,11 +84,14 @@ tasks.getByName("assemble") { } publishing { + repositories { + maven("/Users/stanvanderbend/.m2/repository") + } publications { create("maven") { groupId = "karth.gearth" artifactId = "gearth" - version = "1.5.2" + version = "1.5.3" from(components["java"]) } } diff --git a/G-Wasm/.gitignore b/G-Wasm/.gitignore new file mode 100644 index 0000000..e0b89a7 --- /dev/null +++ b/G-Wasm/.gitignore @@ -0,0 +1,11 @@ +# intelliJ +.idea/ +*.iml +out/ + +# self experiments +src/main/java/misc/ + +# maven +bin/ +**/target/ diff --git a/G-Wasm/README.md b/G-Wasm/README.md new file mode 100644 index 0000000..c2a83f1 --- /dev/null +++ b/G-Wasm/README.md @@ -0,0 +1,4 @@ +# G-Wasm +Java disassembler&assembler for WebAssembly + +#### For the G-Wasm version that is used in G-Earth, go to the branch named "minimal" (runs 8x more memory efficient & 3.5x faster) diff --git a/G-Wasm/build.gradle.kts b/G-Wasm/build.gradle.kts new file mode 100644 index 0000000..fd3ec30 --- /dev/null +++ b/G-Wasm/build.gradle.kts @@ -0,0 +1,13 @@ +import org.gradle.internal.os.OperatingSystem + +plugins { + java + `java-library` +} + +description = "G-Wasm" + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} \ No newline at end of file diff --git a/G-Wasm/pom.xml b/G-Wasm/pom.xml new file mode 100644 index 0000000..647f3c9 --- /dev/null +++ b/G-Wasm/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + + G-Earth + G-Wasm + 1.0.1 + + + + + + + maven-assembly-plugin + 2.5 + + + package + + single + + + + + ${project.build.directory}/bin + + + wasm.GWasm + + + + jar-with-dependencies + + ${project.artifactId} + false + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + + + + + + /src/main/resources + + + + + \ No newline at end of file diff --git a/G-Wasm/src/main/java/wasm/GWasm.java b/G-Wasm/src/main/java/wasm/GWasm.java new file mode 100644 index 0000000..cd2f878 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/GWasm.java @@ -0,0 +1,27 @@ +package wasm; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.modules.Module; + +import java.io.*; +import java.util.ArrayList; + +public class GWasm { + + public static void main(String[] args) throws IOException, InvalidOpCodeException { + + long start = System.currentTimeMillis(); + Module module = new Module("C:\\Users\\jonas\\Desktop\\Projects\\Jznnp\\S\\habbo2020\\rawfiles\\0.23.0_(534)\\habbo2020-global-prod.wasm.gz", true, new ArrayList<>()); + long end = System.currentTimeMillis(); + + System.out.println("Disassemble time: " + (end - start)); + + start = System.currentTimeMillis(); + module.assembleToFile("C:\\Users\\jonas\\Desktop\\Projects\\Jznnp\\S\\habbo2020\\rawfiles\\0.23.0_(534)\\out\\habbo2020-global-prod.wasm.gz", true); + end = System.currentTimeMillis(); + + System.out.println("Assemble time: " + (end - start)); + + System.out.println("hi"); + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/InvalidOpCodeException.java b/G-Wasm/src/main/java/wasm/disassembly/InvalidOpCodeException.java new file mode 100644 index 0000000..e2b0a17 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/InvalidOpCodeException.java @@ -0,0 +1,8 @@ +package wasm.disassembly; + +public class InvalidOpCodeException extends Exception { + + public InvalidOpCodeException(String message) { + super(message); + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/WASMOpCode.java b/G-Wasm/src/main/java/wasm/disassembly/WASMOpCode.java new file mode 100644 index 0000000..686f71b --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/WASMOpCode.java @@ -0,0 +1,9 @@ +package wasm.disassembly; + +import java.io.*; + +public abstract class WASMOpCode { + + public abstract void assemble(OutputStream out) throws IOException, InvalidOpCodeException; + +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/conventions/Assembler.java b/G-Wasm/src/main/java/wasm/disassembly/conventions/Assembler.java new file mode 100644 index 0000000..a340ff2 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/conventions/Assembler.java @@ -0,0 +1,10 @@ +package wasm.disassembly.conventions; + +import java.io.IOException; +import java.io.OutputStream; + +public interface Assembler { + + void assemble(B b, OutputStream out) throws IOException; + +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/conventions/Creator.java b/G-Wasm/src/main/java/wasm/disassembly/conventions/Creator.java new file mode 100644 index 0000000..22d0af3 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/conventions/Creator.java @@ -0,0 +1,13 @@ +package wasm.disassembly.conventions; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.modules.Module; + +import java.io.BufferedInputStream; +import java.io.IOException; + +public interface Creator { + + B create(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException; + +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/conventions/CustomVector.java b/G-Wasm/src/main/java/wasm/disassembly/conventions/CustomVector.java new file mode 100644 index 0000000..63763a0 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/conventions/CustomVector.java @@ -0,0 +1,47 @@ +package wasm.disassembly.conventions; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +public class CustomVector extends WASMOpCode { + + private List elements; + private Assembler assembler; + + public CustomVector(BufferedInputStream in, Creator creator, Assembler assembler, Module module) throws IOException, InvalidOpCodeException { + long length = WUnsignedInt.read(in, 32); + elements = new ArrayList<>(1); + for (int i = 0; i < length; i++) { + elements.add(creator.create(in, module)); + } + this.assembler = assembler; + } + + public CustomVector(List elements, Assembler assembler) { + this.elements = elements; + this.assembler = assembler; + } + + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + WUnsignedInt.write(elements.size(), out, 32); + for (B b : elements) { + assembler.assemble(b, out); + } + } + + public List getElements() { + return elements; + } + + public void setElements(List elements) { + this.elements = elements; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/conventions/Vector.java b/G-Wasm/src/main/java/wasm/disassembly/conventions/Vector.java new file mode 100644 index 0000000..d4337c5 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/conventions/Vector.java @@ -0,0 +1,44 @@ +package wasm.disassembly.conventions; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +public class Vector extends WASMOpCode { + + private List elements; + + public Vector(BufferedInputStream in, Creator creator, Module module) throws IOException, InvalidOpCodeException { + long length = WUnsignedInt.read(in, 32); + elements = new ArrayList<>(1); + for (int i = 0; i < length; i++) { + elements.add(creator.create(in, module)); + } + } + + public Vector(List elements) { + this.elements = elements; + } + + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + WUnsignedInt.write(elements.size(), out, 32); + for (B b : elements) { + b.assemble(out); + } + } + + public List getElements() { + return elements; + } + + public void setElements(List elements) { + this.elements = elements; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/Expression.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/Expression.java new file mode 100644 index 0000000..4fe51ef --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/Expression.java @@ -0,0 +1,44 @@ +package wasm.disassembly.instructions; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +public class Expression extends WASMOpCode { + + private List instructions; + + public Expression(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + instructions = new ArrayList<>(); + InstrType type; + while ((type = InstrFactory.disassembleType(in)) != InstrType.END) { + instructions.add(InstrFactory.disassemble(in, type, module)); + } + } + + public Expression(List instructions) { + this.instructions = instructions; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + for(Instr instr : instructions) { + instr.assemble(out); + } + out.write(InstrType.END.val); + } + + public List getInstructions() { + return instructions; + } + + public void setInstructions(List instructions) { + this.instructions = instructions; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/Instr.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/Instr.java new file mode 100644 index 0000000..b8c105d --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/Instr.java @@ -0,0 +1,33 @@ +package wasm.disassembly.instructions; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; + +import java.io.IOException; +import java.io.OutputStream; + +public abstract class Instr extends WASMOpCode { + + private InstrType instrType; + + public Instr(InstrType instrType) throws IOException { + this.instrType = instrType; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + out.write(instrType.val); + assemble2(out); + } + + protected abstract void assemble2(OutputStream out) throws IOException, InvalidOpCodeException; + + public InstrType getInstrType() { + return instrType; + } + + public void setInstrType(InstrType instrType) { + this.instrType = instrType; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/InstrFactory.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/InstrFactory.java new file mode 100644 index 0000000..d9000a8 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/InstrFactory.java @@ -0,0 +1,86 @@ +package wasm.disassembly.instructions; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.instructions.control.*; +import wasm.disassembly.instructions.memory.Mem0Instr; +import wasm.disassembly.instructions.memory.MemInstr; +import wasm.disassembly.instructions.misc.SingleByteInstr; +import wasm.disassembly.instructions.numeric.*; +import wasm.disassembly.instructions.variable.GlobalVariableInstr; +import wasm.disassembly.instructions.variable.LocalVariableInstr; +import wasm.disassembly.modules.Module; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class InstrFactory { + + public static InstrType disassembleType(BufferedInputStream in) throws IOException, InvalidOpCodeException { + InstrType type = InstrType.from_val(in.read()); + if (type == null) { + throw new InvalidOpCodeException("Invalid instruction prefix"); + } + + return type; + } + + private final static Map map; + static { + map = new HashMap<>(); + + // control instructions + map.put(InstrType.UNREACHABLE, SingleByteInstr::new); + map.put(InstrType.NOP, SingleByteInstr::new); + + map.put(InstrType.BLOCK, BlockInstr::new); + map.put(InstrType.LOOP, BlockInstr::new); + map.put(InstrType.IF, IfElseInstr::new); + + map.put(InstrType.BR, BranchInstr::new); + map.put(InstrType.BR_IF, BranchInstr::new); + map.put(InstrType.BR_TABLE, BranchTableInstr::new); + + map.put(InstrType.RETURN, SingleByteInstr::new); + map.put(InstrType.CALL, CallInstr::new); + map.put(InstrType.CALL_INDIRECT, CallIndirectInstr::new); + + + // parametric instructions + map.put(InstrType.DROP, SingleByteInstr::new); + map.put(InstrType.SELECT, SingleByteInstr::new); + + + // variable instructions + for (int i = 0x20; i <= 0x22; i++) map.put(InstrType.from_val(i), LocalVariableInstr::new); + for (int i = 0x23; i <= 0x24; i++) map.put(InstrType.from_val(i), GlobalVariableInstr::new); + + + // memory instructions + for (int i = 0x28; i <= 0x3E; i++) map.put(InstrType.from_val(i), MemInstr::new); + for (int i = 0x3F; i <= 0x40; i++) map.put(InstrType.from_val(i), Mem0Instr::new); + + + // numeric instructions + map.put(InstrType.I32_CONST, NumericI32ConstInstr::new); + map.put(InstrType.I64_CONST, NumericI64ConstInstr::new); + map.put(InstrType.F32_CONST, NumericF32ConstInstr::new); + map.put(InstrType.F64_CONST, NumericF64ConstInstr::new); + for (int i = 0x45; i <= 0xC4; i++) map.put(InstrType.from_val(i), NumericInstr::new); + map.put(InstrType.IXX_TRUNC_SAT_FXX_SU, TruncSatInstr::new); + } + + public static Instr disassemble(BufferedInputStream in, InstrType instrType, Module module) throws InvalidOpCodeException, IOException { + if (instrType == InstrType.END || instrType == InstrType.ELSE) { + throw new InvalidOpCodeException("Instruction invalid as a standalone instruction"); + } + + if (instrType == null) { + throw new InvalidOpCodeException("Invalid instruction prefix"); + } + + return map.get(instrType).get(in, instrType, module); + } + +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/InstrSupplier.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/InstrSupplier.java new file mode 100644 index 0000000..7d85520 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/InstrSupplier.java @@ -0,0 +1,13 @@ +package wasm.disassembly.instructions; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.modules.Module; + +import java.io.BufferedInputStream; +import java.io.IOException; + +public interface InstrSupplier { + + Instr get(BufferedInputStream in, InstrType type, Module module) throws IOException, InvalidOpCodeException; + +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/InstrType.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/InstrType.java new file mode 100644 index 0000000..da1e0a0 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/InstrType.java @@ -0,0 +1,233 @@ +package wasm.disassembly.instructions; + +import java.util.HashMap; +import java.util.Map; + +public enum InstrType { + + // control instructions + UNREACHABLE(0x00), + NOP(0x01), + BLOCK(0x02), + LOOP(0x03), + IF(0x04), + ELSE(0x05), + + END(0x0B), + BR(0x0C), + BR_IF(0x0D), + BR_TABLE(0x0E), + RETURN(0x0F), + CALL(0x10), + CALL_INDIRECT(0x11), + + + // parametric instructions + DROP(0x1A), + SELECT(0x1B), + + + // variable instructions + LOCAL_GET(0x20), + LOCAL_SET(0x21), + LOCAL_TEE(0x22), + GLOBAL_GET(0x23), + GLOBAL_SET(0x24), + + + // memory instructions + I32_LOAD(0x28), + I64_LOAD(0x29), + F32_LOAD(0x2A), + F64_LOAD(0x2B), + I32_LOAD8_S(0x2C), + I32_LOAD8_U(0x2D), + I32_LOAD16_S(0x2E), + I32_LOAD16_U(0x2F), + I64_LOAD8_S(0x30), + I64_LOAD8_U(0x31), + I64_LOAD16_S(0x32), + I64_LOAD16_U(0x33), + I64_LOAD32_S(0x34), + I64_LOAD32_U(0x35), + + I32_STORE(0x36), + I64_STORE(0x37), + F32_STORE(0x38), + F64_STORE(0x39), + I32_STORE8(0x3A), + I32_STORE16(0x3B), + I64_STORE8(0X3C), + I64_STORE16(0x3D), + I64_STORE32(0x3E), + + MEMORY_SIZE(0x3F), + MEMORY_GROW(0x40), + + + // numeric instructions + I32_CONST(0x41), + I64_CONST(0x42), + F32_CONST(0x43), + F64_CONST(0x44), + + I32_EQZ(0x45), + I32_EQ(0x46), + I32_NE(0x47), + I32_LT_S(0x48), + I32_LT_U(0x49), + I32_GT_S(0x4A), + I32_GT_U(0x4B), + I32_LE_S(0x4C), + I32_LE_U(0x4D), + I32_GE_S(0x4E), + I32_GE_U(0x4F), + + I64_EQZ(0x50), + I64_EQ(0x51), + I64_NE(0x52), + I64_LT_S(0x53), + I64_LT_U(0x54), + I64_GT_S(0x55), + I64_GT_U(0x56), + I64_LE_S(0x57), + I64_LE_U(0x58), + I64_GE_S(0x59), + I64_GE_U(0x5A), + + F32_EQ(0x5B), + F32_NE(0x5C), + F32_LT(0x5D), + F32_GT(0x5E), + F32_LE(0x5F), + F32_GE(0x60), + + F64_EQ(0x61), + F64_NE(0x62), + F64_LT(0x63), + F64_GT(0x64), + F64_LE(0x65), + F64_GE(0x66), + + I32_CLZ(0x67), + I32_CTZ(0x68), + I32_POPCNT(0x69), + I32_ADD(0x6A), + I32_SUB(0x6B), + I32_MUL(0x6C), + I32_DIV_S(0x6D), + I32_DIV_U(0x6E), + I32_REM_S(0x6F), + I32_REM_U(0x70), + I32_AND(0x71), + I32_OR(0x72), + I32_XOR(0x73), + I32_SHL(0x74), + I32_SHR_S(0x75), + I32_SHR_U(0x76), + I32_ROTL(0x77), + I32_ROTR(0x78), + + I64_CLZ(0x79), + I64_CTZ(0x7A), + I64_POPCNT(0x7B), + I64_ADD(0x7C), + I64_SUB(0x7D), + I64_MUL(0x7E), + I64_DIV_S(0x7F), + I64_DIV_U(0x80), + I64_REM_S(0x81), + I64_REM_U(0x82), + I64_AND(0x83), + I64_OR(0x84), + I64_XOR(0x85), + I64_SHL(0x86), + I64_SHR_S(0x87), + I64_SHR_U(0x88), + I64_ROTL(0x89), + I64_ROTR(0x8A), + + F32_ABS(0x8B), + F32_NEG(0x8C), + F32_CEIL(0x8D), + F32_FLOOR(0x8E), + F32_TRUNC(0x8F), + F32_NEAREST(0x90), + F32_SQRT(0x91), + F32_ADD(0x92), + F32_SUB(0x93), + F32_MUL(0x94), + F32_DIV(0x95), + F32_MIN(0x96), + F32_MAX(0x97), + F32_COPYSIGN(0x98), + + F64_ABS(0x99), + F64_NEG(0x9A), + F64_CEIL(0x9B), + F64_FLOOR(0x9C), + F64_TRUNC(0x9D), + F64_NEAREST(0x9E), + F64_SQRT(0x9F), + F64_ADD(0xA0), + F64_SUB(0xA1), + F64_MUL(0xA2), + F64_DIV(0xA3), + F64_MIN(0xA4), + F64_MAX(0xA5), + F64_COPYSIGN(0xA6), + + I32_WRAP_I64(0xA7), + I32_TRUNC_F32_S(0xA8), + I32_TRUNC_F32_U(0xA9), + I32_TRUNC_F64_S(0xAA), + I32_TRUNC_F64_U(0xAB), + I64_EXTEND_I32_S(0xAC), + I64_EXTEND_I32_U(0xAD), + I64_TRUNC_F32_S(0xAE), + I64_TRUNC_F32_U(0xAF), + I64_TRUNC_F64_S(0xB0), + I64_TRUNC_F64_U(0xB1), + F32_CONVERT_I32_S(0xB2), + F32_CONVERT_I32_U(0xB3), + F32_CONVERT_I64_S(0xB4), + F32_CONVERT_I64_U(0xB5), + F32_DEMOTE_F64(0xB6), + F64_CONVERT_I32_S(0xB7), + F64_CONVERT_I32_U(0xB8), + F64_CONVERT_I64_S(0xB9), + F64_CONVERT_I64_U(0xBA), + F64_PROMOTE_F32(0xBB), + I32_REINTERPRET_F32(0xBC), + I64_REINTERPRET_F64(0xBD), + F32_REINTERPRET_I32(0xBE), + F64_REINTERPRET_I64(0xBF), + + I32_EXTEND8_S(0xC0), + I32_EXTENDS16_S(0xC1), + I64_EXTEND8_S(0xC2), + I64_EXTENDS16_6(0xC3), + I64_EXTENDS32_S(0xC4), + + IXX_TRUNC_SAT_FXX_SU(0xFC); + + + + public int val; + InstrType(int val) { + this.val = val; + } + + private static Map map = new HashMap<>(); + static { + for (InstrType valType : InstrType.values()) { + map.put(valType.val, valType); + } + } + + public static InstrType from_val(int val) { + return map.get(val); + } + + +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/control/BlockInstr.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/control/BlockInstr.java new file mode 100644 index 0000000..f737d81 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/control/BlockInstr.java @@ -0,0 +1,62 @@ +package wasm.disassembly.instructions.control; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.instructions.Instr; +import wasm.disassembly.instructions.InstrFactory; +import wasm.disassembly.instructions.InstrType; +import wasm.disassembly.modules.Module; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +public class BlockInstr extends Instr { + + private List blockInstructions; + private BlockType blockType; + + public BlockInstr(BufferedInputStream in, InstrType instrType, Module module) throws IOException, InvalidOpCodeException { + super(instrType); + + blockType = new BlockType(in, module); + + blockInstructions = new ArrayList<>(4); + InstrType type; + while ((type = InstrFactory.disassembleType(in)) != InstrType.END) { + blockInstructions.add(InstrFactory.disassemble(in, type, module)); + } + } + + public BlockInstr(InstrType instrType, List blockInstructions, BlockType blockType) throws IOException { + super(instrType); + this.blockInstructions = blockInstructions; + this.blockType = blockType; + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + blockType.assemble(out); + for(Instr instr : blockInstructions) { + instr.assemble(out); + } + out.write(InstrType.END.val); + } + + public List getBlockInstructions() { + return blockInstructions; + } + + public void setBlockInstructions(List blockInstructions) { + this.blockInstructions = blockInstructions; + } + + public BlockType getBlockType() { + return blockType; + } + + public void setBlockType(BlockType blockType) { + this.blockType = blockType; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/control/BlockType.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/control/BlockType.java new file mode 100644 index 0000000..ed392d8 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/control/BlockType.java @@ -0,0 +1,72 @@ +package wasm.disassembly.instructions.control; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.types.ValType; +import wasm.disassembly.values.WSignedLong; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class BlockType extends WASMOpCode { + + private Object value; + + public BlockType(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + in.mark(1); + int first = in.read(); + + if (first == 0x40) { + value = null; + } + else if (ValType.from_val(first) != null) { + value = ValType.from_val(first); + } + else { + in.reset(); + value = WSignedLong.read(in, 33); + } + } + + public BlockType(Object value) { + this.value = value; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + if (value == null) { + out.write(0x40); + } + else if (value instanceof ValType) { + out.write(((ValType)value).val); + } + else if (value instanceof Long) { + WSignedLong.write((Long)value, out, 33); + } + else { + throw new InvalidOpCodeException("Invalid block type"); + } + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + + public boolean isEmpty() { + return value == null; + } + + public boolean isValueType() { + return value != null && value instanceof ValType; + } + + public boolean isSignedInteger() { + return value != null && value instanceof Long; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/control/BranchInstr.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/control/BranchInstr.java new file mode 100644 index 0000000..4da1a8c --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/control/BranchInstr.java @@ -0,0 +1,39 @@ +package wasm.disassembly.instructions.control; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.instructions.Instr; +import wasm.disassembly.instructions.InstrType; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.indices.LabelIdx; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class BranchInstr extends Instr { + + private LabelIdx labelIdx; + + public BranchInstr(BufferedInputStream in, InstrType instrType, Module module) throws IOException, InvalidOpCodeException { + super(instrType); + labelIdx = new LabelIdx(in, module); + } + + public BranchInstr(InstrType instrType, LabelIdx labelIdx) throws IOException { + super(instrType); + this.labelIdx = labelIdx; + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + labelIdx.assemble(out); + } + + public LabelIdx getLabelIdx() { + return labelIdx; + } + + public void setLabelIdx(LabelIdx labelIdx) { + this.labelIdx = labelIdx; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/control/BranchTableInstr.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/control/BranchTableInstr.java new file mode 100644 index 0000000..bc7f249 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/control/BranchTableInstr.java @@ -0,0 +1,53 @@ +package wasm.disassembly.instructions.control; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.conventions.Creator; +import wasm.disassembly.conventions.Vector; +import wasm.disassembly.instructions.Instr; +import wasm.disassembly.instructions.InstrType; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.indices.LabelIdx; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class BranchTableInstr extends Instr { + + private Vector table; + private LabelIdx labelIdx; + + public BranchTableInstr(BufferedInputStream in, InstrType instrType, Module module) throws IOException, InvalidOpCodeException { + super(instrType); + table = new Vector<>(in, LabelIdx::new, module); + labelIdx = new LabelIdx(in, module); + } + + public BranchTableInstr(InstrType instrType, Vector table, LabelIdx labelIdx) throws IOException { + super(instrType); + this.table = table; + this.labelIdx = labelIdx; + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + table.assemble(out); + labelIdx.assemble(out); + } + + public Vector getTable() { + return table; + } + + public void setTable(Vector table) { + this.table = table; + } + + public LabelIdx getLabelIdx() { + return labelIdx; + } + + public void setLabelIdx(LabelIdx labelIdx) { + this.labelIdx = labelIdx; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/control/CallIndirectInstr.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/control/CallIndirectInstr.java new file mode 100644 index 0000000..03dd552 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/control/CallIndirectInstr.java @@ -0,0 +1,44 @@ +package wasm.disassembly.instructions.control; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.instructions.Instr; +import wasm.disassembly.instructions.InstrType; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.indices.FuncIdx; +import wasm.disassembly.modules.indices.TypeIdx; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class CallIndirectInstr extends Instr { + + private TypeIdx typeIdx; + + public CallIndirectInstr(BufferedInputStream in, InstrType instrType, Module module) throws IOException, InvalidOpCodeException { + super(instrType); + typeIdx = new TypeIdx(in, module); + if (in.read() != 0x00) { + throw new InvalidOpCodeException("Unexpected non-zero byte"); + } + } + + public CallIndirectInstr(InstrType instrType, TypeIdx typeIdx) throws IOException { + super(instrType); + this.typeIdx = typeIdx; + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + typeIdx.assemble(out); + out.write(0x00); + } + + public TypeIdx getTypeIdx() { + return typeIdx; + } + + public void setTypeIdx(TypeIdx typeIdx) { + this.typeIdx = typeIdx; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/control/CallInstr.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/control/CallInstr.java new file mode 100644 index 0000000..acef1f9 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/control/CallInstr.java @@ -0,0 +1,39 @@ +package wasm.disassembly.instructions.control; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.instructions.Instr; +import wasm.disassembly.instructions.InstrType; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.indices.FuncIdx; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class CallInstr extends Instr { + + private FuncIdx funcIdx; + + public CallInstr(BufferedInputStream in, InstrType instrType, Module module) throws IOException, InvalidOpCodeException { + super(instrType); + funcIdx = new FuncIdx(in, module); + } + + public CallInstr(FuncIdx funcIdx) throws IOException { + super(InstrType.CALL); // can only be call instr + this.funcIdx = funcIdx; + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + funcIdx.assemble(out); + } + + public FuncIdx getFuncIdx() { + return funcIdx; + } + + public void setFuncIdx(FuncIdx funcIdx) { + this.funcIdx = funcIdx; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/control/IfElseInstr.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/control/IfElseInstr.java new file mode 100644 index 0000000..a4fd735 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/control/IfElseInstr.java @@ -0,0 +1,88 @@ +package wasm.disassembly.instructions.control; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.instructions.Instr; +import wasm.disassembly.instructions.InstrFactory; +import wasm.disassembly.instructions.InstrType; +import wasm.disassembly.modules.Module; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +public class IfElseInstr extends Instr { + + private List ifInstructions; + private List elseInstructions; + + private BlockType blockType; + + + public IfElseInstr(BufferedInputStream in, InstrType instrType, Module module) throws IOException, InvalidOpCodeException { + super(instrType); + + blockType = new BlockType(in, module); + ifInstructions = new ArrayList<>(2); + elseInstructions = null; + List currentBlock = ifInstructions; + + InstrType type; + while ((type = InstrFactory.disassembleType(in)) != InstrType.END) { + if (type == InstrType.ELSE) { + elseInstructions = new ArrayList<>(2); + currentBlock = elseInstructions; + } + else { + currentBlock.add(InstrFactory.disassemble(in, type, module)); + } + } + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + blockType.assemble(out); + for(Instr instr : ifInstructions) { + instr.assemble(out); + } + if (elseInstructions != null) { + out.write(InstrType.ELSE.val); + for(Instr instr : elseInstructions) { + instr.assemble(out); + } + } + out.write(InstrType.END.val); + } + + public IfElseInstr(InstrType instrType, List ifInstructions, List elseInstructions, BlockType blockType) throws IOException { + super(instrType); + this.ifInstructions = ifInstructions; + this.elseInstructions = elseInstructions; + this.blockType = blockType; + } + + public List getIfInstructions() { + return ifInstructions; + } + + public void setIfInstructions(List ifInstructions) { + this.ifInstructions = ifInstructions; + } + + public List getElseInstructions() { + return elseInstructions; + } + + public void setElseInstructions(List elseInstructions) { + this.elseInstructions = elseInstructions; + } + + public BlockType getBlockType() { + return blockType; + } + + public void setBlockType(BlockType blockType) { + this.blockType = blockType; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/memory/Mem0Instr.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/memory/Mem0Instr.java new file mode 100644 index 0000000..c6fd2a2 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/memory/Mem0Instr.java @@ -0,0 +1,24 @@ +package wasm.disassembly.instructions.memory; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.instructions.Instr; +import wasm.disassembly.instructions.InstrType; +import wasm.disassembly.modules.Module; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class Mem0Instr extends Instr { + public Mem0Instr(BufferedInputStream in, InstrType instrType, Module module) throws IOException, InvalidOpCodeException { + super(instrType); + if (in.read() != 0x00) { + throw new InvalidOpCodeException("Unexpected non-zero byte"); + } + } + + @Override + protected void assemble2(OutputStream out) throws IOException { + out.write(0x00); + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/memory/MemArg.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/memory/MemArg.java new file mode 100644 index 0000000..71e3052 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/memory/MemArg.java @@ -0,0 +1,48 @@ +package wasm.disassembly.instructions.memory; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class MemArg extends WASMOpCode { + + private long align; + private long offset; + + public MemArg(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + align = WUnsignedInt.read(in, 32); + offset = WUnsignedInt.read(in, 32); + } + + public MemArg(long align, long offset) { + this.align = align; + this.offset = offset; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + WUnsignedInt.write(align, out, 32); + WUnsignedInt.write(offset, out, 32); + } + + public long getAlign() { + return align; + } + + public void setAlign(long align) { + this.align = align; + } + + public long getOffset() { + return offset; + } + + public void setOffset(long offset) { + this.offset = offset; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/memory/MemInstr.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/memory/MemInstr.java new file mode 100644 index 0000000..b89ac25 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/memory/MemInstr.java @@ -0,0 +1,38 @@ +package wasm.disassembly.instructions.memory; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.instructions.Instr; +import wasm.disassembly.instructions.InstrType; +import wasm.disassembly.modules.Module; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class MemInstr extends Instr { + + private MemArg memArg; + + public MemInstr(BufferedInputStream in, InstrType instrType, Module module) throws IOException, InvalidOpCodeException { + super(instrType); + memArg = new MemArg(in, module); + } + + public MemInstr(InstrType instrType, MemArg memArg) throws IOException { + super(instrType); + this.memArg = memArg; + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + memArg.assemble(out); + } + + public MemArg getMemArg() { + return memArg; + } + + public void setMemArg(MemArg memArg) { + this.memArg = memArg; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/misc/SingleByteInstr.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/misc/SingleByteInstr.java new file mode 100644 index 0000000..94eede2 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/misc/SingleByteInstr.java @@ -0,0 +1,20 @@ +package wasm.disassembly.instructions.misc; + +import wasm.disassembly.instructions.Instr; +import wasm.disassembly.instructions.InstrType; +import wasm.disassembly.modules.Module; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class SingleByteInstr extends Instr { + public SingleByteInstr(BufferedInputStream in, InstrType instrType, Module module) throws IOException { + super(instrType); + } + + @Override + protected void assemble2(OutputStream out) { + // do nothing + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericF32ConstInstr.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericF32ConstInstr.java new file mode 100644 index 0000000..4254628 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericF32ConstInstr.java @@ -0,0 +1,39 @@ +package wasm.disassembly.instructions.numeric; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.instructions.Instr; +import wasm.disassembly.instructions.InstrType; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WFloat; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class NumericF32ConstInstr extends Instr { + + private float constValue; + + public NumericF32ConstInstr(BufferedInputStream in, InstrType instrType, Module module) throws IOException, InvalidOpCodeException { + super(instrType); + constValue = WFloat.read(in); + } + + public NumericF32ConstInstr(float constValue) throws IOException { + super(InstrType.F32_CONST); + this.constValue = constValue; + } + + @Override + protected void assemble2(OutputStream out) throws IOException { + WFloat.write(constValue, out); + } + + public float getConstValue() { + return constValue; + } + + public void setConstValue(float constValue) { + this.constValue = constValue; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericF64ConstInstr.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericF64ConstInstr.java new file mode 100644 index 0000000..f2b0f3a --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericF64ConstInstr.java @@ -0,0 +1,39 @@ +package wasm.disassembly.instructions.numeric; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.instructions.Instr; +import wasm.disassembly.instructions.InstrType; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WDouble; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class NumericF64ConstInstr extends Instr { + + private double constValue; + + public NumericF64ConstInstr(BufferedInputStream in, InstrType instrType, Module module) throws IOException, InvalidOpCodeException { + super(instrType); + constValue = WDouble.read(in); + } + + public NumericF64ConstInstr(float constValue) throws IOException { + super(InstrType.F64_CONST); + this.constValue = constValue; + } + + @Override + protected void assemble2(OutputStream out) throws IOException { + WDouble.write(constValue, out); + } + + public double getConstValue() { + return constValue; + } + + public void setConstValue(double constValue) { + this.constValue = constValue; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericI32ConstInstr.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericI32ConstInstr.java new file mode 100644 index 0000000..ea0e2d3 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericI32ConstInstr.java @@ -0,0 +1,39 @@ +package wasm.disassembly.instructions.numeric; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.instructions.Instr; +import wasm.disassembly.instructions.InstrType; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WSignedInt; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class NumericI32ConstInstr extends Instr { + + private int constValue; + + public NumericI32ConstInstr(BufferedInputStream in, InstrType instrType, Module module) throws IOException, InvalidOpCodeException { + super(instrType); + constValue = WSignedInt.read(in, 32); + } + + public NumericI32ConstInstr(int constValue) throws IOException { + super(InstrType.I32_CONST); + this.constValue = constValue; + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + WSignedInt.write(constValue, out, 32); + } + + public int getConstValue() { + return constValue; + } + + public void setConstValue(int constValue) { + this.constValue = constValue; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericI64ConstInstr.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericI64ConstInstr.java new file mode 100644 index 0000000..28e4ed8 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericI64ConstInstr.java @@ -0,0 +1,39 @@ +package wasm.disassembly.instructions.numeric; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.instructions.Instr; +import wasm.disassembly.instructions.InstrType; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WSignedLong; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class NumericI64ConstInstr extends Instr { + + private long constValue; + + public NumericI64ConstInstr(BufferedInputStream in, InstrType instrType, Module module) throws IOException, InvalidOpCodeException { + super(instrType); + constValue = WSignedLong.read(in, 64); + } + + public NumericI64ConstInstr(long constValue) throws IOException { + super(InstrType.I64_CONST); + this.constValue = constValue; + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + WSignedLong.write(constValue, out, 64); + } + + public long getConstValue() { + return constValue; + } + + public void setConstValue(long constValue) { + this.constValue = constValue; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericInstr.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericInstr.java new file mode 100644 index 0000000..032c9e6 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/NumericInstr.java @@ -0,0 +1,21 @@ +package wasm.disassembly.instructions.numeric; + +import wasm.disassembly.instructions.Instr; +import wasm.disassembly.instructions.InstrType; +import wasm.disassembly.modules.Module; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class NumericInstr extends Instr { + + public NumericInstr(BufferedInputStream in, InstrType instrType, Module module) throws IOException { + super(instrType); + } + + @Override + protected void assemble2(OutputStream out) { + // nothing + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/TruncSatInstr.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/TruncSatInstr.java new file mode 100644 index 0000000..3d71fa0 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/numeric/TruncSatInstr.java @@ -0,0 +1,42 @@ +package wasm.disassembly.instructions.numeric; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.instructions.Instr; +import wasm.disassembly.instructions.InstrType; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class TruncSatInstr extends Instr { + + private long type; + + public TruncSatInstr(BufferedInputStream in, InstrType instrType, Module module) throws IOException, InvalidOpCodeException { + super(instrType); + type = WUnsignedInt.read(in, 32); + if (type < 0 || type > 7) { + throw new InvalidOpCodeException("Invalid opcode"); + } + } + + public TruncSatInstr(InstrType instrType, long type) throws IOException { + super(instrType); + this.type = type; + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + WUnsignedInt.write(type, out, 32); + } + + public long getType() { + return type; + } + + public void setType(long type) { + this.type = type; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/variable/GlobalVariableInstr.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/variable/GlobalVariableInstr.java new file mode 100644 index 0000000..61137c0 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/variable/GlobalVariableInstr.java @@ -0,0 +1,39 @@ +package wasm.disassembly.instructions.variable; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.instructions.Instr; +import wasm.disassembly.instructions.InstrType; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.indices.GlobalIdx; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class GlobalVariableInstr extends Instr { + + private GlobalIdx globalIdx; + + public GlobalVariableInstr(BufferedInputStream in, InstrType instrType, Module module) throws IOException, InvalidOpCodeException { + super(instrType); + globalIdx = new GlobalIdx(in, module); + } + + public GlobalVariableInstr(InstrType instrType, GlobalIdx globalIdx) throws IOException { + super(instrType); + this.globalIdx = globalIdx; + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + globalIdx.assemble(out); + } + + public GlobalIdx getGlobalIdx() { + return globalIdx; + } + + public void setGlobalIdx(GlobalIdx globalIdx) { + this.globalIdx = globalIdx; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/instructions/variable/LocalVariableInstr.java b/G-Wasm/src/main/java/wasm/disassembly/instructions/variable/LocalVariableInstr.java new file mode 100644 index 0000000..2fa337b --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/instructions/variable/LocalVariableInstr.java @@ -0,0 +1,39 @@ +package wasm.disassembly.instructions.variable; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.instructions.Instr; +import wasm.disassembly.instructions.InstrType; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.indices.LocalIdx; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class LocalVariableInstr extends Instr { + + private LocalIdx localIdx; + + public LocalVariableInstr(BufferedInputStream in, InstrType instrType, Module module) throws IOException, InvalidOpCodeException { + super(instrType); + localIdx = new LocalIdx(in, module); + } + + public LocalVariableInstr(InstrType instrType, LocalIdx localIdx) throws IOException { + super(instrType); + this.localIdx = localIdx; + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + localIdx.assemble(out); + } + + public LocalIdx getLocalIdx() { + return localIdx; + } + + public void setLocalIdx(LocalIdx localIdx) { + this.localIdx = localIdx; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/Magic.java b/G-Wasm/src/main/java/wasm/disassembly/modules/Magic.java new file mode 100644 index 0000000..5fcc8ea --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/Magic.java @@ -0,0 +1,31 @@ +package wasm.disassembly.modules; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Arrays; + +public class Magic extends WASMOpCode { + + private static final byte[] EXPECTED_MAGIC = new byte[]{0x00, 0x61, 0x73, 0x6D}; + + + public Magic(BufferedInputStream in) throws IOException, InvalidOpCodeException { + byte[] magic = new byte[4]; + in.read(magic); + + if (!Arrays.equals(magic, EXPECTED_MAGIC)) { + throw new InvalidOpCodeException("Invalid magic"); + } + } + + public Magic() {} + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + out.write(EXPECTED_MAGIC); + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/Module.java b/G-Wasm/src/main/java/wasm/disassembly/modules/Module.java new file mode 100644 index 0000000..4161f08 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/Module.java @@ -0,0 +1,253 @@ +package wasm.disassembly.modules; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.sections.Section; +import wasm.disassembly.modules.sections.code.CodeSection; +import wasm.disassembly.modules.sections.custom.CustomSection; +import wasm.disassembly.modules.sections.custom.CustomSectionFactory; +import wasm.disassembly.modules.sections.data.DataSection; +import wasm.disassembly.modules.sections.element.ElementSection; +import wasm.disassembly.modules.sections.export.ExportSection; +import wasm.disassembly.modules.sections.function.FunctionSection; +import wasm.disassembly.modules.sections.global.GlobalSection; +import wasm.disassembly.modules.sections.imprt.ImportSection; +import wasm.disassembly.modules.sections.memory.MemorySection; +import wasm.disassembly.modules.sections.start.StartSection; +import wasm.disassembly.modules.sections.table.TableSection; +import wasm.disassembly.modules.sections.type.TypeSection; +import wasm.misc.StreamReplacement; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +public class Module extends WASMOpCode { + + private Magic magic; + private Version version; + + private TypeSection typeSection; + private ImportSection importSection; + private FunctionSection functionSection; + private TableSection tableSection; + private MemorySection memorySection; + private GlobalSection globalSection; + private ExportSection exportSection; + private StartSection startSection; + private ElementSection elementSection; + private CodeSection codeSection; + private DataSection dataSection; + + private List> customSectionsList; + + public final List streamReplacements; + + + public Module(BufferedInputStream in, List streamReplacements) throws IOException, InvalidOpCodeException { + this.streamReplacements = streamReplacements; + + customSectionsList = new ArrayList<>(); + + magic = new Magic(in); + version = new Version(in); + + disassembleCustomSections(in); + typeSection = isNextSection(in, 1) ? new TypeSection(in, this) : null; + disassembleCustomSections(in); + importSection = isNextSection(in, 2) ? new ImportSection(in, this) : null; + disassembleCustomSections(in); + functionSection = isNextSection(in, 3) ? new FunctionSection(in, this) : null; + disassembleCustomSections(in); + tableSection = isNextSection(in, 4) ? new TableSection(in, this) : null; + disassembleCustomSections(in); + memorySection = isNextSection(in, 5) ? new MemorySection(in, this) : null; + disassembleCustomSections(in); + globalSection = isNextSection(in , 6) ? new GlobalSection(in, this) : null; + disassembleCustomSections(in); + exportSection = isNextSection(in, 7) ? new ExportSection(in, this) : null; + disassembleCustomSections(in); + startSection = isNextSection(in, 8) ? new StartSection(in, this) : null; + disassembleCustomSections(in); + elementSection = isNextSection(in, 9) ? new ElementSection(in, this) : null; + disassembleCustomSections(in); + codeSection = isNextSection(in, 10) ? new CodeSection(in, this) : null; + disassembleCustomSections(in); + dataSection = isNextSection(in, 11) ? new DataSection(in, this) : null; + disassembleCustomSections(in); + exportSection.addShittyExports(this); + + in.close(); + } + + public Module(String fileName, boolean gzip, List streamReplacements) throws IOException, InvalidOpCodeException { + this(new BufferedInputStream(gzip ? + new GZIPInputStream(new FileInputStream(new File(fileName))) : + new FileInputStream(new File(fileName))) + , streamReplacements + ); + } + + private void disassembleCustomSections(BufferedInputStream in) throws IOException, InvalidOpCodeException { + List customSections = new ArrayList<>(); + + while (isNextSection(in, 0)) { + customSections.add(CustomSectionFactory.get(in, this)); + } + + in.reset(); + customSectionsList.add(customSections); + } + + private boolean isNextSection(BufferedInputStream in, int id) throws IOException { + in.mark(1); + if (in.read() == id) { + return true; + } + in.reset(); + return false; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + magic.assemble(out); + version.assemble(out); + + Section[] sections = new Section[]{typeSection, importSection, functionSection, tableSection, + memorySection, globalSection, exportSection, startSection, elementSection, codeSection, + dataSection}; + + for (int i = 0; i < 11; i++) { + assembleCustomSections(out, i); + if (sections[i] != null) { + sections[i].assemble(out); + } + } + assembleCustomSections(out, 11); + out.close(); + } + + private void assembleCustomSections(OutputStream out, int location) throws IOException, InvalidOpCodeException { + for(CustomSection section : customSectionsList.get(location)) { + section.assemble(out); + } + } + + public void assembleToFile(String fileName, boolean gzip) throws IOException, InvalidOpCodeException { + assemble(gzip ? new GZIPOutputStream(new FileOutputStream(fileName)) : new FileOutputStream(fileName)); + } + + public Magic getMagic() { + return magic; + } + + public void setMagic(Magic magic) { + this.magic = magic; + } + + public Version getVersion() { + return version; + } + + public void setVersion(Version version) { + this.version = version; + } + + public TypeSection getTypeSection() { + return typeSection; + } + + public void setTypeSection(TypeSection typeSection) { + this.typeSection = typeSection; + } + + public ImportSection getImportSection() { + return importSection; + } + + public void setImportSection(ImportSection importSection) { + this.importSection = importSection; + } + + public FunctionSection getFunctionSection() { + return functionSection; + } + + public void setFunctionSection(FunctionSection functionSection) { + this.functionSection = functionSection; + } + + public TableSection getTableSection() { + return tableSection; + } + + public void setTableSection(TableSection tableSection) { + this.tableSection = tableSection; + } + + public MemorySection getMemorySection() { + return memorySection; + } + + public void setMemorySection(MemorySection memorySection) { + this.memorySection = memorySection; + } + + public GlobalSection getGlobalSection() { + return globalSection; + } + + public void setGlobalSection(GlobalSection globalSection) { + this.globalSection = globalSection; + } + + public ExportSection getExportSection() { + return exportSection; + } + + public void setExportSection(ExportSection exportSection) { + this.exportSection = exportSection; + } + + public StartSection getStartSection() { + return startSection; + } + + public void setStartSection(StartSection startSection) { + this.startSection = startSection; + } + + public ElementSection getElementSection() { + return elementSection; + } + + public void setElementSection(ElementSection elementSection) { + this.elementSection = elementSection; + } + + public CodeSection getCodeSection() { + return codeSection; + } + + public void setCodeSection(CodeSection codeSection) { + this.codeSection = codeSection; + } + + public DataSection getDataSection() { + return dataSection; + } + + public void setDataSection(DataSection dataSection) { + this.dataSection = dataSection; + } + + public List> getCustomSectionsList() { + return customSectionsList; + } + + public void setCustomSectionsList(List> customSectionsList) { + this.customSectionsList = customSectionsList; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/Version.java b/G-Wasm/src/main/java/wasm/disassembly/modules/Version.java new file mode 100644 index 0000000..7d01e96 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/Version.java @@ -0,0 +1,40 @@ +package wasm.disassembly.modules; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class Version extends WASMOpCode { + + byte[] version; + + + public Version(BufferedInputStream in) throws IOException { + version = new byte[4]; + in.read(version); + } + + public Version(byte[] version) { + this.version = version; + } + + public Version() { + version = new byte[]{1, 0, 0, 0}; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + out.write(version); + } + + public byte[] getVersion() { + return version; + } + + public void setVersion(byte[] version) { + this.version = version; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/indices/FuncIdx.java b/G-Wasm/src/main/java/wasm/disassembly/modules/indices/FuncIdx.java new file mode 100644 index 0000000..366eb17 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/indices/FuncIdx.java @@ -0,0 +1,48 @@ +package wasm.disassembly.modules.indices; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class FuncIdx extends WASMOpCode { + + private long x; + + +// public int ref; // debugging purpose + + public FuncIdx(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + x = WUnsignedInt.read(in, 32) + + module.streamReplacements.size(); + + +// ref = CodeSection.currentI; // debugging purpose + } + + public FuncIdx(long x, Module module) { + this.x = x; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + WUnsignedInt.write(x, out, 32); + } + + public long getX() { + return x; + } + + public void setX(long x) { + this.x = x; + } + + @Override + public boolean equals(Object obj) { + return (obj instanceof FuncIdx && ((FuncIdx)obj).getX() == x); + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/indices/GlobalIdx.java b/G-Wasm/src/main/java/wasm/disassembly/modules/indices/GlobalIdx.java new file mode 100644 index 0000000..b546975 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/indices/GlobalIdx.java @@ -0,0 +1,36 @@ +package wasm.disassembly.modules.indices; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class GlobalIdx extends WASMOpCode { + + private long x; + + public GlobalIdx(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + x = WUnsignedInt.read(in, 32); + } + + public GlobalIdx(long x) { + this.x = x; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + WUnsignedInt.write(x, out, 32); + } + + public long getX() { + return x; + } + + public void setX(long x) { + this.x = x; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/indices/LabelIdx.java b/G-Wasm/src/main/java/wasm/disassembly/modules/indices/LabelIdx.java new file mode 100644 index 0000000..5c41bab --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/indices/LabelIdx.java @@ -0,0 +1,36 @@ +package wasm.disassembly.modules.indices; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class LabelIdx extends WASMOpCode { + + private long l; + + public LabelIdx(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + l = WUnsignedInt.read(in, 32); + } + + public LabelIdx(long l) { + this.l = l; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + WUnsignedInt.write(l, out, 32); + } + + public long getL() { + return l; + } + + public void setL(long l) { + this.l = l; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/indices/LocalIdx.java b/G-Wasm/src/main/java/wasm/disassembly/modules/indices/LocalIdx.java new file mode 100644 index 0000000..5612af6 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/indices/LocalIdx.java @@ -0,0 +1,36 @@ +package wasm.disassembly.modules.indices; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class LocalIdx extends WASMOpCode { + + private long x; + + public LocalIdx(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + x = WUnsignedInt.read(in, 32); + } + + public LocalIdx(long x) { + this.x = x; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + WUnsignedInt.write(x, out, 32); + } + + public long getX() { + return x; + } + + public void setX(long x) { + this.x = x; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/indices/MemIdx.java b/G-Wasm/src/main/java/wasm/disassembly/modules/indices/MemIdx.java new file mode 100644 index 0000000..f7f67db --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/indices/MemIdx.java @@ -0,0 +1,36 @@ +package wasm.disassembly.modules.indices; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class MemIdx extends WASMOpCode { + + private long x; + + public MemIdx(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + x = WUnsignedInt.read(in, 32); + } + + public MemIdx(long x) { + this.x = x; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + WUnsignedInt.write(x, out, 32); + } + + public long getX() { + return x; + } + + public void setX(long x) { + this.x = x; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/indices/TableIdx.java b/G-Wasm/src/main/java/wasm/disassembly/modules/indices/TableIdx.java new file mode 100644 index 0000000..cb6b9c1 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/indices/TableIdx.java @@ -0,0 +1,36 @@ +package wasm.disassembly.modules.indices; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class TableIdx extends WASMOpCode { + + private long x; + + public TableIdx(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + x = WUnsignedInt.read(in, 32); + } + + public TableIdx(long x) { + this.x = x; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + WUnsignedInt.write(x, out, 32); + } + + public long getX() { + return x; + } + + public void setX(long x) { + this.x = x; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/indices/TypeIdx.java b/G-Wasm/src/main/java/wasm/disassembly/modules/indices/TypeIdx.java new file mode 100644 index 0000000..4b0856e --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/indices/TypeIdx.java @@ -0,0 +1,41 @@ +package wasm.disassembly.modules.indices; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class TypeIdx extends WASMOpCode { + + private long x; + + public TypeIdx(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + x = WUnsignedInt.read(in, 32); + } + + public TypeIdx(long x) { + this.x = x; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + WUnsignedInt.write(x, out, 32); + } + + public long getX() { + return x; + } + + public void setX(long x) { + this.x = x; + } + + @Override + public boolean equals(Object obj) { + return (obj instanceof TypeIdx && ((TypeIdx)obj).getX() == x); + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/Section.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/Section.java new file mode 100644 index 0000000..fc6aec1 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/Section.java @@ -0,0 +1,57 @@ +package wasm.disassembly.modules.sections; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public abstract class Section extends WASMOpCode { + + private int sectionId; + private long size; + protected Module module; + + public Section(BufferedInputStream in, Module module, int sectionId) throws IOException, InvalidOpCodeException { + this.module = module; + this.sectionId = sectionId; + size = WUnsignedInt.read(in, 32); + } + + public Section(Module module, int sectionId, long size) { + this.module = module; + this.sectionId = sectionId; + this.size = size; + } + + public Section(Module module, int sectionId) { + this(module, sectionId, -1); + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + out.write(sectionId); + + ByteArrayOutputStream fakeOutputStream = new ByteArrayOutputStream(); + assemble2(fakeOutputStream); + byte[] asbytes = fakeOutputStream.toByteArray(); + WUnsignedInt.write(asbytes.length, out, 32); + fakeOutputStream.close(); + out.write(asbytes); + } + + protected abstract void assemble2(OutputStream out) throws IOException, InvalidOpCodeException; + + + public int getSectionId() { + return sectionId; + } + + public long getSize() { + return size; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/SectionSupplier.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/SectionSupplier.java new file mode 100644 index 0000000..a1d37e0 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/SectionSupplier.java @@ -0,0 +1,12 @@ +package wasm.disassembly.modules.sections; + +import wasm.disassembly.InvalidOpCodeException; + +import java.io.BufferedInputStream; +import java.io.IOException; + +public interface SectionSupplier { + + Section get(BufferedInputStream in) throws IOException, InvalidOpCodeException; + +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/code/Code.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/code/Code.java new file mode 100644 index 0000000..3f91bd5 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/code/Code.java @@ -0,0 +1,43 @@ +package wasm.disassembly.modules.sections.code; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class Code extends WASMOpCode { + + private Func code; + + public Code(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + long sizeInBytes = WUnsignedInt.read(in, 32); // don't use + code = new Func(in, module); + } + + public Code(Func code) { + this.code = code; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + ByteArrayOutputStream codeBuffer = new ByteArrayOutputStream(); + code.assemble(codeBuffer); + byte[] codeInBytes = codeBuffer.toByteArray(); + WUnsignedInt.write(codeInBytes.length, out, 32); + out.write(codeInBytes); + codeBuffer.close(); + } + + public Func getCode() { + return code; + } + + public void setCode(Func code) { + this.code = code; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/code/CodeSection.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/code/CodeSection.java new file mode 100644 index 0000000..80ecae8 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/code/CodeSection.java @@ -0,0 +1,123 @@ +package wasm.disassembly.modules.sections.code; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.instructions.Expression; +import wasm.disassembly.instructions.Instr; +import wasm.disassembly.instructions.InstrType; +import wasm.disassembly.instructions.control.CallInstr; +import wasm.disassembly.instructions.variable.LocalVariableInstr; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.indices.FuncIdx; +import wasm.disassembly.modules.indices.LocalIdx; +import wasm.disassembly.modules.sections.Section; +import wasm.disassembly.values.WUnsignedInt; +import wasm.misc.StreamReplacement; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +public class CodeSection extends Section { + + public static final int CODE_SECTION_ID = 10; + +// public static int currentI = 0; + + public final byte[] asBytes; + public long length; + public int copiesLength; +// private Vector codesEntries; + + public CodeSection(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + super(in, module, CODE_SECTION_ID); + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + Code[] copies = new Code[module.streamReplacements.size()]; + +// codesEntries = new Vector<>(in, Code::new, module); + length = WUnsignedInt.read(in, 32); + for (int i = 0; i < length; i++) { + Code code = new Code(in, module); + + + Func func = code.getCode(); + for (int j = 0; j < module.streamReplacements.size(); j++) { + + if (module.getFunctionSection().matchesSearchFunctionsTypes.get(j).contains(i)) { + + if (module.streamReplacements.get(j).codeMatches(func)) { + StreamReplacement.ReplacementType actionTaken = module.streamReplacements.get(j).getReplacementType(); + if (actionTaken == StreamReplacement.ReplacementType.HOOK) { + CallInstr call = new CallInstr(new FuncIdx(j, module)); + + List newInstrs = new ArrayList<>(); + for (int k = 0; k < module.streamReplacements.get(j).getFuncType().getParameterType().typeList().size(); k++) { + newInstrs.add(new LocalVariableInstr(InstrType.LOCAL_GET, new LocalIdx(k))); + } + newInstrs.add(call); + newInstrs.addAll(func.getExpression().getInstructions()); + func.getExpression().setInstructions(newInstrs); + } + else if (actionTaken == StreamReplacement.ReplacementType.HOOKCOPYEXPORT) { + copies[j] = new Code(new Func(func.getLocalss(), new Expression(func.getExpression().getInstructions()))); + + CallInstr call = new CallInstr(new FuncIdx(j, module)); + List newInstrs = new ArrayList<>(); + for (int k = 0; k < module.streamReplacements.get(j).getFuncType().getParameterType().typeList().size(); k++) { + newInstrs.add(new LocalVariableInstr(InstrType.LOCAL_GET, new LocalIdx(k))); + } + newInstrs.add(call); + func.getExpression().setInstructions(newInstrs); + } + } + + } + } + + + code.assemble(buffer); + } + + for (Code code : copies) { + if (code != null) { + code.assemble(buffer); + length++; + copiesLength++; + } + } + + asBytes = buffer.toByteArray(); + } + +// public CodeSection(Module module, List codesEntries) { +// super(module, CODE_SECTION_ID); +// this.codesEntries = new Vector<>(codesEntries); +// } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { +// codesEntries.assemble(out); + + WUnsignedInt.write(length, out, 32); + out.write(asBytes); + } + +// public Code getCodeByIdx(FuncIdx funcIdx) { +// return codesEntries.getElements().get((int)(funcIdx.getX()) - module.getImportSection().getTotalFuncImports()); +// } +// +// public Func getByIdx(FuncIdx funcIdx) { +// return getCodeByIdx(funcIdx).getCode(); +// } +// +// public List getCodesEntries() { +// return codesEntries.getElements(); +// } +// +// public void setCodesEntries(List codesEntries) { +// this.codesEntries = new Vector<>(codesEntries); +// } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/code/Func.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/code/Func.java new file mode 100644 index 0000000..142ae97 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/code/Func.java @@ -0,0 +1,75 @@ +package wasm.disassembly.modules.sections.code; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.conventions.Vector; +import wasm.disassembly.instructions.Expression; +import wasm.disassembly.modules.Module; +import wasm.disassembly.types.ValType; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +public class Func extends WASMOpCode { + + private Vector localss; // intended double s + private Expression expression; + + + public Func(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + localss = new Vector<>(in, Locals::new, module); + expression = new Expression(in, module); + } + + public Func(List localss, Expression expression) { + this.localss = new Vector<>(localss); + this.expression = expression; + } + + public Func(ValType[] localVariables, Expression expression) { + setLocalVariables(localVariables); + this.expression = expression; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + localss.assemble(out); + expression.assemble(out); + } + + public List getLocalss() { + return localss.getElements(); + } + + public void setLocalss(List localss) { + this.localss = new Vector<>(localss); + } + + public Expression getExpression() { + return expression; + } + + public void setExpression(Expression expression) { + this.expression = expression; + } + + public void setLocalVariables(ValType[] locals) { + List localss = new ArrayList<>(); + + Locals current = null; + for (ValType valType : locals) { + if (current == null || current.getValType() != valType) { + if (current != null) localss.add(current); + current = new Locals(1, valType); + } + else { + current.setAmount(current.getAmount() + 1); + } + } + if (current != null) localss.add(current); + this.localss = new Vector<>(localss); + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/code/Locals.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/code/Locals.java new file mode 100644 index 0000000..9a3b336 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/code/Locals.java @@ -0,0 +1,57 @@ +package wasm.disassembly.modules.sections.code; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.types.ValType; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class Locals extends WASMOpCode { + + private long amount; + private ValType valType; + + public Locals(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + amount = WUnsignedInt.read(in, 32); + valType = ValType.from_val(in.read()); + } + + public Locals(long amount, ValType valType) { + this.amount = amount; + this.valType = valType; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + WUnsignedInt.write(amount, out, 32); + out.write(valType.val); + } + + public long getAmount() { + return amount; + } + + public void setAmount(long amount) { + this.amount = amount; + } + + public ValType getValType() { + return valType; + } + + public void setValType(ValType valType) { + this.valType = valType; + } + + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Locals)) return false; + Locals other = (Locals) obj; + return amount == other.amount && valType.val == other.valType.val; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/CustomSection.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/CustomSection.java new file mode 100644 index 0000000..3002bf4 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/CustomSection.java @@ -0,0 +1,38 @@ +package wasm.disassembly.modules.sections.custom; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.sections.Section; +import wasm.disassembly.values.WName; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; + +public abstract class CustomSection extends Section { + + public static final int CUSTOM_SECTION_ID = 0; + + private String name; + + public CustomSection(Module module, long size, String name) throws IOException, InvalidOpCodeException { + super(module, CUSTOM_SECTION_ID, size); + this.name = name; + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + WName.write(name, out); + assemble3(out); + } + + protected abstract void assemble3(OutputStream out) throws IOException, InvalidOpCodeException; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/CustomSectionFactory.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/CustomSectionFactory.java new file mode 100644 index 0000000..9126484 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/CustomSectionFactory.java @@ -0,0 +1,24 @@ +package wasm.disassembly.modules.sections.custom; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.sections.custom.namesection.NameSection; +import wasm.disassembly.values.WName; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.IOException; + +public class CustomSectionFactory { + + public static CustomSection get(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + long size = WUnsignedInt.read(in, 32); + String name = WName.read(in); + + if (name.equals("name")) { + return new NameSection(in, module, size); + } + + return new UnImplementedCustomSection(in, module, size, name); + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/UnImplementedCustomSection.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/UnImplementedCustomSection.java new file mode 100644 index 0000000..32ac0ab --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/UnImplementedCustomSection.java @@ -0,0 +1,40 @@ +package wasm.disassembly.modules.sections.custom; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.sections.custom.CustomSection; +import wasm.disassembly.values.WName; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; + +public class UnImplementedCustomSection extends CustomSection { + + private byte[] bytes; + + public UnImplementedCustomSection(BufferedInputStream in, Module module, long size, String name) throws IOException, InvalidOpCodeException { + super(module, size, name); + + ByteArrayOutputStream nameOut = new ByteArrayOutputStream(); + WName.write(name, nameOut); + + bytes = new byte[(int)size - nameOut.toByteArray().length]; + in.read(bytes); + } + + @Override + protected void assemble3(OutputStream out) throws IOException, InvalidOpCodeException { + out.write(bytes); + } + + public byte[] getBytes() { + return bytes; + } + + public void setBytes(byte[] bytes) { + this.bytes = bytes; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/NameSection.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/NameSection.java new file mode 100644 index 0000000..c35ed71 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/NameSection.java @@ -0,0 +1,74 @@ +package wasm.disassembly.modules.sections.custom.namesection; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.sections.custom.CustomSection; +import wasm.disassembly.modules.sections.custom.namesection.subsections.FunctionNamesSubSection; +import wasm.disassembly.modules.sections.custom.namesection.subsections.LocalNamesSubSection; +import wasm.disassembly.modules.sections.custom.namesection.subsections.ModuleNameSubSection; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class NameSection extends CustomSection { + + private ModuleNameSubSection moduleName; + private FunctionNamesSubSection functionNames; + private LocalNamesSubSection localNames; + + public NameSection(BufferedInputStream in, Module module, long size) throws IOException, InvalidOpCodeException { + super(module, size, "name"); + + moduleName = isNextSection(in, 0) ? new ModuleNameSubSection(in, module) : null; + functionNames = isNextSection(in, 1) ? new FunctionNamesSubSection(in, module) : null; + localNames = isNextSection(in, 2) ? new LocalNamesSubSection(in, module) : null; + } + + public NameSection(Module module, long size, String name, ModuleNameSubSection moduleName, FunctionNamesSubSection functionNames, LocalNamesSubSection localNames) throws IOException, InvalidOpCodeException { + super(module, size, name); + this.moduleName = moduleName; + this.functionNames = functionNames; + this.localNames = localNames; + } + + public ModuleNameSubSection getModuleName() { + return moduleName; + } + + public void setModuleName(ModuleNameSubSection moduleName) { + this.moduleName = moduleName; + } + + public FunctionNamesSubSection getFunctionNames() { + return functionNames; + } + + public void setFunctionNames(FunctionNamesSubSection functionNames) { + this.functionNames = functionNames; + } + + public LocalNamesSubSection getLocalNames() { + return localNames; + } + + public void setLocalNames(LocalNamesSubSection localNames) { + this.localNames = localNames; + } + + @Override + protected void assemble3(OutputStream out) throws IOException, InvalidOpCodeException { + if (moduleName != null) moduleName.assemble(out); + if (functionNames != null) functionNames.assemble(out); + if (localNames != null) localNames.assemble(out); + } + + private boolean isNextSection(BufferedInputStream in, int id) throws IOException { + in.mark(1); + if (in.read() == id) { + return true; + } + in.reset(); + return false; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/FunctionNamesSubSection.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/FunctionNamesSubSection.java new file mode 100644 index 0000000..0c89de6 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/FunctionNamesSubSection.java @@ -0,0 +1,40 @@ +package wasm.disassembly.modules.sections.custom.namesection.subsections; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.conventions.Creator; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.indices.FuncIdx; +import wasm.disassembly.modules.sections.custom.namesection.subsections.namemaps.NameMap; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class FunctionNamesSubSection extends SubSection { + + public static final int FUNCTION_NAMES_SUBSECTION_ID = 1; + private NameMap nameMap; + + public FunctionNamesSubSection(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + super(in, FUNCTION_NAMES_SUBSECTION_ID); + nameMap = new NameMap<>(in, module, FuncIdx::new); + } + + public FunctionNamesSubSection(NameMap nameMap) { + super(FUNCTION_NAMES_SUBSECTION_ID); + this.nameMap = nameMap; + } + + public NameMap getNameMap() { + return nameMap; + } + + public void setNameMap(NameMap nameMap) { + this.nameMap = nameMap; + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + nameMap.assemble(out); + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/LocalNamesSubSection.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/LocalNamesSubSection.java new file mode 100644 index 0000000..fdbee7c --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/LocalNamesSubSection.java @@ -0,0 +1,42 @@ +package wasm.disassembly.modules.sections.custom.namesection.subsections; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.conventions.Creator; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.indices.FuncIdx; +import wasm.disassembly.modules.indices.LocalIdx; +import wasm.disassembly.modules.sections.custom.namesection.subsections.namemaps.IndirectNameMap; +import wasm.disassembly.modules.sections.custom.namesection.subsections.namemaps.NameMap; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class LocalNamesSubSection extends SubSection { + + public static final int LOCAL_NAMES_SUBSECTION_ID = 2; + private IndirectNameMap indirectNameMap; + + public LocalNamesSubSection(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + super(in, LOCAL_NAMES_SUBSECTION_ID); + indirectNameMap = new IndirectNameMap<>(in, module, FuncIdx::new, LocalIdx::new); + } + + public LocalNamesSubSection(IndirectNameMap indirectNameMap) { + super(LOCAL_NAMES_SUBSECTION_ID); + this.indirectNameMap = indirectNameMap; + } + + public IndirectNameMap getIndirectNameMap() { + return indirectNameMap; + } + + public void setIndirectNameMap(IndirectNameMap indirectNameMap) { + this.indirectNameMap = indirectNameMap; + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + indirectNameMap.assemble(out); + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/ModuleNameSubSection.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/ModuleNameSubSection.java new file mode 100644 index 0000000..f7ccc12 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/ModuleNameSubSection.java @@ -0,0 +1,39 @@ +package wasm.disassembly.modules.sections.custom.namesection.subsections; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WName; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class ModuleNameSubSection extends SubSection { + + public static final int MODULE_NAME_SUBSECTION_ID = 0; + + private String name; + + public ModuleNameSubSection(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + super(in, MODULE_NAME_SUBSECTION_ID); + name = WName.read(in); + } + + public ModuleNameSubSection(String name) { + super(MODULE_NAME_SUBSECTION_ID); + this.name = name; + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + WName.write(name, out); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/SubSection.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/SubSection.java new file mode 100644 index 0000000..30a576f --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/SubSection.java @@ -0,0 +1,44 @@ +package wasm.disassembly.modules.sections.custom.namesection.subsections; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.values.WName; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public abstract class SubSection extends WASMOpCode { + + private long size; + private int subSectionId; + + public SubSection(BufferedInputStream in, int subSectionId) throws IOException, InvalidOpCodeException { + this.subSectionId = subSectionId; + size = WUnsignedInt.read(in, 32); + } + + public SubSection(int subSectionId) { + this.subSectionId = subSectionId; + size = -1; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + out.write(subSectionId); + + ByteArrayOutputStream fakeOutputStream = new ByteArrayOutputStream(); + assemble2(fakeOutputStream); + byte[] asbytes = fakeOutputStream.toByteArray(); + WUnsignedInt.write(asbytes.length, out, 32); + out.write(asbytes); + } + + protected abstract void assemble2(OutputStream out) throws IOException, InvalidOpCodeException; + + public int getSubSectionId() { + return subSectionId; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/namemaps/IndirectNameAssoc.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/namemaps/IndirectNameAssoc.java new file mode 100644 index 0000000..f8a1510 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/namemaps/IndirectNameAssoc.java @@ -0,0 +1,48 @@ +package wasm.disassembly.modules.sections.custom.namesection.subsections.namemaps; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.conventions.Creator; +import wasm.disassembly.modules.Module; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class IndirectNameAssoc extends WASMOpCode { + + private Idx idx; + private NameMap nameMap; + + public IndirectNameAssoc(BufferedInputStream in, Module module, Creator creator, Creator innerCreator) throws IOException, InvalidOpCodeException { + idx = creator.create(in, module); + nameMap = new NameMap<>(in, module, innerCreator); + } + + public IndirectNameAssoc(Idx idx, NameMap nameMap) { + this.idx = idx; + this.nameMap = nameMap; + } + + public Idx getIdx() { + return idx; + } + + public void setIdx(Idx idx) { + this.idx = idx; + } + + public NameMap getNameMap() { + return nameMap; + } + + public void setNameMap(NameMap nameMap) { + this.nameMap = nameMap; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + idx.assemble(out); + nameMap.assemble(out); + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/namemaps/IndirectNameMap.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/namemaps/IndirectNameMap.java new file mode 100644 index 0000000..104e0fe --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/namemaps/IndirectNameMap.java @@ -0,0 +1,38 @@ +package wasm.disassembly.modules.sections.custom.namesection.subsections.namemaps; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.conventions.Creator; +import wasm.disassembly.conventions.Vector; +import wasm.disassembly.modules.Module; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +public class IndirectNameMap extends WASMOpCode { + + private Vector> idxAndMaps; + + public IndirectNameMap(BufferedInputStream in, Module module, Creator creator, Creator innerCreator) throws IOException, InvalidOpCodeException { + idxAndMaps = new Vector<>(in, (in1, m) -> new IndirectNameAssoc<>(in1, m, creator, innerCreator), module); + } + + public IndirectNameMap(Vector> idxAndMaps) { + this.idxAndMaps = idxAndMaps; + } + + public List> getIdxAndMaps() { + return idxAndMaps.getElements(); + } + + public void setIdxAndMaps(List> idxAndMaps) { + this.idxAndMaps = new Vector<>(idxAndMaps); + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + idxAndMaps.assemble(out); + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/namemaps/NameAssoc.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/namemaps/NameAssoc.java new file mode 100644 index 0000000..04e3c00 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/namemaps/NameAssoc.java @@ -0,0 +1,49 @@ +package wasm.disassembly.modules.sections.custom.namesection.subsections.namemaps; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.conventions.Creator; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WName; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class NameAssoc extends WASMOpCode { + + private Idx idx; + private String name; + + public NameAssoc(BufferedInputStream in, Module module, Creator creator) throws IOException, InvalidOpCodeException { + idx = creator.create(in, module); + name = WName.read(in); + } + + public NameAssoc(Idx idx, String name) { + this.idx = idx; + this.name = name; + } + + public Idx getIdx() { + return idx; + } + + public void setIdx(Idx idx) { + this.idx = idx; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + idx.assemble(out); + WName.write(name, out); + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/namemaps/NameMap.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/namemaps/NameMap.java new file mode 100644 index 0000000..6ae2b21 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/custom/namesection/subsections/namemaps/NameMap.java @@ -0,0 +1,38 @@ +package wasm.disassembly.modules.sections.custom.namesection.subsections.namemaps; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.conventions.Creator; +import wasm.disassembly.conventions.Vector; +import wasm.disassembly.modules.Module; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +public class NameMap extends WASMOpCode { + + private Vector> idxAndNames; + + public NameMap(BufferedInputStream in, Module module, Creator creator) throws IOException, InvalidOpCodeException { + idxAndNames = new Vector<>(in, (in1, m) -> new NameAssoc<>(in1, m, creator), module); + } + + public NameMap(Vector> idxAndNames) { + this.idxAndNames = idxAndNames; + } + + public List> getIdxAndNames() { + return idxAndNames.getElements(); + } + + public void setIdxAndNames(List> idxAndNames) { + this.idxAndNames = new Vector<>(idxAndNames); + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + idxAndNames.assemble(out); + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/data/Data.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/data/Data.java new file mode 100644 index 0000000..eaa806f --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/data/Data.java @@ -0,0 +1,67 @@ +package wasm.disassembly.modules.sections.data; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.instructions.Expression; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.indices.MemIdx; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class Data extends WASMOpCode { + + private MemIdx dataMemId; + private Expression offset; + private byte[] data; + + + public Data(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + dataMemId = new MemIdx(in, module); + offset = new Expression(in, module); + long length = WUnsignedInt.read(in, 32); + data = new byte[(int)length]; + in.read(data); + } + + public Data(MemIdx dataMemId, Expression offset, byte[] data) { + this.dataMemId = dataMemId; + this.offset = offset; + this.data = data; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + dataMemId.assemble(out); + offset.assemble(out); + WUnsignedInt.write(data.length, out, 32); + out.write(data); + } + + + public MemIdx getDataMemId() { + return dataMemId; + } + + public void setDataMemId(MemIdx dataMemId) { + this.dataMemId = dataMemId; + } + + public Expression getOffset() { + return offset; + } + + public void setOffset(Expression offset) { + this.offset = offset; + } + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/data/DataSection.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/data/DataSection.java new file mode 100644 index 0000000..9fa347d --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/data/DataSection.java @@ -0,0 +1,57 @@ +package wasm.disassembly.modules.sections.data; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.conventions.Vector; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.sections.Section; +import wasm.disassembly.modules.sections.element.Elem; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +public class DataSection extends Section { + + public static final int DATA_SECTION_ID = 11; + private final byte[] asBytes; + private long length; + +// private Vector dataSegments; + + public DataSection(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + super(in, module, DATA_SECTION_ID); +// dataSegments = new Vector<>(in, Data::new, module); + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + length = WUnsignedInt.read(in, 32); + for (int i = 0; i < length; i++) { + new Data(in, module).assemble(buffer); + } + asBytes = buffer.toByteArray(); + } + +// public DataSection(Module module, List dataSegments) { +// super(module, DATA_SECTION_ID); +// this.dataSegments = new Vector<>(dataSegments); +// } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { +// dataSegments.assemble(out); + + WUnsignedInt.write(length, out, 32); + out.write(asBytes); + } + +// +// public List getDataSegments() { +// return dataSegments.getElements(); +// } +// +// public void setDataSegments(List dataSegments) { +// this.dataSegments = new Vector<>(dataSegments); +// } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/element/Elem.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/element/Elem.java new file mode 100644 index 0000000..d1c4e3b --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/element/Elem.java @@ -0,0 +1,63 @@ +package wasm.disassembly.modules.sections.element; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.conventions.Vector; +import wasm.disassembly.instructions.Expression; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.indices.FuncIdx; +import wasm.disassembly.modules.indices.TableIdx; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class Elem extends WASMOpCode { + + private TableIdx tableIdx; + private Expression offset; + private Vector init; + + public Elem(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + tableIdx = new TableIdx(in, module); + offset = new Expression(in, module); + init = new Vector<>(in, FuncIdx::new, module); + } + + public Elem(TableIdx tableIdx, Expression offset, Vector init) { + this.tableIdx = tableIdx; + this.offset = offset; + this.init = init; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + tableIdx.assemble(out); + offset.assemble(out); + init.assemble(out); + } + + public TableIdx getTableIdx() { + return tableIdx; + } + + public void setTableIdx(TableIdx tableIdx) { + this.tableIdx = tableIdx; + } + + public Expression getOffset() { + return offset; + } + + public void setOffset(Expression offset) { + this.offset = offset; + } + + public Vector getInit() { + return init; + } + + public void setInit(Vector init) { + this.init = init; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/element/ElementSection.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/element/ElementSection.java new file mode 100644 index 0000000..6fb0c89 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/element/ElementSection.java @@ -0,0 +1,57 @@ +package wasm.disassembly.modules.sections.element; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.conventions.Vector; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.indices.TypeIdx; +import wasm.disassembly.modules.sections.Section; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +public class ElementSection extends Section { + + public static final int ELEMENT_SECTION_ID = 9; + +// private Vector elementSegments; + + private final byte[] asBytes; + private long length; + + public ElementSection(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + super(in, module, ELEMENT_SECTION_ID); +// elementSegments = new Vector<>(in, Elem::new, module); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + length = WUnsignedInt.read(in, 32); + for (int i = 0; i < length; i++) { + new Elem(in, module).assemble(buffer); + } + + asBytes = buffer.toByteArray(); + } + +// public ElementSection(Module module, List elementSegments) { +// super(module, ELEMENT_SECTION_ID); +// this.elementSegments = new Vector<>(elementSegments); +// } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { +// elementSegments.assemble(out); + + WUnsignedInt.write(length, out, 32); + out.write(asBytes); + } + +// public List getElementSegments() { +// return elementSegments.getElements(); +// } +// +// public void setElementSegments(List elementSegments) { +// this.elementSegments = new Vector<>(elementSegments); +// } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/export/Export.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/export/Export.java new file mode 100644 index 0000000..89b91cb --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/export/Export.java @@ -0,0 +1,48 @@ +package wasm.disassembly.modules.sections.export; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WName; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class Export extends WASMOpCode { + + private String name; + private ExportDesc exportDesc; + + public Export(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + name = WName.read(in); + exportDesc = new ExportDesc(in, module); + } + + public Export(String name, ExportDesc exportDesc) { + this.name = name; + this.exportDesc = exportDesc; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + WName.write(name, out); + exportDesc.assemble(out); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public ExportDesc getExportDesc() { + return exportDesc; + } + + public void setExportDesc(ExportDesc exportDesc) { + this.exportDesc = exportDesc; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/export/ExportDesc.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/export/ExportDesc.java new file mode 100644 index 0000000..c866e43 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/export/ExportDesc.java @@ -0,0 +1,76 @@ +package wasm.disassembly.modules.sections.export; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.indices.FuncIdx; +import wasm.disassembly.modules.indices.GlobalIdx; +import wasm.disassembly.modules.indices.MemIdx; +import wasm.disassembly.modules.indices.TableIdx; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class ExportDesc extends WASMOpCode { + + private WASMOpCode exportValue; + private int exportType; + + + public ExportDesc(BufferedInputStream in, Module module) throws InvalidOpCodeException, IOException { + exportType = in.read(); + if (exportType < 0x00 || exportType > 0x03) { + throw new InvalidOpCodeException("invalid exportdesc type"); + } + + exportValue = exportType == 0x00 ? new FuncIdx(in, module) : + (exportType == 0x01 ? new TableIdx(in, module) : + (exportType == 0x02 ? new MemIdx(in, module) : + new GlobalIdx(in, module))); + } + + public ExportDesc(WASMOpCode exportValue, int exportType) { + this.exportValue = exportValue; + this.exportType = exportType; + } + + public ExportDesc(FuncIdx funcIdx) { + this(funcIdx, 0x00); + } + + public ExportDesc(TableIdx tableIdx) { + this(tableIdx, 0x01); + } + + public ExportDesc(MemIdx memIdx) { + this(memIdx, 0x02); + } + + public ExportDesc(GlobalIdx globalIdx) { + this(globalIdx, 0x03); + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + out.write(exportType); + exportValue.assemble(out); + } + + + public WASMOpCode getExportValue() { + return exportValue; + } + + public void setExportValue(WASMOpCode exportValue) { + this.exportValue = exportValue; + } + + public int getExportType() { + return exportType; + } + + public void setExportType(int exportType) { + this.exportType = exportType; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/export/ExportSection.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/export/ExportSection.java new file mode 100644 index 0000000..6a1d71b --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/export/ExportSection.java @@ -0,0 +1,58 @@ +package wasm.disassembly.modules.sections.export; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.conventions.Vector; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.indices.FuncIdx; +import wasm.disassembly.modules.sections.Section; +import wasm.misc.StreamReplacement; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +public class ExportSection extends Section { + + public static final int EXPORT_SECTION_ID = 7; + + private Vector exports; + + public ExportSection(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + super(in, module, EXPORT_SECTION_ID); + exports = new Vector<>(in, Export::new, module); + } + + public ExportSection(Module module, List exports) { + super(module, EXPORT_SECTION_ID); + this.exports = new Vector<>(exports); + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + exports.assemble(out); + } + + public List getExports() { + return exports.getElements(); + } + + public void setExports(List exports) { + this.exports = new Vector<>(exports); + } + + + public void addShittyExports(Module module) { + int count = 0; + for (int i = 0; i < module.streamReplacements.size(); i++) { + StreamReplacement.ReplacementType actionTaken = module.streamReplacements.get(i).getReplacementType(); + if (actionTaken == StreamReplacement.ReplacementType.HOOKCOPYEXPORT) { + getExports().add(new Export(module.streamReplacements.get(i).getExportName(), new ExportDesc(new FuncIdx( + module.getCodeSection().length + module.getImportSection().getTotalFuncImports() - + module.getCodeSection().copiesLength + count, module + )))); + count++; + } + } + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/function/FunctionSection.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/function/FunctionSection.java new file mode 100644 index 0000000..adb4b24 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/function/FunctionSection.java @@ -0,0 +1,90 @@ +package wasm.disassembly.modules.sections.function; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.indices.TypeIdx; +import wasm.disassembly.modules.sections.Section; +import wasm.disassembly.values.WUnsignedInt; +import wasm.misc.StreamReplacement; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class FunctionSection extends Section { + + public static final int FUNCTION_SECTION_ID = 3; + +// private Vector typeIdxVector; + private final byte[] asBytes; + private long length; + + public List> matchesSearchFunctionsTypes = new ArrayList<>(); + + + public FunctionSection(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + super(in, module, FUNCTION_SECTION_ID); + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + List searchFunctions = new ArrayList<>(); + for (int i = 0; i < module.streamReplacements.size(); i++) { + StreamReplacement f = module.streamReplacements.get(i); + searchFunctions.add(module.getTypeSection().getTypeIdxForFuncType(f.getFuncType())); + matchesSearchFunctionsTypes.add(new HashSet<>()); + } + +// typeIdxVector = new Vector<>(in, TypeIdx::new, module); + length = WUnsignedInt.read(in, 32); + for (int i = 0; i < length; i++) { + TypeIdx typeIdx = new TypeIdx(in, module); + for (int j = 0; j < searchFunctions.size(); j++) { + if (typeIdx.equals(searchFunctions.get(j))) { + matchesSearchFunctionsTypes.get(j).add(i); + } + } + typeIdx.assemble(buffer); + } + + for (int i = 0; i < module.streamReplacements.size(); i++) { + StreamReplacement.ReplacementType actionTaken = module.streamReplacements.get(i).getReplacementType(); + // new function will be created + if (actionTaken == StreamReplacement.ReplacementType.HOOKCOPYEXPORT) { + searchFunctions.get(i).assemble(buffer); + length++; + } + } + + asBytes = buffer.toByteArray(); + } + +// public FunctionSection(Module module, List typeIdxList) { +// super(module, FUNCTION_SECTION_ID); +// this.typeIdxVector = new Vector<>(typeIdxList); +// } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { +// typeIdxVector.assemble(out); + WUnsignedInt.write(length, out, 32); + out.write(asBytes); + } + +// public TypeIdx getByIdx(FuncIdx funcIdx) { +// return typeIdxVector.getElements().get((int)(funcIdx.getX()) - module.getImportSection().getTotalFuncImports()); +// } +// +// public List getTypeIdxVector() { +// return typeIdxVector.getElements(); +// } +// +// public void setTypeIdxVector(List typeIdxVector) { +// this.typeIdxVector = new Vector<>(typeIdxVector); +// } + +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/global/Global.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/global/Global.java new file mode 100644 index 0000000..65e2e15 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/global/Global.java @@ -0,0 +1,49 @@ +package wasm.disassembly.modules.sections.global; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.instructions.Expression; +import wasm.disassembly.modules.Module; +import wasm.disassembly.types.GlobalType; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class Global extends WASMOpCode { + + private GlobalType globalType; + private Expression expression; + + public Global(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + globalType = new GlobalType(in, module); + expression = new Expression(in, module); + } + + public Global(GlobalType globalType, Expression expression) { + this.globalType = globalType; + this.expression = expression; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + globalType.assemble(out); + expression.assemble(out); + } + + public GlobalType getGlobalType() { + return globalType; + } + + public void setGlobalType(GlobalType globalType) { + this.globalType = globalType; + } + + public Expression getExpression() { + return expression; + } + + public void setExpression(Expression expression) { + this.expression = expression; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/global/GlobalSection.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/global/GlobalSection.java new file mode 100644 index 0000000..486e55b --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/global/GlobalSection.java @@ -0,0 +1,42 @@ +package wasm.disassembly.modules.sections.global; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.conventions.Vector; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.sections.Section; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +public class GlobalSection extends Section { + + public static final int GLOBAL_SECTION_ID = 6; + + private Vector globals; + + + public GlobalSection(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + super(in, module, GLOBAL_SECTION_ID); + globals = new Vector<>(in, Global::new, module); + } + + public GlobalSection(Module module, List globals) { + super(module, GLOBAL_SECTION_ID); + this.globals = new Vector<>(globals); + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + globals.assemble(out); + } + + public List getGlobals() { + return globals.getElements(); + } + + public void setGlobals(List globals) { + this.globals = new Vector<>(globals); + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/imprt/Import.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/imprt/Import.java new file mode 100644 index 0000000..003b251 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/imprt/Import.java @@ -0,0 +1,60 @@ +package wasm.disassembly.modules.sections.imprt; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WName; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class Import extends WASMOpCode { + + private String module; + private String name; + private ImportDesc importDescription; + + public Import(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + this.module = WName.read(in); + name = WName.read(in); + importDescription = new ImportDesc(in, module); + } + + public Import(String module, String name, ImportDesc importDescription) { + this.module = module; + this.name = name; + this.importDescription = importDescription; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + WName.write(module, out); + WName.write(name, out); + importDescription.assemble(out); + } + + public String getModule() { + return module; + } + + public void setModule(String module) { + this.module = module; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public ImportDesc getImportDescription() { + return importDescription; + } + + public void setImportDescription(ImportDesc importDescription) { + this.importDescription = importDescription; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/imprt/ImportDesc.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/imprt/ImportDesc.java new file mode 100644 index 0000000..a9ab10f --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/imprt/ImportDesc.java @@ -0,0 +1,75 @@ +package wasm.disassembly.modules.sections.imprt; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.indices.FuncIdx; +import wasm.disassembly.modules.indices.TypeIdx; +import wasm.disassembly.types.GlobalType; +import wasm.disassembly.types.MemType; +import wasm.disassembly.types.TableType; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class ImportDesc extends WASMOpCode { + + private WASMOpCode importValue; + private int importType; + + public ImportDesc(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + importType = in.read(); + if (importType < 0x00 || importType > 0x03) { + throw new InvalidOpCodeException("invalid importdesc type"); + } + + importValue = importType == 0x00 ? new TypeIdx(in, module) : + (importType == 0x01 ? new TableType(in, module) : + (importType == 0x02 ? new MemType(in, module) : + new GlobalType(in, module))); + } + + public ImportDesc(WASMOpCode importValue, int importType) { + this.importValue = importValue; + this.importType = importType; + } + + public ImportDesc(TypeIdx typeIdx) { + this(typeIdx, 0x00); + } + + public ImportDesc(TableType tableType) { + this(tableType, 0x01); + } + + public ImportDesc(MemType memType) { + this(memType, 0x02); + } + + public ImportDesc(GlobalType globalType) { + this(globalType, 0x03); + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + out.write(importType); + importValue.assemble(out); + } + + public WASMOpCode getImportValue() { + return importValue; + } + + public void setImportValue(WASMOpCode importValue) { + this.importValue = importValue; + } + + public int getImportType() { + return importType; + } + + public void setImportType(int importType) { + this.importType = importType; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/imprt/ImportSection.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/imprt/ImportSection.java new file mode 100644 index 0000000..041ab81 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/imprt/ImportSection.java @@ -0,0 +1,119 @@ +package wasm.disassembly.modules.sections.imprt; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.conventions.Vector; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.indices.FuncIdx; +import wasm.disassembly.modules.sections.Section; +import wasm.disassembly.types.FuncType; +import wasm.disassembly.types.ResultType; +import wasm.misc.StreamReplacement; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class ImportSection extends Section { + + public static final int IMPORT_SECTION_ID = 2; + private Module module; + + private int totalFuncImports; + + private Vector imports; + + + public ImportSection(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + super(in, module, IMPORT_SECTION_ID); + this.module = module; + imports = new Vector<>(in, Import::new, module); + + totalFuncImports = 0; + + int first = -1; + for (int i = 0; i < imports.getElements().size(); i++) { + Import imprt = imports.getElements().get(i); + + if (imprt.getImportDescription().getImportType() == 0) { + if (totalFuncImports == 0) { + first = i; + } + totalFuncImports++; + } + } + + List newImports = new ArrayList<>(); + + + + for (StreamReplacement streamReplacement : module.streamReplacements) { + newImports.add(new Import("env", streamReplacement.getImportName(), new ImportDesc( + module.getTypeSection().getTypeIdxForFuncType(new FuncType( + streamReplacement.getFuncType().getParameterType(), + streamReplacement.getReplacementType() == StreamReplacement.ReplacementType.HOOK ? new ResultType(Collections.emptyList()) : + streamReplacement.getFuncType().getResultType() + )) + ))); + } + + List f = new ArrayList<>(imports.getElements().subList(0, first)); + f.addAll(newImports); + f.addAll(imports.getElements().subList(first, imports.getElements().size())); + imports.setElements(f); + totalFuncImports += newImports.size(); + } + + public ImportSection(Module module, List imports) { + super(module, IMPORT_SECTION_ID); + this.imports = new Vector<>(imports); + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + imports.assemble(out); + } + + public List getImports() { + return imports.getElements(); + } + + public void setImports(List imports) { + this.imports = new Vector<>(imports); + } + +// public List importFunctions(List functions) throws InvalidOpCodeException { +// for (Import imprt : functions) { +// if (imprt.getImportDescription().getImportType() != 0) { +// throw new InvalidOpCodeException("Tried to import non-function as function"); +// } +// } +// +// for (FuncIdx funcIdx : module.getAllFuncIdxs()) { +// if (funcIdx.getX() >= totalFuncImports) { +// funcIdx.setX(funcIdx.getX() + functions.size()); +// } +// } +// List newFuncIdxs = new ArrayList<>(); +// for (long i = totalFuncImports; i < totalFuncImports + functions.size(); i++) { +// newFuncIdxs.add(new FuncIdx(i, module)); +// } +// imports.getElements().addAll(functions); +// totalFuncImports += functions.size(); +// return newFuncIdxs; +// } + +// public FuncIdx importFunction(Import function) throws InvalidOpCodeException { +// return importFunctions(Collections.singletonList(function)).get(0); +// } + + public Import getByIdx(FuncIdx funcIdx) { + return imports.getElements().get((int)funcIdx.getX()); + } + + public int getTotalFuncImports() { + return totalFuncImports; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/memory/Mem.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/memory/Mem.java new file mode 100644 index 0000000..da97cc5 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/memory/Mem.java @@ -0,0 +1,37 @@ +package wasm.disassembly.modules.sections.memory; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.types.MemType; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class Mem extends WASMOpCode { + + private MemType memType; + + public Mem(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + memType = new MemType(in, module); + } + + public Mem(MemType memType) { + this.memType = memType; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + memType.assemble(out); + } + + + public MemType getMemType() { + return memType; + } + + public void setMemType(MemType memType) { + this.memType = memType; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/memory/MemorySection.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/memory/MemorySection.java new file mode 100644 index 0000000..d1bf5b5 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/memory/MemorySection.java @@ -0,0 +1,43 @@ +package wasm.disassembly.modules.sections.memory; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.conventions.Vector; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.sections.Section; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +public class MemorySection extends Section { + + public static final int MEMORY_SECTION_ID = 5; + + private Vector memories; + + + public MemorySection(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + super(in, module, MEMORY_SECTION_ID); + memories = new Vector<>(in, Mem::new, module); + } + + public MemorySection(Module module, List memories) { + super(module, MEMORY_SECTION_ID); + this.memories = new Vector<>(memories); + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + memories.assemble(out); + } + + + public List getMemories() { + return memories.getElements(); + } + + public void setMemories(List memories) { + this.memories = new Vector<>(memories); + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/start/Start.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/start/Start.java new file mode 100644 index 0000000..d83f881 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/start/Start.java @@ -0,0 +1,37 @@ +package wasm.disassembly.modules.sections.start; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.indices.FuncIdx; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class Start extends WASMOpCode { + + private FuncIdx funcIdx; + + public Start(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + funcIdx = new FuncIdx(in, module); + } + + public Start(FuncIdx funcIdx) { + this.funcIdx = funcIdx; + } + + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + funcIdx.assemble(out); + } + + public FuncIdx getFuncIdx() { + return funcIdx; + } + + public void setFuncIdx(FuncIdx funcIdx) { + this.funcIdx = funcIdx; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/start/StartSection.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/start/StartSection.java new file mode 100644 index 0000000..5927a31 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/start/StartSection.java @@ -0,0 +1,40 @@ +package wasm.disassembly.modules.sections.start; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.sections.Section; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class StartSection extends Section { + + public static final int START_SECTION_ID = 8; + + private Start start; + + public StartSection(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + super(in, module, START_SECTION_ID); + start = new Start(in, module); + } + + public StartSection(Module module, Start start) { + super(module, START_SECTION_ID); + this.start = start; + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + start.assemble(out); + } + + + public Start getStart() { + return start; + } + + public void setStart(Start start) { + this.start = start; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/table/Table.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/table/Table.java new file mode 100644 index 0000000..7cb30d1 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/table/Table.java @@ -0,0 +1,36 @@ +package wasm.disassembly.modules.sections.table; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.types.TableType; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class Table extends WASMOpCode { + + private TableType tableType; + + public Table(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + tableType = new TableType(in, module); + } + + public Table(TableType tableType) { + this.tableType = tableType; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + tableType.assemble(out); + } + + public TableType getTableType() { + return tableType; + } + + public void setTableType(TableType tableType) { + this.tableType = tableType; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/table/TableSection.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/table/TableSection.java new file mode 100644 index 0000000..b0a4937 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/table/TableSection.java @@ -0,0 +1,42 @@ +package wasm.disassembly.modules.sections.table; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.conventions.Vector; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.sections.Section; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +public class TableSection extends Section { + + public static final int TABLE_SECTION_ID = 4; + + private Vector tables; + + + public TableSection(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + super(in, module, TABLE_SECTION_ID); + tables = new Vector<>(in, Table::new, module); + } + + public TableSection(Module module, List
tables) { + super(module, TABLE_SECTION_ID); + this.tables = new Vector<>(tables); + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + tables.assemble(out); + } + + public List
getTables() { + return tables.getElements(); + } + + public void setTables(List
tables) { + this.tables = new Vector<>(tables); + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/modules/sections/type/TypeSection.java b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/type/TypeSection.java new file mode 100644 index 0000000..c0f7ca9 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/modules/sections/type/TypeSection.java @@ -0,0 +1,65 @@ +package wasm.disassembly.modules.sections.type; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.conventions.Vector; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.indices.FuncIdx; +import wasm.disassembly.modules.indices.TypeIdx; +import wasm.disassembly.modules.sections.Section; +import wasm.disassembly.types.FuncType; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +public class TypeSection extends Section { + + public static final int TYPE_SECTION_ID = 1; + + private Vector functionTypes; + + + public TypeSection(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + super(in, module, TYPE_SECTION_ID); + functionTypes = new Vector<>(in, FuncType::new, module); + } + + public TypeSection(Module module, List functionTypes) { + super(module, TYPE_SECTION_ID); + this.functionTypes = new Vector<>(functionTypes); + } + + @Override + protected void assemble2(OutputStream out) throws IOException, InvalidOpCodeException { + functionTypes.assemble(out); + } + +// public FuncType getByFuncIdx(FuncIdx funcIdx) { +// return getByTypeIdx(module.getFunctionSection().getByIdx(funcIdx)); +// } + + public List getFunctionTypes() { + return functionTypes.getElements(); + } + + public FuncType getByTypeIdx(TypeIdx typeIdx) { + return functionTypes.getElements().get((int)(typeIdx.getX())); + } + + public void setFunctionTypes(List functionTypes) { + this.functionTypes = new Vector<>(functionTypes); + } + + public TypeIdx getTypeIdxForFuncType(FuncType newFuncType) { + for (int i = 0; i < getFunctionTypes().size(); i++) { + FuncType funcType = getFunctionTypes().get(i); + if (funcType.equals(newFuncType)) { + return new TypeIdx(i); + } + } + + getFunctionTypes().add(newFuncType); + return new TypeIdx(getFunctionTypes().size() - 1); + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/types/ElemType.java b/G-Wasm/src/main/java/wasm/disassembly/types/ElemType.java new file mode 100644 index 0000000..c337143 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/types/ElemType.java @@ -0,0 +1,26 @@ +package wasm.disassembly.types; + +import java.util.HashMap; +import java.util.Map; + +public enum ElemType { + FUNCREF(0x70); + + + public int val; + ElemType(int val) { + this.val = val; + } + + private static Map map = new HashMap<>(); + static { + for (ElemType valType : ElemType.values()) { + map.put(valType.val, valType); + } + } + + public static ElemType from_val(int val) { + return map.get(val); + } + +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/types/FuncType.java b/G-Wasm/src/main/java/wasm/disassembly/types/FuncType.java new file mode 100644 index 0000000..bb0975e --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/types/FuncType.java @@ -0,0 +1,68 @@ +package wasm.disassembly.types; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.modules.sections.code.Func; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class FuncType extends WASMOpCode { + + private ResultType parameterType; + private ResultType resultType; + + public FuncType(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + if (in.read() != 0x60) throw new InvalidOpCodeException("Function types must be encoded with 0x60"); + + parameterType = new ResultType(in, module); + resultType = new ResultType(in, module); + } + + public FuncType(ResultType parameterType, ResultType resultType) { + this.parameterType = parameterType; + this.resultType = resultType; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + out.write(0x60); + parameterType.assemble(out); + resultType.assemble(out); + } + + public ResultType getParameterType() { + return parameterType; + } + + public void setParameterType(ResultType parameterType) { + this.parameterType = parameterType; + } + + public ResultType getResultType() { + return resultType; + } + + public void setResultType(ResultType resultType) { + this.resultType = resultType; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof FuncType)) { + return false; + } + + FuncType other = (FuncType) obj; + + return parameterType.equals(other.parameterType) && + resultType.equals(other.resultType); + } + + @Override + public String toString() { + return parameterType + " -> " + resultType; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/types/GlobalType.java b/G-Wasm/src/main/java/wasm/disassembly/types/GlobalType.java new file mode 100644 index 0000000..cf1e7c8 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/types/GlobalType.java @@ -0,0 +1,47 @@ +package wasm.disassembly.types; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class GlobalType extends WASMOpCode { + + private ValType valType; + private Mutability mutability; + + public GlobalType(BufferedInputStream in, Module module) throws IOException { + valType = ValType.from_val(in.read()); + mutability = Mutability.from_val(in.read()); + } + + public GlobalType(ValType valType, Mutability mutability) { + this.valType = valType; + this.mutability = mutability; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + out.write(valType.val); + out.write(mutability.val); + } + + public ValType getValType() { + return valType; + } + + public void setValType(ValType valType) { + this.valType = valType; + } + + public Mutability getMutability() { + return mutability; + } + + public void setMutability(Mutability mutability) { + this.mutability = mutability; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/types/Limits.java b/G-Wasm/src/main/java/wasm/disassembly/types/Limits.java new file mode 100644 index 0000000..064c1ad --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/types/Limits.java @@ -0,0 +1,62 @@ +package wasm.disassembly.types; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; +import wasm.disassembly.values.WUnsignedInt; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class Limits extends WASMOpCode { + + private long min; + private long max; + + public Limits(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + int flag = in.read(); + if (flag == 0x00) { + min = WUnsignedInt.read(in, 32); + max = -1; + } + else if (flag == 0x01) { + min = WUnsignedInt.read(in, 32); + max = WUnsignedInt.read(in, 32); + } + else throw new InvalidOpCodeException("Function types must be encoded with 0x00 or 0x01"); + } + + public Limits(long min, long max) { + this.min = min; + this.max = max; + } + + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + out.write(max == -1 ? 0x00 : 0x01); + WUnsignedInt.write(min, out, 32); + if (max != -1) { + WUnsignedInt.write(max, out, 32); + } + } + + public long getMax() { + return max; + } + + public long getMin() { + return min; + } + + public boolean hasMax() { + return max != -1; + } + + public void setMin(long min) { + this.min = min; + } + + public void setMax(long max) { + this.max = max; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/types/MemType.java b/G-Wasm/src/main/java/wasm/disassembly/types/MemType.java new file mode 100644 index 0000000..965acf4 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/types/MemType.java @@ -0,0 +1,34 @@ +package wasm.disassembly.types; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class MemType extends WASMOpCode { + + private Limits limits; + + public MemType(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + limits = new Limits(in, module); + } + + public MemType(Limits limits) { + this.limits = limits; + } + + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + limits.assemble(out); + } + + public Limits getLimits() { + return limits; + } + + public void setLimits(Limits limits) { + this.limits = limits; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/types/Mutability.java b/G-Wasm/src/main/java/wasm/disassembly/types/Mutability.java new file mode 100644 index 0000000..fe80511 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/types/Mutability.java @@ -0,0 +1,26 @@ +package wasm.disassembly.types; + +import java.util.HashMap; +import java.util.Map; + +public enum Mutability { + CONST(0x00), + VAR(0x01); + + public int val; + Mutability(int val) { + this.val = val; + } + + private static Map map = new HashMap<>(); + static { + for (Mutability valType : Mutability.values()) { + map.put(valType.val, valType); + } + } + + public static Mutability from_val(int val) { + return map.get(val); + } + +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/types/ResultType.java b/G-Wasm/src/main/java/wasm/disassembly/types/ResultType.java new file mode 100644 index 0000000..55fbc48 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/types/ResultType.java @@ -0,0 +1,70 @@ +package wasm.disassembly.types; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.conventions.CustomVector; +import wasm.disassembly.modules.Module; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class ResultType extends WASMOpCode { + + private CustomVector vector; + + public ResultType(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + vector = new CustomVector<>( + in, + (in1, m) -> ValType.from_val(in1.read()), + (valType, out) -> out.write(valType.val), + module + ); + } + + public ResultType(List valTypes) { + vector = new CustomVector<>( + valTypes, + (valType, out) -> out.write(valType.val) + ); + } + + public ResultType(CustomVector vector) { + this.vector = vector; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + vector.assemble(out); + } + + public List typeList() { + return vector.getElements(); + } + + public CustomVector getVector() { + return vector; + } + + public void setVector(CustomVector vector) { + this.vector = vector; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof ResultType)) { + return false; + } + + ResultType other = (ResultType) obj; + return vector.getElements().equals(other.vector.getElements()); + } + + @Override + public String toString() { + return "(" + vector.getElements().stream().map(Enum::name).collect(Collectors.joining(" ")) + ")"; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/types/TableType.java b/G-Wasm/src/main/java/wasm/disassembly/types/TableType.java new file mode 100644 index 0000000..e96cd02 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/types/TableType.java @@ -0,0 +1,50 @@ +package wasm.disassembly.types; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; +import wasm.disassembly.modules.Module; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class TableType extends WASMOpCode { + + private ElemType elemType; + private Limits limits; + + public TableType(BufferedInputStream in, Module module) throws IOException, InvalidOpCodeException { + elemType = ElemType.from_val(in.read()); + if (elemType == null) { + throw new InvalidOpCodeException("No such element type"); + } + limits = new Limits(in, module); + } + + public TableType(ElemType elemType, Limits limits) { + this.elemType = elemType; + this.limits = limits; + } + + @Override + public void assemble(OutputStream out) throws IOException, InvalidOpCodeException { + out.write(elemType.val); + limits.assemble(out); + } + + public ElemType getElemType() { + return elemType; + } + + public void setElemType(ElemType elemType) { + this.elemType = elemType; + } + + public Limits getLimits() { + return limits; + } + + public void setLimits(Limits limits) { + this.limits = limits; + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/types/ValType.java b/G-Wasm/src/main/java/wasm/disassembly/types/ValType.java new file mode 100644 index 0000000..239d286 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/types/ValType.java @@ -0,0 +1,29 @@ +package wasm.disassembly.types; + +import java.util.HashMap; +import java.util.Map; + +public enum ValType { + I32(0x7f), + I64(0x7e), + F32(0x7d), + F64(0x7c); + + + public int val; + ValType(int val) { + this.val = val; + } + + private static Map map = new HashMap<>(); + static { + for (ValType valType : ValType.values()) { + map.put(valType.val, valType); + } + } + + public static ValType from_val(int val) { + return map.get(val); + } + +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/values/WDouble.java b/G-Wasm/src/main/java/wasm/disassembly/values/WDouble.java new file mode 100644 index 0000000..05bd15a --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/values/WDouble.java @@ -0,0 +1,22 @@ +package wasm.disassembly.values; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.ByteBuffer; + +public class WDouble { + + public static double read(BufferedInputStream in) throws IOException { + byte[] bytes = new byte[8]; + in.read(bytes); + return ByteBuffer.wrap(bytes).getDouble(); + } + + public static void write(double value, OutputStream out) throws IOException { + byte[] bytes = new byte[8]; + ByteBuffer.wrap(bytes).putDouble(value); + out.write(bytes); + } + +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/values/WFloat.java b/G-Wasm/src/main/java/wasm/disassembly/values/WFloat.java new file mode 100644 index 0000000..d4388f7 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/values/WFloat.java @@ -0,0 +1,22 @@ +package wasm.disassembly.values; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.ByteBuffer; + +public class WFloat { + + public static float read(BufferedInputStream in) throws IOException { + byte[] bytes = new byte[4]; + in.read(bytes); + return ByteBuffer.wrap(bytes).getFloat(); + } + + public static void write(float value, OutputStream out) throws IOException { + byte[] bytes = new byte[4]; + ByteBuffer.wrap(bytes).putFloat(value); + out.write(bytes); + } + +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/values/WName.java b/G-Wasm/src/main/java/wasm/disassembly/values/WName.java new file mode 100644 index 0000000..fd97381 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/values/WName.java @@ -0,0 +1,25 @@ +package wasm.disassembly.values; + +import wasm.disassembly.InvalidOpCodeException; +import wasm.disassembly.WASMOpCode; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; + +public class WName { + + public static String read(BufferedInputStream in) throws IOException, InvalidOpCodeException { + long length = WUnsignedInt.read(in, 32); + byte[] arr = new byte[(int)length]; + in.read(arr); + return new String(arr, StandardCharsets.UTF_8); + } + + public static void write(String value, OutputStream out) throws IOException, InvalidOpCodeException { + byte[] bytes = value.getBytes(StandardCharsets.UTF_8); + WUnsignedInt.write(bytes.length, out, 32); + out.write(bytes); + } +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/values/WSignedInt.java b/G-Wasm/src/main/java/wasm/disassembly/values/WSignedInt.java new file mode 100644 index 0000000..71d185d --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/values/WSignedInt.java @@ -0,0 +1,59 @@ +package wasm.disassembly.values; + +import wasm.disassembly.InvalidOpCodeException; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class WSignedInt { + + + // everything with N <= 32 + public static int read(BufferedInputStream in, int N) throws InvalidOpCodeException, IOException { + if (N > 32) throw new InvalidOpCodeException("Invalid integer size"); + + int result = 0; + int cur; + int count = 0; + int signBits = -1; + + int limit = N/7 + (N%7 != 0 ? 1 : 0); + + do { + cur = (in.read()) & 0xff; + result |= (cur & 0x7f) << (count * 7); + signBits <<= 7; + count++; + } while (((cur & 0x80) == 0x80) && count < limit); + + if ((cur & 0x80) == 0x80) { + throw new InvalidOpCodeException("invalid LEB128 sequence"); + } + + // Sign extend if appropriate + if (((signBits >> 1) & result) != 0 ) { + result |= signBits; + } + + return result; + } + + public static void write(int value, OutputStream out, int N) throws InvalidOpCodeException, IOException { + if (N > 32) throw new InvalidOpCodeException("Invalid integer size"); + + int remaining = value >> 7; + boolean hasMore = true; + int end = ((value & Integer.MIN_VALUE) == 0) ? 0 : -1; + + while (hasMore) { + hasMore = (remaining != end) + || ((remaining & 1) != ((value >> 6) & 1)); + + out.write((byte)((value & 0x7f) | (hasMore ? 0x80 : 0))); + value = remaining; + remaining >>= 7; + } + } + +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/values/WSignedLong.java b/G-Wasm/src/main/java/wasm/disassembly/values/WSignedLong.java new file mode 100644 index 0000000..eeb86fc --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/values/WSignedLong.java @@ -0,0 +1,54 @@ +package wasm.disassembly.values; + +import wasm.disassembly.InvalidOpCodeException; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class WSignedLong { + + // everything with N > 32 && N <= 64 + public static long read(BufferedInputStream in, int N) throws InvalidOpCodeException, IOException { + long result = 0; + long cur; + int count = 0; + long signBits = -1; + + long limit = N/7 + (N%7 != 0 ? 1 : 0); + + do { + cur = (in.read()) & 0xff; + result |= (cur & 0x7f) << (count * 7); + signBits <<= 7; + count++; + } while (((cur & 0x80) == 0x80) && count < limit); + + if ((cur & 0x80) == 0x80) { + throw new InvalidOpCodeException("invalid LEB128 sequence"); + } + + // Sign extend if appropriate + if (((signBits >> 1) & result) != 0 ) { + result |= signBits; + } + + return result; + } + + public static void write(long value, OutputStream out, int N) throws InvalidOpCodeException, IOException { + long remaining = value >> 7; + boolean hasMore = true; + long end = ((value & Long.MIN_VALUE) == 0) ? 0 : -1; + + while (hasMore) { + hasMore = (remaining != end) + || ((remaining & 1) != ((value >> 6) & 1)); + + out.write((byte)((value & 0x7f) | (hasMore ? 0x80 : 0))); + value = remaining; + remaining >>= 7; + } + } + +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/values/WUnsignedInt.java b/G-Wasm/src/main/java/wasm/disassembly/values/WUnsignedInt.java new file mode 100644 index 0000000..b79ce06 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/values/WUnsignedInt.java @@ -0,0 +1,47 @@ +package wasm.disassembly.values; + +import wasm.disassembly.InvalidOpCodeException; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class WUnsignedInt { + + // everything with N <= 63 + public static long read(BufferedInputStream in, int N) throws InvalidOpCodeException, IOException, IOException { + if (N >= 64) throw new InvalidOpCodeException("Invalid integer size"); + + long result = 0; + long cur; + int count = 0; + int limit = N/7 + (N%7 != 0 ? 1 : 0); + + do { + cur = in.read() & 0xff; + result |= (cur & 0x7f) << (count * 7); + count++; + } while (((cur & 0x80) == 0x80) && count < limit); + + if ((cur & 0x80) == 0x80) { + throw new InvalidOpCodeException("invalid LEB128 sequence"); + } + + return result; + } + + public static void write(long value, OutputStream out, int N) throws InvalidOpCodeException, IOException { + if (N >= 64) throw new InvalidOpCodeException("Invalid integer size"); + + long remaining = value >>> 7; + + while (remaining != 0) { + out.write((byte)((value & 0x7f) | 0x80)); + value = remaining; + remaining >>>= 7; + } + + out.write((byte)(value & 0x7f)); + } + +} diff --git a/G-Wasm/src/main/java/wasm/disassembly/values/WUnsignedLong.java b/G-Wasm/src/main/java/wasm/disassembly/values/WUnsignedLong.java new file mode 100644 index 0000000..42e83a5 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/disassembly/values/WUnsignedLong.java @@ -0,0 +1,58 @@ +package wasm.disassembly.values; + +import wasm.disassembly.InvalidOpCodeException; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.math.BigInteger; + +public class WUnsignedLong { + + // everything with N > 63 + public static BigInteger read(BufferedInputStream in, int N) throws InvalidOpCodeException, IOException, IOException { + BigInteger result = BigInteger.ZERO; + long cur; + int count = 0; + int limit = N/7 + (N%7 != 0 ? 1 : 0); + + do { + cur = in.read() & 0xff; + result = result.or(BigInteger.valueOf(cur & 0x7f).shiftLeft(count * 7)); + count++; + } while (((cur & 0x80) == 0x80) && count < limit); + + if ((cur & 0x80) == 0x80) { + throw new InvalidOpCodeException("invalid LEB128 sequence"); + } + + return result; + } + + + public static void write(BigInteger value, OutputStream out, int N) throws InvalidOpCodeException, IOException { + long remaining = value.shiftRight(7).longValueExact(); + long l_value = -1; + boolean first = true; + + while (remaining != 0) { + if (first) { + out.write((byte) ((value.longValue() & 0x7f) | 0x80)); + first = false; + } + else { + out.write((byte) ((l_value & 0x7f) | 0x80)); + } + l_value = remaining; + remaining >>>= 7; + } + if (first) { + out.write((byte) (value.longValue() & 0x7f)); + } + else { + out.write((byte) (l_value & 0x7f)); + } + } + + +} diff --git a/G-Wasm/src/main/java/wasm/misc/Function.java b/G-Wasm/src/main/java/wasm/misc/Function.java new file mode 100644 index 0000000..ba4b85f --- /dev/null +++ b/G-Wasm/src/main/java/wasm/misc/Function.java @@ -0,0 +1,78 @@ +package wasm.misc; + +import wasm.disassembly.instructions.Expression; +import wasm.disassembly.modules.sections.code.Locals; +import wasm.disassembly.types.FuncType; +import wasm.disassembly.types.ValType; + +import java.util.ArrayList; +import java.util.List; + +public class Function { + + private FuncType funcType = null; + private List locals = null; + private Expression code = null; + + public Function(FuncType funcType, List locals, Expression code) { + this.funcType = funcType; + this.locals = locals; + this.code = code; + } + +// public Function(Module module, FuncIdx funcIdx) { +// funcType = module.getTypeSection().getByFuncIdx(funcIdx); +// +// Func code = module.getCodeSection().getByIdx(funcIdx); +// this.code = code.getExpression(); +// locals = code.getLocalss(); +// } + +// public FuncIdx addToModule(Module module) { +// TypeIdx typeIdx = module.getTypeSection().getTypeIdxForFuncType(funcType); +// Func func = new Func(locals, code); +// +// module.getFunctionSection().getTypeIdxVector().add(typeIdx); +// module.getCodeSection().getCodesEntries().add(new Code(func)); +// return new FuncIdx( +// module.getImportSection().getTotalFuncImports() + module.getCodeSection().getCodesEntries().size() - 1, +// module +// ); +// } + + + public FuncType getFuncType() { + return funcType; + } + + public void setFuncType(FuncType funcType) { + this.funcType = funcType; + } + + public List getLocals() { + return locals; + } + + public List getLocalsFloored() { + List result = new ArrayList<>(); + for (Locals loc : locals) { + for (int i = 0; i < loc.getAmount(); i++) { + result.add(loc.getValType()); + } + } + + return result; + } + + public void setLocals(List locals) { + this.locals = locals; + } + + public Expression getCode() { + return code; + } + + public void setCode(Expression code) { + this.code = code; + } +} diff --git a/G-Wasm/src/main/java/wasm/misc/StreamReplacement.java b/G-Wasm/src/main/java/wasm/misc/StreamReplacement.java new file mode 100644 index 0000000..2aa3385 --- /dev/null +++ b/G-Wasm/src/main/java/wasm/misc/StreamReplacement.java @@ -0,0 +1,19 @@ +package wasm.misc; + +import wasm.disassembly.modules.sections.code.Func; +import wasm.disassembly.types.FuncType; + +public interface StreamReplacement { + + + enum ReplacementType { + HOOK, + HOOKCOPYEXPORT + } + + FuncType getFuncType(); + ReplacementType getReplacementType(); + String getImportName(); + String getExportName(); + boolean codeMatches(Func code); +} diff --git a/settings.gradle.kts b/settings.gradle.kts index e22c723..a9857cd 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,3 +6,4 @@ rootProject.name = "G-Earth-Parent" include(":G-Earth") +include(":G-Wasm")