Asm mixins that "work"
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor;
|
||||
|
||||
public class MethodGarbageValue
|
||||
{
|
||||
|
||||
private final String type;
|
||||
private final int value;
|
||||
|
||||
public MethodGarbageValue(int value)
|
||||
{
|
||||
if(value <= Byte.MAX_VALUE && value >= Byte.MIN_VALUE)
|
||||
{
|
||||
type = "B";
|
||||
}
|
||||
else if(value <= Short.MAX_VALUE && value >= Short.MIN_VALUE)
|
||||
{
|
||||
type = "S";
|
||||
}
|
||||
else
|
||||
{
|
||||
type = "I";
|
||||
}
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "MethodGarbageValue[type="+getType()+",value="+getValue()+"]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor;
|
||||
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.common.reflect.ClassPath;
|
||||
import io.sigpipe.jbsdiff.Patch;
|
||||
import javassist.ClassPool;
|
||||
import javassist.CtClass;
|
||||
import javassist.LoaderClassPath;
|
||||
import org.objectweb.asm.AnnotationVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.FieldVisitor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import us.runelitepl.mixinprocessor.generators.AnnotationProcessor;
|
||||
import us.runelitepl.mixinprocessor.generators.PatchGenerator;
|
||||
import us.runelitepl.mixinprocessor.generators.StaticGenerator;
|
||||
import us.runelitepl.mixinprocessor.generators.StaticStageTwoGenerator;
|
||||
import us.runelitepl.mixinprocessor.parsers.GamepackDownloader;
|
||||
import us.runelitepl.mixinprocessor.parsers.HooksParser;
|
||||
import us.runelitepl.mixinprocessor.transformers.AsmMethodGarbageTransformer;
|
||||
import us.runelitepl.mixinprocessor.transformers.AsmMethodSignatureTransformer;
|
||||
import us.runelitepl.mixinprocessor.util.JavassistUtils;
|
||||
import us.runelitepl.mixinprocessor.util.RefUtils;
|
||||
import org.apache.maven.plugin.AbstractMojo;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||
import org.apache.maven.plugins.annotations.Mojo;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Goal which touches a timestamp file.
|
||||
*/
|
||||
@Mojo(name = "process-mixins", defaultPhase = LifecyclePhase.PROCESS_CLASSES, requiresDependencyResolution =
|
||||
ResolutionScope.COMPILE)
|
||||
public class MixinProcessorMojo
|
||||
extends AbstractMojo implements Opcodes
|
||||
{
|
||||
private static final String PATCHES_PACKAGE = "us.runelitepl.mixins";
|
||||
/**
|
||||
* Location of the file.
|
||||
*/
|
||||
@Parameter(defaultValue = "${project.build.directory}", property = "outputDir", required = true)
|
||||
private File outputDirectory;
|
||||
|
||||
@Parameter(defaultValue = "${project}", required = true, readonly = true)
|
||||
private MavenProject project;
|
||||
|
||||
@Parameter(property = "process-mixins.hooks", defaultValue = "hooks.json", required = true)
|
||||
private String hooks;
|
||||
|
||||
@Parameter(property = "process-mixins.ops", defaultValue = "gamepack.deob.jar.op.json", required = true)
|
||||
private String ops;
|
||||
|
||||
private static MixinProcessorMojo INST;
|
||||
|
||||
public static ClassPool classPool;
|
||||
|
||||
public static HashMap<String, Long> fieldDecoders = new HashMap<>();
|
||||
|
||||
public static HashMap<String, String> classNames = new HashMap<>();
|
||||
public static HashMap<String, String> methodNames = new HashMap<>();
|
||||
public static HashMap<String, String> fieldNames = new HashMap<>();
|
||||
|
||||
public static HashMap<String, Boolean> isFieldTagged = new HashMap<>();
|
||||
public static HashMap<String, Boolean> isMethodTagged = new HashMap<>();
|
||||
|
||||
public static HashMap<String, MethodGarbageValue> methodGarbageValues = new HashMap<>();
|
||||
|
||||
public static HashMap<String, byte[]> gamepack = new HashMap<>();
|
||||
|
||||
public static final int BUFFER_SIZE = 1024 * 1024 * 4;
|
||||
|
||||
public void execute()
|
||||
throws MojoExecutionException
|
||||
{
|
||||
INST = this;
|
||||
try
|
||||
{
|
||||
List runtimeClasspathElements = project.getRuntimeClasspathElements();
|
||||
URL[] runtimeUrls = new URL[runtimeClasspathElements.size()];
|
||||
for (int i = 0; i < runtimeClasspathElements.size(); i++)
|
||||
{
|
||||
String element = (String) runtimeClasspathElements.get(i);
|
||||
runtimeUrls[i] = new File(element).toURI().toURL();
|
||||
}
|
||||
URLClassLoader classLoader = new URLClassLoader(runtimeUrls,
|
||||
Thread.currentThread().getContextClassLoader());
|
||||
|
||||
File outputFolder = new File(project.getBuild().getOutputDirectory());
|
||||
File projectDir = new File(System.getProperty("user.dir"));
|
||||
|
||||
File hooksFile = new File(projectDir, hooks);
|
||||
File opsFile = new File(projectDir, ops);
|
||||
|
||||
outputFolder.mkdirs();
|
||||
|
||||
GamepackDownloader.downloadGamepack(gamepack);
|
||||
|
||||
ByteArrayOutputStream patchOutputStream = new ByteArrayOutputStream(BUFFER_SIZE); // 4mb
|
||||
|
||||
HooksParser.run(hooksFile, opsFile);
|
||||
|
||||
classPool = new ClassPool();
|
||||
|
||||
classPool.appendClassPath((new LoaderClassPath(classLoader)));
|
||||
|
||||
for (Map.Entry<String, byte[]> entry : gamepack.entrySet())
|
||||
{
|
||||
byte[] b1_;
|
||||
try (InputStream is = getClass().getResourceAsStream("/patch/" + entry.getKey() + ".class.bs"))
|
||||
{
|
||||
if (is == null)
|
||||
{
|
||||
stderr("IS null for %s", entry.getKey());
|
||||
continue;
|
||||
}
|
||||
|
||||
b1_ = ByteStreams.toByteArray(is);
|
||||
}
|
||||
patchOutputStream.reset();
|
||||
Patch.patch(entry.getValue(), b1_, patchOutputStream);
|
||||
entry.setValue(patchOutputStream.toByteArray());
|
||||
|
||||
classPool.makeClass(new ByteArrayInputStream(entry.getValue()));
|
||||
}
|
||||
|
||||
|
||||
HashMap<String, byte[]> finalClasses = new HashMap<>();
|
||||
|
||||
ImmutableSet<ClassPath.ClassInfo> classes =
|
||||
ClassPath.from(classLoader).getTopLevelClassesRecursive(PATCHES_PACKAGE);
|
||||
|
||||
for (ClassPath.ClassInfo clazz : classes)
|
||||
{
|
||||
|
||||
stderr("");
|
||||
stderr("Annotations: %s", clazz.getSimpleName());
|
||||
|
||||
CtClass ctClass = classPool.get(clazz.getName());
|
||||
|
||||
String className = ctClass.getSimpleName();
|
||||
className = RefUtils.getObbedClassName(className);
|
||||
|
||||
byte[] finalCode = JavassistUtils.getClassBytecode(ctClass);
|
||||
|
||||
finalCode = new AnnotationProcessor(className, finalCode).run();
|
||||
|
||||
finalClasses.put(className, finalCode);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, byte[]> entry : finalClasses.entrySet())
|
||||
{
|
||||
String className = entry.getKey();
|
||||
byte[] finalCode = entry.getValue();
|
||||
|
||||
stderr("");
|
||||
stderr("Pass 1: %s", className);
|
||||
finalCode = new AsmMethodSignatureTransformer(className, finalCode).transform();
|
||||
finalCode = new AsmMethodGarbageTransformer(className, finalCode, finalClasses).transform();
|
||||
finalClasses.put(className, finalCode);
|
||||
}
|
||||
|
||||
stderr("");
|
||||
stderr("Pass Statics");
|
||||
|
||||
new StaticGenerator().run(finalClasses.get(RefUtils.STATICS_STRING));
|
||||
|
||||
new StaticStageTwoGenerator(finalClasses).run();
|
||||
|
||||
for (Map.Entry<String, byte[]> entry : finalClasses.entrySet())
|
||||
{
|
||||
String className = entry.getKey();
|
||||
if (className == null)
|
||||
{
|
||||
stderr("Class name null? %s", entry.getValue().length);
|
||||
continue;
|
||||
}
|
||||
if (className.endsWith(RefUtils.STATICS_STRING))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
stderr("");
|
||||
stderr("Pass 2: %s", className);
|
||||
|
||||
byte[] finalCode = entry.getValue();
|
||||
finalCode = new PatchGenerator(className, finalCode).run();
|
||||
|
||||
|
||||
entry.setValue(finalCode);
|
||||
}
|
||||
|
||||
deleteDir(new File(outputFolder, "us/runelitepl/mixins"));
|
||||
|
||||
outputFolder = new File(outputFolder, "extended-mixins");
|
||||
outputFolder.mkdirs();
|
||||
|
||||
for (Map.Entry<String, byte[]> entry : finalClasses.entrySet())
|
||||
{
|
||||
if (entry.getKey().contains(RefUtils.STATICS_STRING))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Files.write(new File(outputFolder, entry.getKey() + ".class").toPath(),
|
||||
entry.getValue());
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
throw new MojoExecutionException(ex.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void stderr(String s, Object... format)
|
||||
{
|
||||
getLog().info(String.format(s, format));
|
||||
}
|
||||
|
||||
public static void log(String s, Object... format)
|
||||
{
|
||||
INST.stderr(s, format);
|
||||
}
|
||||
|
||||
static void deleteDir(File file) throws IOException
|
||||
{
|
||||
if (!file.exists())
|
||||
{
|
||||
return;
|
||||
}
|
||||
Files.walk(file.toPath())
|
||||
.sorted(Comparator.reverseOrder())
|
||||
.map(Path::toFile)
|
||||
.forEach(File::delete);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Append
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Inject
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Overwrite
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Prepend
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Provided
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Reobfuscate
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.enums;
|
||||
|
||||
public enum InjectionType
|
||||
{
|
||||
INJECT,
|
||||
APPEND,
|
||||
OVERWRITE,
|
||||
PREPEND,
|
||||
PROVIDED;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.generators;
|
||||
|
||||
import javassist.CannotCompileException;
|
||||
import javassist.CtClass;
|
||||
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
|
||||
import us.runelitepl.mixinprocessor.parsers.FieldAnnotationParser;
|
||||
import us.runelitepl.mixinprocessor.parsers.MethodAnnotationParser;
|
||||
import us.runelitepl.mixinprocessor.util.JavassistUtils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class AnnotationProcessor
|
||||
{
|
||||
|
||||
private final String className;
|
||||
private final byte[] finalCode;
|
||||
|
||||
public AnnotationProcessor(String className, byte[] finalCode)
|
||||
{
|
||||
this.className = className;
|
||||
this.finalCode = finalCode;
|
||||
}
|
||||
|
||||
public byte[] run() throws IOException, CannotCompileException, ClassNotFoundException
|
||||
{
|
||||
byte[] newCode = finalCode;
|
||||
|
||||
CtClass clazz = MixinProcessorMojo.classPool.makeClass(new ByteArrayInputStream(newCode));
|
||||
new FieldAnnotationParser(clazz).run();
|
||||
new MethodAnnotationParser(clazz).run();
|
||||
newCode = JavassistUtils.getClassBytecode(clazz);
|
||||
|
||||
return newCode;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.generators;
|
||||
|
||||
import us.runelitepl.mixinprocessor.transformers.AnnotationRemoverTransformer;
|
||||
import us.runelitepl.mixinprocessor.transformers.AsmMethodGarbageTransformer;
|
||||
import us.runelitepl.mixinprocessor.transformers.AsmMethodSignatureTransformer;
|
||||
import us.runelitepl.mixinprocessor.transformers.AsmNameTransformer;
|
||||
import us.runelitepl.mixinprocessor.transformers.AsmStaticUsageTransformer;
|
||||
import us.runelitepl.mixinprocessor.transformers.DoNothingTransformer;
|
||||
import us.runelitepl.mixinprocessor.transformers.GetFieldDecoderTransformer;
|
||||
import us.runelitepl.mixinprocessor.transformers.ProvidedRemoverTransformer;
|
||||
|
||||
public class PatchGenerator
|
||||
{
|
||||
|
||||
private final String className;
|
||||
private final byte[] bytecode;
|
||||
|
||||
public PatchGenerator(String className, byte[] bytecode)
|
||||
{
|
||||
this.className = className;
|
||||
this.bytecode = bytecode;
|
||||
}
|
||||
|
||||
public byte[] run()
|
||||
{
|
||||
byte[] newCode = bytecode;
|
||||
|
||||
newCode = new GetFieldDecoderTransformer(className, newCode).transform();
|
||||
// https://asm.ow2.io/javadoc/org/objectweb/asm/commons/Remapper.html
|
||||
// https://asm.ow2.io/javadoc/org/objectweb/asm/commons/ClassRemapper.html
|
||||
newCode = new AsmStaticUsageTransformer(className, newCode).transform();
|
||||
newCode = new AsmNameTransformer(className, newCode).transform();
|
||||
newCode = new ProvidedRemoverTransformer(className, newCode).transform();
|
||||
newCode = new AnnotationRemoverTransformer(className, newCode).transform();
|
||||
|
||||
|
||||
newCode = new DoNothingTransformer(className, newCode).transform();
|
||||
return newCode;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.generators;
|
||||
|
||||
import javassist.CannotCompileException;
|
||||
import javassist.CtClass;
|
||||
import javassist.NotFoundException;
|
||||
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
|
||||
import us.runelitepl.mixinprocessor.util.JavassistUtils;
|
||||
import us.runelitepl.mixinprocessor.util.RefUtils;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.FieldNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class StaticGenerator
|
||||
{
|
||||
|
||||
public static HashMap<String, ArrayList<MethodNode>> staticMethods = new HashMap<>();
|
||||
public static HashMap<String, ArrayList<FieldNode>> staticFields = new HashMap<>();
|
||||
public static Set<String> modifiedClasses = new HashSet<>();
|
||||
|
||||
public void run(byte[] bytecode) throws NotFoundException, IOException, CannotCompileException
|
||||
{
|
||||
ClassReader cr = new ClassReader(bytecode);
|
||||
|
||||
ClassNode node = new ClassNode();
|
||||
cr.accept(node, 0);
|
||||
|
||||
for (Object aaa : node.methods)
|
||||
{
|
||||
MethodNode method = (MethodNode) aaa;
|
||||
|
||||
String methodName = method.name;
|
||||
method.desc = RefUtils.reobMethodDescriptor(method.desc);
|
||||
int access = method.access;
|
||||
if ((access & 8) != 8)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String reobbed = RefUtils.reobMethodName(RefUtils.STATICS_STRING, methodName, method.desc);
|
||||
if(reobbed == null)
|
||||
{
|
||||
MixinProcessorMojo.log("Failed to reob static method: %s %s", methodName, method.desc);
|
||||
throw new RuntimeException();
|
||||
}
|
||||
String[] split = reobbed.split(" ");
|
||||
method.name = split[1];
|
||||
ArrayList<MethodNode> list = staticMethods.getOrDefault(split[0], new ArrayList<>());
|
||||
list.add(method);
|
||||
staticMethods.put(split[0], list);
|
||||
modifiedClasses.add(split[0]);
|
||||
}
|
||||
|
||||
for (Object aaa : node.fields)
|
||||
{
|
||||
FieldNode field = (FieldNode) aaa;
|
||||
|
||||
String fieldName = field.name;
|
||||
field.desc = RefUtils.reobDescriptor(field.desc);
|
||||
int access = field.access;
|
||||
if ((access & 8) != 8)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String reobbed = RefUtils.reobFieldName(RefUtils.STATICS_STRING, fieldName, field.desc);
|
||||
if(reobbed == null)
|
||||
{
|
||||
MixinProcessorMojo.log("Failed to reob static field: %s %s", fieldName, field.desc);
|
||||
throw new RuntimeException();
|
||||
}
|
||||
String[] split = reobbed.split(" ");
|
||||
field.name = split[1];
|
||||
ArrayList<FieldNode> list = staticFields.getOrDefault(split[0], new ArrayList<>());
|
||||
list.add(field);
|
||||
staticFields.put(split[0], list);
|
||||
modifiedClasses.add(split[0]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.generators;
|
||||
|
||||
import org.objectweb.asm.Attribute;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.FieldVisitor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.AnnotationNode;
|
||||
import org.objectweb.asm.tree.FieldNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
import org.objectweb.asm.tree.TypeAnnotationNode;
|
||||
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
|
||||
import us.runelitepl.mixinprocessor.parsers.MethodReflector;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import static us.runelitepl.mixinprocessor.generators.StaticGenerator.modifiedClasses;
|
||||
import static us.runelitepl.mixinprocessor.generators.StaticGenerator.staticFields;
|
||||
import static us.runelitepl.mixinprocessor.generators.StaticGenerator.staticMethods;
|
||||
|
||||
public class StaticStageTwoGenerator implements Opcodes
|
||||
{
|
||||
|
||||
private HashMap<String, byte[]> classes;
|
||||
|
||||
public StaticStageTwoGenerator(HashMap<String, byte[]> classes)
|
||||
{
|
||||
this.classes = classes;
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
for (String className : modifiedClasses)
|
||||
{
|
||||
byte[] targetBytecode = classes.getOrDefault(className, null);
|
||||
if (targetBytecode == null)
|
||||
{
|
||||
//create new class
|
||||
ClassWriter cw = new ClassWriter(0);
|
||||
FieldVisitor fv;
|
||||
MethodVisitor mv;
|
||||
|
||||
cw.visit(V1_6, ACC_PUBLIC, className, null, "java/lang/Object", null);
|
||||
|
||||
if (staticMethods.get(className) != null)
|
||||
{
|
||||
for (MethodNode method : staticMethods.get(className))
|
||||
{
|
||||
mv = cw.visitMethod(method.access, method.name, method.desc, method.signature,
|
||||
(String[]) method.exceptions.toArray(new String[0]));
|
||||
MethodReflector reflector = new MethodReflector(mv);
|
||||
method.accept(reflector);
|
||||
}
|
||||
}
|
||||
|
||||
if (staticFields.get(className) != null)
|
||||
{
|
||||
for (FieldNode field : staticFields.get(className))
|
||||
{
|
||||
fv = cw.visitField(field.access, field.name, field.desc, field.signature, field.value);
|
||||
int i;
|
||||
int n;
|
||||
AnnotationNode annotation;
|
||||
if (field.visibleAnnotations != null)
|
||||
{
|
||||
i = 0;
|
||||
|
||||
for (n = field.visibleAnnotations.size(); i < n; ++i)
|
||||
{
|
||||
annotation = (AnnotationNode) field.visibleAnnotations.get(i);
|
||||
annotation.accept(fv.visitAnnotation(annotation.desc, true));
|
||||
}
|
||||
}
|
||||
|
||||
if (field.invisibleAnnotations != null)
|
||||
{
|
||||
i = 0;
|
||||
|
||||
for (n = field.invisibleAnnotations.size(); i < n; ++i)
|
||||
{
|
||||
annotation = (AnnotationNode) field.invisibleAnnotations.get(i);
|
||||
annotation.accept(fv.visitAnnotation(annotation.desc, false));
|
||||
}
|
||||
}
|
||||
|
||||
TypeAnnotationNode typeAnnotation;
|
||||
if (field.visibleTypeAnnotations != null)
|
||||
{
|
||||
i = 0;
|
||||
|
||||
for (n = field.visibleTypeAnnotations.size(); i < n; ++i)
|
||||
{
|
||||
typeAnnotation = (TypeAnnotationNode) field.visibleTypeAnnotations.get(i);
|
||||
typeAnnotation.accept(fv
|
||||
.visitTypeAnnotation(typeAnnotation.typeRef, typeAnnotation.typePath,
|
||||
typeAnnotation.desc, true));
|
||||
}
|
||||
}
|
||||
|
||||
if (field.invisibleTypeAnnotations != null)
|
||||
{
|
||||
i = 0;
|
||||
|
||||
for (n = field.invisibleTypeAnnotations.size(); i < n; ++i)
|
||||
{
|
||||
typeAnnotation = (TypeAnnotationNode) field.invisibleTypeAnnotations.get(i);
|
||||
typeAnnotation.accept(fv
|
||||
.visitTypeAnnotation(typeAnnotation.typeRef, typeAnnotation.typePath,
|
||||
typeAnnotation.desc, false));
|
||||
}
|
||||
}
|
||||
|
||||
if (field.attrs != null)
|
||||
{
|
||||
i = 0;
|
||||
|
||||
for (n = field.attrs.size(); i < n; ++i)
|
||||
{
|
||||
fv.visitAttribute((Attribute) field.attrs.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
fv.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
cw.visitEnd();
|
||||
|
||||
targetBytecode = cw.toByteArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
ClassReader cr = new ClassReader(targetBytecode);
|
||||
ClassWriter cw = new ClassWriter(cr, 0);
|
||||
ClassVisitor cv = new ClassVisitor(ASM6)
|
||||
{
|
||||
@Override
|
||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
|
||||
{
|
||||
super.visit(version, access, name, signature, superName, interfaces);
|
||||
if (staticMethods.get(className) != null)
|
||||
{
|
||||
for (MethodNode method : staticMethods.get(className))
|
||||
{
|
||||
MethodVisitor mv = visitMethod(method.access, method.name, method.desc,
|
||||
method.signature, (String[]) method.exceptions.toArray(new String[0]));
|
||||
MethodReflector reflector = new MethodReflector(mv);
|
||||
method.accept(reflector);
|
||||
}
|
||||
}
|
||||
|
||||
if (staticFields.get(className) != null)
|
||||
{
|
||||
for (FieldNode field : staticFields.get(className))
|
||||
{
|
||||
FieldVisitor fv = visitField(field.access, field.name, field.desc, field.signature,
|
||||
field.value);
|
||||
int i;
|
||||
int n;
|
||||
AnnotationNode annotation;
|
||||
if (field.visibleAnnotations != null)
|
||||
{
|
||||
i = 0;
|
||||
|
||||
for (n = field.visibleAnnotations.size(); i < n; ++i)
|
||||
{
|
||||
annotation = (AnnotationNode) field.visibleAnnotations.get(i);
|
||||
annotation.accept(fv.visitAnnotation(annotation.desc, true));
|
||||
}
|
||||
}
|
||||
|
||||
if (field.invisibleAnnotations != null)
|
||||
{
|
||||
i = 0;
|
||||
|
||||
for (n = field.invisibleAnnotations.size(); i < n; ++i)
|
||||
{
|
||||
annotation = (AnnotationNode) field.invisibleAnnotations.get(i);
|
||||
annotation.accept(fv.visitAnnotation(annotation.desc, false));
|
||||
}
|
||||
}
|
||||
|
||||
TypeAnnotationNode typeAnnotation;
|
||||
if (field.visibleTypeAnnotations != null)
|
||||
{
|
||||
i = 0;
|
||||
|
||||
for (n = field.visibleTypeAnnotations.size(); i < n; ++i)
|
||||
{
|
||||
typeAnnotation = (TypeAnnotationNode) field.visibleTypeAnnotations.get(i);
|
||||
typeAnnotation.accept(fv
|
||||
.visitTypeAnnotation(typeAnnotation.typeRef, typeAnnotation.typePath,
|
||||
typeAnnotation.desc, true));
|
||||
}
|
||||
}
|
||||
|
||||
if (field.invisibleTypeAnnotations != null)
|
||||
{
|
||||
i = 0;
|
||||
|
||||
for (n = field.invisibleTypeAnnotations.size(); i < n; ++i)
|
||||
{
|
||||
typeAnnotation = (TypeAnnotationNode) field.invisibleTypeAnnotations.get(i);
|
||||
typeAnnotation.accept(fv
|
||||
.visitTypeAnnotation(typeAnnotation.typeRef, typeAnnotation.typePath,
|
||||
typeAnnotation.desc, false));
|
||||
}
|
||||
}
|
||||
|
||||
if (field.attrs != null)
|
||||
{
|
||||
i = 0;
|
||||
|
||||
for (n = field.attrs.size(); i < n; ++i)
|
||||
{
|
||||
fv.visitAttribute((Attribute) field.attrs.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
fv.visitEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
cr.accept(cv, 0);
|
||||
|
||||
targetBytecode = cw.toByteArray();
|
||||
}
|
||||
|
||||
classes.put(className, targetBytecode);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.parsers;
|
||||
|
||||
import javassist.CtClass;
|
||||
import javassist.CtField;
|
||||
import us.runelitepl.mixinprocessor.annotations.Append;
|
||||
import us.runelitepl.mixinprocessor.annotations.Inject;
|
||||
import us.runelitepl.mixinprocessor.annotations.Overwrite;
|
||||
import us.runelitepl.mixinprocessor.annotations.Prepend;
|
||||
import us.runelitepl.mixinprocessor.annotations.Provided;
|
||||
import us.runelitepl.mixinprocessor.annotations.Reobfuscate;
|
||||
import us.runelitepl.mixinprocessor.enums.InjectionType;
|
||||
import us.runelitepl.mixinprocessor.util.RefUtils;
|
||||
|
||||
import static us.runelitepl.mixinprocessor.MixinProcessorMojo.isFieldTagged;
|
||||
|
||||
public class FieldAnnotationParser
|
||||
{
|
||||
|
||||
private CtClass clazz;
|
||||
|
||||
public FieldAnnotationParser(CtClass clazz)
|
||||
{
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
public void run() throws ClassNotFoundException
|
||||
{
|
||||
for (CtField field : clazz.getDeclaredFields())
|
||||
{
|
||||
Object[] annotations = field.getAnnotations();
|
||||
|
||||
InjectionType type = null;
|
||||
boolean reobfuscate = false;
|
||||
|
||||
for (Object obj : annotations)
|
||||
{
|
||||
reobfuscate = obj instanceof Reobfuscate || reobfuscate;
|
||||
if (obj instanceof Inject)
|
||||
{
|
||||
type = InjectionType.INJECT;
|
||||
}
|
||||
else if (obj instanceof Append)
|
||||
{
|
||||
type = InjectionType.APPEND;
|
||||
}
|
||||
else if (obj instanceof Overwrite)
|
||||
{
|
||||
type = InjectionType.OVERWRITE;
|
||||
}
|
||||
else if (obj instanceof Prepend)
|
||||
{
|
||||
type = InjectionType.PREPEND;
|
||||
}
|
||||
else if (obj instanceof Provided)
|
||||
{
|
||||
type = InjectionType.PROVIDED;
|
||||
}
|
||||
}
|
||||
|
||||
String fieldOwner = field.getDeclaringClass().getSimpleName();
|
||||
String fieldName = field.getName();
|
||||
String fieldDescriptor = RefUtils.reobDescriptor(field.getSignature());
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
throw new RuntimeException(
|
||||
field.getDeclaringClass().getSimpleName() + "." + field.getName() + " is unannotated" +
|
||||
"!");
|
||||
}
|
||||
|
||||
if (type != InjectionType.PROVIDED && type != InjectionType.INJECT)
|
||||
{
|
||||
throw new RuntimeException(
|
||||
field.getDeclaringClass().getSimpleName() + "." + field.getName() + " has an invalid " +
|
||||
"annotation! @" + type);
|
||||
}
|
||||
|
||||
if (reobfuscate)
|
||||
{
|
||||
isFieldTagged.put(fieldOwner + " " + fieldName + " " + fieldDescriptor, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.parsers;
|
||||
|
||||
import us.runelitepl.mixinprocessor.util.WebUtils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
public class GamepackDownloader
|
||||
{
|
||||
|
||||
private static final String CONFIG_URL = "http://oldschool.runescape.com/jav_config.ws";
|
||||
private static String codebase;
|
||||
private static String initial_jar;
|
||||
|
||||
public static void downloadGamepack(HashMap<String, byte[]> output) throws IOException
|
||||
{
|
||||
parseConfig();
|
||||
byte[] gamepackJarAry = WebUtils.downloadFile(getGamepackUrl());
|
||||
ZipInputStream zipInputStream = new ZipInputStream(new ByteArrayInputStream(gamepackJarAry));
|
||||
byte[] buffer = new byte[2048];
|
||||
ZipEntry entry;
|
||||
ByteArrayOutputStream fileContent = new ByteArrayOutputStream(1024*1024*4);
|
||||
while ((entry = zipInputStream.getNextEntry()) != null)
|
||||
{
|
||||
if (entry.getName().startsWith("META-INF"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String key = entry.getName().replace(".class", "");
|
||||
int len = 0;
|
||||
while((len = zipInputStream.read(buffer)) > 0)
|
||||
{
|
||||
fileContent.write(buffer, 0, len);
|
||||
}
|
||||
output.put(key, fileContent.toByteArray());
|
||||
fileContent.reset();
|
||||
}
|
||||
zipInputStream.close();
|
||||
}
|
||||
|
||||
private static void parseConfig() throws IOException
|
||||
{
|
||||
String pageText = WebUtils.getUrlContent(CONFIG_URL);
|
||||
for (String line : pageText.split("\n"))
|
||||
{
|
||||
if (line.startsWith("codebase="))
|
||||
{
|
||||
codebase = line.replace("codebase=", "");
|
||||
}
|
||||
else if (line.startsWith("initial_jar="))
|
||||
{
|
||||
initial_jar = line.replace("initial_jar=", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String getGamepackUrl()
|
||||
{
|
||||
return codebase + initial_jar;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.parsers;
|
||||
|
||||
import us.runelitepl.mixinprocessor.MethodGarbageValue;
|
||||
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Map;
|
||||
|
||||
public class HooksParser
|
||||
{
|
||||
|
||||
public static void run(File hooksFile, File opsFile) throws IOException, ParseException
|
||||
{
|
||||
JSONParser parser = new JSONParser();
|
||||
//region hooksFile
|
||||
String jsonContent = String.join("\n", Files.readAllLines(hooksFile.toPath()));
|
||||
JSONArray array = (JSONArray) parser.parse(jsonContent);
|
||||
|
||||
for (Object object : array)
|
||||
{
|
||||
JSONObject rootObject = (JSONObject) object;
|
||||
String c_obbedName = (String) rootObject.get("name");
|
||||
String c_deobbedName = (String) rootObject.get("class");
|
||||
MixinProcessorMojo.classNames.put(c_deobbedName, c_obbedName);
|
||||
}
|
||||
|
||||
int failedFields = 0;
|
||||
int failedMethods = 0;
|
||||
for (Object object : array)
|
||||
{
|
||||
JSONObject rootObject = (JSONObject) object;
|
||||
|
||||
JSONArray fieldArray = (JSONArray) rootObject.get("fields");
|
||||
for (Object fieldObj : fieldArray)
|
||||
{
|
||||
JSONObject field = (JSONObject) fieldObj;
|
||||
String f_deobbedName = (String) field.get("field");
|
||||
String f_obbedName = (String) field.get("name");
|
||||
String f_descriptor = (String) field.get("descriptor");
|
||||
String f_owner = (String) field.get("owner");
|
||||
long f_decoder = (long) field.getOrDefault("decoder", (long) 1);
|
||||
String f_deobbedOwner = null;
|
||||
if(f_deobbedName.startsWith("__"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (Map.Entry<String, String> entry : MixinProcessorMojo.classNames.entrySet())
|
||||
{
|
||||
if (entry.getValue().equals(f_owner))
|
||||
{
|
||||
f_deobbedOwner = entry.getKey();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (f_deobbedOwner == null)
|
||||
{
|
||||
failedFields++;
|
||||
//stderr("Failed to find deobbed owner for field %s.%s %s", f_owner, f_obbedName, f_descriptor);
|
||||
continue;
|
||||
}
|
||||
MixinProcessorMojo.fieldNames.put(String.format("%s %s %s", f_deobbedOwner, f_deobbedName, f_descriptor),
|
||||
String.format("%s %s", f_owner, f_obbedName));
|
||||
MixinProcessorMojo.fieldDecoders.put(String.format("%s %s", f_deobbedOwner, f_deobbedName),
|
||||
f_decoder);
|
||||
}
|
||||
|
||||
JSONArray methodArray = (JSONArray) rootObject.get("methods");
|
||||
for (Object methodObj : methodArray)
|
||||
{
|
||||
JSONObject method = (JSONObject) methodObj;
|
||||
String m_deobbedName = (String) method.get("method");
|
||||
String m_owner = (String) method.get("owner");
|
||||
String m_deobbedOwner = null;
|
||||
String m_obbedName = (String) method.get("name");
|
||||
String m_descriptor = (String) method.get("descriptor");
|
||||
if(m_deobbedName.startsWith("__"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (Map.Entry<String, String> entry : MixinProcessorMojo.classNames.entrySet())
|
||||
{
|
||||
if (entry.getValue().equals(m_owner))
|
||||
{
|
||||
m_deobbedOwner = entry.getKey();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m_deobbedOwner == null)
|
||||
{
|
||||
failedMethods++;
|
||||
//stderr("Failed to find deobbed owner for method %s.%s %s", m_owner, m_obbedName, m_descriptor);
|
||||
continue;
|
||||
}
|
||||
MixinProcessorMojo.methodNames.put(String.format("%s %s %s", m_deobbedOwner, m_deobbedName, m_descriptor),
|
||||
String.format("%s %s", m_owner, m_obbedName));
|
||||
}
|
||||
}
|
||||
MixinProcessorMojo.log("%d unidentified fields", failedFields);
|
||||
MixinProcessorMojo.log("%d unidentified methods", failedMethods);
|
||||
//endregion
|
||||
|
||||
//region opsFile
|
||||
String opsContent = String.join("\n", Files.readAllLines(opsFile.toPath()));
|
||||
JSONObject opsRoot = (JSONObject) parser.parse(opsContent);
|
||||
opsRoot.forEach((key, value) ->
|
||||
{
|
||||
String k = (String) key;
|
||||
MixinProcessorMojo.methodGarbageValues.put(k, new MethodGarbageValue(Math.toIntExact((Long) value)));
|
||||
});
|
||||
//endregion
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.parsers;
|
||||
|
||||
import javassist.CtClass;
|
||||
import javassist.CtMethod;
|
||||
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
|
||||
import us.runelitepl.mixinprocessor.annotations.Append;
|
||||
import us.runelitepl.mixinprocessor.annotations.Inject;
|
||||
import us.runelitepl.mixinprocessor.annotations.Overwrite;
|
||||
import us.runelitepl.mixinprocessor.annotations.Prepend;
|
||||
import us.runelitepl.mixinprocessor.annotations.Provided;
|
||||
import us.runelitepl.mixinprocessor.annotations.Reobfuscate;
|
||||
import us.runelitepl.mixinprocessor.enums.InjectionType;
|
||||
import us.runelitepl.mixinprocessor.util.RefUtils;
|
||||
|
||||
import static us.runelitepl.mixinprocessor.MixinProcessorMojo.isMethodTagged;
|
||||
|
||||
public class MethodAnnotationParser
|
||||
{
|
||||
|
||||
private final CtClass patch;
|
||||
|
||||
public MethodAnnotationParser(CtClass patch)
|
||||
{
|
||||
this.patch = patch;
|
||||
}
|
||||
|
||||
public void run() throws ClassNotFoundException
|
||||
{
|
||||
for(CtMethod method : patch.getDeclaredMethods())
|
||||
{
|
||||
Object[] annotations = method.getAnnotations();
|
||||
|
||||
boolean reobfuscate = false;
|
||||
InjectionType type = null;
|
||||
|
||||
for (Object obj : annotations)
|
||||
{
|
||||
reobfuscate = obj instanceof Reobfuscate || reobfuscate;
|
||||
if (obj instanceof Inject)
|
||||
{
|
||||
type = InjectionType.INJECT;
|
||||
}
|
||||
else if (obj instanceof Append)
|
||||
{
|
||||
type = InjectionType.APPEND;
|
||||
}
|
||||
else if (obj instanceof Overwrite)
|
||||
{
|
||||
type = InjectionType.OVERWRITE;
|
||||
}
|
||||
else if (obj instanceof Prepend)
|
||||
{
|
||||
type = InjectionType.PREPEND;
|
||||
}
|
||||
else if (obj instanceof Provided)
|
||||
{
|
||||
type = InjectionType.PROVIDED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
throw new RuntimeException(
|
||||
method.getDeclaringClass().getSimpleName() + "." + method.getName() + " is unannotated" +
|
||||
"!");
|
||||
}
|
||||
|
||||
String methodName = method.getName();
|
||||
if (type == InjectionType.PREPEND)
|
||||
{
|
||||
if (!methodName.startsWith("prepend$"))
|
||||
{
|
||||
throw new RuntimeException(
|
||||
method.getDeclaringClass().getSimpleName() + "." + method.getName() + " has a @Prepend " +
|
||||
"annotation without beginning with \"prepend$\"!");
|
||||
}
|
||||
}
|
||||
else if (type == InjectionType.APPEND)
|
||||
{
|
||||
if (!methodName.startsWith("append$"))
|
||||
{
|
||||
throw new RuntimeException(
|
||||
method.getDeclaringClass().getSimpleName() + "." + method.getName() + " has a @Append " +
|
||||
"annotation without beginning with \"append$\"!");
|
||||
}
|
||||
}
|
||||
|
||||
if(reobfuscate)
|
||||
{
|
||||
MixinProcessorMojo.log("Marking: %s %s %s", method.getDeclaringClass().getSimpleName(), methodName,
|
||||
RefUtils.reobMethodDescriptor(method.getSignature()));
|
||||
String r = String.format("%s %s %s", method.getDeclaringClass().getSimpleName(), methodName,
|
||||
RefUtils.reobMethodDescriptor(method.getSignature()));
|
||||
isMethodTagged.put(r, true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.parsers;
|
||||
|
||||
import org.objectweb.asm.AnnotationVisitor;
|
||||
import org.objectweb.asm.Attribute;
|
||||
import org.objectweb.asm.Handle;
|
||||
import org.objectweb.asm.Label;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.TypePath;
|
||||
|
||||
public class MethodReflector extends MethodVisitor
|
||||
{
|
||||
|
||||
private MethodVisitor target;
|
||||
|
||||
public MethodReflector(MethodVisitor target)
|
||||
{
|
||||
super(Opcodes.ASM6);
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public void visitCode()
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitCode();
|
||||
}
|
||||
super.visitCode();
|
||||
}
|
||||
|
||||
public void visitEnd()
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitEnd();
|
||||
}
|
||||
super.visitEnd();
|
||||
}
|
||||
|
||||
public void visitParameter(String var1, int var2)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitParameter(var1, var2);
|
||||
}
|
||||
super.visitParameter(var1, var2);
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitAnnotationDefault()
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitAnnotationDefault();
|
||||
}
|
||||
return super.visitAnnotationDefault();
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitAnnotation(String var1, boolean var2)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitAnnotation(var1, var2);
|
||||
}
|
||||
return super.visitAnnotation(var1, var2);
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitTypeAnnotation(int var1, TypePath var2, String var3, boolean var4)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitTypeAnnotation(var1, var2, var3, var4);
|
||||
}
|
||||
return super.visitTypeAnnotation(var1, var2, var3, var4);
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitParameterAnnotation(int var1, String var2, boolean var3)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitParameterAnnotation(var1, var2, var3);
|
||||
}
|
||||
return super.visitParameterAnnotation(var1, var2, var3);
|
||||
}
|
||||
|
||||
public void visitAttribute(Attribute var1)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitAttribute(var1);
|
||||
}
|
||||
super.visitAttribute(var1);
|
||||
}
|
||||
|
||||
public void visitFrame(int var1, int var2, Object[] var3, int var4, Object[] var5)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitFrame(var1, var2, var3, var4, var5);
|
||||
}
|
||||
super.visitFrame(var1, var2, var3, var4, var5);
|
||||
}
|
||||
|
||||
public void visitInsn(int var1)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitInsn(var1);
|
||||
}
|
||||
super.visitInsn(var1);
|
||||
}
|
||||
|
||||
public void visitIntInsn(int var1, int var2)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitIntInsn(var1, var2);
|
||||
}
|
||||
super.visitIntInsn(var1, var2);
|
||||
}
|
||||
|
||||
public void visitVarInsn(int var1, int var2)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitVarInsn(var1, var2);
|
||||
}
|
||||
super.visitVarInsn(var1, var2);
|
||||
}
|
||||
|
||||
public void visitTypeInsn(int var1, String var2)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitTypeInsn(var1, var2);
|
||||
}
|
||||
super.visitTypeInsn(var1, var2);
|
||||
}
|
||||
|
||||
public void visitFieldInsn(int var1, String var2, String var3, String var4)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitFieldInsn(var1, var2, var3, var4);
|
||||
}
|
||||
super.visitFieldInsn(var1, var2, var3, var4);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public void visitMethodInsn(int var1, String var2, String var3, String var4)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitMethodInsn(var1, var2, var3, var4);
|
||||
}
|
||||
super.visitMethodInsn(var1, var2, var3, var4);
|
||||
}
|
||||
|
||||
public void visitMethodInsn(int var1, String var2, String var3, String var4, boolean var5)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitMethodInsn(var1, var2, var3, var4, var5);
|
||||
}
|
||||
super.visitMethodInsn(var1, var2, var3, var4, var5);
|
||||
}
|
||||
|
||||
public void visitInvokeDynamicInsn(String var1, String var2, Handle var3, Object... var4)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitInvokeDynamicInsn(var1, var2, var3, var4);
|
||||
}
|
||||
super.visitInvokeDynamicInsn(var1, var2, var3, var4);
|
||||
}
|
||||
|
||||
public void visitJumpInsn(int var1, Label var2)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitJumpInsn(var1, var2);
|
||||
}
|
||||
super.visitJumpInsn(var1, var2);
|
||||
}
|
||||
|
||||
public void visitLabel(Label var1)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitLabel(var1);
|
||||
}
|
||||
super.visitLabel(var1);
|
||||
}
|
||||
|
||||
public void visitLdcInsn(Object var1)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitLdcInsn(var1);
|
||||
}
|
||||
super.visitLdcInsn(var1);
|
||||
}
|
||||
|
||||
public void visitIincInsn(int var1, int var2)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitIincInsn(var1, var2);
|
||||
}
|
||||
super.visitIincInsn(var1, var2);
|
||||
}
|
||||
|
||||
public void visitTableSwitchInsn(int var1, int var2, Label var3, Label... var4)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitTableSwitchInsn(var1, var2, var3, var4);
|
||||
}
|
||||
super.visitTableSwitchInsn(var1, var2, var3, var4);
|
||||
}
|
||||
|
||||
public void visitLookupSwitchInsn(Label var1, int[] var2, Label[] var3)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitLookupSwitchInsn(var1, var2, var3);
|
||||
}
|
||||
super.visitLookupSwitchInsn(var1, var2, var3);
|
||||
}
|
||||
|
||||
public void visitMultiANewArrayInsn(String var1, int var2)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitMultiANewArrayInsn(var1, var2);
|
||||
}
|
||||
super.visitMultiANewArrayInsn(var1, var2);
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitInsnAnnotation(int var1, TypePath var2, String var3, boolean var4)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitInsnAnnotation(var1, var2, var3, var4);
|
||||
}
|
||||
return super.visitInsnAnnotation(var1, var2, var3, var4);
|
||||
}
|
||||
|
||||
public void visitTryCatchBlock(Label var1, Label var2, Label var3, String var4)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitTryCatchBlock(var1, var2, var3, var4);
|
||||
}
|
||||
super.visitTryCatchBlock(var1, var2, var3, var4);
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitTryCatchAnnotation(int var1, TypePath var2, String var3, boolean var4)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitTryCatchAnnotation(var1, var2, var3, var4);
|
||||
}
|
||||
return super.visitTryCatchAnnotation(var1, var2, var3, var4);
|
||||
}
|
||||
|
||||
public void visitLocalVariable(String var1, String var2, String var3, Label var4, Label var5, int var6)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitLocalVariable(var1, var2, var3, var4, var5, var6);
|
||||
}
|
||||
super.visitLocalVariable(var1, var2, var3, var4, var5, var6);
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitLocalVariableAnnotation(int var1, TypePath var2, Label[] var3, Label[] var4, int[] var5, String var6, boolean var7)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitLocalVariableAnnotation(var1, var2, var3, var4, var5, var6, var7);
|
||||
}
|
||||
return super.visitLocalVariableAnnotation(var1, var2, var3, var4, var5, var6, var7);
|
||||
}
|
||||
|
||||
public void visitLineNumber(int var1, Label var2)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitLineNumber(var1, var2);
|
||||
}
|
||||
super.visitLineNumber(var1, var2);
|
||||
}
|
||||
|
||||
public void visitMaxs(int var1, int var2)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.visitMaxs(var1, var2);
|
||||
}
|
||||
super.visitMaxs(var1, var2);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.transformers;
|
||||
|
||||
import org.objectweb.asm.AnnotationVisitor;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.FieldVisitor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
public class AnnotationRemoverTransformer extends AsmBaseTransformer
|
||||
{
|
||||
|
||||
private final String className;
|
||||
private final byte[] bytecode;
|
||||
|
||||
public AnnotationRemoverTransformer(String className, byte[] bytecode)
|
||||
{
|
||||
this.className = className;
|
||||
this.bytecode = bytecode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform()
|
||||
{
|
||||
ClassReader cr = new ClassReader(bytecode);
|
||||
ClassWriter cw = new ClassWriter(cr, 0);
|
||||
cr.accept(new ClassVisitor(Opcodes.ASM6, cw)
|
||||
{
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
|
||||
{
|
||||
MethodVisitor visitor = super.visitMethod(access, name, desc, signature, exceptions);
|
||||
MethodVisitor mv = new MethodVisitor(Opcodes.ASM6, visitor)
|
||||
{
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(String descriptor, boolean hidden)
|
||||
{
|
||||
if (descriptor.equals(makeAnnotationDescriptor("Reobfuscate")))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return super.visitAnnotation(descriptor, hidden);
|
||||
}
|
||||
};
|
||||
return mv;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value)
|
||||
{
|
||||
FieldVisitor visitor = super.visitField(access, name, descriptor, signature, value);
|
||||
return new FieldVisitor(Opcodes.ASM6, visitor)
|
||||
{
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(String descriptor, boolean hidden)
|
||||
{
|
||||
if (descriptor.equals(makeAnnotationDescriptor("Reobfuscate")))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (descriptor.equals(makeAnnotationDescriptor("Provided")))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return super.visitAnnotation(descriptor, hidden);
|
||||
}
|
||||
};
|
||||
}
|
||||
}, 0);
|
||||
return cw.toByteArray();
|
||||
}
|
||||
|
||||
public static String makeAnnotationDescriptor(String s)
|
||||
{
|
||||
return "Lus/runelitepl/mixinprocessor/annotations/" + s + ";";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.transformers;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public abstract class AsmBaseTransformer implements Opcodes
|
||||
{
|
||||
|
||||
protected final ArrayList<String> validMethods = new ArrayList<>();
|
||||
protected final ArrayList<String> validFields = new ArrayList<>();
|
||||
|
||||
protected void buildMethodList(){}
|
||||
|
||||
protected void buildFieldList(){}
|
||||
|
||||
public abstract byte[] transform();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.transformers;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import us.runelitepl.mixinprocessor.MethodGarbageValue;
|
||||
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
|
||||
import us.runelitepl.mixinprocessor.util.RefUtils;
|
||||
|
||||
import java.sql.Ref;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class AsmMethodGarbageTransformer extends AsmBaseTransformer
|
||||
{
|
||||
|
||||
private final String className;
|
||||
private final byte[] bytecode;
|
||||
private HashMap<String, byte[]> classSet;
|
||||
|
||||
public AsmMethodGarbageTransformer(String className, byte[] bytecode, HashMap<String, byte[]> classSet)
|
||||
{
|
||||
this.className = className;
|
||||
this.bytecode = bytecode;
|
||||
this.classSet = classSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform()
|
||||
{
|
||||
|
||||
ClassReader cr = new ClassReader(bytecode);
|
||||
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
|
||||
|
||||
cr.accept(new ClassVisitor(ASM6, cw)
|
||||
{
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
|
||||
{
|
||||
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
|
||||
return new MethodVisitor(ASM6, mv)
|
||||
{
|
||||
@Override
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf)
|
||||
{
|
||||
// get method owner.string(desc)
|
||||
// check if method is annotated with @Reobfuscate
|
||||
// brute force actual descriptor (check with shouldReobMethod(owner, name desc) )
|
||||
// mv.visitLdcInsn(BIPUSH, constant);
|
||||
// call super method with new descriptor
|
||||
|
||||
if(RefUtils.shouldReobMethod(owner, name, desc))
|
||||
{
|
||||
String nc = RefUtils.reobMethodName(owner, name, desc).split(" ")[0];
|
||||
String nn = RefUtils.reobMethodName(owner, name, desc).split(" ")[1];
|
||||
String nd = RefUtils.reobMethodDescriptor(desc);
|
||||
MethodGarbageValue value;
|
||||
if((value = MixinProcessorMojo.methodGarbageValues.getOrDefault(String.format("%s.%s%s",
|
||||
nc, nn, nd), null)) != null)
|
||||
{
|
||||
switch (value.getType())
|
||||
{
|
||||
case "I":
|
||||
super.visitLdcInsn(new Integer(value.getValue()));
|
||||
break;
|
||||
case "S":
|
||||
super.visitIntInsn(SIPUSH, (short) value.getValue());
|
||||
break;
|
||||
case "B":
|
||||
super.visitIntInsn(BIPUSH, (byte) value.getValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.visitMethodInsn(opcode, owner, name, desc, itf);
|
||||
}
|
||||
};
|
||||
}
|
||||
}, 0);
|
||||
|
||||
return cw.toByteArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.transformers;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
|
||||
import us.runelitepl.mixinprocessor.util.RefUtils;
|
||||
|
||||
public class AsmMethodSignatureTransformer extends AsmBaseTransformer
|
||||
{
|
||||
|
||||
private final String className;
|
||||
private final byte[] bytecode;
|
||||
|
||||
public AsmMethodSignatureTransformer(String className, byte[] bytecode)
|
||||
{
|
||||
this.className = RefUtils.deobClassName(className);
|
||||
this.bytecode = bytecode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform()
|
||||
{
|
||||
ClassReader cr = new ClassReader(bytecode);
|
||||
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
|
||||
|
||||
cr.accept(new ClassVisitor(ASM6, cw)
|
||||
{
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String sig, String[] exceptions)
|
||||
{
|
||||
MethodVisitor mv = super.visitMethod(access, name, fixMethodDesc(className, name, desc), sig, exceptions);
|
||||
return new MethodVisitor(ASM6, mv)
|
||||
{
|
||||
@Override
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf)
|
||||
{
|
||||
super.visitMethodInsn(opcode, owner, name, fixMethodDesc(owner, name, desc), itf);
|
||||
}
|
||||
};
|
||||
}
|
||||
}, 0);
|
||||
|
||||
return cw.toByteArray();
|
||||
}
|
||||
|
||||
private String fixMethodDesc(String className, String name, String desc)
|
||||
{
|
||||
if(className.startsWith(RefUtils.TYPE_PREFIX))
|
||||
{
|
||||
className = className.substring(RefUtils.TYPE_PREFIX.length());
|
||||
}
|
||||
if (RefUtils.shouldReobMethod(className, name, desc))
|
||||
{
|
||||
if (RefUtils.reobMethodName(className, name, desc) == null)
|
||||
{
|
||||
// get correct descriptor
|
||||
String realDesc = null;
|
||||
for (String s : RefUtils.POSSIBLE_GARBAGE_TYPES)
|
||||
{
|
||||
String check = RefUtils.reobMethodName(className, name, RefUtils.appendArgument(desc, s));
|
||||
if (check != null)
|
||||
{
|
||||
realDesc = RefUtils.appendArgument(desc, s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (realDesc == null)
|
||||
{
|
||||
MixinProcessorMojo.log("Failed to find actual method descriptor for %s.%s%s", className,
|
||||
name, desc);
|
||||
throw new RuntimeException();
|
||||
}
|
||||
// fixed = realDesc
|
||||
MixinProcessorMojo.isMethodTagged.put(String.format("%s %s %s", className, name, realDesc), true);
|
||||
return realDesc;
|
||||
}
|
||||
}
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.transformers;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.commons.ClassRemapper;
|
||||
import org.objectweb.asm.commons.Remapper;
|
||||
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
|
||||
import us.runelitepl.mixinprocessor.util.RefUtils;
|
||||
|
||||
public class AsmNameTransformer extends AsmBaseTransformer
|
||||
{
|
||||
|
||||
private String className;
|
||||
private byte[] bytecode;
|
||||
|
||||
public AsmNameTransformer(String className, byte[] bytecode)
|
||||
{
|
||||
this.className = className;
|
||||
this.bytecode = bytecode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform()
|
||||
{
|
||||
ClassReader cr = new ClassReader(bytecode);
|
||||
ClassWriter cw = new ClassWriter(cr, 0);
|
||||
ClassRemapper remapper = new ClassRemapper(cw, new Remapper()
|
||||
{
|
||||
|
||||
final String TYPE_PREFIX = "us/runelitepl/mixins/";
|
||||
|
||||
@Override
|
||||
public String map(String internalName)
|
||||
{
|
||||
return super.map(internalName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String mapDesc(String descriptor)
|
||||
{
|
||||
return RefUtils.reobDescriptor(descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String mapFieldName(String owner, String name, String descriptor)
|
||||
{
|
||||
String oldName = name;
|
||||
String noPackage = owner.replace(TYPE_PREFIX, "");
|
||||
|
||||
descriptor = mapDesc(descriptor);
|
||||
|
||||
owner = RefUtils.reobClassName(owner);
|
||||
if (RefUtils.shouldReobField(noPackage, name, descriptor))
|
||||
{
|
||||
name = RefUtils.reobFieldName(noPackage, name, descriptor);
|
||||
if (name == null)
|
||||
{
|
||||
MixinProcessorMojo.log("Failed to reobfuscate field name %s.%s", noPackage, oldName);
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
return super.mapFieldName(owner, name, descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String mapInvokeDynamicMethodName(String name, String descriptor)
|
||||
{
|
||||
throw new UnsupportedOperationException("mapInvokeDynamicMethodName: Not implemented yet," +
|
||||
"\nAsmNameTransformer#mapInvokeDynamicMethodName(" + name + ", " + descriptor + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String mapMethodDesc(String descriptor)
|
||||
{
|
||||
return RefUtils.reobMethodDescriptor(descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String mapMethodName(String owner, String name, String descriptor)
|
||||
{
|
||||
String originalClass = owner;
|
||||
if (originalClass.startsWith(TYPE_PREFIX))
|
||||
{
|
||||
originalClass = originalClass.substring(TYPE_PREFIX.length());
|
||||
}
|
||||
owner = RefUtils.reobClassName(owner);
|
||||
if (name.startsWith("protect$"))
|
||||
{
|
||||
name = "1" + name;
|
||||
}
|
||||
// descriptor for reob checking is obfuscated
|
||||
descriptor = mapMethodDesc(descriptor);
|
||||
boolean reob = RefUtils.shouldReobMethod(originalClass, name, descriptor);
|
||||
|
||||
if (reob)
|
||||
{
|
||||
String originalName = name;
|
||||
name = RefUtils.reobMethodName(originalClass, name, descriptor);
|
||||
if (name == null)
|
||||
{
|
||||
MixinProcessorMojo.log("Failed to reobfuscate method: %s.%s%s", originalClass, originalName,
|
||||
descriptor);
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//stderr("mapMethodName %s %s %s", owner, name, descriptor);
|
||||
return super.mapMethodName(owner, name, descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String mapPackageName(String name)
|
||||
{
|
||||
throw new UnsupportedOperationException("mapPackageName: Not implemented yet," +
|
||||
"\nAsmNameTransformer#mapPackageName(" + name + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String mapSignature(String signature, boolean isTypeSig)
|
||||
{
|
||||
return super.mapSignature(signature, isTypeSig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String mapType(String internalName)
|
||||
{
|
||||
internalName = RefUtils.reobClassName(internalName);
|
||||
return super.mapType(internalName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] mapTypes(String[] internalNames)
|
||||
{
|
||||
return super.mapTypes(internalNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object mapValue(Object value)
|
||||
{
|
||||
return super.mapValue(value);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
cr.accept(remapper, 0);
|
||||
|
||||
return cw.toByteArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.transformers;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
|
||||
import us.runelitepl.mixinprocessor.util.RefUtils;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.ASM6;
|
||||
import static org.objectweb.asm.Opcodes.GETSTATIC;
|
||||
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
|
||||
import static org.objectweb.asm.Opcodes.PUTSTATIC;
|
||||
|
||||
public class AsmStaticUsageTransformer extends AsmBaseTransformer
|
||||
{
|
||||
|
||||
private String className;
|
||||
private byte[] bytecode;
|
||||
private final String TYPE_PREFIX = "us/runelitepl/mixins/";
|
||||
|
||||
public AsmStaticUsageTransformer(String className, byte[] bytecode)
|
||||
{
|
||||
this.className = className;
|
||||
this.bytecode = bytecode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform()
|
||||
{
|
||||
ClassReader cr = new ClassReader(bytecode);
|
||||
ClassWriter cw = new ClassWriter(cr, 0);
|
||||
ClassVisitor cv = new ClassVisitor(ASM6, cw)
|
||||
{
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions)
|
||||
{
|
||||
MethodVisitor visitor = super.visitMethod(access, name, descriptor, signature, exceptions);
|
||||
return new MethodVisitor(ASM6, visitor)
|
||||
{
|
||||
@Override
|
||||
public void visitFieldInsn(int opcode, String owner, String name, String descriptor)
|
||||
{
|
||||
if ((opcode == GETSTATIC || opcode == PUTSTATIC) && owner.endsWith(RefUtils.STATICS_STRING))
|
||||
{
|
||||
String oldName = name;
|
||||
String originalOwner = owner.replace(TYPE_PREFIX, "");
|
||||
String temp = RefUtils.reobFieldNameDangerous(name, RefUtils.reobDescriptor(descriptor));
|
||||
if (temp == null)
|
||||
{
|
||||
MixinProcessorMojo.log("Failed to reobfuscate class name for field %s %s %s", owner,
|
||||
name, descriptor);
|
||||
throw new RuntimeException();
|
||||
}
|
||||
owner = temp.split(" ")[0];
|
||||
if (RefUtils.shouldReobField(originalOwner, name, RefUtils.reobDescriptor(descriptor)))
|
||||
{
|
||||
name = temp.split(" ")[1];
|
||||
}
|
||||
}
|
||||
super.visitFieldInsn(opcode, owner, name, descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface)
|
||||
{
|
||||
if(opcode == INVOKESTATIC && owner.endsWith(RefUtils.STATICS_STRING))
|
||||
{
|
||||
String originalOwner = owner.replace(TYPE_PREFIX, "");
|
||||
String temp = RefUtils.reobMethodName(RefUtils.STATICS_STRING, name, descriptor);
|
||||
if (temp == null)
|
||||
{
|
||||
MixinProcessorMojo.log("Failed to reobfuscate class name for method %s %s %s", owner,
|
||||
name, descriptor);
|
||||
throw new RuntimeException();
|
||||
}
|
||||
owner = temp.split(" ")[0];
|
||||
if (RefUtils.shouldReobMethod(originalOwner, name, descriptor))
|
||||
{
|
||||
name = temp.split(" ")[1];
|
||||
}
|
||||
}
|
||||
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
cr.accept(cv, 0);
|
||||
|
||||
return cw.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.transformers;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
|
||||
public class DoNothingTransformer extends AsmBaseTransformer
|
||||
{
|
||||
|
||||
private final String className;
|
||||
private final byte[] bytecode;
|
||||
|
||||
public DoNothingTransformer(String className, byte[] bytecode)
|
||||
{
|
||||
this.className = className;
|
||||
this.bytecode = bytecode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform()
|
||||
{
|
||||
|
||||
ClassReader cr = new ClassReader(bytecode);
|
||||
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
|
||||
|
||||
cr.accept(new ClassVisitor(ASM6, cw)
|
||||
{}, 0);
|
||||
|
||||
return cw.toByteArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.transformers;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
|
||||
import us.runelitepl.mixinprocessor.util.RefUtils;
|
||||
|
||||
public class GetFieldDecoderTransformer extends AsmBaseTransformer
|
||||
{
|
||||
|
||||
private final String className;
|
||||
private final byte[] classFileBytecode;
|
||||
|
||||
public GetFieldDecoderTransformer(String className, byte[] bytes)
|
||||
{
|
||||
this.className = className;
|
||||
this.classFileBytecode = bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildMethodList()
|
||||
{
|
||||
ClassReader cr = new ClassReader(classFileBytecode);
|
||||
ClassWriter cw = new ClassWriter(cr, 0);
|
||||
cr.accept(new ClassVisitor(Opcodes.ASM6, cw)
|
||||
{
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature,
|
||||
String[] exceptions)
|
||||
{
|
||||
final boolean[] valid = {true};
|
||||
MethodVisitor visitor = super.visitMethod(access, name, desc, signature, exceptions);
|
||||
return new MethodVisitor(Opcodes.ASM6, visitor)
|
||||
{
|
||||
int opcodeCount = 0;
|
||||
|
||||
@Override
|
||||
public void visitEnd()
|
||||
{
|
||||
if (valid[0])
|
||||
{
|
||||
MixinProcessorMojo.log("Valid method: %s %s %s %s", access, name, desc, signature);
|
||||
validMethods.add(access + " " + name + " " + desc + " " + signature);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitVarInsn(int opcode, int var)
|
||||
{
|
||||
if (opcode != Opcodes.ALOAD || var != 0 || opcodeCount != 0)
|
||||
{
|
||||
valid[0] = false;
|
||||
}
|
||||
opcodeCount++;
|
||||
|
||||
super.visitVarInsn(opcode, var);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFieldInsn(int opcode, String owner, String fieldName, String signature)
|
||||
{
|
||||
if (opcode != Opcodes.GETFIELD || opcodeCount != 1)
|
||||
{
|
||||
valid[0] = false;
|
||||
}
|
||||
opcodeCount++;
|
||||
|
||||
super.visitFieldInsn(opcode, owner, fieldName, signature);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLdcInsn(Object o)
|
||||
{
|
||||
if (!(o instanceof Integer) && !(o instanceof Long))
|
||||
{
|
||||
valid[0] = false;
|
||||
}
|
||||
if (opcodeCount != 2)
|
||||
{
|
||||
valid[0] = false;
|
||||
}
|
||||
opcodeCount++;
|
||||
super.visitLdcInsn(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInsn(int opcode)
|
||||
{
|
||||
switch (opcode)
|
||||
{
|
||||
case Opcodes.IMUL:
|
||||
if (opcodeCount != 3)
|
||||
{
|
||||
valid[0] = false;
|
||||
}
|
||||
break;
|
||||
case Opcodes.IRETURN:
|
||||
if (opcodeCount != 4)
|
||||
{
|
||||
valid[0] = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
valid[0] = false;
|
||||
break;
|
||||
}
|
||||
opcodeCount++;
|
||||
super.visitInsn(opcode);
|
||||
}
|
||||
};
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
|
||||
public byte[] transform()
|
||||
{
|
||||
buildMethodList();
|
||||
ClassReader cr = new ClassReader(classFileBytecode);
|
||||
ClassWriter cw = new ClassWriter(cr, 0);
|
||||
cr.accept(new ClassVisitor(Opcodes.ASM6, cw)
|
||||
{
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
|
||||
{
|
||||
MethodVisitor visitor = super.visitMethod(access, name, desc, signature, exceptions);
|
||||
if (!validMethods.contains(access + " " + name + " " + desc + " " + signature))
|
||||
{
|
||||
return visitor;
|
||||
}
|
||||
return new MethodVisitor(Opcodes.ASM6, visitor)
|
||||
{
|
||||
String target = null;
|
||||
|
||||
@Override
|
||||
public void visitFieldInsn(int opcode, String owner, String fieldName, String signature)
|
||||
{
|
||||
target = fieldName;
|
||||
super.visitFieldInsn(opcode, owner, fieldName, signature);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLdcInsn(Object o)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
if (o instanceof Long)
|
||||
{
|
||||
o = MixinProcessorMojo.fieldDecoders.getOrDefault(
|
||||
RefUtils.deobClassName(className) + " " + target, 1L);
|
||||
}
|
||||
else
|
||||
{
|
||||
o = Math.toIntExact(MixinProcessorMojo.fieldDecoders.getOrDefault(RefUtils.deobClassName(className) +
|
||||
" " + target,
|
||||
1L));
|
||||
}
|
||||
}
|
||||
MixinProcessorMojo.log("\tGetFieldDecoderTransformer: %s %s %s %s %s",
|
||||
RefUtils.deobClassName(className), name, target, desc, o);
|
||||
super.visitLdcInsn(o);
|
||||
}
|
||||
};
|
||||
}
|
||||
}, 0);
|
||||
return cw.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.transformers;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.AnnotationNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
|
||||
|
||||
public class ProvidedRemoverTransformer extends AsmBaseTransformer
|
||||
{
|
||||
|
||||
private final String className;
|
||||
private final byte[] bytecode;
|
||||
|
||||
public ProvidedRemoverTransformer(String className, byte[] bytecode)
|
||||
{
|
||||
this.className = className;
|
||||
this.bytecode = bytecode;
|
||||
}
|
||||
|
||||
public void buildMethodList()
|
||||
{
|
||||
ClassReader cr = new ClassReader(bytecode);
|
||||
ClassNode node = new ClassNode();
|
||||
cr.accept(node, 0);
|
||||
|
||||
for(Object obj : node.methods)
|
||||
{
|
||||
MethodNode method = (MethodNode) obj;
|
||||
if(method == null)
|
||||
{
|
||||
MixinProcessorMojo.log("ProvidedRemoverTransformer: Method null?");
|
||||
continue;
|
||||
}
|
||||
if(method.visibleAnnotations == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for(Object obj2 : method.visibleAnnotations)
|
||||
{
|
||||
AnnotationNode annot = (AnnotationNode) obj2;
|
||||
if(annot.desc.equals(AnnotationRemoverTransformer.makeAnnotationDescriptor("Provided")))
|
||||
{
|
||||
validMethods.add(method.access + " " + method.desc + " " + method.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform()
|
||||
{
|
||||
buildMethodList();
|
||||
ClassReader cr = new ClassReader(bytecode);
|
||||
ClassWriter cw = new ClassWriter(cr, 0);
|
||||
cr.accept(new ClassVisitor(Opcodes.ASM6, cw)
|
||||
{
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature,
|
||||
String[] exceptions)
|
||||
{
|
||||
if(validMethods.contains(access + " " + desc + " " + name))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return super.visitMethod(access, name, desc, signature, exceptions);
|
||||
}
|
||||
}, 0);
|
||||
|
||||
return cw.toByteArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.util;
|
||||
|
||||
import javassist.CannotCompileException;
|
||||
import javassist.CtClass;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class JavassistUtils
|
||||
{
|
||||
|
||||
public static byte[] getClassBytecode(CtClass clazz) throws IOException, CannotCompileException
|
||||
{
|
||||
clazz.stopPruning(true);
|
||||
byte[] retVal = clazz.toBytecode();
|
||||
clazz.defrost();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.util;
|
||||
|
||||
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class RefUtils
|
||||
{
|
||||
|
||||
public static final String TYPE_PREFIX = "us/runelitepl/mixins/";
|
||||
public static final String STATICS_STRING = "_Statics_";
|
||||
public static final String[] POSSIBLE_GARBAGE_TYPES = {"I", "B", "S"};
|
||||
|
||||
public static String deobClassName(String obbed)
|
||||
{
|
||||
for (Map.Entry<String, String> entry : MixinProcessorMojo.classNames.entrySet())
|
||||
{
|
||||
if (entry.getValue().equals(obbed))
|
||||
{
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
return obbed;
|
||||
}
|
||||
|
||||
public static String getObbedClassName(String deob)
|
||||
{
|
||||
return MixinProcessorMojo.classNames.getOrDefault(deob, deob);
|
||||
}
|
||||
|
||||
public static String reobClassName(String deobbed)
|
||||
{
|
||||
String old = deobbed;
|
||||
if (deobbed.contains("/"))
|
||||
{
|
||||
deobbed = deobbed.replaceAll(TYPE_PREFIX, "");
|
||||
deobbed = getObbedClassName(deobbed);
|
||||
if (deobbed == null)
|
||||
{
|
||||
return old;
|
||||
}
|
||||
}
|
||||
return deobbed;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static String reobFieldNameDangerous(String deob, String desc)
|
||||
{
|
||||
int i = 0;
|
||||
Map.Entry<String, String> e1 = null;
|
||||
for (Map.Entry<String, String> entry : MixinProcessorMojo.fieldNames.entrySet())
|
||||
{
|
||||
if (entry.getKey().endsWith(deob + " " + desc))
|
||||
{
|
||||
i++;
|
||||
e1 = entry;
|
||||
}
|
||||
}
|
||||
if (i == 1)
|
||||
{
|
||||
return e1.getValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static String reobMethodNameDangerous(String deob, String signature)
|
||||
{
|
||||
int i = 0;
|
||||
Map.Entry<String, String> e1 = null;
|
||||
for (Map.Entry<String, String> entry : MixinProcessorMojo.methodNames.entrySet())
|
||||
{
|
||||
if (entry.getKey().endsWith(" " + deob + " " + signature))
|
||||
{
|
||||
i++;
|
||||
e1 = entry;
|
||||
}
|
||||
}
|
||||
if (i == 1)
|
||||
{
|
||||
return e1.getValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String reobFieldName(String owner, String deob, String desc)
|
||||
{
|
||||
if (owner.equals(RefUtils.STATICS_STRING))
|
||||
{
|
||||
return reobFieldNameDangerous(deob, desc);
|
||||
}
|
||||
String asd = MixinProcessorMojo.fieldNames.getOrDefault(owner + " " + deob + " " + desc, null);
|
||||
if (asd == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return asd.split(" ")[1];
|
||||
}
|
||||
|
||||
public static String reobMethodName(String owner, String deob, String signature)
|
||||
{
|
||||
String prefix = "";
|
||||
if(owner.startsWith(RefUtils.TYPE_PREFIX))
|
||||
{
|
||||
owner = owner.substring(RefUtils.TYPE_PREFIX.length());
|
||||
}
|
||||
if (deob.startsWith("prepend$"))
|
||||
{
|
||||
prefix = "prepend$";
|
||||
deob = deob.substring("prepend$".length());
|
||||
}
|
||||
else if (deob.startsWith("append$"))
|
||||
{
|
||||
prefix = "append$";
|
||||
deob = deob.substring("append$".length());
|
||||
}
|
||||
if (owner.equals(RefUtils.STATICS_STRING))
|
||||
{
|
||||
String retVal = reobMethodNameDangerous(deob, signature);
|
||||
if (retVal == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String[] split = retVal.split(" ");
|
||||
split[1] = prefix + split[1];
|
||||
return String.join(" ", split);
|
||||
}
|
||||
String asd = MixinProcessorMojo.methodNames.getOrDefault(owner + " " + deob + " " + signature, null);
|
||||
if (asd == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return prefix + asd.split(" ")[1];
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static boolean shouldReobFieldDangerous(String deob, String desc)
|
||||
{
|
||||
int i = 0;
|
||||
for (Map.Entry<String, Boolean> entry : MixinProcessorMojo.isFieldTagged.entrySet())
|
||||
{
|
||||
if (entry.getKey().endsWith(deob + " " + desc))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (i == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static boolean shouldReobMethodDangerous(String deob, String desc)
|
||||
{
|
||||
int i = 0;
|
||||
for (Map.Entry<String, Boolean> entry : MixinProcessorMojo.isMethodTagged.entrySet())
|
||||
{
|
||||
if (entry.getKey().endsWith(" " + deob + " " + desc))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (i == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean shouldReobField(String owner, String deob, String desc)
|
||||
{
|
||||
if (owner.equals(RefUtils.STATICS_STRING))
|
||||
{
|
||||
return shouldReobFieldDangerous(deob, desc);
|
||||
}
|
||||
return MixinProcessorMojo.isFieldTagged.getOrDefault(owner + " " + deob + " " + desc, false);
|
||||
}
|
||||
|
||||
public static boolean shouldReobMethod(String owner, String deob, String desc)
|
||||
{
|
||||
if(owner.startsWith(RefUtils.TYPE_PREFIX))
|
||||
{
|
||||
owner = owner.substring(RefUtils.TYPE_PREFIX.length());
|
||||
}
|
||||
if (owner.equals(RefUtils.STATICS_STRING))
|
||||
{
|
||||
return shouldReobMethodDangerous(deob, desc);
|
||||
}
|
||||
return MixinProcessorMojo.isMethodTagged.getOrDefault(owner + " " + deob + " " + desc, false);
|
||||
}
|
||||
|
||||
public static String reobDescriptor(String descriptor)
|
||||
{
|
||||
if (!descriptor.startsWith("L"))
|
||||
{
|
||||
return descriptor;
|
||||
}
|
||||
if (!descriptor.contains("us/runelitepl/mixins/"))
|
||||
{
|
||||
return descriptor;
|
||||
}
|
||||
String orig = descriptor;
|
||||
descriptor = descriptor.replace("us/runelitepl/mixins/", "");
|
||||
descriptor = descriptor.substring(1, descriptor.length() - 1);
|
||||
descriptor = getObbedClassName(descriptor);
|
||||
if (descriptor == null)
|
||||
{
|
||||
return orig;
|
||||
}
|
||||
return "L" + descriptor + ";";
|
||||
}
|
||||
|
||||
public static String reobMethodDescriptor(String descriptor)
|
||||
{
|
||||
int strIndex = 0;
|
||||
if (descriptor.charAt(0) != '(')
|
||||
{
|
||||
throw new IllegalArgumentException("sig is not a method signature: " + descriptor);
|
||||
}
|
||||
StringBuilder deobbed = new StringBuilder(1024 * 1024);
|
||||
while (strIndex < descriptor.length())
|
||||
{
|
||||
switch (descriptor.charAt(strIndex))
|
||||
{
|
||||
case '(':
|
||||
case ')':
|
||||
case 'I':
|
||||
case 'B':
|
||||
case 'J':
|
||||
case 'S':
|
||||
case 'D':
|
||||
case 'F':
|
||||
case 'C':
|
||||
case 'Z':
|
||||
case 'V':
|
||||
case '[':
|
||||
deobbed.append(descriptor.charAt(strIndex));
|
||||
strIndex++;
|
||||
break;
|
||||
case 'L':
|
||||
try
|
||||
{
|
||||
String sigPart = descriptor.substring(strIndex, descriptor.indexOf(";", strIndex) + 1);
|
||||
String className = sigPart.substring(1, sigPart.length() - 1);
|
||||
className = className.replace(TYPE_PREFIX, "");
|
||||
String obbedName = MixinProcessorMojo.classNames.getOrDefault(className, null);
|
||||
if (obbedName == null)
|
||||
{
|
||||
obbedName = className;
|
||||
}
|
||||
deobbed.append("L" + obbedName + ";");
|
||||
strIndex += sigPart.length();
|
||||
}
|
||||
catch (StringIndexOutOfBoundsException ex)
|
||||
{
|
||||
System.err.println(
|
||||
"Method signature %s is probably missing a semi-colon".replace("%s", descriptor));
|
||||
throw ex;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("signature is invalid: " + descriptor);
|
||||
}
|
||||
}
|
||||
return deobbed.toString();
|
||||
}
|
||||
|
||||
public static String appendArgument(String desc, String append)
|
||||
{
|
||||
int strIndex = 0;
|
||||
if (desc.charAt(0) != '(')
|
||||
{
|
||||
throw new IllegalArgumentException("sig is not a method signature: " + desc);
|
||||
}
|
||||
StringBuilder deobbed = new StringBuilder(1024 * 1024);
|
||||
while (strIndex < desc.length())
|
||||
{
|
||||
switch (desc.charAt(strIndex))
|
||||
{
|
||||
case ')':
|
||||
deobbed.append(append);
|
||||
deobbed.append(")");
|
||||
strIndex++;
|
||||
break;
|
||||
case '(':
|
||||
case 'I':
|
||||
case 'B':
|
||||
case 'J':
|
||||
case 'S':
|
||||
case 'D':
|
||||
case 'F':
|
||||
case 'C':
|
||||
case 'Z':
|
||||
case 'V':
|
||||
case '[':
|
||||
deobbed.append(desc.charAt(strIndex));
|
||||
strIndex++;
|
||||
break;
|
||||
case 'L':
|
||||
try
|
||||
{
|
||||
String sigPart = desc.substring(strIndex, desc.indexOf(";", strIndex) + 1);
|
||||
deobbed.append(sigPart);
|
||||
strIndex += sigPart.length();
|
||||
}
|
||||
catch (StringIndexOutOfBoundsException ex)
|
||||
{
|
||||
System.err.println(
|
||||
"Method signature %s is probably missing a semi-colon".replace("%s", desc));
|
||||
throw ex;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("signature is invalid: " + desc);
|
||||
}
|
||||
}
|
||||
return deobbed.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package us.runelitepl.mixinprocessor.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class WebUtils
|
||||
{
|
||||
|
||||
public static String getUrlContent(String url) throws IOException
|
||||
{
|
||||
String pageText;
|
||||
URLConnection conn = new URL(url).openConnection();
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)))
|
||||
{
|
||||
pageText = reader.lines().collect(Collectors.joining("\n"));
|
||||
}
|
||||
return pageText;
|
||||
}
|
||||
|
||||
public static byte[] downloadFile(String urlText) throws IOException {
|
||||
URL url = new URL(urlText);
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
|
||||
try (InputStream inputStream = url.openStream()) {
|
||||
int n = 0;
|
||||
byte [] buffer = new byte[ 1024 ];
|
||||
while (-1 != (n = inputStream.read(buffer))) {
|
||||
output.write(buffer, 0, n);
|
||||
}
|
||||
}
|
||||
|
||||
return output.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user