From 122843da5c6e65d90668953583a9ebb6cce3277e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lise=20Valentin?= Date: Tue, 5 Nov 2024 10:13:50 +0100 Subject: [PATCH 01/11] Add ConstantPool --- .../java/org/momento/lycoris/Lycoris.java | 23 ++++- .../org/momento/lycoris/agent/JavaAgent.java | 30 ++++++ .../momento/lycoris/api/MixinRegistry.java | 9 ++ .../momento/lycoris/mixins/Boostrapper.java | 7 ++ .../momento/lycoris/mixins/mixin/Mixin.java | 15 +++ .../mixins/mixin/classe/ByteCodec.java | 9 ++ .../mixins/mixin/classe/ClassWrapper.java | 15 +++ .../mixin/classe/structures/ConstantPool.java | 93 +++++++++++++++++++ .../classe/structures/infos/ClassInfo.java | 27 ++++++ .../classe/structures/infos/DoubleInfo.java | 27 ++++++ .../classe/structures/infos/FloatInfo.java | 27 ++++++ .../mixin/classe/structures/infos/Info.java | 22 +++++ .../classe/structures/infos/IntegerInfo.java | 27 ++++++ .../structures/infos/InvokeDynamicInfo.java | 31 +++++++ .../classe/structures/infos/LongInfo.java | 27 ++++++ .../structures/infos/MethodHandleInfo.java | 31 +++++++ .../structures/infos/MethodTypeInfo.java | 27 ++++++ .../classe/structures/infos/NameTypeInfo.java | 31 +++++++ .../classe/structures/infos/RefInfo.java | 31 +++++++ .../classe/structures/infos/StringInfo.java | 27 ++++++ .../classe/structures/infos/UTF8Info.java | 34 +++++++ 21 files changed, 568 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/momento/lycoris/agent/JavaAgent.java create mode 100644 src/main/java/org/momento/lycoris/api/MixinRegistry.java create mode 100644 src/main/java/org/momento/lycoris/mixins/Boostrapper.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/Mixin.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/ByteCodec.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/ClassWrapper.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/ConstantPool.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/ClassInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/DoubleInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/FloatInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/Info.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/IntegerInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/InvokeDynamicInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/LongInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/MethodHandleInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/MethodTypeInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/NameTypeInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/RefInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/StringInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/UTF8Info.java diff --git a/src/main/java/org/momento/lycoris/Lycoris.java b/src/main/java/org/momento/lycoris/Lycoris.java index 986c5f8..f9d5a45 100644 --- a/src/main/java/org/momento/lycoris/Lycoris.java +++ b/src/main/java/org/momento/lycoris/Lycoris.java @@ -1,13 +1,32 @@ package org.momento.lycoris; +import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; +import org.momento.lycoris.agent.JavaAgent; + +import javax.xml.transform.Transformer; +import java.lang.instrument.ClassDefinition; +import java.lang.instrument.Instrumentation; +import java.util.logging.Level; +import java.util.logging.Logger; public final class Lycoris extends JavaPlugin { + public static Logger LOGGER; + @Override public void onEnable() { - // Plugin startup logic - + LOGGER = getLogger(); + Instrumentation inst; + try { + inst = JavaAgent.load(); + } catch (Exception error) { + LOGGER.log(Level.SEVERE, error.getMessage()); + Bukkit.getPluginManager().disablePlugin(this); + return; + } + ClassPool + ClassDefinition definition = new ClassDefinition() } @Override diff --git a/src/main/java/org/momento/lycoris/agent/JavaAgent.java b/src/main/java/org/momento/lycoris/agent/JavaAgent.java new file mode 100644 index 0000000..bacd6b6 --- /dev/null +++ b/src/main/java/org/momento/lycoris/agent/JavaAgent.java @@ -0,0 +1,30 @@ +package org.momento.lycoris.agent; + +import com.sun.tools.attach.AgentInitializationException; +import com.sun.tools.attach.AgentLoadException; +import com.sun.tools.attach.AttachNotSupportedException; +import com.sun.tools.attach.VirtualMachine; + +import java.io.IOException; +import java.lang.instrument.Instrumentation; +import java.lang.management.ManagementFactory; + +public class JavaAgent { + + public static final String PID = ManagementFactory.getRuntimeMXBean().getName().split("@")[0]; + + private static Instrumentation ins; + + public static Instrumentation load() throws IOException, AttachNotSupportedException, AgentLoadException, AgentInitializationException { + VirtualMachine vm = VirtualMachine.attach(PID); + vm.loadAgent(JavaAgent.class.getProtectionDomain().getCodeSource().getLocation().getPath()); + vm.detach(); + if (ins == null) + throw new IllegalStateException("JavaAgent not initialized"); + return ins; + } + + public static void agentmain(final String args, final Instrumentation instrumentation) { + ins = instrumentation; + } +} diff --git a/src/main/java/org/momento/lycoris/api/MixinRegistry.java b/src/main/java/org/momento/lycoris/api/MixinRegistry.java new file mode 100644 index 0000000..50cdb55 --- /dev/null +++ b/src/main/java/org/momento/lycoris/api/MixinRegistry.java @@ -0,0 +1,9 @@ +package org.momento.lycoris.api; + +public class MixinRegistry { + + public static void addMixin() { + + } + +} diff --git a/src/main/java/org/momento/lycoris/mixins/Boostrapper.java b/src/main/java/org/momento/lycoris/mixins/Boostrapper.java new file mode 100644 index 0000000..334e353 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/Boostrapper.java @@ -0,0 +1,7 @@ +package org.momento.lycoris.mixins; + +public class Boostrapper { + + + +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/Mixin.java b/src/main/java/org/momento/lycoris/mixins/mixin/Mixin.java new file mode 100644 index 0000000..fabb581 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/Mixin.java @@ -0,0 +1,15 @@ +package org.momento.lycoris.mixins.mixin; + +public class Mixin { + + private Class classe; + + public Mixin(Class classe) { + this.classe = classe; + } + + public byte[] getBytecode() { + Cl + } + +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/ByteCodec.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/ByteCodec.java new file mode 100644 index 0000000..133b49c --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/ByteCodec.java @@ -0,0 +1,9 @@ +package org.momento.lycoris.mixins.mixin.classe; + +import java.nio.ByteBuffer; + +public interface ByteCodec { + + void encode(ByteBuffer buffer); + +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/ClassWrapper.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/ClassWrapper.java new file mode 100644 index 0000000..a6e7f9a --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/ClassWrapper.java @@ -0,0 +1,15 @@ +package org.momento.lycoris.mixins.mixin.classe; + +import java.nio.ByteBuffer; + +public class ClassWrapper implements ByteCodec { + + + public ClassWrapper() {} + + + @Override + public void encode(ByteBuffer buffer) { + + } +} \ No newline at end of file diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/ConstantPool.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/ConstantPool.java new file mode 100644 index 0000000..885816d --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/ConstantPool.java @@ -0,0 +1,93 @@ +package org.momento.lycoris.mixins.mixin.classe.structures; + +import org.momento.lycoris.mixins.mixin.classe.ByteCodec; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.*; + +import java.nio.ByteBuffer; + +public class ConstantPool implements ByteCodec { + + public enum Tag { + + Class((byte) 7), + FieldRef((byte) 9), + MethodRef((byte) 10), + InterfaceMethodRef((byte) 1), + String((byte) 8), + Integer((byte) 3), + Float((byte) 4), + Long((byte) 5), + Double((byte) 6), + NameAndType((byte) 12), + UTF8((byte) 1), + MethodHandle((byte) 15), + MethodType((byte) 16), + InvokeDynamic((byte) 18); + + private final byte value; + + Tag(final byte value) { + this.value = value; + } + + public byte getValue() { + return value; + } + + public static Tag getTag(final byte value) { + for (final Tag tag : Tag.values()) { + if (tag.value == value) + return tag; + } + throw new IllegalArgumentException(); + } + + } + + private Tag tag; + private Info info; + + + public ConstantPool(final Tag tag, final Info info) { + this.tag = tag; + this.info = info; + } + + public static ConstantPool decode(ByteBuffer buffer) { + Tag tag = Tag.getTag(buffer.get()); + Info info = switch (tag) { + case Class: yield ClassInfo.decode(buffer); + case FieldRef: + case MethodRef: + case InterfaceMethodRef: + yield RefInfo.decode(tag, buffer); + case String: + yield StringInfo.decode(buffer); + case Integer: + yield IntegerInfo.decode(buffer); + case Float: + yield FloatInfo.decode(buffer); + case Long: + yield LongInfo.decode(buffer); + case Double: + yield DoubleInfo.decode(buffer); + case NameAndType: + yield NameTypeInfo.decode(buffer); + case UTF8: + yield UTF8Info.decode(buffer); + case MethodHandle: + yield MethodHandleInfo.decode(buffer); + case MethodType: + yield MethodTypeInfo.decode(buffer); + case InvokeDynamic: + yield InvokeDynamicInfo.decode(buffer); + }; + return new ConstantPool(tag, info); + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.put(tag.getValue()); + info.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/ClassInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/ClassInfo.java new file mode 100644 index 0000000..bfe2b77 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/ClassInfo.java @@ -0,0 +1,27 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; + +import java.nio.ByteBuffer; + +public class ClassInfo extends Info { + + private final char nameIndex; + + public ClassInfo(final ConstantPool.Tag tag, final char nameIndex) { + super(tag); + this.nameIndex = nameIndex; + } + + public char getNameIndex() { return nameIndex; } + + public static ClassInfo decode(ByteBuffer buffer) { + return new ClassInfo(ConstantPool.Tag.Class, buffer.getChar()); + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar(nameIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/DoubleInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/DoubleInfo.java new file mode 100644 index 0000000..d20c1cd --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/DoubleInfo.java @@ -0,0 +1,27 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; + +import java.nio.ByteBuffer; + +public class DoubleInfo extends Info { + + private final double bytes; + + public DoubleInfo(final ConstantPool.Tag tag, final double bytes) { + super(tag); + this.bytes = bytes; + } + + public double getValue() { return bytes; } + + public static DoubleInfo decode(ByteBuffer buffer) { + return new DoubleInfo(ConstantPool.Tag.Float, buffer.getDouble()); + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putDouble(bytes); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/FloatInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/FloatInfo.java new file mode 100644 index 0000000..6c412a4 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/FloatInfo.java @@ -0,0 +1,27 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; + +import java.nio.ByteBuffer; + +public class FloatInfo extends Info { + + private final float bytes; + + public FloatInfo(final ConstantPool.Tag tag, final float bytes) { + super(tag); + this.bytes = bytes; + } + + public float getValue() { return bytes; } + + public static FloatInfo decode(ByteBuffer buffer) { + return new FloatInfo(ConstantPool.Tag.Float, buffer.getFloat()); + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putFloat(bytes); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/Info.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/Info.java new file mode 100644 index 0000000..398f76a --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/Info.java @@ -0,0 +1,22 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos; + +import org.momento.lycoris.mixins.mixin.classe.ByteCodec; +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; + +import java.nio.ByteBuffer; + +public abstract class Info implements ByteCodec { + + private ConstantPool.Tag tag; + + public Info(final ConstantPool.Tag tag) { + this.tag = tag; + } + + public ConstantPool.Tag getTag() { return tag; } + + @Override + public void encode(ByteBuffer buffer) { + buffer.put(tag.getValue()); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/IntegerInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/IntegerInfo.java new file mode 100644 index 0000000..7446aa0 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/IntegerInfo.java @@ -0,0 +1,27 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; + +import java.nio.ByteBuffer; + +public class IntegerInfo extends Info { + + private final int bytes; + + public IntegerInfo(final ConstantPool.Tag tag, final int bytes) { + super(tag); + this.bytes = bytes; + } + + public int getValue() { return bytes; } + + public static IntegerInfo decode(ByteBuffer buffer) { + return new IntegerInfo(ConstantPool.Tag.Integer, buffer.getInt()); + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putInt(bytes); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/InvokeDynamicInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/InvokeDynamicInfo.java new file mode 100644 index 0000000..777c707 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/InvokeDynamicInfo.java @@ -0,0 +1,31 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; + +import java.nio.ByteBuffer; + +public class InvokeDynamicInfo extends Info { + + private final char bootstrapMethodAttrIndex; + private final char nameTypeIndex; + + public InvokeDynamicInfo(final ConstantPool.Tag tag, final char bootstrapMethodAttrIndex, final char nameTypeIndex) { + super(tag); + this.bootstrapMethodAttrIndex = bootstrapMethodAttrIndex; + this.nameTypeIndex = nameTypeIndex; + } + + public char getBootstrapMethodAttrIndex() { return bootstrapMethodAttrIndex; } + public char getNameTypeIndex() { return nameTypeIndex; } + + public static InvokeDynamicInfo decode(ByteBuffer buffer) { + return new InvokeDynamicInfo(ConstantPool.Tag.InvokeDynamic, buffer.getChar(), buffer.getChar()); + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar(bootstrapMethodAttrIndex); + buffer.putChar(nameTypeIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/LongInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/LongInfo.java new file mode 100644 index 0000000..e552316 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/LongInfo.java @@ -0,0 +1,27 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; + +import java.nio.ByteBuffer; + +public class LongInfo extends Info { + + private final long bytes; + + public LongInfo(final ConstantPool.Tag tag, final long bytes) { + super(tag); + this.bytes = bytes; + } + + public long getValue() { return bytes; } + + public static LongInfo decode(ByteBuffer buffer) { + return new LongInfo(ConstantPool.Tag.Integer, buffer.getLong()); + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putLong(bytes); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/MethodHandleInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/MethodHandleInfo.java new file mode 100644 index 0000000..08990fb --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/MethodHandleInfo.java @@ -0,0 +1,31 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; + +import java.nio.ByteBuffer; + +public class MethodHandleInfo extends Info { + + private final byte referenceKind; + private final char referenceIndex; + + public MethodHandleInfo(final ConstantPool.Tag tag, final byte referenceKind, final char referenceIndex) { + super(tag); + this.referenceKind = referenceKind; + this.referenceIndex = referenceIndex; + } + + public byte getReferenceKind() { return referenceKind; } + public char getReferenceIndex() { return referenceIndex; } + + public static MethodHandleInfo decode(ByteBuffer buffer) { + return new MethodHandleInfo(ConstantPool.Tag.MethodType, buffer.get(), buffer.getChar()); + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.put(referenceKind); + buffer.putChar(referenceIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/MethodTypeInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/MethodTypeInfo.java new file mode 100644 index 0000000..9bfe6bb --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/MethodTypeInfo.java @@ -0,0 +1,27 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; + +import java.nio.ByteBuffer; + +public class MethodTypeInfo extends Info { + + private final char descriptorIndex; + + public MethodTypeInfo(final ConstantPool.Tag tag, final char descriptorIndex) { + super(tag); + this.descriptorIndex = descriptorIndex; + } + + public char getDescriptorIndex() { return descriptorIndex; } + + public static MethodTypeInfo decode(ByteBuffer buffer) { + return new MethodTypeInfo(ConstantPool.Tag.MethodType, buffer.getChar()); + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar(descriptorIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/NameTypeInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/NameTypeInfo.java new file mode 100644 index 0000000..57f9bc4 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/NameTypeInfo.java @@ -0,0 +1,31 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; + +import java.nio.ByteBuffer; + +public class NameTypeInfo extends Info { + + private final char nameIndex; + private final char descriptorIndex; + + public NameTypeInfo(final ConstantPool.Tag tag, final char nameIndex, final char descriptorIndex) { + super(tag); + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + } + + public char getNameIndex() { return nameIndex; } + public char getDescriptorIndex() { return descriptorIndex; } + + public static NameTypeInfo decode(ByteBuffer buffer) { + return new NameTypeInfo(ConstantPool.Tag.NameAndType, buffer.getChar(), buffer.getChar()); + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar(nameIndex); + buffer.putChar(descriptorIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/RefInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/RefInfo.java new file mode 100644 index 0000000..38d6c73 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/RefInfo.java @@ -0,0 +1,31 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; + +import java.nio.ByteBuffer; + +public class RefInfo extends Info { + + private final char classeIndex; + private final char nameTypeIndex; + + public RefInfo(final ConstantPool.Tag tag, final char classeIndex, final char nameTypeIndex) { + super(tag); + this.classeIndex = classeIndex; + this.nameTypeIndex = nameTypeIndex; + } + + public char getClasseIndex() { return classeIndex; } + public char getNameTypeIndex() { return nameTypeIndex; } + + public static RefInfo decode(final ConstantPool.Tag tag, final ByteBuffer buffer) { + return new RefInfo(tag, buffer.getChar(), buffer.getChar()); + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar(classeIndex); + buffer.putChar(nameTypeIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/StringInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/StringInfo.java new file mode 100644 index 0000000..9851491 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/StringInfo.java @@ -0,0 +1,27 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; + +import java.nio.ByteBuffer; + +public class StringInfo extends Info { + + private final char stringIndex; + + public StringInfo(final ConstantPool.Tag tag, final char stringIndex) { + super(tag); + this.stringIndex = stringIndex; + } + + public char getStringIndex() { return stringIndex; } + + public static StringInfo decode(ByteBuffer buffer) { + return new StringInfo(ConstantPool.Tag.String, buffer.getChar()); + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar(stringIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/UTF8Info.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/UTF8Info.java new file mode 100644 index 0000000..3c80c89 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/UTF8Info.java @@ -0,0 +1,34 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; + +import java.nio.ByteBuffer; + +public class UTF8Info extends Info { + + private final char length; + private final byte bytes[]; + + public UTF8Info(final ConstantPool.Tag tag, final char length, final byte[] bytes) { + super(tag); + this.length = length; + this.bytes = bytes; + } + + public char getLength() { return length; } + public byte[] getBytes() { return bytes; } + + public static UTF8Info decode(ByteBuffer buffer) { + char length = buffer.getChar(); + byte[] bytes = new byte[length]; + buffer.get(bytes); + return new UTF8Info(ConstantPool.Tag.UTF8, length, bytes); + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar(length); + buffer.put(bytes); + } +} From 20a162182908070077e8af95cc02a5322a288ea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lise=20Valentin?= Date: Tue, 5 Nov 2024 13:15:45 +0100 Subject: [PATCH 02/11] WIP add attributes info --- .../mixins/mixin/classe/ByteCodec.java | 2 +- .../mixin/classe/structures/ConstantPool.java | 51 +++++++---------- .../{infos => constants}/ClassInfo.java | 4 +- .../Info.java => constants/ConstantInfo.java} | 6 +- .../{infos => constants}/DoubleInfo.java | 4 +- .../{infos => constants}/FloatInfo.java | 4 +- .../{infos => constants}/IntegerInfo.java | 4 +- .../InvokeDynamicInfo.java | 4 +- .../{infos => constants}/LongInfo.java | 4 +- .../MethodHandleInfo.java | 4 +- .../{infos => constants}/MethodTypeInfo.java | 4 +- .../{infos => constants}/NameTypeInfo.java | 4 +- .../{infos => constants}/RefInfo.java | 4 +- .../{infos => constants}/StringInfo.java | 4 +- .../classe/structures/constants/UTF8Info.java | 33 +++++++++++ .../structures/infos/AttributeInfo.java | 57 +++++++++++++++++++ .../classe/structures/infos/UTF8Info.java | 34 ----------- .../infos/attributes/Attribute.java | 9 +++ .../structures/infos/attributes/Code.java | 15 +++++ .../infos/attributes/ConstantValue.java | 24 ++++++++ 20 files changed, 185 insertions(+), 90 deletions(-) rename src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/{infos => constants}/ClassInfo.java (80%) rename src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/{infos/Info.java => constants/ConstantInfo.java} (65%) rename src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/{infos => constants}/DoubleInfo.java (80%) rename src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/{infos => constants}/FloatInfo.java (80%) rename src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/{infos => constants}/IntegerInfo.java (79%) rename src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/{infos => constants}/InvokeDynamicInfo.java (86%) rename src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/{infos => constants}/LongInfo.java (79%) rename src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/{infos => constants}/MethodHandleInfo.java (85%) rename src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/{infos => constants}/MethodTypeInfo.java (81%) rename src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/{infos => constants}/NameTypeInfo.java (85%) rename src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/{infos => constants}/RefInfo.java (85%) rename src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/{infos => constants}/StringInfo.java (80%) create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/UTF8Info.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java delete mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/UTF8Info.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Attribute.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Code.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/ConstantValue.java diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/ByteCodec.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/ByteCodec.java index 133b49c..0a1a107 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/ByteCodec.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/ByteCodec.java @@ -2,7 +2,7 @@ import java.nio.ByteBuffer; -public interface ByteCodec { +public interface ByteCodec { void encode(ByteBuffer buffer); diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/ConstantPool.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/ConstantPool.java index 885816d..1634971 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/ConstantPool.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/ConstantPool.java @@ -1,11 +1,11 @@ package org.momento.lycoris.mixins.mixin.classe.structures; import org.momento.lycoris.mixins.mixin.classe.ByteCodec; -import org.momento.lycoris.mixins.mixin.classe.structures.infos.*; +import org.momento.lycoris.mixins.mixin.classe.structures.constants.*; import java.nio.ByteBuffer; -public class ConstantPool implements ByteCodec { +public class ConstantPool implements ByteCodec { public enum Tag { @@ -45,42 +45,32 @@ public static Tag getTag(final byte value) { } private Tag tag; - private Info info; + private ConstantInfo info; - public ConstantPool(final Tag tag, final Info info) { + public ConstantPool(final Tag tag, final ConstantInfo info) { this.tag = tag; this.info = info; } + public Tag getTag() { return tag; } + public ConstantInfo getInfo() { return info; } + public static ConstantPool decode(ByteBuffer buffer) { Tag tag = Tag.getTag(buffer.get()); - Info info = switch (tag) { - case Class: yield ClassInfo.decode(buffer); - case FieldRef: - case MethodRef: - case InterfaceMethodRef: - yield RefInfo.decode(tag, buffer); - case String: - yield StringInfo.decode(buffer); - case Integer: - yield IntegerInfo.decode(buffer); - case Float: - yield FloatInfo.decode(buffer); - case Long: - yield LongInfo.decode(buffer); - case Double: - yield DoubleInfo.decode(buffer); - case NameAndType: - yield NameTypeInfo.decode(buffer); - case UTF8: - yield UTF8Info.decode(buffer); - case MethodHandle: - yield MethodHandleInfo.decode(buffer); - case MethodType: - yield MethodTypeInfo.decode(buffer); - case InvokeDynamic: - yield InvokeDynamicInfo.decode(buffer); + ConstantInfo info = switch (tag) { + case Class -> ClassInfo.decode(buffer); + case FieldRef, MethodRef, InterfaceMethodRef -> RefInfo.decode(tag, buffer); + case String -> StringInfo.decode(buffer); + case Integer -> IntegerInfo.decode(buffer); + case Float -> FloatInfo.decode(buffer); + case Long -> LongInfo.decode(buffer); + case Double -> DoubleInfo.decode(buffer); + case NameAndType -> NameTypeInfo.decode(buffer); + case UTF8 -> UTF8Info.decode(buffer); + case MethodHandle -> MethodHandleInfo.decode(buffer); + case MethodType -> MethodTypeInfo.decode(buffer); + case InvokeDynamic -> InvokeDynamicInfo.decode(buffer); }; return new ConstantPool(tag, info); } @@ -90,4 +80,5 @@ public void encode(ByteBuffer buffer) { buffer.put(tag.getValue()); info.encode(buffer); } + } diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/ClassInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/ClassInfo.java similarity index 80% rename from src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/ClassInfo.java rename to src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/ClassInfo.java index bfe2b77..97b4c5e 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/ClassInfo.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/ClassInfo.java @@ -1,10 +1,10 @@ -package org.momento.lycoris.mixins.mixin.classe.structures.infos; +package org.momento.lycoris.mixins.mixin.classe.structures.constants; import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; import java.nio.ByteBuffer; -public class ClassInfo extends Info { +public class ClassInfo extends ConstantInfo { private final char nameIndex; diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/Info.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/ConstantInfo.java similarity index 65% rename from src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/Info.java rename to src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/ConstantInfo.java index 398f76a..5874da3 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/Info.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/ConstantInfo.java @@ -1,15 +1,15 @@ -package org.momento.lycoris.mixins.mixin.classe.structures.infos; +package org.momento.lycoris.mixins.mixin.classe.structures.constants; import org.momento.lycoris.mixins.mixin.classe.ByteCodec; import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; import java.nio.ByteBuffer; -public abstract class Info implements ByteCodec { +public abstract class ConstantInfo implements ByteCodec { private ConstantPool.Tag tag; - public Info(final ConstantPool.Tag tag) { + public ConstantInfo(final ConstantPool.Tag tag) { this.tag = tag; } diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/DoubleInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/DoubleInfo.java similarity index 80% rename from src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/DoubleInfo.java rename to src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/DoubleInfo.java index d20c1cd..93ea560 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/DoubleInfo.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/DoubleInfo.java @@ -1,10 +1,10 @@ -package org.momento.lycoris.mixins.mixin.classe.structures.infos; +package org.momento.lycoris.mixins.mixin.classe.structures.constants; import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; import java.nio.ByteBuffer; -public class DoubleInfo extends Info { +public class DoubleInfo extends ConstantInfo { private final double bytes; diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/FloatInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/FloatInfo.java similarity index 80% rename from src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/FloatInfo.java rename to src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/FloatInfo.java index 6c412a4..e777869 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/FloatInfo.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/FloatInfo.java @@ -1,10 +1,10 @@ -package org.momento.lycoris.mixins.mixin.classe.structures.infos; +package org.momento.lycoris.mixins.mixin.classe.structures.constants; import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; import java.nio.ByteBuffer; -public class FloatInfo extends Info { +public class FloatInfo extends ConstantInfo { private final float bytes; diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/IntegerInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/IntegerInfo.java similarity index 79% rename from src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/IntegerInfo.java rename to src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/IntegerInfo.java index 7446aa0..200e505 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/IntegerInfo.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/IntegerInfo.java @@ -1,10 +1,10 @@ -package org.momento.lycoris.mixins.mixin.classe.structures.infos; +package org.momento.lycoris.mixins.mixin.classe.structures.constants; import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; import java.nio.ByteBuffer; -public class IntegerInfo extends Info { +public class IntegerInfo extends ConstantInfo { private final int bytes; diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/InvokeDynamicInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/InvokeDynamicInfo.java similarity index 86% rename from src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/InvokeDynamicInfo.java rename to src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/InvokeDynamicInfo.java index 777c707..c53ecb9 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/InvokeDynamicInfo.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/InvokeDynamicInfo.java @@ -1,10 +1,10 @@ -package org.momento.lycoris.mixins.mixin.classe.structures.infos; +package org.momento.lycoris.mixins.mixin.classe.structures.constants; import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; import java.nio.ByteBuffer; -public class InvokeDynamicInfo extends Info { +public class InvokeDynamicInfo extends ConstantInfo { private final char bootstrapMethodAttrIndex; private final char nameTypeIndex; diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/LongInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/LongInfo.java similarity index 79% rename from src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/LongInfo.java rename to src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/LongInfo.java index e552316..8ca0e3a 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/LongInfo.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/LongInfo.java @@ -1,10 +1,10 @@ -package org.momento.lycoris.mixins.mixin.classe.structures.infos; +package org.momento.lycoris.mixins.mixin.classe.structures.constants; import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; import java.nio.ByteBuffer; -public class LongInfo extends Info { +public class LongInfo extends ConstantInfo { private final long bytes; diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/MethodHandleInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/MethodHandleInfo.java similarity index 85% rename from src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/MethodHandleInfo.java rename to src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/MethodHandleInfo.java index 08990fb..6d5c75d 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/MethodHandleInfo.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/MethodHandleInfo.java @@ -1,10 +1,10 @@ -package org.momento.lycoris.mixins.mixin.classe.structures.infos; +package org.momento.lycoris.mixins.mixin.classe.structures.constants; import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; import java.nio.ByteBuffer; -public class MethodHandleInfo extends Info { +public class MethodHandleInfo extends ConstantInfo { private final byte referenceKind; private final char referenceIndex; diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/MethodTypeInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/MethodTypeInfo.java similarity index 81% rename from src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/MethodTypeInfo.java rename to src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/MethodTypeInfo.java index 9bfe6bb..0025ad9 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/MethodTypeInfo.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/MethodTypeInfo.java @@ -1,10 +1,10 @@ -package org.momento.lycoris.mixins.mixin.classe.structures.infos; +package org.momento.lycoris.mixins.mixin.classe.structures.constants; import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; import java.nio.ByteBuffer; -public class MethodTypeInfo extends Info { +public class MethodTypeInfo extends ConstantInfo { private final char descriptorIndex; diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/NameTypeInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/NameTypeInfo.java similarity index 85% rename from src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/NameTypeInfo.java rename to src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/NameTypeInfo.java index 57f9bc4..ebcaab3 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/NameTypeInfo.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/NameTypeInfo.java @@ -1,10 +1,10 @@ -package org.momento.lycoris.mixins.mixin.classe.structures.infos; +package org.momento.lycoris.mixins.mixin.classe.structures.constants; import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; import java.nio.ByteBuffer; -public class NameTypeInfo extends Info { +public class NameTypeInfo extends ConstantInfo { private final char nameIndex; private final char descriptorIndex; diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/RefInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/RefInfo.java similarity index 85% rename from src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/RefInfo.java rename to src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/RefInfo.java index 38d6c73..e488d24 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/RefInfo.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/RefInfo.java @@ -1,10 +1,10 @@ -package org.momento.lycoris.mixins.mixin.classe.structures.infos; +package org.momento.lycoris.mixins.mixin.classe.structures.constants; import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; import java.nio.ByteBuffer; -public class RefInfo extends Info { +public class RefInfo extends ConstantInfo { private final char classeIndex; private final char nameTypeIndex; diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/StringInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/StringInfo.java similarity index 80% rename from src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/StringInfo.java rename to src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/StringInfo.java index 9851491..a3394b6 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/StringInfo.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/StringInfo.java @@ -1,10 +1,10 @@ -package org.momento.lycoris.mixins.mixin.classe.structures.infos; +package org.momento.lycoris.mixins.mixin.classe.structures.constants; import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; import java.nio.ByteBuffer; -public class StringInfo extends Info { +public class StringInfo extends ConstantInfo { private final char stringIndex; diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/UTF8Info.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/UTF8Info.java new file mode 100644 index 0000000..7bbd165 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/UTF8Info.java @@ -0,0 +1,33 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.constants; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; + +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; + +public class UTF8Info extends ConstantInfo { + + private final String string; + + public UTF8Info(final ConstantPool.Tag tag, String string) { + super(tag); + this.string = string; + } + + public String getString() { return string; } + + public static UTF8Info decode(ByteBuffer buffer) { + char length = buffer.getChar(); + byte[] bytes = new byte[length]; + buffer.get(bytes); + String string = new String(bytes, StandardCharsets.UTF_8); + return new UTF8Info(ConstantPool.Tag.UTF8, string); + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar((char) string.length()); + buffer.put(StandardCharsets.UTF_8.encode(string)); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java new file mode 100644 index 0000000..f174457 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java @@ -0,0 +1,57 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos + +import org.momento.lycoris.mixins.mixin.classe.ByteCodec; +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; +import org.momento.lycoris.mixins.mixin.classe.structures.constants.ConstantInfo; +import org.momento.lycoris.mixins.mixin.classe.structures.constants.UTF8Info; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.Attribute; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.ConstantValue; + +import java.nio.ByteBuffer; + +public class AttributeInfo implements ByteCodec { + + private final char nameIndex; + private final Attribute attribute; + + public AttributeInfo(final char nameIndex, final Attribute attribute) { + this.nameIndex = nameIndex; + this.attribute = attribute; + } + + public static AttributeInfo decode(final ConstantPool[] constantPools, ByteBuffer buffer) { + char nameIndex = buffer.getChar(); + ConstantInfo info = constantPools[nameIndex].getInfo(); + if (info == null || info.getTag() != ConstantPool.Tag.UTF8) + throw new RuntimeException(); + String attributeName = ((UTF8Info) info).getString(); + buffer.position(buffer.position() + 4); + Attribute attribute = switch (attributeName) { + case "ConstantValue" -> ConstantValue.decode(buffer); + case "Code" -> + case "LineNumberTable" -> + case "LocalVariableTable" -> + case "SourceFile" -> + case "Deprecated" -> + case "Synthetic" -> + case "Exceptions" -> + case "InnerClasses" -> + case "EnclosingMethod" -> + case "Signature" -> + case "StackMapTable" -> + case "BoostrapMethods" + }; + return new AttributeInfo(nameIndex, attribute); + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(nameIndex); + if (attribute == null) { + buffer.putInt(0); + return; + } + buffer.putInt(attribute.getSize()); + attribute.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/UTF8Info.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/UTF8Info.java deleted file mode 100644 index 3c80c89..0000000 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/UTF8Info.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.momento.lycoris.mixins.mixin.classe.structures.infos; - -import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; - -import java.nio.ByteBuffer; - -public class UTF8Info extends Info { - - private final char length; - private final byte bytes[]; - - public UTF8Info(final ConstantPool.Tag tag, final char length, final byte[] bytes) { - super(tag); - this.length = length; - this.bytes = bytes; - } - - public char getLength() { return length; } - public byte[] getBytes() { return bytes; } - - public static UTF8Info decode(ByteBuffer buffer) { - char length = buffer.getChar(); - byte[] bytes = new byte[length]; - buffer.get(bytes); - return new UTF8Info(ConstantPool.Tag.UTF8, length, bytes); - } - - @Override - public void encode(ByteBuffer buffer) { - super.encode(buffer); - buffer.putChar(length); - buffer.put(bytes); - } -} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Attribute.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Attribute.java new file mode 100644 index 0000000..bbce577 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Attribute.java @@ -0,0 +1,9 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import org.momento.lycoris.mixins.mixin.classe.ByteCodec; + +public interface Attribute extends ByteCodec { + + int getSize(); + +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Code.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Code.java new file mode 100644 index 0000000..342d87e --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Code.java @@ -0,0 +1,15 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import java.nio.ByteBuffer; + +public class Code implements Attribute { + @Override + public int getSize() { + return 0; + } + + @Override + public void encode(ByteBuffer buffer) { + + } +} \ No newline at end of file diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/ConstantValue.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/ConstantValue.java new file mode 100644 index 0000000..e800452 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/ConstantValue.java @@ -0,0 +1,24 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import java.nio.ByteBuffer; + +public class ConstantValue implements Attribute { + + private final char valueIndex; + + public ConstantValue(final char valueIndex) { + this.valueIndex = valueIndex; + } + + @Override + public int getSize() { return 2; } + + public static ConstantValue decode(final ByteBuffer buffer) { + return new ConstantValue(buffer.getChar()); + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(valueIndex); + } +} From c94fea8f1a8694e12c07c2f2dbcdc1aef71df095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lise=20Valentin?= Date: Thu, 7 Nov 2024 15:23:06 +0100 Subject: [PATCH 03/11] WIP add some frames --- .../structures/infos/AttributeInfo.java | 36 ++++---- .../structures/infos/attributes/Code.java | 89 ++++++++++++++++++- .../infos/attributes/ConstantValue.java | 2 +- .../{Attribute.java => SizedByteCodec.java} | 2 +- .../infos/attributes/StackMapTable.java | 49 ++++++++++ .../attributes/frames/StackMapFrame.java | 59 ++++++++++++ 6 files changed, 217 insertions(+), 20 deletions(-) rename src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/{Attribute.java => SizedByteCodec.java} (72%) create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/StackMapTable.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/StackMapFrame.java diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java index f174457..a6eb6c0 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java @@ -5,16 +5,19 @@ import org.momento.lycoris.mixins.mixin.classe.structures.constants.ConstantInfo; import org.momento.lycoris.mixins.mixin.classe.structures.constants.UTF8Info; import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.Attribute; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.Code; import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.ConstantValue; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.StackMapTable; import java.nio.ByteBuffer; public class AttributeInfo implements ByteCodec { private final char nameIndex; - private final Attribute attribute; + private final SizedByteCodec attribute; - public AttributeInfo(final char nameIndex, final Attribute attribute) { + public AttributeInfo(final char nameIndex, final SizedByteCodec attribute) { this.nameIndex = nameIndex; this.attribute = attribute; } @@ -26,24 +29,27 @@ public static AttributeInfo decode(final ConstantPool[] constantPools, ByteBuffe throw new RuntimeException(); String attributeName = ((UTF8Info) info).getString(); buffer.position(buffer.position() + 4); - Attribute attribute = switch (attributeName) { + SizedByteCodec attribute = switch (attributeName) { case "ConstantValue" -> ConstantValue.decode(buffer); - case "Code" -> - case "LineNumberTable" -> - case "LocalVariableTable" -> - case "SourceFile" -> - case "Deprecated" -> - case "Synthetic" -> - case "Exceptions" -> - case "InnerClasses" -> - case "EnclosingMethod" -> - case "Signature" -> - case "StackMapTable" -> - case "BoostrapMethods" + case "Code" -> Code.decode(constantPools, buffer); + case "StackMapTable" -> StackMapTable.decode(buffer); + case "LineNumberTable" -> null; + case "LocalVariableTable" -> null; + case "SourceFile" -> null; + case "Deprecated" -> null; + case "Synthetic" -> null; + case "Exceptions" -> null; + case "InnerClasses" -> null; + case "EnclosingMethod" -> null; + case "Signature" -> null; + case "BoostrapMethods" -> null; + default -> throw new IllegalStateException("Unexpected value: " + attributeName); }; return new AttributeInfo(nameIndex, attribute); } + public int getSize() { return 6 + attribute.getSize(); } + @Override public void encode(ByteBuffer buffer) { buffer.putChar(nameIndex); diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Code.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Code.java index 342d87e..950d81a 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Code.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Code.java @@ -1,15 +1,98 @@ package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; +import org.momento.lycoris.mixins.mixin.classe.ByteCodec; +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.AttributeInfo; + import java.nio.ByteBuffer; -public class Code implements Attribute { +public class Code implements SizedByteCodec { + + public static class Exception implements SizedByteCodec { + private final char startPC; + private final char endPC; + private final char handlerPC; + private final char catchType; + + public Exception(final char startPC, final char endPC, final char handlerPC, final char catchType) { + this.startPC = startPC; + this.endPC = endPC; + this.handlerPC = handlerPC; + this.catchType = catchType; + } + + public char getStartPC() { return startPC; } + public char getEndPC() { return endPC; } + public char getHandlerPC() { return handlerPC; } + public char getCatchType() { return catchType; } + + + public static Exception decode(ByteBuffer buffer) { + return new Exception(buffer.getChar(), buffer.getChar(), buffer.getChar(), buffer.getChar()); + } + + @Override + public int getSize() { return 4; } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(startPC); + buffer.putChar(endPC); + buffer.putChar(handlerPC); + buffer.putChar(catchType); + } + } + + private final char maxStack; + private final char maxLocals; + private final byte[] code; + private final Exception[] exceptionTable; + private final AttributeInfo[] attributes; + + public Code(final char maxStack, final char maxLocals, final byte[] code, final Exception[] exceptionTable, final AttributeInfo[] attributes) { + this.maxStack = maxStack; + this.maxLocals = maxLocals; + this.code = code; + this.exceptionTable = exceptionTable; + this.attributes = attributes; + + } + + public static Code decode(final ConstantPool[] constantPools, ByteBuffer buffer) { + char maxStack = buffer.getChar(); + char maxLocals = buffer.getChar(); + byte[] code = new byte[buffer.getInt()]; + buffer.get(code); + Exception[] exceptionTable = new Exception[buffer.getChar()]; + for (int i = 0; i < exceptionTable.length; ++i) + exceptionTable[i] = Exception.decode(buffer); + AttributeInfo[] attributes = new AttributeInfo[buffer.getChar()]; + for (int i = 0; i < attributes.length; ++i) + attributes[i] = AttributeInfo.decode(constantPools, buffer); + return new Code(maxStack, maxLocals, code, exceptionTable, attributes); + } + @Override public int getSize() { - return 0; + int baseSize = 18 + code.length; + for (Exception exception : exceptionTable) + baseSize += exception.getSize(); + for (AttributeInfo attribute : attributes) + baseSize += attribute.getSize(); + return baseSize; } @Override public void encode(ByteBuffer buffer) { - + buffer.putChar(maxStack); + buffer.putChar(maxLocals); + buffer.putInt(code.length); + buffer.put(code); + buffer.putChar((char) exceptionTable.length); + for (Exception exception : exceptionTable) + exception.encode(buffer); + buffer.putChar((char) attributes.length); + for (AttributeInfo attribute : attributes) + attribute.encode(buffer); } } \ No newline at end of file diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/ConstantValue.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/ConstantValue.java index e800452..bca9424 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/ConstantValue.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/ConstantValue.java @@ -2,7 +2,7 @@ import java.nio.ByteBuffer; -public class ConstantValue implements Attribute { +public class ConstantValue implements SizedByteCodec { private final char valueIndex; diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Attribute.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/SizedByteCodec.java similarity index 72% rename from src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Attribute.java rename to src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/SizedByteCodec.java index bbce577..2d030e6 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Attribute.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/SizedByteCodec.java @@ -2,7 +2,7 @@ import org.momento.lycoris.mixins.mixin.classe.ByteCodec; -public interface Attribute extends ByteCodec { +public interface SizedByteCodec extends ByteCodec { int getSize(); diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/StackMapTable.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/StackMapTable.java new file mode 100644 index 0000000..8652326 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/StackMapTable.java @@ -0,0 +1,49 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import org.momento.lycoris.mixins.mixin.classe.ByteCodec; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames.StackMapFrame; + +import java.nio.ByteBuffer; + +public class StackMapTable implements SizedByteCodec { + + private final StackMapFrame[] entries; + + public StackMapTable(final StackMapFrame[] entries) { + this.entries = entries; + } + + @Override + public int getSize() { + int baseSize = 2; + for (StackMapFrame entry : entries) + baseSize += entry.getSize(); + return baseSize; + } + + public StackMapFrame[] getEntries() { return entries; } + + public static StackMapTable decode(ByteBuffer buffer) { + StackMapFrame[] entries = new StackMapFrame[buffer.getChar()]; + for (int i = 0; i < entries.length; ++i) { + byte frameType = buffer.get(); + entries[i] = switch (StackMapFrame.Type.fromValue(frameType)) { + case SAME -> null; + case SAME_LOCAL_1_STACk_ITEM -> null; + case SAME_LOCAL_1_STACK_ITEM_EXTENDED -> null; + case CHOP -> null; + case SAME_FRAME_EXTENDED -> null; + case APPEND -> null; + case FULL_FRAME -> null; + }; + } + return new StackMapTable(entries); + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar((char) entries.length); + for (StackMapFrame entry : entries) + entry.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/StackMapFrame.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/StackMapFrame.java new file mode 100644 index 0000000..530cb73 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/StackMapFrame.java @@ -0,0 +1,59 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; + +import java.nio.ByteBuffer; + +public abstract class StackMapFrame implements SizedByteCodec { + + public static enum Type { + SAME((byte) 0), + SAME_LOCAL_1_STACk_ITEM((byte) 64), + SAME_LOCAL_1_STACK_ITEM_EXTENDED((byte) 247), + CHOP((byte) 248), + SAME_FRAME_EXTENDED((byte) 251), + APPEND((byte) 252), + FULL_FRAME((byte) 255); + + private byte value; + + Type(final byte value) { + this.value = value; + } + + public byte getValue() { return value; } + + public static Type fromValue(final byte value) { + Type type; + if (value < 64) + type = SAME; + else if (value < 128) + type = SAME_LOCAL_1_STACk_ITEM; + else if (value < 248) + type = SAME_LOCAL_1_STACK_ITEM_EXTENDED; + else if (value < 251) + type = CHOP; + else if (value == 251) + type = SAME_FRAME_EXTENDED; + else if (value < 255) + type = APPEND; + else + type = FULL_FRAME; + type.value = value; + return type; + } + } + + private final Type type; + + public StackMapFrame(final Type type) { + this.type = type; + } + + public Type getType() { return type; } + + @Override + public void encode(ByteBuffer buffer) { + buffer.put(type.value); + } +} From afd21e2ec8b4085e38e22b240fed6477d091558e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lise=20Valentin?= Date: Mon, 11 Nov 2024 15:29:57 +0100 Subject: [PATCH 04/11] Add some frames --- .../structures/infos/AttributeInfo.java | 3 +- .../infos/attributes/StackMapTable.java | 17 +++--- .../infos/attributes/frames/AppendFrame.java | 42 +++++++++++++++ .../infos/attributes/frames/ChopFrame.java | 30 +++++++++++ .../infos/attributes/frames/FullFrame.java | 20 +++++++ .../infos/attributes/frames/SameExFrame.java | 30 +++++++++++ .../infos/attributes/frames/SameFrame.java | 7 +++ .../frames/SameLocalStackItemExtFrame.java | 31 +++++++++++ .../frames/SameLocalStackItemFrame.java | 34 ++++++++++++ .../attributes/frames/StackMapFrame.java | 7 ++- .../frames/VerificationTypeInfo.java | 52 +++++++++++++++++++ .../frames/variables/ObjectVariableInfo.java | 32 ++++++++++++ .../variables/UninitializedVariableInfo.java | 32 ++++++++++++ .../frames/variables/VariableInfo.java | 27 ++++++++++ 14 files changed, 353 insertions(+), 11 deletions(-) create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/AppendFrame.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/ChopFrame.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/FullFrame.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/SameExFrame.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/SameFrame.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/SameLocalStackItemExtFrame.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/SameLocalStackItemFrame.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/VerificationTypeInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/variables/ObjectVariableInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/variables/UninitializedVariableInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/variables/VariableInfo.java diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java index a6eb6c0..d8d4a52 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java @@ -1,10 +1,9 @@ -package org.momento.lycoris.mixins.mixin.classe.structures.infos +package org.momento.lycoris.mixins.mixin.classe.structures.infos; import org.momento.lycoris.mixins.mixin.classe.ByteCodec; import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; import org.momento.lycoris.mixins.mixin.classe.structures.constants.ConstantInfo; import org.momento.lycoris.mixins.mixin.classe.structures.constants.UTF8Info; -import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.Attribute; import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.Code; import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.ConstantValue; import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/StackMapTable.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/StackMapTable.java index 8652326..048837a 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/StackMapTable.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/StackMapTable.java @@ -1,7 +1,7 @@ package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; import org.momento.lycoris.mixins.mixin.classe.ByteCodec; -import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames.StackMapFrame; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames.*; import java.nio.ByteBuffer; @@ -27,13 +27,14 @@ public static StackMapTable decode(ByteBuffer buffer) { StackMapFrame[] entries = new StackMapFrame[buffer.getChar()]; for (int i = 0; i < entries.length; ++i) { byte frameType = buffer.get(); - entries[i] = switch (StackMapFrame.Type.fromValue(frameType)) { - case SAME -> null; - case SAME_LOCAL_1_STACk_ITEM -> null; - case SAME_LOCAL_1_STACK_ITEM_EXTENDED -> null; - case CHOP -> null; - case SAME_FRAME_EXTENDED -> null; - case APPEND -> null; + StackMapFrame.Type type = StackMapFrame.Type.fromValue(frameType); + entries[i] = switch (type) { + case SAME -> new SameFrame(type); + case SAME_LOCAL_1_STACk_ITEM -> SameLocalStackItemFrame.decode(type, buffer); + case SAME_LOCAL_1_STACK_ITEM_EXTENDED -> SameLocalStackItemExtFrame.decode(type, buffer); + case CHOP -> ChopFrame.decode(type, buffer); + case SAME_FRAME_EXTENDED -> SameExFrame.decode(type, buffer); + case APPEND -> AppendFrame.decode(type, buffer); case FULL_FRAME -> null; }; } diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/AppendFrame.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/AppendFrame.java new file mode 100644 index 0000000..2a281dd --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/AppendFrame.java @@ -0,0 +1,42 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames; + +import java.nio.ByteBuffer; + +public class AppendFrame extends StackMapFrame { + + private final char offsetDelta; + private final VerificationTypeInfo[] locals; + + public AppendFrame(final Type type, final char offsetDelta, final VerificationTypeInfo[] locals) { + super(type); + this.offsetDelta = offsetDelta; + this.locals = locals; + } + + public char getOffsetDelta() { return offsetDelta; } + public VerificationTypeInfo[] getLocals() { return locals; } + + public static AppendFrame decode(final Type type, ByteBuffer buffer) { + char offsetDelta = buffer.getChar(); + VerificationTypeInfo[] locals = new VerificationTypeInfo[type.getValue()]; + for (int i = 0; i < locals.length; ++i) + locals[i] = VerificationTypeInfo.decode(buffer); + return new AppendFrame(type, offsetDelta, locals); + } + + @Override + public int getSize() { + int baseSize = super.getSize() + 2; + for (VerificationTypeInfo local: locals) + baseSize += local.getSize(); + return baseSize; + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar(offsetDelta); + for (VerificationTypeInfo local: locals) + local.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/ChopFrame.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/ChopFrame.java new file mode 100644 index 0000000..5bda0cb --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/ChopFrame.java @@ -0,0 +1,30 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames; + +import java.nio.ByteBuffer; + +public class ChopFrame extends StackMapFrame { + + private final char offsetDelta; + + public ChopFrame(final Type type, final char offsetDelta) { + super(type); + this.offsetDelta = offsetDelta; + } + + public char getOffsetDelta() { return offsetDelta; } + + public static ChopFrame decode(final Type type, ByteBuffer buffer) { + return new ChopFrame(type, buffer.getChar()); + } + + @Override + public int getSize() { + return super.getSize() + 2; + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar(offsetDelta); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/FullFrame.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/FullFrame.java new file mode 100644 index 0000000..1990000 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/FullFrame.java @@ -0,0 +1,20 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames; + +public class FullFrame extends StackMapFrame { + + private final char offsetDelta; + private final VerificationTypeInfo[] locals; + private final VerificationTypeInfo[] stack; + + + public FullFrame(final Type type, final char offsetDelta, final VerificationTypeInfo[] locals, final VerificationTypeInfo[] stack) { + super(type); + this.offsetDelta = offsetDelta; + this.locals = locals; + this.stack = stack; + } + + public char getOffsetDelta() { return offsetDelta; } + public VerificationTypeInfo[] getLocals() { return locals; } + public VerificationTypeInfo[] getStack() { return stack; } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/SameExFrame.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/SameExFrame.java new file mode 100644 index 0000000..85d2f14 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/SameExFrame.java @@ -0,0 +1,30 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames; + +import java.nio.ByteBuffer; + +public class SameExFrame extends SameFrame { + + private final char offsetDelta; + + public SameExFrame(final Type type, final char offsetDelta) { + super(type); + this.offsetDelta = offsetDelta; + } + + public char getOffsetDelta() { return offsetDelta; } + + public static SameExFrame decode(final Type type, ByteBuffer buffer) { + return new SameExFrame(type, buffer.getChar()); + } + + @Override + public int getSize() { + return super.getSize() + 2; + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar(offsetDelta); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/SameFrame.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/SameFrame.java new file mode 100644 index 0000000..b054177 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/SameFrame.java @@ -0,0 +1,7 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames; + +public class SameFrame extends StackMapFrame { + public SameFrame(Type type) { + super(type); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/SameLocalStackItemExtFrame.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/SameLocalStackItemExtFrame.java new file mode 100644 index 0000000..010bf19 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/SameLocalStackItemExtFrame.java @@ -0,0 +1,31 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames; + +import java.nio.ByteBuffer; + +public class SameLocalStackItemExtFrame extends SameLocalStackItemFrame { + + private final char offsetDelta; + + public SameLocalStackItemExtFrame(final Type type, final char offsetDelta, final VerificationTypeInfo verificationTypeInfo) { + super(type, verificationTypeInfo); + this.offsetDelta = offsetDelta; + } + + public char getOffsetDelta() { return offsetDelta; } + + @Override + public int getSize() { + return super.getSize() + 2; + } + + public static SameLocalStackItemExtFrame decode(final Type type, ByteBuffer buffer) { + return new SameLocalStackItemExtFrame(type, buffer.getChar(), VerificationTypeInfo.decode(buffer)); + } + + @Override + public void encode(ByteBuffer buffer) { + encodePrimitive(buffer); + buffer.putChar(offsetDelta); + verificationTypeInfo.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/SameLocalStackItemFrame.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/SameLocalStackItemFrame.java new file mode 100644 index 0000000..aa0d197 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/SameLocalStackItemFrame.java @@ -0,0 +1,34 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames; + +import java.nio.ByteBuffer; + +public class SameLocalStackItemFrame extends StackMapFrame { + + protected final VerificationTypeInfo verificationTypeInfo; + + public SameLocalStackItemFrame(final Type type, final VerificationTypeInfo verificationTypeInfo) { + super(type); + this.verificationTypeInfo = verificationTypeInfo; + } + + public VerificationTypeInfo getVerificationTypeInfo() { return verificationTypeInfo; } + + @Override + public int getSize() { + return super.getSize() + verificationTypeInfo.getSize(); + } + + public static SameLocalStackItemFrame decode(final Type type, ByteBuffer buffer) { + return new SameLocalStackItemFrame(type, VerificationTypeInfo.decode(buffer)); + } + + @Override + public void encode(ByteBuffer buffer) { + encodePrimitive(buffer); + verificationTypeInfo.encode(buffer); + } + + protected void encodePrimitive(ByteBuffer buffer) { + super.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/StackMapFrame.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/StackMapFrame.java index 530cb73..ec26f4c 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/StackMapFrame.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/StackMapFrame.java @@ -6,7 +6,7 @@ public abstract class StackMapFrame implements SizedByteCodec { - public static enum Type { + public enum Type { SAME((byte) 0), SAME_LOCAL_1_STACk_ITEM((byte) 64), SAME_LOCAL_1_STACK_ITEM_EXTENDED((byte) 247), @@ -52,6 +52,11 @@ public StackMapFrame(final Type type) { public Type getType() { return type; } + @Override + public int getSize() { + return 1; + } + @Override public void encode(ByteBuffer buffer) { buffer.put(type.value); diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/VerificationTypeInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/VerificationTypeInfo.java new file mode 100644 index 0000000..26636ab --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/VerificationTypeInfo.java @@ -0,0 +1,52 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames.variables.ObjectVariableInfo; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames.variables.UninitializedVariableInfo; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames.variables.VariableInfo; + +import java.nio.ByteBuffer; + +public class VerificationTypeInfo implements SizedByteCodec { + + private final VariableInfo variableInfo; + + public enum Tag { + TOP, + INTEGER, + FLOAT, + DOUBLE, + LONG, + NULL, + UNINITIALIZED_THIS, + OBJECT, + UNINITIALIZED; + } + + public VerificationTypeInfo(final VariableInfo variableInfo) { + this.variableInfo = variableInfo; + } + + + public VariableInfo getVariableInfo() { return variableInfo; } + + public static VerificationTypeInfo decode(ByteBuffer buffer) { + Tag tag = Tag.values()[buffer.get() & 0xFF]; + VariableInfo variableInfo = switch (tag) { + case TOP, INTEGER, FLOAT, LONG, DOUBLE, NULL, UNINITIALIZED_THIS -> new VariableInfo(tag); + case OBJECT -> ObjectVariableInfo.decode(buffer); + case UNINITIALIZED -> UninitializedVariableInfo.decode(buffer); + }; + return new VerificationTypeInfo(variableInfo); + } + + @Override + public int getSize() { + return variableInfo.getSize(); + } + + @Override + public void encode(ByteBuffer buffer) { + variableInfo.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/variables/ObjectVariableInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/variables/ObjectVariableInfo.java new file mode 100644 index 0000000..167cb16 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/variables/ObjectVariableInfo.java @@ -0,0 +1,32 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames.variables; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames.VerificationTypeInfo; + +import java.nio.ByteBuffer; + +public class ObjectVariableInfo extends VariableInfo { + + private final char cPoolIndex; + + public ObjectVariableInfo(final char cPoolIndex) { + super(VerificationTypeInfo.Tag.OBJECT); + this.cPoolIndex = cPoolIndex; + } + + public char getPoolIndex() { return cPoolIndex; } + + public static ObjectVariableInfo decode(ByteBuffer buffer) { + return new ObjectVariableInfo(buffer.getChar()); + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar(cPoolIndex); + } + + @Override + public int getSize() { + return super.getSize() + 2; + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/variables/UninitializedVariableInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/variables/UninitializedVariableInfo.java new file mode 100644 index 0000000..c6f829a --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/variables/UninitializedVariableInfo.java @@ -0,0 +1,32 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames.variables; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames.VerificationTypeInfo; + +import java.nio.ByteBuffer; + +public class UninitializedVariableInfo extends VariableInfo { + + private final char offset; + + public UninitializedVariableInfo(final char offset) { + super(VerificationTypeInfo.Tag.OBJECT); + this.offset = offset; + } + + public char getOffset() { return offset; } + + public static UninitializedVariableInfo decode(ByteBuffer buffer) { + return new UninitializedVariableInfo(buffer.getChar()); + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar(offset); + } + + @Override + public int getSize() { + return super.getSize() + 2; + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/variables/VariableInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/variables/VariableInfo.java new file mode 100644 index 0000000..d1a5d1c --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/variables/VariableInfo.java @@ -0,0 +1,27 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames.variables; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames.VerificationTypeInfo; + +import java.nio.ByteBuffer; + +public class VariableInfo implements SizedByteCodec { + + private final VerificationTypeInfo.Tag tag; + + public VariableInfo(final VerificationTypeInfo.Tag tag) { + this.tag = tag; + } + + public VerificationTypeInfo.Tag getTag() { return tag; } + + @Override + public int getSize() { + return 1; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.put((byte) tag.ordinal()); + } +} From 2b85827998971cf6dab45119bc5146a4e9fecb3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lise=20Valentin?= Date: Tue, 12 Nov 2024 13:06:33 +0100 Subject: [PATCH 05/11] Add some attributes --- .../structures/infos/AttributeInfo.java | 27 +++--- .../infos/attributes/EnclosingMethod.java | 32 +++++++ .../infos/attributes/Exceptions.java | 33 +++++++ .../infos/attributes/InnerClasses.java | 96 +++++++++++++++++++ .../infos/attributes/LineNumberTable.java | 55 +++++++++++ .../infos/attributes/LocalVariableTable.java | 59 ++++++++++++ .../attributes/RuntimeVisibleAnnotations.java | 89 +++++++++++++++++ .../infos/attributes/Signature.java | 28 ++++++ .../attributes/SourceDebugExtension.java | 30 ++++++ .../infos/attributes/SourceFile.java | 28 ++++++ .../infos/attributes/StackMapTable.java | 2 +- .../infos/attributes/frames/FullFrame.java | 36 +++++++ .../attributes/values/AnnotationValue.java | 32 +++++++ .../infos/attributes/values/ArrayValue.java | 35 +++++++ .../attributes/values/ClassConstValue.java | 30 ++++++ .../infos/attributes/values/ConstValue.java | 30 ++++++ .../infos/attributes/values/ElementValue.java | 58 +++++++++++ .../attributes/values/EnumConstValue.java | 34 +++++++ .../java/org/momento/lycoris/utils/Pair.java | 19 ++++ 19 files changed, 736 insertions(+), 17 deletions(-) create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/EnclosingMethod.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Exceptions.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/InnerClasses.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/LineNumberTable.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/LocalVariableTable.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeVisibleAnnotations.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Signature.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/SourceDebugExtension.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/SourceFile.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/AnnotationValue.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ArrayValue.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ClassConstValue.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ConstValue.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ElementValue.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/EnumConstValue.java create mode 100644 src/main/java/org/momento/lycoris/utils/Pair.java diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java index d8d4a52..c748b86 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java @@ -4,10 +4,7 @@ import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; import org.momento.lycoris.mixins.mixin.classe.structures.constants.ConstantInfo; import org.momento.lycoris.mixins.mixin.classe.structures.constants.UTF8Info; -import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.Code; -import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.ConstantValue; -import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; -import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.StackMapTable; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.*; import java.nio.ByteBuffer; @@ -27,22 +24,20 @@ public static AttributeInfo decode(final ConstantPool[] constantPools, ByteBuffe if (info == null || info.getTag() != ConstantPool.Tag.UTF8) throw new RuntimeException(); String attributeName = ((UTF8Info) info).getString(); - buffer.position(buffer.position() + 4); + int length = buffer.getInt(); SizedByteCodec attribute = switch (attributeName) { case "ConstantValue" -> ConstantValue.decode(buffer); case "Code" -> Code.decode(constantPools, buffer); case "StackMapTable" -> StackMapTable.decode(buffer); - case "LineNumberTable" -> null; - case "LocalVariableTable" -> null; - case "SourceFile" -> null; - case "Deprecated" -> null; - case "Synthetic" -> null; - case "Exceptions" -> null; - case "InnerClasses" -> null; - case "EnclosingMethod" -> null; - case "Signature" -> null; - case "BoostrapMethods" -> null; - default -> throw new IllegalStateException("Unexpected value: " + attributeName); + case "Exceptions" -> Exceptions.decode(buffer); + case "InnerClasses" -> InnerClasses.decode(buffer); + case "EnclosingMethod" -> EnclosingMethod.decode(buffer); + case "Signature" -> Signature.decode(buffer); + case "SourceFile" -> SourceFile.decode(buffer); + case "SourceDebugExtension" -> SourceDebugExtension.decode(length, buffer); + case "LineNumberTable" -> LineNumberTable.decode(buffer); + case "LocalVariableTable", "LocalVariableTypeTable" -> LocalVariableTable.decode(buffer); + default -> null; }; return new AttributeInfo(nameIndex, attribute); } diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/EnclosingMethod.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/EnclosingMethod.java new file mode 100644 index 0000000..86f3449 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/EnclosingMethod.java @@ -0,0 +1,32 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import java.nio.ByteBuffer; + +public class EnclosingMethod implements SizedByteCodec { + + private final char classIndex; + private final char methodIndex; + + public EnclosingMethod(final char classIndex, final char methodIndex) { + this.classIndex = classIndex; + this.methodIndex = methodIndex; + } + + public static EnclosingMethod decode(ByteBuffer buffer) { + return new EnclosingMethod(buffer.getChar(), buffer.getChar()); + } + + public char getClassIndex() { return classIndex; } + public char getMethodIndex() { return methodIndex; } + + @Override + public int getSize() { + return 4; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(classIndex); + buffer.putChar(methodIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Exceptions.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Exceptions.java new file mode 100644 index 0000000..ca02d57 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Exceptions.java @@ -0,0 +1,33 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import java.nio.ByteBuffer; + +public class Exceptions implements SizedByteCodec { + + private final char[] exceptionIndexTable; + + public Exceptions(final char[] exceptionIndexTable) { + this.exceptionIndexTable = exceptionIndexTable; + } + + public static Exceptions decode(ByteBuffer buffer) { + char[] exceptionIndexTable = new char[buffer.getChar()]; + for (int i = 0; i < exceptionIndexTable.length; i++) + exceptionIndexTable[i] = buffer.getChar(); + return new Exceptions(exceptionIndexTable); + } + + public char[] getExceptionIndexTable() { return exceptionIndexTable; } + + @Override + public int getSize() { + return 2 * exceptionIndexTable.length; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar((char) exceptionIndexTable.length); + for (char index : exceptionIndexTable) + buffer.putChar(index); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/InnerClasses.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/InnerClasses.java new file mode 100644 index 0000000..4eee987 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/InnerClasses.java @@ -0,0 +1,96 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import java.nio.ByteBuffer; + +public class InnerClasses implements SizedByteCodec { + + public enum Flag { + PUBLIC((char) 0x1), + PRIVATE((char) 0x2), + PROTECTED((char) 0x4), + STATIC((char) 0x8), + FINAL((char) 0x10), + INTERFACE((char) 0x200), + ABSTRACT((char) 0x400), + SYNTHETIC((char) 0x1000), + ANNOTATION((char) 0x2000), + ENUM((char) 0x4000); + + private final char value; + + Flag(final char value) { + this.value = value; + } + + public char getValue() { return value; } + + public static Flag fromValue(final char value) { + for (final Flag flag : Flag.values()) { + if (flag.getValue() == value) + return flag; + } + return null; + } + } + + public static class Classes implements SizedByteCodec { + + final char innerClassInfoIndex; + final char outerClassInfoIndex; + final char innerNameIndex; + final Flag innerClassAccessFlags; + + public Classes(final char innerClassInfoIndex, final char outerClassInfoIndex, final char innerNameIndex, final Flag innerClassAccessFlags) { + this.innerClassInfoIndex = innerClassInfoIndex; + this.outerClassInfoIndex = outerClassInfoIndex; + this.innerNameIndex = innerNameIndex; + this.innerClassAccessFlags = innerClassAccessFlags; + } + + public static Classes decode(ByteBuffer buffer) { + return new Classes(buffer.getChar(), buffer.getChar(), buffer.getChar(), Flag.fromValue(buffer.getChar())); + } + + + @Override + public int getSize() { + return 8; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(innerClassInfoIndex); + buffer.putChar(outerClassInfoIndex); + buffer.putChar(innerNameIndex); + buffer.putChar(innerClassAccessFlags.getValue()); + } + } + + private final Classes[] classes; + + public InnerClasses(final Classes[] classes) { + this.classes = classes; + } + + public static InnerClasses decode(ByteBuffer buffer) { + Classes[] classes = new Classes[buffer.getChar()]; + for (int i = 0; i < classes.length; i++) + classes[i] = Classes.decode(buffer); + return new InnerClasses(classes); + } + + @Override + public int getSize() { + int size = 0; + for (Classes classe : classes) + size += classe.getSize(); + return size; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar((char) classes.length); + for (Classes classe : classes) + classe.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/LineNumberTable.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/LineNumberTable.java new file mode 100644 index 0000000..bbaa249 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/LineNumberTable.java @@ -0,0 +1,55 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import java.nio.ByteBuffer; + +public class LineNumberTable implements SizedByteCodec { + + public record Table(char startPC, char lineNumber) implements SizedByteCodec { + + public static Table decode(ByteBuffer buffer) { + return new Table(buffer.getChar(), buffer.getChar()); + } + + @Override + public int getSize() { + return 4; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(startPC); + buffer.putChar(lineNumber); + } + } + + private final Table[] table; + + public LineNumberTable(final Table[] table) { + this.table = table; + } + + public Table[] getTable() { return table; } + + public static LineNumberTable decode(ByteBuffer buffer) { + char length = buffer.getChar(); + Table[] table = new Table[(int)length]; + for (int i = 0; i < table.length; i++) + table[i] = Table.decode(buffer); + return new LineNumberTable(table); + } + + @Override + public int getSize() { + int baseSize = 2; + for (Table table : table) + baseSize += table.getSize(); + return baseSize; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar((char) table.length); + for (Table table : table) + table.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/LocalVariableTable.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/LocalVariableTable.java new file mode 100644 index 0000000..d113290 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/LocalVariableTable.java @@ -0,0 +1,59 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import java.nio.ByteBuffer; + +public class LocalVariableTable implements SizedByteCodec { + + public record Table(char startPC, char length, char nameIndex, char descriptorIndex, + char index) implements SizedByteCodec { + + public static Table decode(ByteBuffer buffer) { + return new Table(buffer.getChar(), buffer.getChar(), buffer.getChar(), buffer.getChar(), buffer.getChar()); + } + + @Override + public int getSize() { + return 10; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(startPC); + buffer.putChar(length); + buffer.putChar(nameIndex); + buffer.putChar(descriptorIndex); + buffer.putChar(index); + } + } + + private final Table[] table; + + public LocalVariableTable(final Table[] table) { + this.table = table; + } + + public Table[] getTable() { return table; } + + public static LocalVariableTable decode(ByteBuffer buffer) { + char length = buffer.getChar(); + Table[] table = new Table[(int)length]; + for (int i = 0; i < table.length; i++) + table[i] = Table.decode(buffer); + return new LocalVariableTable(table); + } + + @Override + public int getSize() { + int baseSize = 2; + for (Table table : table) + baseSize += table.getSize(); + return baseSize; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar((char) table.length); + for (Table table : table) + table.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeVisibleAnnotations.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeVisibleAnnotations.java new file mode 100644 index 0000000..af5ca3b --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeVisibleAnnotations.java @@ -0,0 +1,89 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.values.*; +import org.momento.lycoris.utils.Pair; + +import java.nio.ByteBuffer; + +public class RuntimeVisibleAnnotations implements SizedByteCodec { + + public static class Annotation implements SizedByteCodec { + + private final char typeIndex; + private final Pair[] pairs; + + public Annotation(final char typeIndex, final Pair[] pairs) { + this.typeIndex = typeIndex; + this.pairs = pairs; + } + + public char getTypeIndex() { return typeIndex; } + public Pair[] getPairs() { return pairs; } + + public static Annotation decode(ByteBuffer buffer) { + char typeIndex = buffer.getChar(); + Pair[] pairs = new Pair[buffer.getChar()]; + for (int i = 0; i < pairs.length; i++) { + char nameIndex = buffer.getChar(); + ElementValue.Tag tag = ElementValue.Tag.fromValue(buffer.get()); + ElementValue value = switch (tag) { + case BYTE, CHAR, DOUBLE, FLOAT, INT, LONG, SHORT, BOOLEAN, STRING -> ConstValue.decode(tag, buffer); + case ENUMCONSTANT -> EnumConstValue.decode(tag, buffer); + case CLASS -> ClassConstValue.decode(tag, buffer); + case ANNOTATION -> AnnotationValue.decode(tag, buffer); + case ARRAY -> ArrayValue.decode(tag, buffer); + }; + pairs[i] = new Pair<>(nameIndex, value); + } + return new Annotation(typeIndex, pairs); + } + + @Override + public int getSize() { + int baseSize = 4; + for (Pair pair : pairs) + baseSize += 2 + pair.getSecond().getSize(); + return baseSize; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(typeIndex); + for (Pair pair : pairs) { + buffer.putChar(pair.getFirst()); + pair.getSecond().encode(buffer); + } + } + } + + private final Annotation[] annotations; + + public RuntimeVisibleAnnotations(final Annotation[] annotations) { + this.annotations = annotations; + } + + public Annotation[] getAnnotations() { return annotations; } + + public static RuntimeVisibleAnnotations decode(ByteBuffer buffer) { + final Annotation[] annotations = new Annotation[buffer.getChar()]; + for (int i = 0; i < annotations.length; i++) { + annotations[i] = null; + } + return new RuntimeVisibleAnnotations(annotations); + } + + @Override + public int getSize() { + int baseSize = 2; + for (Annotation annotation : annotations) + baseSize += annotation.getSize(); + return baseSize; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar((char) annotations.length); + for (Annotation annotation : annotations) + annotation.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Signature.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Signature.java new file mode 100644 index 0000000..95b7ab2 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Signature.java @@ -0,0 +1,28 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import java.nio.ByteBuffer; + +public class Signature implements SizedByteCodec { + + private final char signatureIndex; + + public Signature(final char signatureIndex) { + this.signatureIndex = signatureIndex; + } + + public char getSignatureIndex() { return signatureIndex; } + + public static Signature decode(ByteBuffer buffer) { + return new Signature(buffer.getChar()); + } + + @Override + public int getSize() { + return 2; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(signatureIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/SourceDebugExtension.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/SourceDebugExtension.java new file mode 100644 index 0000000..2b2e91e --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/SourceDebugExtension.java @@ -0,0 +1,30 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import java.nio.ByteBuffer; + +public class SourceDebugExtension implements SizedByteCodec { + + private final byte[] debugExtension; + + public SourceDebugExtension(final byte[] debugExtension) { + this.debugExtension = debugExtension; + } + + public byte[] getDebugExtension() { return debugExtension; } + + public static SourceDebugExtension decode(final int length, ByteBuffer buffer) { + byte[] debugExtension = new byte[length]; + buffer.get(debugExtension); + return new SourceDebugExtension(debugExtension); + } + + @Override + public int getSize() { + return debugExtension.length; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.put(debugExtension); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/SourceFile.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/SourceFile.java new file mode 100644 index 0000000..3c1f72c --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/SourceFile.java @@ -0,0 +1,28 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import java.nio.ByteBuffer; + +public class SourceFile implements SizedByteCodec { + + private final char sourceFileIndex; + + public SourceFile(final char sourceFileIndex) { + this.sourceFileIndex = sourceFileIndex; + } + + public char getSourceFileIndex() { return sourceFileIndex; } + + public static SourceFile decode(ByteBuffer buffer) { + return new SourceFile(buffer.getChar()); + } + + @Override + public int getSize() { + return 2; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(sourceFileIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/StackMapTable.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/StackMapTable.java index 048837a..7ae384b 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/StackMapTable.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/StackMapTable.java @@ -35,7 +35,7 @@ public static StackMapTable decode(ByteBuffer buffer) { case CHOP -> ChopFrame.decode(type, buffer); case SAME_FRAME_EXTENDED -> SameExFrame.decode(type, buffer); case APPEND -> AppendFrame.decode(type, buffer); - case FULL_FRAME -> null; + case FULL_FRAME -> FullFrame.decode(type, buffer); }; } return new StackMapTable(entries); diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/FullFrame.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/FullFrame.java index 1990000..22dc84c 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/FullFrame.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/FullFrame.java @@ -1,5 +1,7 @@ package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.frames; +import java.nio.ByteBuffer; + public class FullFrame extends StackMapFrame { private final char offsetDelta; @@ -17,4 +19,38 @@ public FullFrame(final Type type, final char offsetDelta, final VerificationType public char getOffsetDelta() { return offsetDelta; } public VerificationTypeInfo[] getLocals() { return locals; } public VerificationTypeInfo[] getStack() { return stack; } + + public static FullFrame decode(Type type, ByteBuffer buffer) { + char offsetDelta = buffer.getChar(); + VerificationTypeInfo[] locals = new VerificationTypeInfo[buffer.getChar()]; + for (int i = 0; i < locals.length; ++i) + locals[i] = VerificationTypeInfo.decode(buffer); + VerificationTypeInfo[] stack = new VerificationTypeInfo[buffer.getChar()]; + for (int i = 0; i < stack.length; ++i) + stack[i] = VerificationTypeInfo.decode(buffer); + return new FullFrame(type, offsetDelta, locals, stack); + } + + @Override + public int getSize() { + int baseSize = super.getSize() + 6; + for (VerificationTypeInfo local: locals) + baseSize += local.getSize(); + for (VerificationTypeInfo stack: stack) + baseSize += stack.getSize(); + return baseSize; + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar(offsetDelta); + buffer.putChar((char) locals.length); + for (VerificationTypeInfo local: locals) + local.encode(buffer); + buffer.putChar((char) stack.length); + for (VerificationTypeInfo stack: stack) + stack.encode(buffer); + + } } diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/AnnotationValue.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/AnnotationValue.java new file mode 100644 index 0000000..d95ac6b --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/AnnotationValue.java @@ -0,0 +1,32 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.values; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.RuntimeVisibleAnnotations; + +import java.nio.ByteBuffer; + +public class AnnotationValue extends ElementValue { + + private final RuntimeVisibleAnnotations.Annotation value; + + public AnnotationValue(final Tag tag, final RuntimeVisibleAnnotations.Annotation value) { + super(tag); + this.value = value; + } + + public RuntimeVisibleAnnotations.Annotation getValue() { return value; } + + public static AnnotationValue decode(final Tag tag, ByteBuffer buffer) { + return new AnnotationValue(tag, RuntimeVisibleAnnotations.Annotation.decode(buffer)); + } + + @Override + public int getSize() { + return super.getSize() + value.getSize(); + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + value.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ArrayValue.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ArrayValue.java new file mode 100644 index 0000000..88af30d --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ArrayValue.java @@ -0,0 +1,35 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.values; + +import java.nio.ByteBuffer; + +public class ArrayValue extends ElementValue { + + private final ElementValue[] elements; + + public ArrayValue(final Tag tag, final ElementValue[] elements) { + super(tag); + this.elements = elements; + } + + public ElementValue[] getElements() { return elements; } + + public static ArrayValue decode(final Tag tag, ByteBuffer buffer) { + ElementValue[] elements = new ElementValue[buffer.getChar()]; + for (int i = 0; i < elements.length; i++) + elements[i] = null; //TODO MODIFY THIS + return new ArrayValue(tag, elements); + } + + @Override + public int getSize() { + return super.getSize() + 2 + elements.length; + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar((char) elements.length); + for (ElementValue element : elements) + element.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ClassConstValue.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ClassConstValue.java new file mode 100644 index 0000000..819e6a2 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ClassConstValue.java @@ -0,0 +1,30 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.values; + +import java.nio.ByteBuffer; + +public class ClassConstValue extends ElementValue { + + private final char infoIndex; + + public ClassConstValue(final Tag tag, final char infoIndex) { + super(tag); + this.infoIndex = infoIndex; + } + + public char getInfoIndex() { return infoIndex; } + + public static ClassConstValue decode(final Tag tag, ByteBuffer buffer) { + return new ClassConstValue(tag, buffer.getChar()); + } + + @Override + public int getSize() { + return super.getSize() + 2; + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar(infoIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ConstValue.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ConstValue.java new file mode 100644 index 0000000..9884606 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ConstValue.java @@ -0,0 +1,30 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.values; + +import java.nio.ByteBuffer; + +public class ConstValue extends ElementValue { + + private final char valueIndex; + + public ConstValue(final Tag tag, final char valueIndex) { + super(tag); + this.valueIndex = valueIndex; + } + + public char getValueIndex() { return valueIndex; } + + public static ConstValue decode(final Tag tag, ByteBuffer buffer) { + return new ConstValue(tag, buffer.getChar()); + } + + @Override + public int getSize() { + return super.getSize() + 2; + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar(valueIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ElementValue.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ElementValue.java new file mode 100644 index 0000000..ef6087e --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ElementValue.java @@ -0,0 +1,58 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.values; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; + +import java.nio.ByteBuffer; + +public abstract class ElementValue implements SizedByteCodec { + + public enum Tag { + BYTE((byte) 'B'), + CHAR((byte) 'C'), + DOUBLE((byte) 'D'), + FLOAT((byte) 'F'), + INT((byte) 'I'), + LONG((byte) 'J'), + SHORT((byte) 'S'), + BOOLEAN((byte) 'Z'), + STRING((byte) 's'), + ENUMCONSTANT((byte) 'e'), + CLASS((byte) 'c'), + ANNOTATION((byte) '@'), + ARRAY((byte) '['); + + private final byte value; + + Tag(final byte value) { + this.value = value; + } + + public byte getValue() { return value; } + + public static Tag fromValue(final byte value) { + for (final Tag tag : Tag.values()) { + if (tag.getValue() == value) + return tag; + } + return null; + } + } + + private final Tag tag; + + public ElementValue(final Tag tag) { + this.tag = tag; + } + + public Tag getTag() { return tag; } + + @Override + public int getSize() { + return 1; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.put(tag.getValue()); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/EnumConstValue.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/EnumConstValue.java new file mode 100644 index 0000000..747470e --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/EnumConstValue.java @@ -0,0 +1,34 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.values; + +import java.nio.ByteBuffer; + +public class EnumConstValue extends ElementValue { + + private final char typeNameIndex; + private final char constNameIndex; + + public EnumConstValue(final Tag tag, final char typeNameIndex, final char constNameIndex) { + super(tag); + this.typeNameIndex = typeNameIndex; + this.constNameIndex = constNameIndex; + } + + public char getTypeNameIndex() { return typeNameIndex; } + public char getConstNameIndex() { return constNameIndex; } + + public static EnumConstValue decode(final Tag tag, ByteBuffer buffer) { + return new EnumConstValue(tag, buffer.getChar(), buffer.getChar()); + } + + @Override + public int getSize() { + return super.getSize() + 4; + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar(typeNameIndex); + buffer.putChar(constNameIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/utils/Pair.java b/src/main/java/org/momento/lycoris/utils/Pair.java new file mode 100644 index 0000000..f844ea7 --- /dev/null +++ b/src/main/java/org/momento/lycoris/utils/Pair.java @@ -0,0 +1,19 @@ +package org.momento.lycoris.utils; + +public class Pair { + + private T first; + private U second; + + public Pair(T first, U second) { + this.first = first; + this.second = second; + } + + public T getFirst() { return first; } + public U getSecond() { return second; } + + public void setFirst(T first) { this.first = first; } + public void setSecond(U second) { this.second = second; } + +} From 5eed9b4debdd0c4b71e4f00886ea944f7c9fa193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lise=20Valentin?= Date: Thu, 14 Nov 2024 16:22:06 +0100 Subject: [PATCH 06/11] Add remaining attributes --- .../mixins/mixin/classe/ClassWrapper.java | 7 ++ .../structures/infos/AttributeInfo.java | 4 + .../infos/attributes/Annotation.java | 52 +++++++++++ .../infos/attributes/AnnotationDefault.java | 30 +++++++ .../infos/attributes/BootstrapMethods.java | 68 ++++++++++++++ .../infos/attributes/RuntimeAnnotations.java | 37 ++++++++ .../RuntimeParameterAnnotations.java | 45 ++++++++++ .../attributes/RuntimeVisibleAnnotations.java | 89 ------------------- .../attributes/values/AnnotationValue.java | 10 +-- .../infos/attributes/values/ArrayValue.java | 2 +- .../infos/attributes/values/ElementValue.java | 12 +++ 11 files changed, 261 insertions(+), 95 deletions(-) create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Annotation.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/AnnotationDefault.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/BootstrapMethods.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeAnnotations.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeParameterAnnotations.java delete mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeVisibleAnnotations.java diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/ClassWrapper.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/ClassWrapper.java index a6e7f9a..02ff1e3 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/ClassWrapper.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/ClassWrapper.java @@ -1,10 +1,17 @@ package org.momento.lycoris.mixins.mixin.classe; +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; + import java.nio.ByteBuffer; public class ClassWrapper implements ByteCodec { + private final int magic; + private final char minorVersion; + private final char majorVersion; + private final ConstantPool[] constantPool; + public ClassWrapper() {} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java index c748b86..6e79ef3 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java @@ -37,6 +37,10 @@ public static AttributeInfo decode(final ConstantPool[] constantPools, ByteBuffe case "SourceDebugExtension" -> SourceDebugExtension.decode(length, buffer); case "LineNumberTable" -> LineNumberTable.decode(buffer); case "LocalVariableTable", "LocalVariableTypeTable" -> LocalVariableTable.decode(buffer); + case "RuntimeInvisibleAnnotations", "RuntimeVisibleAnnotations" -> RuntimeAnnotations.decode(buffer); + case "RuntimeInvisibleParameterAnnotations", "RuntimeVisibleParameterAnnotations" -> RuntimeParameterAnnotations.decode(buffer); + case "AnnotationDefault" -> AnnotationDefault.decode(buffer); + case "BootstrapMethods" -> BootstrapMethods.decode(buffer); default -> null; }; return new AttributeInfo(nameIndex, attribute); diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Annotation.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Annotation.java new file mode 100644 index 0000000..d3e1714 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Annotation.java @@ -0,0 +1,52 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.values.ElementValue; +import org.momento.lycoris.utils.Pair; + +import java.nio.ByteBuffer; + +public class Annotation implements SizedByteCodec { + + private final char typeIndex; + private final Pair[] pairs; + + public Annotation(final char typeIndex, final Pair[] pairs) { + this.typeIndex = typeIndex; + this.pairs = pairs; + } + + public char getTypeIndex() { + return typeIndex; + } + + public Pair[] getPairs() { + return pairs; + } + + public static Annotation decode(ByteBuffer buffer) { + char typeIndex = buffer.getChar(); + Pair[] pairs = new Pair[buffer.getChar()]; + for (int i = 0; i < pairs.length; i++) { + char nameIndex = buffer.getChar(); + pairs[i] = new Pair<>(nameIndex, ElementValue.decode(buffer)); + } + return new Annotation(typeIndex, pairs); + } + + @Override + public int getSize() { + int baseSize = 4; + for (Pair pair : pairs) + baseSize += 2 + pair.getSecond().getSize(); + return baseSize; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(typeIndex); + for (Pair pair : pairs) { + buffer.putChar(pair.getFirst()); + pair.getSecond().encode(buffer); + } + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/AnnotationDefault.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/AnnotationDefault.java new file mode 100644 index 0000000..a1971ba --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/AnnotationDefault.java @@ -0,0 +1,30 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.values.ElementValue; + +import java.nio.ByteBuffer; + +public class AnnotationDefault implements SizedByteCodec { + + private final ElementValue value; + + public AnnotationDefault(final ElementValue value) { + this.value = value; + } + + public ElementValue getValue() { return value; } + + public static AnnotationDefault decode(ByteBuffer buffer) { + return new AnnotationDefault(ElementValue.decode(buffer)); + } + + @Override + public int getSize() { + return value.getSize(); + } + + @Override + public void encode(ByteBuffer buffer) { + value.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/BootstrapMethods.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/BootstrapMethods.java new file mode 100644 index 0000000..3dda967 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/BootstrapMethods.java @@ -0,0 +1,68 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import java.nio.ByteBuffer; + +public class BootstrapMethods implements SizedByteCodec { + + public static class BootsrapMethod implements SizedByteCodec { + + private final char ref; + private final char[] args; + + public BootsrapMethod(final char ref, final char[] args) { + this.ref = ref; + this.args = args; + } + + public char getRef() { return ref; } + public char[] getArgs() { return args; } + + public static BootsrapMethod decode(ByteBuffer buffer) { + char ref = buffer.getChar(); + char[] args = new char[buffer.getChar()]; + for (int i = 0; i < args.length; i++) + args[i] = buffer.getChar(); + return new BootsrapMethod(ref, args); + } + + @Override + public int getSize() { + return 2 + args.length * 2; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(ref); + buffer.putChar((char) args.length); + for (int i = 0; i < args.length; i++) + buffer.putChar(args[i]); + } + } + + private final BootsrapMethod[] methods; + + public BootstrapMethods(final BootsrapMethod[] methods) { + this.methods = methods; + } + + public BootsrapMethod[] getMethods() { return methods; } + + public static BootstrapMethods decode(ByteBuffer buffer) { + BootsrapMethod[] methods = new BootsrapMethod[buffer.getChar()]; + for (int i = 0; i < methods.length; ++i) + methods[i] = BootsrapMethod.decode(buffer); + return new BootstrapMethods(methods); + } + + @Override + public int getSize() { + return 0; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar((char) methods.length); + for (BootsrapMethod method : methods) + method.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeAnnotations.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeAnnotations.java new file mode 100644 index 0000000..5604ba5 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeAnnotations.java @@ -0,0 +1,37 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import java.nio.ByteBuffer; + +public class RuntimeAnnotations implements SizedByteCodec { + + private final Annotation[] annotations; + + public RuntimeAnnotations(final Annotation[] annotations) { + this.annotations = annotations; + } + + public Annotation[] getAnnotations() { return annotations; } + + public static RuntimeAnnotations decode(ByteBuffer buffer) { + final Annotation[] annotations = new Annotation[buffer.getChar()]; + for (int i = 0; i < annotations.length; i++) { + annotations[i] = Annotation.decode(buffer); + } + return new RuntimeAnnotations(annotations); + } + + @Override + public int getSize() { + int baseSize = 2; + for (Annotation annotation : annotations) + baseSize += annotation.getSize(); + return baseSize; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar((char) annotations.length); + for (Annotation annotation : annotations) + annotation.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeParameterAnnotations.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeParameterAnnotations.java new file mode 100644 index 0000000..2aac186 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeParameterAnnotations.java @@ -0,0 +1,45 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import java.nio.ByteBuffer; + +public class RuntimeParameterAnnotations implements SizedByteCodec { + + private final Annotation[][] parameters; + + public RuntimeParameterAnnotations(final Annotation[][] parameters) { + this.parameters = parameters; + } + + public Annotation[] getParameters() { return parameters[0]; } + + public static RuntimeParameterAnnotations decode(ByteBuffer buffer) { + final Annotation[][] parameters = new Annotation[buffer.getChar()][]; + for (int i = 0; i < parameters.length; i++) { + parameters[i] = new Annotation[buffer.getChar()]; + for (int j = 0; j < parameters[i].length; j++) + parameters[i][j] = Annotation.decode(buffer); + } + return new RuntimeParameterAnnotations(parameters); + } + + @Override + public int getSize() { + int baseSize = 2; + for (Annotation[] annotations : parameters) { + baseSize += 2; + for (Annotation annotation : annotations) + baseSize += annotation.getSize(); + } + return baseSize; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar((char) parameters.length); + for (Annotation[] annotations : parameters) { + buffer.putChar((char) annotations.length); + for (Annotation annotation : annotations) + annotation.encode(buffer); + } + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeVisibleAnnotations.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeVisibleAnnotations.java deleted file mode 100644 index af5ca3b..0000000 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeVisibleAnnotations.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; - -import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.values.*; -import org.momento.lycoris.utils.Pair; - -import java.nio.ByteBuffer; - -public class RuntimeVisibleAnnotations implements SizedByteCodec { - - public static class Annotation implements SizedByteCodec { - - private final char typeIndex; - private final Pair[] pairs; - - public Annotation(final char typeIndex, final Pair[] pairs) { - this.typeIndex = typeIndex; - this.pairs = pairs; - } - - public char getTypeIndex() { return typeIndex; } - public Pair[] getPairs() { return pairs; } - - public static Annotation decode(ByteBuffer buffer) { - char typeIndex = buffer.getChar(); - Pair[] pairs = new Pair[buffer.getChar()]; - for (int i = 0; i < pairs.length; i++) { - char nameIndex = buffer.getChar(); - ElementValue.Tag tag = ElementValue.Tag.fromValue(buffer.get()); - ElementValue value = switch (tag) { - case BYTE, CHAR, DOUBLE, FLOAT, INT, LONG, SHORT, BOOLEAN, STRING -> ConstValue.decode(tag, buffer); - case ENUMCONSTANT -> EnumConstValue.decode(tag, buffer); - case CLASS -> ClassConstValue.decode(tag, buffer); - case ANNOTATION -> AnnotationValue.decode(tag, buffer); - case ARRAY -> ArrayValue.decode(tag, buffer); - }; - pairs[i] = new Pair<>(nameIndex, value); - } - return new Annotation(typeIndex, pairs); - } - - @Override - public int getSize() { - int baseSize = 4; - for (Pair pair : pairs) - baseSize += 2 + pair.getSecond().getSize(); - return baseSize; - } - - @Override - public void encode(ByteBuffer buffer) { - buffer.putChar(typeIndex); - for (Pair pair : pairs) { - buffer.putChar(pair.getFirst()); - pair.getSecond().encode(buffer); - } - } - } - - private final Annotation[] annotations; - - public RuntimeVisibleAnnotations(final Annotation[] annotations) { - this.annotations = annotations; - } - - public Annotation[] getAnnotations() { return annotations; } - - public static RuntimeVisibleAnnotations decode(ByteBuffer buffer) { - final Annotation[] annotations = new Annotation[buffer.getChar()]; - for (int i = 0; i < annotations.length; i++) { - annotations[i] = null; - } - return new RuntimeVisibleAnnotations(annotations); - } - - @Override - public int getSize() { - int baseSize = 2; - for (Annotation annotation : annotations) - baseSize += annotation.getSize(); - return baseSize; - } - - @Override - public void encode(ByteBuffer buffer) { - buffer.putChar((char) annotations.length); - for (Annotation annotation : annotations) - annotation.encode(buffer); - } -} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/AnnotationValue.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/AnnotationValue.java index d95ac6b..ae99549 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/AnnotationValue.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/AnnotationValue.java @@ -1,22 +1,22 @@ package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.values; -import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.RuntimeVisibleAnnotations; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.Annotation; import java.nio.ByteBuffer; public class AnnotationValue extends ElementValue { - private final RuntimeVisibleAnnotations.Annotation value; + private final Annotation value; - public AnnotationValue(final Tag tag, final RuntimeVisibleAnnotations.Annotation value) { + public AnnotationValue(final Tag tag, final Annotation value) { super(tag); this.value = value; } - public RuntimeVisibleAnnotations.Annotation getValue() { return value; } + public Annotation getValue() { return value; } public static AnnotationValue decode(final Tag tag, ByteBuffer buffer) { - return new AnnotationValue(tag, RuntimeVisibleAnnotations.Annotation.decode(buffer)); + return new AnnotationValue(tag, Annotation.decode(buffer)); } @Override diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ArrayValue.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ArrayValue.java index 88af30d..4da5348 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ArrayValue.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ArrayValue.java @@ -16,7 +16,7 @@ public ArrayValue(final Tag tag, final ElementValue[] elements) { public static ArrayValue decode(final Tag tag, ByteBuffer buffer) { ElementValue[] elements = new ElementValue[buffer.getChar()]; for (int i = 0; i < elements.length; i++) - elements[i] = null; //TODO MODIFY THIS + elements[i] = ElementValue.decode(buffer); return new ArrayValue(tag, elements); } diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ElementValue.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ElementValue.java index ef6087e..2843811 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ElementValue.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/values/ElementValue.java @@ -46,6 +46,18 @@ public ElementValue(final Tag tag) { public Tag getTag() { return tag; } + public static ElementValue decode(ByteBuffer buffer) { + ElementValue.Tag tag = ElementValue.Tag.fromValue(buffer.get()); + assert tag != null; + return switch (tag) { + case BYTE, CHAR, DOUBLE, FLOAT, INT, LONG, SHORT, BOOLEAN, STRING -> ConstValue.decode(tag, buffer); + case ENUMCONSTANT -> EnumConstValue.decode(tag, buffer); + case CLASS -> ClassConstValue.decode(tag, buffer); + case ANNOTATION -> AnnotationValue.decode(tag, buffer); + case ARRAY -> ArrayValue.decode(tag, buffer); + }; + } + @Override public int getSize() { return 1; From ef2c13614906b216967c05bfd5cd655e9412b727 Mon Sep 17 00:00:00 2001 From: Elty <30352734+EltyDev@users.noreply.github.com> Date: Thu, 28 Nov 2024 02:00:12 +0100 Subject: [PATCH 07/11] Fix index error on attributes --- .../java/org/momento/lycoris/Lycoris.java | 2 - .../momento/lycoris/mixins/mixin/Mixin.java | 4 - .../mixins/mixin/classe/ClassWrapper.java | 147 +++++++++++++++++- .../mixin/classe/structures/ConstantPool.java | 4 +- .../classe/structures/constants/UTF8Info.java | 3 +- .../structures/infos/AttributeInfo.java | 6 +- .../classe/structures/infos/FieldInfo.java | 106 +++++++++++++ .../classe/structures/infos/MethodInfo.java | 109 +++++++++++++ .../infos/attributes/AccessFlag.java | 32 ++++ .../infos/attributes/InnerClasses.java | 35 +---- .../infos/attributes/LineNumberTable.java | 2 +- .../infos/attributes/LocalVariableTable.java | 3 +- 12 files changed, 403 insertions(+), 50 deletions(-) create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/FieldInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/MethodInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/AccessFlag.java diff --git a/src/main/java/org/momento/lycoris/Lycoris.java b/src/main/java/org/momento/lycoris/Lycoris.java index f9d5a45..ef6a579 100644 --- a/src/main/java/org/momento/lycoris/Lycoris.java +++ b/src/main/java/org/momento/lycoris/Lycoris.java @@ -25,8 +25,6 @@ public void onEnable() { Bukkit.getPluginManager().disablePlugin(this); return; } - ClassPool - ClassDefinition definition = new ClassDefinition() } @Override diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/Mixin.java b/src/main/java/org/momento/lycoris/mixins/mixin/Mixin.java index fabb581..5423b1d 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/Mixin.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/Mixin.java @@ -8,8 +8,4 @@ public Mixin(Class classe) { this.classe = classe; } - public byte[] getBytecode() { - Cl - } - } diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/ClassWrapper.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/ClassWrapper.java index 02ff1e3..c9ec746 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/ClassWrapper.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/ClassWrapper.java @@ -1,22 +1,165 @@ package org.momento.lycoris.mixins.mixin.classe; import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.AttributeInfo; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.FieldInfo; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.MethodInfo; +import java.io.IOException; import java.nio.ByteBuffer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; public class ClassWrapper implements ByteCodec { + public enum AccessFlag { + + MASKED((char) 0x0), + PUBLIC((char) 0x1), + FINAL((char) 0x10), + SUPER((char) 0x20), + INTERFACE((char) 0x200), + ABSTRACT((char) 0x400), + SYNTHETIC((char) 0x1000), + ANNOTATION((char) 0x2000), + ENUM((char) 0x4000), + MODULE((char) 0x8000); + + private char value; + + AccessFlag(char value) { + this.value = value; + } + + public char getValue() { return value; } + public char setValue(char value) { this.value = value; return value; } + + + public static AccessFlag fromValue(final char value) { + for (final AccessFlag flag : AccessFlag.values()) { + if (flag.getValue() == value) + return flag; + } + AccessFlag flag = MASKED; + flag.setValue(value); + return flag; + } + + public AccessFlag[] getAccessFlags() { + List flags = new ArrayList<>(); + for (AccessFlag flag : AccessFlag.values()) { + if ((value & flag.getValue()) != 0) + flags.add(flag); + } + return flags.toArray(new AccessFlag[0]); + } + + public void addAccessFlag(final AccessFlag flag) { + this.value = (char) (value | flag.value); + } + + public void removeAccessFlag(final AccessFlag flag) { + this.value = (char) (value & ~flag.value); + } + } private final int magic; private final char minorVersion; private final char majorVersion; private final ConstantPool[] constantPool; + private final AccessFlag flags; + private final char thisClass; + private final char superClass; + private final char[] interfaces; + private final FieldInfo[] fields; + private final MethodInfo[] methods; + private final AttributeInfo[] attributes; + + public ClassWrapper(final int magic, final char minorVersion, final char majorVersion, + final ConstantPool[] constantPool, final AccessFlag flags, final char thisClass, + final char superClass, final char[] interfaces, final FieldInfo[] fields, + final MethodInfo[] methods, final AttributeInfo[] attributes) { + this.magic = magic; + this.minorVersion = minorVersion; + this.majorVersion = majorVersion; + this.constantPool = constantPool; + this.flags = flags; + this.thisClass = thisClass; + this.superClass = superClass; + this.interfaces = interfaces; + this.fields = fields; + this.methods = methods; + this.attributes = attributes; + } - public ClassWrapper() {} + public int getMagic() { return magic; } + public char getMinorVersion() { return minorVersion; } + public char getMajorVersion() { return majorVersion; } + public ConstantPool[] getConstantPool() { return constantPool; } + public AccessFlag getFlags() { return flags; } + public char getThisClass() { return thisClass; } + public char getSuperClass() { return superClass; } + public char[] getInterfaces() { return interfaces; } + public FieldInfo[] getFields() { return fields; } + public MethodInfo[] getMethods() { return methods; } + public AttributeInfo[] getAttributes() { return attributes; } + public static ClassWrapper decode(ByteBuffer buffer) { + int magic = buffer.getInt(); + char minorVersion = buffer.getChar(); + char majorVersion = buffer.getChar(); + ConstantPool[] constantPool = new ConstantPool[buffer.getChar() - 1]; + for (int i = 0; i < constantPool.length; ++i) + constantPool[i] = ConstantPool.decode(buffer); + AccessFlag flag = AccessFlag.fromValue(buffer.getChar()); + char thisClass = buffer.getChar(); + char superClass = buffer.getChar(); + char[] interfaces = new char[buffer.getChar()]; + for (int i = 0; i < interfaces.length; ++i) + interfaces[i] = buffer.getChar(); + FieldInfo[] fields = new FieldInfo[buffer.getChar()]; + for (int i = 0; i < fields.length; ++i) + fields[i] = FieldInfo.decode(constantPool, buffer); + MethodInfo[] methods = new MethodInfo[buffer.getChar()]; + for (int i = 0; i < methods.length; ++i) { + methods[i] = MethodInfo.decode(constantPool, buffer); + } + AttributeInfo[] attributes = new AttributeInfo[buffer.getChar()]; + for (int i = 0; i < attributes.length; ++i) + attributes[i] = AttributeInfo.decode(constantPool, buffer); + return new ClassWrapper(magic, minorVersion, majorVersion, constantPool, flag, thisClass, superClass, interfaces, fields, methods, attributes); + } + + public static ClassWrapper decode(Path path) throws IOException { + byte[] bytes = Files.readAllBytes(path); + ByteBuffer buffer = ByteBuffer.wrap(bytes); + return decode(buffer); + } @Override public void encode(ByteBuffer buffer) { - + buffer.putInt(magic); + buffer.putChar(minorVersion); + buffer.putChar(majorVersion); + buffer.putChar((char) (constantPool.length + 1)); + for (ConstantPool cp : constantPool) + cp.encode(buffer); + buffer.putChar(flags.getValue()); + buffer.putChar(thisClass); + buffer.putChar(superClass); + buffer.putChar((char) interfaces.length); + for (char c : interfaces) + buffer.putChar(c); + buffer.putChar((char) fields.length); + for (FieldInfo f : fields) + f.encode(buffer); + buffer.putChar((char) methods.length); + for (MethodInfo m : methods) + m.encode(buffer); + buffer.putChar((char) attributes.length); + for (AttributeInfo a : attributes) + a.encode(buffer); } } \ No newline at end of file diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/ConstantPool.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/ConstantPool.java index 1634971..263d4f5 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/ConstantPool.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/ConstantPool.java @@ -12,7 +12,7 @@ public enum Tag { Class((byte) 7), FieldRef((byte) 9), MethodRef((byte) 10), - InterfaceMethodRef((byte) 1), + InterfaceMethodRef((byte) 11), String((byte) 8), Integer((byte) 3), Float((byte) 4), @@ -39,7 +39,7 @@ public static Tag getTag(final byte value) { if (tag.value == value) return tag; } - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Unknown tag: " + value); } } diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/UTF8Info.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/UTF8Info.java index 7bbd165..95cdb1a 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/UTF8Info.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/UTF8Info.java @@ -17,8 +17,7 @@ public UTF8Info(final ConstantPool.Tag tag, String string) { public String getString() { return string; } public static UTF8Info decode(ByteBuffer buffer) { - char length = buffer.getChar(); - byte[] bytes = new byte[length]; + byte[] bytes = new byte[buffer.getChar()]; buffer.get(bytes); String string = new String(bytes, StandardCharsets.UTF_8); return new UTF8Info(ConstantPool.Tag.UTF8, string); diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java index 6e79ef3..7527cf3 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java @@ -20,9 +20,9 @@ public AttributeInfo(final char nameIndex, final SizedByteCodec attribute) { public static AttributeInfo decode(final ConstantPool[] constantPools, ByteBuffer buffer) { char nameIndex = buffer.getChar(); - ConstantInfo info = constantPools[nameIndex].getInfo(); + ConstantInfo info = constantPools[nameIndex - 1].getInfo(); if (info == null || info.getTag() != ConstantPool.Tag.UTF8) - throw new RuntimeException(); + throw new RuntimeException("Unexpected tag: " + info.getTag()); String attributeName = ((UTF8Info) info).getString(); int length = buffer.getInt(); SizedByteCodec attribute = switch (attributeName) { @@ -46,7 +46,7 @@ public static AttributeInfo decode(final ConstantPool[] constantPools, ByteBuffe return new AttributeInfo(nameIndex, attribute); } - public int getSize() { return 6 + attribute.getSize(); } + public int getSize() { return attribute.getSize(); } @Override public void encode(ByteBuffer buffer) { diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/FieldInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/FieldInfo.java new file mode 100644 index 0000000..5fbae34 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/FieldInfo.java @@ -0,0 +1,106 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +public class FieldInfo implements SizedByteCodec { + + public enum AccessFlag { + + MASKED((char) 0x0), + PUBLIC((char) 0x1), + PRIVATE((char) 0x2), + PROTECTED((char) 0x4), + STATIC((char) 0x8), + FINAL((char) 0x10), + VOLATILE((char) 0x40), + TRANSIENT((char) 0x80), + SYNTHETIC((char) 0x1000), + ENUM((char) 0x4000); + + private char value; + + AccessFlag(char value) { + this.value = value; + } + + public char getValue() { return value; } + public void setValue(char value) { this.value = value; } + + public static AccessFlag fromValue(final char value) { + for (final AccessFlag flag : AccessFlag.values()) { + if (flag.getValue() == value) + return flag; + } + AccessFlag flag = MASKED; + MASKED.setValue(value); + return flag; + } + + public AccessFlag[] getAccessFlags() { + List flags = new ArrayList<>(); + for (AccessFlag flag : AccessFlag.values()) { + if ((value & flag.getValue()) != 0) + flags.add(flag); + } + return flags.toArray(new AccessFlag[0]); + } + + public void addAccessFlag(final AccessFlag flag) { + this.value = (char) (value | flag.value); + } + + public void removeAccessFlag(final AccessFlag flag) { + this.value = (char) (value & ~flag.value); + } + } + + private final AccessFlag flags; + private final char nameIndex; + private final char descriptorIndex; + private final AttributeInfo[] attributes; + + public FieldInfo(final AccessFlag flags, final char nameIndex, final char descriptorIndex, final AttributeInfo[] attributes) { + this.flags = flags; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + this.attributes = attributes; + } + + public AccessFlag getFlags() { return flags; } + public char getNameIndex() { return nameIndex; } + public char getDescriptorIndex() { return descriptorIndex; } + public AttributeInfo[] getAttributes() { return attributes; } + + public static FieldInfo decode(final ConstantPool[] constantPool, ByteBuffer buffer) { + AccessFlag flag = AccessFlag.fromValue(buffer.getChar()); + char nameIndex = buffer.getChar(); + char descriptorIndex = buffer.getChar(); + AttributeInfo[] attributes = new AttributeInfo[buffer.getChar()]; + for (int i = 0; i < attributes.length; i++) + attributes[i] = AttributeInfo.decode(constantPool, buffer); + return new FieldInfo(flag, nameIndex, descriptorIndex, attributes); + } + + @Override + public int getSize() { + int baseSize = 8; + for (AttributeInfo attribute : attributes) + baseSize += attribute.getSize(); + return baseSize; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(flags.getValue()); + buffer.putChar(nameIndex); + buffer.putChar(descriptorIndex); + buffer.putChar((char) attributes.length); + for (AttributeInfo attribute : attributes) + attribute.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/MethodInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/MethodInfo.java new file mode 100644 index 0000000..38e82ae --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/MethodInfo.java @@ -0,0 +1,109 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +public class MethodInfo implements SizedByteCodec { + + public enum AccessFlag { + + MASKED((char) 0x0), + PUBLIC((char) 0x1), + PRIVATE((char) 0x2), + PROTECTED((char) 0x4), + STATIC((char) 0x8), + FINAL((char) 0x10), + SYNCHRONIZED((char) 0x20), + BRIDGE((char) 0x40), + VARARGS((char) 0x80), + NATIVE((char) 0x100), + ABSTRACT((char) 0x400), + STRICT((char) 0x800), + SYNTHETIC((char) 0x1000); + + private char value; + + AccessFlag(char value) { + this.value = value; + } + + public char getValue() { return value; } + public void setValue(char value) { this.value = value; } + + public static AccessFlag fromValue(final char value) { + for (final AccessFlag flag : AccessFlag.values()) { + if (flag.getValue() == value) + return flag; + } + AccessFlag flag = MASKED; + MASKED.setValue(value); + return flag; + } + + public AccessFlag[] getAccessFlags() { + List flags = new ArrayList<>(); + for (AccessFlag flag : AccessFlag.values()) { + if ((value & flag.getValue()) != 0) + flags.add(flag); + } + return flags.toArray(new AccessFlag[0]); + } + + public void addAccessFlag(final AccessFlag flag) { + this.value = (char) (value | flag.value); + } + + public void removeAccessFlag(final AccessFlag flag) { + this.value = (char) (value & ~flag.value); + } + } + + private final AccessFlag flags; + private final char nameIndex; + private final char descriptorIndex; + private final AttributeInfo[] attributes; + + public MethodInfo(final AccessFlag flags, final char nameIndex, final char descriptorIndex, final AttributeInfo[] attributes) { + this.flags = flags; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + this.attributes = attributes; + } + + public AccessFlag getFlags() { return flags; } + public char getNameIndex() { return nameIndex; } + public char getDescriptorIndex() { return descriptorIndex; } + public AttributeInfo[] getAttributes() { return attributes; } + + public static MethodInfo decode(final ConstantPool[] constantPool, ByteBuffer buffer) { + AccessFlag flag = AccessFlag.fromValue(buffer.getChar()); + char nameIndex = buffer.getChar(); + char descriptorIndex = buffer.getChar(); + AttributeInfo[] attributes = new AttributeInfo[buffer.getChar()]; + for (int i = 0; i < attributes.length; ++i) + attributes[i] = AttributeInfo.decode(constantPool, buffer); + return new MethodInfo(flag, nameIndex, descriptorIndex, attributes); + } + + @Override + public int getSize() { + int baseSize = 8; + for (AttributeInfo attribute : attributes) + baseSize += attribute.getSize(); + return baseSize; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(flags.getValue()); + buffer.putChar(nameIndex); + buffer.putChar(descriptorIndex); + buffer.putChar((char) attributes.length); + for (AttributeInfo attribute : attributes) + attribute.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/AccessFlag.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/AccessFlag.java new file mode 100644 index 0000000..5d6f74d --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/AccessFlag.java @@ -0,0 +1,32 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +public enum AccessFlag { + PUBLIC((char) 0x1), + PRIVATE((char) 0x2), + PROTECTED((char) 0x4), + STATIC((char) 0x8), + FINAL((char) 0x10), + VOLATILE((char) 0x40), + TRANSIENT((char) 0x80), + INTERFACE((char) 0x200), + ABSTRACT((char) 0x400), + SYNTHETIC((char) 0x1000), + ANNOTATION((char) 0x2000), + ENUM((char) 0x4000); + + private final char value; + + AccessFlag(final char value) { + this.value = value; + } + + public char getValue() { return value; } + + public static AccessFlag fromValue(final char value) { + for (final AccessFlag flag : AccessFlag.values()) { + if (flag.getValue() == value) + return flag; + } + return null; + } +} \ No newline at end of file diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/InnerClasses.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/InnerClasses.java index 4eee987..5cad902 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/InnerClasses.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/InnerClasses.java @@ -4,43 +4,14 @@ public class InnerClasses implements SizedByteCodec { - public enum Flag { - PUBLIC((char) 0x1), - PRIVATE((char) 0x2), - PROTECTED((char) 0x4), - STATIC((char) 0x8), - FINAL((char) 0x10), - INTERFACE((char) 0x200), - ABSTRACT((char) 0x400), - SYNTHETIC((char) 0x1000), - ANNOTATION((char) 0x2000), - ENUM((char) 0x4000); - - private final char value; - - Flag(final char value) { - this.value = value; - } - - public char getValue() { return value; } - - public static Flag fromValue(final char value) { - for (final Flag flag : Flag.values()) { - if (flag.getValue() == value) - return flag; - } - return null; - } - } - public static class Classes implements SizedByteCodec { final char innerClassInfoIndex; final char outerClassInfoIndex; final char innerNameIndex; - final Flag innerClassAccessFlags; + final AccessFlag innerClassAccessFlags; - public Classes(final char innerClassInfoIndex, final char outerClassInfoIndex, final char innerNameIndex, final Flag innerClassAccessFlags) { + public Classes(final char innerClassInfoIndex, final char outerClassInfoIndex, final char innerNameIndex, final AccessFlag innerClassAccessFlags) { this.innerClassInfoIndex = innerClassInfoIndex; this.outerClassInfoIndex = outerClassInfoIndex; this.innerNameIndex = innerNameIndex; @@ -48,7 +19,7 @@ public Classes(final char innerClassInfoIndex, final char outerClassInfoIndex, f } public static Classes decode(ByteBuffer buffer) { - return new Classes(buffer.getChar(), buffer.getChar(), buffer.getChar(), Flag.fromValue(buffer.getChar())); + return new Classes(buffer.getChar(), buffer.getChar(), buffer.getChar(), AccessFlag.fromValue(buffer.getChar())); } diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/LineNumberTable.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/LineNumberTable.java index bbaa249..44da9f8 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/LineNumberTable.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/LineNumberTable.java @@ -32,7 +32,7 @@ public LineNumberTable(final Table[] table) { public static LineNumberTable decode(ByteBuffer buffer) { char length = buffer.getChar(); - Table[] table = new Table[(int)length]; + Table[] table = new Table[length]; for (int i = 0; i < table.length; i++) table[i] = Table.decode(buffer); return new LineNumberTable(table); diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/LocalVariableTable.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/LocalVariableTable.java index d113290..57d7899 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/LocalVariableTable.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/LocalVariableTable.java @@ -35,8 +35,7 @@ public LocalVariableTable(final Table[] table) { public Table[] getTable() { return table; } public static LocalVariableTable decode(ByteBuffer buffer) { - char length = buffer.getChar(); - Table[] table = new Table[(int)length]; + Table[] table = new Table[buffer.getChar()]; for (int i = 0; i < table.length; i++) table[i] = Table.decode(buffer); return new LocalVariableTable(table); From 5a129454855ee78690127460289903d5cdede543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lise=20Valentin?= Date: Thu, 28 Nov 2024 13:45:47 +0100 Subject: [PATCH 08/11] Add NestMembers and fix some problems --- .../mixins/mixin/classe/ClassWrapper.java | 5 ++- .../structures/infos/AttributeInfo.java | 1 + .../infos/attributes/NestMembers.java | 33 +++++++++++++++++++ .../infos/attributes/StackMapTable.java | 2 +- .../infos/attributes/frames/AppendFrame.java | 2 +- .../attributes/frames/StackMapFrame.java | 24 +++++++------- 6 files changed, 50 insertions(+), 17 deletions(-) create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/NestMembers.java diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/ClassWrapper.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/ClassWrapper.java index c9ec746..27921d9 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/ClassWrapper.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/ClassWrapper.java @@ -122,10 +122,9 @@ public static ClassWrapper decode(ByteBuffer buffer) { FieldInfo[] fields = new FieldInfo[buffer.getChar()]; for (int i = 0; i < fields.length; ++i) fields[i] = FieldInfo.decode(constantPool, buffer); - MethodInfo[] methods = new MethodInfo[buffer.getChar()]; - for (int i = 0; i < methods.length; ++i) { + MethodInfo[] methods = new MethodInfo[buffer.getChar()]; + for (int i = 0; i < methods.length; ++i) methods[i] = MethodInfo.decode(constantPool, buffer); - } AttributeInfo[] attributes = new AttributeInfo[buffer.getChar()]; for (int i = 0; i < attributes.length; ++i) attributes[i] = AttributeInfo.decode(constantPool, buffer); diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java index 7527cf3..dec5854 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java @@ -41,6 +41,7 @@ public static AttributeInfo decode(final ConstantPool[] constantPools, ByteBuffe case "RuntimeInvisibleParameterAnnotations", "RuntimeVisibleParameterAnnotations" -> RuntimeParameterAnnotations.decode(buffer); case "AnnotationDefault" -> AnnotationDefault.decode(buffer); case "BootstrapMethods" -> BootstrapMethods.decode(buffer); + case "NestMembers" -> NestMembers.decode(buffer); default -> null; }; return new AttributeInfo(nameIndex, attribute); diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/NestMembers.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/NestMembers.java new file mode 100644 index 0000000..e21a9c4 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/NestMembers.java @@ -0,0 +1,33 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import java.nio.ByteBuffer; + +public class NestMembers implements SizedByteCodec { + + private final char[] classes; + + public NestMembers(char[] classes) { + this.classes = classes; + } + + public char[] getClasses() { return classes; } + + @Override + public int getSize() { + return 2 + classes.length * 2; + } + + public static NestMembers decode(ByteBuffer buffer) { + char[] classes = new char[buffer.getChar()]; + for (int i = 0; i < classes.length; i++) + classes[i] = buffer.getChar(); + return new NestMembers(classes); + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar((char) classes.length); + for (char classe : classes) + buffer.putChar(classe); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/StackMapTable.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/StackMapTable.java index 7ae384b..7b3b961 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/StackMapTable.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/StackMapTable.java @@ -26,7 +26,7 @@ public int getSize() { public static StackMapTable decode(ByteBuffer buffer) { StackMapFrame[] entries = new StackMapFrame[buffer.getChar()]; for (int i = 0; i < entries.length; ++i) { - byte frameType = buffer.get(); + char frameType = (char) (buffer.get() & 0xFF); StackMapFrame.Type type = StackMapFrame.Type.fromValue(frameType); entries[i] = switch (type) { case SAME -> new SameFrame(type); diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/AppendFrame.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/AppendFrame.java index 2a281dd..06e7a1e 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/AppendFrame.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/AppendFrame.java @@ -18,7 +18,7 @@ public AppendFrame(final Type type, final char offsetDelta, final VerificationTy public static AppendFrame decode(final Type type, ByteBuffer buffer) { char offsetDelta = buffer.getChar(); - VerificationTypeInfo[] locals = new VerificationTypeInfo[type.getValue()]; + VerificationTypeInfo[] locals = new VerificationTypeInfo[type.getValue() - 251]; for (int i = 0; i < locals.length; ++i) locals[i] = VerificationTypeInfo.decode(buffer); return new AppendFrame(type, offsetDelta, locals); diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/StackMapFrame.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/StackMapFrame.java index ec26f4c..988ee54 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/StackMapFrame.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/frames/StackMapFrame.java @@ -7,23 +7,23 @@ public abstract class StackMapFrame implements SizedByteCodec { public enum Type { - SAME((byte) 0), - SAME_LOCAL_1_STACk_ITEM((byte) 64), - SAME_LOCAL_1_STACK_ITEM_EXTENDED((byte) 247), - CHOP((byte) 248), - SAME_FRAME_EXTENDED((byte) 251), - APPEND((byte) 252), - FULL_FRAME((byte) 255); + SAME((char) 0), + SAME_LOCAL_1_STACk_ITEM((char) 64), + SAME_LOCAL_1_STACK_ITEM_EXTENDED((char) 247), + CHOP((char) 248), + SAME_FRAME_EXTENDED((char) 251), + APPEND((char) 252), + FULL_FRAME((char) 255); - private byte value; + private char value; - Type(final byte value) { + Type(final char value) { this.value = value; } - public byte getValue() { return value; } + public char getValue() { return value; } - public static Type fromValue(final byte value) { + public static Type fromValue(final char value) { Type type; if (value < 64) type = SAME; @@ -59,6 +59,6 @@ public int getSize() { @Override public void encode(ByteBuffer buffer) { - buffer.put(type.value); + buffer.put((byte) type.value); } } From 9840b8fc48ebe4526b2b0c13b631d12ce18e2fc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lise=20Valentin?= Date: Thu, 28 Nov 2024 14:28:41 +0100 Subject: [PATCH 09/11] Rename terrible file --- .../lycoris/mixins/{Boostrapper.java => Bootstrapper.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/main/java/org/momento/lycoris/mixins/{Boostrapper.java => Bootstrapper.java} (54%) diff --git a/src/main/java/org/momento/lycoris/mixins/Boostrapper.java b/src/main/java/org/momento/lycoris/mixins/Bootstrapper.java similarity index 54% rename from src/main/java/org/momento/lycoris/mixins/Boostrapper.java rename to src/main/java/org/momento/lycoris/mixins/Bootstrapper.java index 334e353..7aa8e93 100644 --- a/src/main/java/org/momento/lycoris/mixins/Boostrapper.java +++ b/src/main/java/org/momento/lycoris/mixins/Bootstrapper.java @@ -1,6 +1,6 @@ package org.momento.lycoris.mixins; -public class Boostrapper { +public class Bootstrapper { From 0904d262ebf591b475c74942294309d74af220c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lise=20Valentin?= Date: Sat, 18 Jan 2025 21:51:13 +0100 Subject: [PATCH 10/11] Add TypeAnnotations --- .../mixin/classe/structures/ConstantPool.java | 8 +- .../structures/constants/PackageInfo.java | 26 +++++ .../structures/infos/AttributeInfo.java | 8 ++ .../attributes/RuntimeTypeAnnotations.java | 36 +++++++ .../infos/attributes/TypeAnnotation.java | 101 ++++++++++++++++++ .../structures/infos/attributes/TypePath.java | 39 +++++++ .../infos/attributes/targets/CatchTarget.java | 30 ++++++ .../infos/attributes/targets/EmptyTarget.java | 20 ++++ .../attributes/targets/OffsetTarget.java | 30 ++++++ .../attributes/targets/SuperTypeTarget.java | 31 ++++++ .../attributes/targets/ThrowsTarget.java | 28 +++++ .../targets/TypeArgumentTarget.java | 34 ++++++ 12 files changed, 390 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/PackageInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeTypeAnnotations.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/TypeAnnotation.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/TypePath.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/CatchTarget.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/EmptyTarget.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/OffsetTarget.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/SuperTypeTarget.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/ThrowsTarget.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/TypeArgumentTarget.java diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/ConstantPool.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/ConstantPool.java index 263d4f5..7a96c3b 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/ConstantPool.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/ConstantPool.java @@ -22,7 +22,10 @@ public enum Tag { UTF8((byte) 1), MethodHandle((byte) 15), MethodType((byte) 16), - InvokeDynamic((byte) 18); + Dynamic((byte) 17), + InvokeDynamic((byte) 18), + Module((byte) 19), + Package((byte) 20); private final byte value; @@ -70,7 +73,10 @@ public static ConstantPool decode(ByteBuffer buffer) { case UTF8 -> UTF8Info.decode(buffer); case MethodHandle -> MethodHandleInfo.decode(buffer); case MethodType -> MethodTypeInfo.decode(buffer); + case Dynamic -> DynamicInfo.decode(buffer); case InvokeDynamic -> InvokeDynamicInfo.decode(buffer); + case Module -> ModuleInfo.decode(buffer); + case Package -> PackageInfo.decode(buffer); }; return new ConstantPool(tag, info); } diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/PackageInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/PackageInfo.java new file mode 100644 index 0000000..21e30e4 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/PackageInfo.java @@ -0,0 +1,26 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.constants; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; + +import java.nio.ByteBuffer; + +public class PackageInfo extends ConstantInfo { + + private char nameIndex; + + public PackageInfo(ConstantPool.Tag tag, char nameIndex) { + super(tag); + } + + public char getNameIndex() { return nameIndex; } + + public static PackageInfo decode(ByteBuffer buffer) { + return new PackageInfo(ConstantPool.Tag.Package, buffer.getChar()); + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar(nameIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java index dec5854..135318e 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java @@ -41,7 +41,15 @@ public static AttributeInfo decode(final ConstantPool[] constantPools, ByteBuffe case "RuntimeInvisibleParameterAnnotations", "RuntimeVisibleParameterAnnotations" -> RuntimeParameterAnnotations.decode(buffer); case "AnnotationDefault" -> AnnotationDefault.decode(buffer); case "BootstrapMethods" -> BootstrapMethods.decode(buffer); + case "RuntimeVisibleTypeAnnotations", "RuntimeInvisibleTypeAnnotations" -> RuntimeTypeAnnotations.decode(buffer); + //case "MethodParameters" + //case "Module" + //case "ModulePackages" + //case "ModuleMainClass" + //case "NestHost" case "NestMembers" -> NestMembers.decode(buffer); + //case "Record" + //case "PermittedSubclasses" default -> null; }; return new AttributeInfo(nameIndex, attribute); diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeTypeAnnotations.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeTypeAnnotations.java new file mode 100644 index 0000000..71b8407 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RuntimeTypeAnnotations.java @@ -0,0 +1,36 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import java.nio.ByteBuffer; + +public class RuntimeTypeAnnotations implements SizedByteCodec { + + private final TypeAnnotation[] typeAnnotations; + + public RuntimeTypeAnnotations(TypeAnnotation[] typeAnnotations) { + this.typeAnnotations = typeAnnotations; + } + + public TypeAnnotation[] getTypeAnnotations() { return typeAnnotations; } + + public static RuntimeTypeAnnotations decode(ByteBuffer buffer) { + TypeAnnotation[] typeAnnotations = new TypeAnnotation[buffer.getChar()]; + for (int i = 0; i < typeAnnotations.length; i++) + typeAnnotations[i] = TypeAnnotation.decode(buffer); + return new RuntimeTypeAnnotations(typeAnnotations); + } + + @Override + public int getSize() { + int baseSize = 2; + for (TypeAnnotation typeAnnotation : typeAnnotations) + baseSize += typeAnnotation.getSize(); + return baseSize; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar((char) typeAnnotations.length); + for (TypeAnnotation annotation : typeAnnotations) + annotation.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/TypeAnnotation.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/TypeAnnotation.java new file mode 100644 index 0000000..b33f492 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/TypeAnnotation.java @@ -0,0 +1,101 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.targets.*; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.targets.EmptyTarget; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.values.ElementValue; +import org.momento.lycoris.utils.Pair; + +import java.nio.ByteBuffer; + +public class TypeAnnotation implements SizedByteCodec { + + public enum Type { + GENERIC_CLASS((byte) 0x0), + GENERIC_METHOD((byte) 0x01), + SUPER_CLASS((byte) 0x10), + BOUND_GENERIC_CLASS((byte) 0x11), + BOUND_GENERIC_METHOD((byte) 0x12), + FIELD_TYPE((byte) 0x13), + RETURN_TYPE((byte) 0x14), + RECEIVER_TYPE((byte) 0x15), + PARAMETER_TYPE((byte) 0x16), + THROW_TYPE((byte) 0x17); + + + private final byte value; + + Type(byte value) { + this.value = value; + } + + public byte getValue() { return value; } + + public static Type fromValue(byte value) { + for (Type type : Type.values()) { + if (type.getValue() == value) { + return type; + } + } + return null; + } + } + + private final Type targetType; + private final EmptyTarget targetInfo; + private final TypePath targetPath; + private final char typeIndex; + private final Pair[] elementValuePairs; + + public TypeAnnotation(Type targetType, EmptyTarget targetInfo, TypePath targetPath, char typeIndex, Pair[] elementValuePairs) { + this.targetType = targetType; + this.targetInfo = targetInfo; + this.targetPath = targetPath; + this.typeIndex = typeIndex; + this.elementValuePairs = elementValuePairs; + } + + public Type getEmptyTargetType() { return targetType; } + public EmptyTarget getEmptyTargetInfo() { return targetInfo; } + public TypePath getEmptyTargetPath() { return targetPath; } + public char getTypeIndex() { return typeIndex; } + public Pair[] getElementValuePairs() { return elementValuePairs; } + + public static TypeAnnotation decode(ByteBuffer buffer) { + Type targetType = Type.fromValue(buffer.get()); + EmptyTarget target = switch (targetType) { + case GENERIC_CLASS, GENERIC_METHOD -> TypeParameterTarget.decode(buffer); + case SUPER_CLASS -> SuperTypeTarget.decode(buffer); + case BOUND_GENERIC_CLASS, BOUND_GENERIC_METHOD -> TypeParameterBoundTarget.decode(buffer); + case FIELD_TYPE, RETURN_TYPE, RECEIVER_TYPE -> EmptyTarget.decode(buffer); + case PARAMETER_TYPE -> FormalParameterTarget.decode(buffer); + case THROW_TYPE -> ThrowsTarget.decode(buffer); + }; + TypePath path = TypePath.decode(buffer); + char typeIndex = buffer.getChar(); + Pair[] elementValuePairs = new Pair[buffer.getChar()]; + for (int i = 0; i < elementValuePairs.length; i++) + elementValuePairs[i] = new Pair<>(buffer.getChar(), ElementValue.decode(buffer)); + return new TypeAnnotation(targetType, target, path, typeIndex, elementValuePairs); + } + + @Override + public int getSize() { + int baseSize = 1 + targetInfo.getSize() + targetPath.getSize() + 4; + for (Pair pair : elementValuePairs) + baseSize += 2 + pair.getSecond().getSize(); + return baseSize; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.put(targetType.value); + targetInfo.encode(buffer); + targetPath.encode(buffer); + buffer.putChar(typeIndex); + buffer.putChar((char) elementValuePairs.length); + for (Pair pair : elementValuePairs) { + buffer.putChar(pair.getFirst()); + pair.getSecond().encode(buffer); + } + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/TypePath.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/TypePath.java new file mode 100644 index 0000000..ee5c0d4 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/TypePath.java @@ -0,0 +1,39 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import org.momento.lycoris.utils.Pair; + +import java.nio.ByteBuffer; + +public class TypePath implements SizedByteCodec { + + private final Pair[] paths; + + public TypePath(Pair[] paths) { + this.paths = paths; + } + + + public Pair[] getPaths() { return paths; } + + @Override + public int getSize() { + return 1 + paths.length * 2; + } + + public static TypePath decode(ByteBuffer buffer) { + Pair[] paths = new Pair[buffer.get()]; + for (int i = 0; i < paths.length; i++) { + paths[i] = new Pair<>(buffer.get(), buffer.get()); + } + return new TypePath(paths); + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.put((byte) paths.length); + for (Pair path : paths) { + buffer.put(path.getFirst()); + buffer.put(path.getSecond()); + } + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/CatchTarget.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/CatchTarget.java new file mode 100644 index 0000000..0d23239 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/CatchTarget.java @@ -0,0 +1,30 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.targets; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; + +import java.nio.ByteBuffer; + +public class CatchTarget extends EmptyTarget { + + private final char exceptionTableIndex; + + public CatchTarget(char exceptionTableIndex) { + this.exceptionTableIndex = exceptionTableIndex; + } + + public char getExceptionTableIndex() { return exceptionTableIndex; } + + public static CatchTarget decode(ByteBuffer buffer) { + return new CatchTarget(buffer.getChar()); + } + + @Override + public int getSize() { + return 2; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(exceptionTableIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/EmptyTarget.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/EmptyTarget.java new file mode 100644 index 0000000..3d1602c --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/EmptyTarget.java @@ -0,0 +1,20 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.targets; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; + +import java.nio.ByteBuffer; + +public class EmptyTarget implements SizedByteCodec { + + @Override + public int getSize() { + return 0; + } + + public static EmptyTarget decode(ByteBuffer buffer) { + return new EmptyTarget(); + } + + @Override + public void encode(ByteBuffer buffer) {} +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/OffsetTarget.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/OffsetTarget.java new file mode 100644 index 0000000..902b2f4 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/OffsetTarget.java @@ -0,0 +1,30 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.targets; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; + +import java.nio.ByteBuffer; + +public class OffsetTarget extends EmptyTarget { + + private final char offset; + + public OffsetTarget(char offset) { + this.offset = offset; + } + + public char getOffset() { return offset; } + + public static OffsetTarget decode(ByteBuffer buffer) { + return new OffsetTarget(buffer.getChar()); + } + + @Override + public int getSize() { + return 2; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(offset); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/SuperTypeTarget.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/SuperTypeTarget.java new file mode 100644 index 0000000..7dba896 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/SuperTypeTarget.java @@ -0,0 +1,31 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.targets; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; + +import java.nio.ByteBuffer; + +public class SuperTypeTarget extends EmptyTarget { + + private final char superTypeIndex; + + + public SuperTypeTarget(char superTypeIndex) { + this.superTypeIndex = superTypeIndex; + } + + public char getSuperTypeIndex() { return superTypeIndex; } + + public static SuperTypeTarget decode(ByteBuffer buffer) { + return new SuperTypeTarget(buffer.getChar()); + } + + @Override + public int getSize() { + return 1; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(superTypeIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/ThrowsTarget.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/ThrowsTarget.java new file mode 100644 index 0000000..88f5e75 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/ThrowsTarget.java @@ -0,0 +1,28 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.targets; + +import java.nio.ByteBuffer; + +public class ThrowsTarget extends EmptyTarget { + + private final char throwsTypeIndex; + + public ThrowsTarget(char throwsTypeIndex) { + this.throwsTypeIndex = throwsTypeIndex; + } + + public char getThrowsTypeIndex() { return throwsTypeIndex; } + + public static ThrowsTarget decode(ByteBuffer buffer) { + return new ThrowsTarget(buffer.getChar()); + } + + @Override + public int getSize() { + return 2; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(throwsTypeIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/TypeArgumentTarget.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/TypeArgumentTarget.java new file mode 100644 index 0000000..1cb8d52 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/TypeArgumentTarget.java @@ -0,0 +1,34 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.targets; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; + +import java.nio.ByteBuffer; + +public class TypeArgumentTarget extends EmptyTarget { + + private final char offset; + private final byte typeArgumentIndex; + + public TypeArgumentTarget(char offset, byte typeArgumentIndex) { + this.offset = offset; + this.typeArgumentIndex = typeArgumentIndex; + } + + public char getOffset() { return offset; } + public byte getTypeArgumentIndex() { return typeArgumentIndex; } + + public static TypeArgumentTarget decode(ByteBuffer buffer) { + return new TypeArgumentTarget(buffer.getChar(), buffer.get()); + } + + @Override + public int getSize() { + return 3; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(offset); + buffer.put(typeArgumentIndex); + } +} From 9962bef3d0bedf1a7ab562fb55dbc7c89778ce8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lise=20Valentin?= Date: Sat, 18 Jan 2025 23:16:29 +0100 Subject: [PATCH 11/11] Add missing attributes --- .../structures/constants/DynamicInfo.java | 31 +++++ .../structures/constants/ModuleInfo.java | 26 ++++ .../structures/infos/AttributeInfo.java | 16 +-- .../infos/attributes/MethodParameters.java | 39 ++++++ .../structures/infos/attributes/Module.java | 111 ++++++++++++++++++ .../infos/attributes/ModuleMainClass.java | 30 +++++ .../infos/attributes/ModulePackages.java | 31 +++++ .../structures/infos/attributes/NestHost.java | 28 +++++ .../infos/attributes/PermittedSubclasses.java | 35 ++++++ .../structures/infos/attributes/Record.java | 40 +++++++ .../infos/attributes/RecordComponentInfo.java | 48 ++++++++ .../infos/attributes/counts/ExportsCount.java | 46 ++++++++ .../infos/attributes/counts/OpensCount.java | 46 ++++++++ .../attributes/counts/ProvidesCount.java | 40 +++++++ .../attributes/counts/RequiresCount.java | 38 ++++++ .../targets/FormalParameterTarget.java | 30 +++++ .../attributes/targets/LocalVarTarget.java | 74 ++++++++++++ .../targets/TypeParameterBoundTarget.java | 36 ++++++ .../targets/TypeParameterTarget.java | 31 +++++ 19 files changed, 769 insertions(+), 7 deletions(-) create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/DynamicInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/ModuleInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/MethodParameters.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Module.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/ModuleMainClass.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/ModulePackages.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/NestHost.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/PermittedSubclasses.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Record.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RecordComponentInfo.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/counts/ExportsCount.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/counts/OpensCount.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/counts/ProvidesCount.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/counts/RequiresCount.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/FormalParameterTarget.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/LocalVarTarget.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/TypeParameterBoundTarget.java create mode 100644 src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/TypeParameterTarget.java diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/DynamicInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/DynamicInfo.java new file mode 100644 index 0000000..72a5c09 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/DynamicInfo.java @@ -0,0 +1,31 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.constants; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; + +import java.nio.ByteBuffer; + +public class DynamicInfo extends ConstantInfo { + + private final char bootstrapMethodAttrIndex; + private final char nameTypeIndex; + + public DynamicInfo(final ConstantPool.Tag tag, final char bootstrapMethodAttrIndex, final char nameTypeIndex) { + super(tag); + this.bootstrapMethodAttrIndex = bootstrapMethodAttrIndex; + this.nameTypeIndex = nameTypeIndex; + } + + public char getBootstrapMethodAttrIndex() { return bootstrapMethodAttrIndex; } + public char getNameTypeIndex() { return nameTypeIndex; } + + public static DynamicInfo decode(ByteBuffer buffer) { + return new DynamicInfo(ConstantPool.Tag.Dynamic, buffer.getChar(), buffer.getChar()); + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar(bootstrapMethodAttrIndex); + buffer.putChar(nameTypeIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/ModuleInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/ModuleInfo.java new file mode 100644 index 0000000..b34818f --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/constants/ModuleInfo.java @@ -0,0 +1,26 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.constants; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; + +import java.nio.ByteBuffer; + +public class ModuleInfo extends ConstantInfo { + + private char nameIndex; + + public ModuleInfo(ConstantPool.Tag tag, char nameIndex) { + super(tag); + } + + public char getNameIndex() { return nameIndex; } + + public static ModuleInfo decode(ByteBuffer buffer) { + return new ModuleInfo(ConstantPool.Tag.Module, buffer.getChar()); + } + + @Override + public void encode(ByteBuffer buffer) { + super.encode(buffer); + buffer.putChar(nameIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java index 135318e..2ffd69a 100644 --- a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/AttributeInfo.java @@ -5,6 +5,8 @@ import org.momento.lycoris.mixins.mixin.classe.structures.constants.ConstantInfo; import org.momento.lycoris.mixins.mixin.classe.structures.constants.UTF8Info; import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.*; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.Module; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.Record; import java.nio.ByteBuffer; @@ -42,14 +44,14 @@ public static AttributeInfo decode(final ConstantPool[] constantPools, ByteBuffe case "AnnotationDefault" -> AnnotationDefault.decode(buffer); case "BootstrapMethods" -> BootstrapMethods.decode(buffer); case "RuntimeVisibleTypeAnnotations", "RuntimeInvisibleTypeAnnotations" -> RuntimeTypeAnnotations.decode(buffer); - //case "MethodParameters" - //case "Module" - //case "ModulePackages" - //case "ModuleMainClass" - //case "NestHost" + case "MethodParameters" -> MethodParameters.decode(buffer); + case "Module" -> Module.decode(buffer); + case "ModulePackages" -> ModulePackages.decode(buffer); + case "ModuleMainClass" -> ModuleMainClass.decode(buffer); + case "NestHost" -> NestHost.decode(buffer); case "NestMembers" -> NestMembers.decode(buffer); - //case "Record" - //case "PermittedSubclasses" + case "Record" -> Record.decode(constantPools, buffer); + case "PermittedSubclasses" -> PermittedSubclasses.decode(buffer); default -> null; }; return new AttributeInfo(nameIndex, attribute); diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/MethodParameters.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/MethodParameters.java new file mode 100644 index 0000000..c59d784 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/MethodParameters.java @@ -0,0 +1,39 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.AttributeInfo; +import org.momento.lycoris.utils.Pair; + +import java.nio.ByteBuffer; + +public class MethodParameters implements SizedByteCodec { + + private final Pair[] parameters; + + public MethodParameters(Pair[] parameters) { + this.parameters = parameters; + } + + public Pair[] getParameters() { return parameters; } + + public static MethodParameters decode(ByteBuffer buffer) { + Pair[] parameters = new Pair[buffer.get()]; + for (int i = 0; i < parameters.length; i++) { + parameters[i] = new Pair<>(buffer.getChar(), buffer.getChar()); + } + return new MethodParameters(parameters); + } + + @Override + public int getSize() { + return 1 + parameters.length * 4; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.put((byte) parameters.length); + for (Pair parameter : parameters) { + buffer.putChar(parameter.getFirst()); + buffer.putChar(parameter.getSecond()); + } + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Module.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Module.java new file mode 100644 index 0000000..2b2b439 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Module.java @@ -0,0 +1,111 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.counts.ExportsCount; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.counts.OpensCount; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.counts.ProvidesCount; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.counts.RequiresCount; + +import java.nio.ByteBuffer; + +public class Module implements SizedByteCodec { + + public enum Flag { + ACC_OPEN((char ) 0x20), + ACC_SYNTHETIC((char) 0x1000), + ACC_MANDATED((char) 0x8000); + + private final char value; + + Flag(char value) { + this.value = value; + } + + public char getValue() { + return value; + } + + public static Flag fromValue(char value) { + for (Flag flag : Flag.values()) { + if (flag.getValue() == value) { + return flag; + } + } + return null; + } + } + + private char moduleNameIndex; + private Flag moduleFlags; + private char moduleVersionIndex; + private RequiresCount[] requires; + private ExportsCount[] exports; + private OpensCount[] opens; + private char[] usesIndex; + private ProvidesCount[] provides; + + public Module(char moduleNameIndex, Flag moduleFlags, char moduleVersionIndex, RequiresCount[] requires, ExportsCount[] exports, OpensCount[] opens, char[] usesIndex, ProvidesCount[] provides) { + this.moduleNameIndex = moduleNameIndex; + this.moduleFlags = moduleFlags; + this.moduleVersionIndex = moduleVersionIndex; + this.requires = requires; + this.exports = exports; + this.opens = opens; + this.usesIndex = usesIndex; + this.provides = provides; + } + + public static Module decode(ByteBuffer buffer) { + char moduleNameIndex = buffer.getChar(); + Flag moduleFlags = Flag.fromValue(buffer.getChar()); + char moduleVersionIndex = buffer.getChar(); + RequiresCount[] requires = new RequiresCount[buffer.getChar()]; + for (int i = 0; i < requires.length; i++) + requires[i] = RequiresCount.decode(buffer); + ExportsCount[] exports = new ExportsCount[buffer.getChar()]; + for (int i = 0; i < exports.length; i++) + exports[i] = ExportsCount.decode(buffer); + OpensCount[] opens = new OpensCount[buffer.getChar()]; + for (int i = 0; i < opens.length; i++) + opens[i] = OpensCount.decode(buffer); + char[] usesIndex = new char[buffer.getChar()]; + for (int i = 0; i < usesIndex.length; i++) + usesIndex[i] = buffer.getChar(); + ProvidesCount[] provides = new ProvidesCount[buffer.getChar()]; + for (int i = 0; i < provides.length; i++) + provides[i] = ProvidesCount.decode(buffer); + return new Module(moduleNameIndex, moduleFlags, moduleVersionIndex, requires, exports, opens,usesIndex, provides); + } + + @Override + public int getSize() { + int baseSize = 16; + for (RequiresCount requiresCount : requires) + baseSize += requiresCount.getSize(); + for (ExportsCount exportsCount : exports) + baseSize += exportsCount.getSize(); + for (OpensCount opensCount : opens) + baseSize += opensCount.getSize(); + baseSize += usesIndex.length * 2; + for (ProvidesCount providesCount : provides) + baseSize += providesCount.getSize(); + return baseSize; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(moduleNameIndex); + buffer.putChar(moduleFlags.getValue()); + buffer.putChar(moduleVersionIndex); + buffer.putChar((char) requires.length); + for (RequiresCount requiresCount : requires) + requiresCount.encode(buffer); + buffer.putChar((char) exports.length); + for (ExportsCount exportsCount : exports) + exportsCount.encode(buffer); + buffer.putChar((char) usesIndex.length); + for (int i = 0; i < usesIndex.length; i++) + buffer.putChar(usesIndex[i]); + for (ProvidesCount providesCount : provides) + providesCount.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/ModuleMainClass.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/ModuleMainClass.java new file mode 100644 index 0000000..56ec970 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/ModuleMainClass.java @@ -0,0 +1,30 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import java.nio.ByteBuffer; + +public class ModuleMainClass implements SizedByteCodec { + + private char mainClassIndex; + + public ModuleMainClass(char mainClassIndex) { + this.mainClassIndex = mainClassIndex; + } + + private char getMainClassIndex() { + return mainClassIndex; + } + + public static ModuleMainClass decode(ByteBuffer buffer) { + return new ModuleMainClass(buffer.getChar()); + } + + @Override + public int getSize() { + return 2; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(mainClassIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/ModulePackages.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/ModulePackages.java new file mode 100644 index 0000000..f51cee0 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/ModulePackages.java @@ -0,0 +1,31 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import java.nio.ByteBuffer; + +public class ModulePackages implements SizedByteCodec { + + private char[] packageIndex; + + public ModulePackages(char[] packageIndex) { + this.packageIndex = packageIndex; + } + + public char[] getPackageIndex() { return packageIndex; } + + public static ModulePackages decode(ByteBuffer buffer) { + char[] packageIndex = new char[buffer.getChar()]; + return new ModulePackages(packageIndex); + } + + @Override + public int getSize() { + return 2 + 2 * packageIndex.length; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar((char) packageIndex.length); + for (int i = 0; i < packageIndex.length; i++) + buffer.putChar(packageIndex[i]); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/NestHost.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/NestHost.java new file mode 100644 index 0000000..23c51d0 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/NestHost.java @@ -0,0 +1,28 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import java.nio.ByteBuffer; + +public class NestHost implements SizedByteCodec { + + private char hostClassIndex; + + public NestHost(char hostClassIndex) { + this.hostClassIndex = hostClassIndex; + } + + public char getHostClassIndex() { return hostClassIndex; } + + public static NestHost decode(ByteBuffer buffer) { + return new NestHost(buffer.getChar()); + } + + @Override + public int getSize() { + return 2; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(hostClassIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/PermittedSubclasses.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/PermittedSubclasses.java new file mode 100644 index 0000000..b22581f --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/PermittedSubclasses.java @@ -0,0 +1,35 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import org.momento.lycoris.mixins.mixin.Mixin; + +import java.nio.ByteBuffer; + +public class PermittedSubclasses implements SizedByteCodec { + + private char[] classes; + + public PermittedSubclasses(char[] classes) { + this.classes = classes; + } + + public char[] getClasses() { return classes; } + + public static PermittedSubclasses decode(ByteBuffer buffer) { + char[] classes = new char[buffer.getChar()]; + for (int i = 0; i < classes.length; i++) + classes[i] = buffer.getChar(); + return new PermittedSubclasses(classes); + } + + @Override + public int getSize() { + return 2 + 2 * classes.length; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar((char) classes.length); + for (int i = 0; i < classes.length; i++) + buffer.putChar(classes[i]); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Record.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Record.java new file mode 100644 index 0000000..306ba69 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/Record.java @@ -0,0 +1,40 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; + +import java.nio.ByteBuffer; + +public class Record implements SizedByteCodec { + + private RecordComponentInfo[] components; + + public Record(RecordComponentInfo[] components) { + this.components = components; + } + + public RecordComponentInfo[] getComponents() { + return components; + } + + public static Record decode(ConstantPool[] constantPools, ByteBuffer buffer) { + RecordComponentInfo[] components = new RecordComponentInfo[buffer.getChar()]; + for (int i = 0; i < components.length; i++) + components[i] = RecordComponentInfo.decode(constantPools, buffer); + return new Record(components); + } + + @Override + public int getSize() { + int baseSize = 2; + for (RecordComponentInfo component : components) + baseSize += component.getSize(); + return baseSize; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar((char) components.length); + for (RecordComponentInfo component : components) + component.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RecordComponentInfo.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RecordComponentInfo.java new file mode 100644 index 0000000..0c365be --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/RecordComponentInfo.java @@ -0,0 +1,48 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes; + +import org.momento.lycoris.mixins.mixin.classe.structures.ConstantPool; +import org.momento.lycoris.mixins.mixin.classe.structures.infos.AttributeInfo; + +import java.nio.ByteBuffer; + +public class RecordComponentInfo implements SizedByteCodec { + + private char nameIndex; + private char descriptorIndex; + private AttributeInfo[] attributes; + + public RecordComponentInfo(char nameIndex, char descriptorIndex, AttributeInfo[] attributes) { + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + this.attributes = attributes; + } + + public char getNameIndex() { return nameIndex; } + public char getDescriptorIndex() { return descriptorIndex; } + public AttributeInfo[] getAttributes() { return attributes; } + + public static RecordComponentInfo decode(final ConstantPool[] constantPools, ByteBuffer buffer) { + char nameIndex = buffer.getChar(); + char descriptorIndex = buffer.getChar(); + AttributeInfo[] attributes = new AttributeInfo[buffer.getChar()]; + for (int i = 0; i < attributes.length; i++) + attributes[i] = AttributeInfo.decode(constantPools, buffer); + return new RecordComponentInfo(nameIndex, descriptorIndex, attributes); + } + + @Override + public int getSize() { + int baseSize = 6; + for (AttributeInfo attribute : attributes) + baseSize += attribute.getSize(); + return baseSize; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(nameIndex); + buffer.putChar(descriptorIndex); + for (AttributeInfo attribute : attributes) + attribute.encode(buffer); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/counts/ExportsCount.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/counts/ExportsCount.java new file mode 100644 index 0000000..26a6f9b --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/counts/ExportsCount.java @@ -0,0 +1,46 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.counts; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; + +import java.nio.ByteBuffer; + +public class ExportsCount implements SizedByteCodec { + + private final char exportsIndex; + private final char exportsFlags; + private final char[] exportsToIndex; + + public ExportsCount(char exportsIndex, char exportsFlags, char[] exportsToIndex) { + this.exportsIndex = exportsIndex; + this.exportsFlags = exportsFlags; + this.exportsToIndex = exportsToIndex; + } + + public char getExportsIndex() { return exportsIndex; } + public char getExportsFlags() { return exportsFlags; } + public char[] getExportsToIndex() { return exportsToIndex; } + + public static ExportsCount decode(ByteBuffer buffer) { + char exportsIndex = buffer.getChar(); + char exportsFlags = buffer.getChar(); + char[] exportsToIndex = new char[buffer.getChar()]; + for (int i = 0; i < exportsToIndex.length; i++) + exportsToIndex[i] = buffer.getChar(); + return new ExportsCount(exportsIndex, exportsFlags, exportsToIndex); + } + + @Override + public int getSize() { + return 6 + 2 * exportsToIndex.length; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(exportsIndex); + buffer.putChar(exportsFlags); + buffer.putChar(exportsIndex); + buffer.putChar((char) exportsToIndex.length); + for (int i = 0; i < exportsToIndex.length; i++) + buffer.putChar(exportsToIndex[i]); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/counts/OpensCount.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/counts/OpensCount.java new file mode 100644 index 0000000..c3e29ed --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/counts/OpensCount.java @@ -0,0 +1,46 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.counts; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; + +import java.nio.ByteBuffer; + +public class OpensCount implements SizedByteCodec { + + private final char opensIndex; + private final char opensFlags; + private final char[] opensToIndex; + + public OpensCount(char opensIndex, char opensFlags, char[] opensToIndex) { + this.opensIndex = opensIndex; + this.opensFlags = opensFlags; + this.opensToIndex = opensToIndex; + } + + public char getIndex() { return opensIndex; } + public char getExportsFlags() { return opensFlags; } + public char[] getExportsToIndex() { return opensToIndex; } + + public static OpensCount decode(ByteBuffer buffer) { + char opensIndex = buffer.getChar(); + char opensFlags = buffer.getChar(); + char[] opensToIndex = new char[buffer.getChar()]; + for (int i = 0; i < opensToIndex.length; i++) + opensToIndex[i] = buffer.getChar(); + return new OpensCount(opensIndex, opensFlags, opensToIndex); + } + + @Override + public int getSize() { + return 6 + 2 * opensToIndex.length; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(opensIndex); + buffer.putChar(opensFlags); + buffer.putChar(opensIndex); + buffer.putChar((char) opensToIndex.length); + for (int i = 0; i < opensToIndex.length; i++) + buffer.putChar(opensToIndex[i]); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/counts/ProvidesCount.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/counts/ProvidesCount.java new file mode 100644 index 0000000..e3e9a43 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/counts/ProvidesCount.java @@ -0,0 +1,40 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.counts; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; + +import java.nio.ByteBuffer; + +public class ProvidesCount implements SizedByteCodec { + + private char providesIndex; + private char[] providesWithIndex; + + public ProvidesCount(char providesIndex, char[] providesWithIndex) { + this.providesIndex = providesIndex; + this.providesWithIndex = providesWithIndex; + } + + public char getProvidesIndex() { return providesIndex; } + public char[] getProvidesWithIndex() { return providesWithIndex; } + + public static ProvidesCount decode(ByteBuffer buffer) { + char providesIndex = buffer.getChar(); + char[] providesWithIndex = new char[buffer.getChar()]; + for (int i = 0; i < providesWithIndex.length; i++) + providesWithIndex[i] = buffer.getChar(); + return new ProvidesCount(providesIndex, providesWithIndex); + } + + @Override + public int getSize() { + return 4 + 2 * providesWithIndex.length; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(providesIndex); + buffer.putChar((char) providesWithIndex.length); + for (int i = 0; i < providesWithIndex.length; i++) + buffer.putChar(providesWithIndex[i]); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/counts/RequiresCount.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/counts/RequiresCount.java new file mode 100644 index 0000000..b39d852 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/counts/RequiresCount.java @@ -0,0 +1,38 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.counts; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; + +import java.nio.ByteBuffer; + +public class RequiresCount implements SizedByteCodec { + + private final char requiresIndex; + private final char requiresFlags; + private final char requiresVersionIndex; + + public RequiresCount(char requiresIndex, char requiresFlags, char requiresVersionIndex) { + this.requiresIndex = requiresIndex; + this.requiresFlags = requiresFlags; + this.requiresVersionIndex = requiresVersionIndex; + } + + public char getRequiresIndex() { return requiresIndex; } + public char getRequiresFlags() { return requiresFlags; } + public char getRequiresVersionIndex() { return requiresVersionIndex; } + + @Override + public int getSize() { + return 6; + } + + public static RequiresCount decode(ByteBuffer buffer) { + return new RequiresCount(buffer.getChar(), buffer.getChar(), buffer.getChar()); + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(requiresIndex); + buffer.putChar(requiresFlags); + buffer.putChar(requiresVersionIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/FormalParameterTarget.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/FormalParameterTarget.java new file mode 100644 index 0000000..d14e340 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/FormalParameterTarget.java @@ -0,0 +1,30 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.targets; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; + +import java.nio.ByteBuffer; + +public class FormalParameterTarget extends EmptyTarget { + + private byte formalParameterIndex; + + public FormalParameterTarget(byte formalParameterIndex) { + this.formalParameterIndex = formalParameterIndex; + } + + public byte getFormalParameterIndex() { return formalParameterIndex; } + + public static FormalParameterTarget decode(ByteBuffer buffer) { + return new FormalParameterTarget(buffer.get()); + } + + @Override + public int getSize() { + return 1; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.put(formalParameterIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/LocalVarTarget.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/LocalVarTarget.java new file mode 100644 index 0000000..75cd6d2 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/LocalVarTarget.java @@ -0,0 +1,74 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.targets; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; + +import java.nio.ByteBuffer; + +public class LocalVarTarget extends EmptyTarget { + + public static class Table implements SizedByteCodec { + + private final char startPC; + private final char length; + private final char index; + + public Table(char startPC, char length, char index) { + this.startPC = startPC; + this.length = length; + this.index = index; + } + + public char getStartPC() { return startPC; } + public char getLength() { return length; } + public char getIndex() { return index; } + + public static Table decode(ByteBuffer buffer) { + return new Table(buffer.getChar(), buffer.getChar(), buffer.getChar()); + } + + @Override + public int getSize() { + return 6; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar(startPC); + buffer.putChar(length); + buffer.putChar(index); + } + } + + private final Table[] tables; + + public LocalVarTarget(Table[] tables) { + this.tables = tables; + } + + public Table[] getTables() { return tables; } + + public static LocalVarTarget decode(ByteBuffer buffer) { + Table[] tables = new Table[buffer.getChar()]; + for (int i = 0; i < tables.length; i++) { + tables[i] = Table.decode(buffer); + } + return new LocalVarTarget(tables); + } + + @Override + public int getSize() { + int baseSize = 2; + for (Table table : tables) + baseSize += table.getSize(); + return baseSize; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.putChar((char) tables.length); + for (Table table : tables) + table.encode(buffer); + } + + +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/TypeParameterBoundTarget.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/TypeParameterBoundTarget.java new file mode 100644 index 0000000..92da69b --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/TypeParameterBoundTarget.java @@ -0,0 +1,36 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.targets; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; + +import java.lang.annotation.Target; +import java.nio.ByteBuffer; + +public class TypeParameterBoundTarget extends EmptyTarget { + + private final byte typeParameterIndex; + private final byte boundIndex; + + + public TypeParameterBoundTarget(byte typeParameterIndex, byte boundIndex) { + this.typeParameterIndex = typeParameterIndex; + this.boundIndex = boundIndex; + } + + public byte getTypeParameterIndex() { return typeParameterIndex; } + public byte getBoundIndex() { return boundIndex; } + + public static TypeParameterBoundTarget decode(ByteBuffer buffer) { + return new TypeParameterBoundTarget(buffer.get(), buffer.get()); + } + + @Override + public int getSize() { + return 1; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.put(typeParameterIndex); + buffer.put(boundIndex); + } +} diff --git a/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/TypeParameterTarget.java b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/TypeParameterTarget.java new file mode 100644 index 0000000..4759f41 --- /dev/null +++ b/src/main/java/org/momento/lycoris/mixins/mixin/classe/structures/infos/attributes/targets/TypeParameterTarget.java @@ -0,0 +1,31 @@ +package org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.targets; + +import org.momento.lycoris.mixins.mixin.classe.structures.infos.attributes.SizedByteCodec; + +import java.nio.ByteBuffer; + +public class TypeParameterTarget extends EmptyTarget { + + private final byte typeParameterIndex; + + + public TypeParameterTarget(byte typeParameterIndex) { + this.typeParameterIndex = typeParameterIndex; + } + + public byte getTypeParameterIndex() { return typeParameterIndex; } + + public static TypeParameterTarget decode(ByteBuffer buffer) { + return new TypeParameterTarget(buffer.get()); + } + + @Override + public int getSize() { + return 1; + } + + @Override + public void encode(ByteBuffer buffer) { + buffer.put(typeParameterIndex); + } +}